Commit 8b13eb81 authored by George Zagaris's avatar George Zagaris
Browse files

Merge remote-tracking branch 'origin/master' into AMR-Refactoring

parents 2b1747b6 5075ec2f
......@@ -121,6 +121,7 @@ SET(CTEST_CUSTOM_WARNING_EXCEPTION
"vtkfreetype.*note: initialized from here"
"vtkfreetype.*warning: .* may be used uninitialized in this function"
"vtkfreetype.*note: .* was declared here"
"vtkfreetype/.*warning: .* set but not used"
# vtknetcdf occasionally has warnings for things that are not a problem.
"vtknetcdf.*warning: dereferencing type-punned pointer"
"vtknetcdf.*warning: passing argument .* of .* as .*signed due to prototype"
......@@ -206,11 +207,13 @@ SET(CTEST_CUSTOM_WARNING_EXCEPTION
"Utilities.vtksqlite.vtk_sqlite3.c.*warning: negative integer implicitly converted to unsigned type"
"Utilities.vtksqlite.vtk_sqlite3.c.*warning: assuming signed overflow"
"Utilities.vtksqlite.vtk_sqlite3.c.*warning: .* may be used uninitialized in this function"
"Utilities.vtksqlite.vtk_sqlite3.c.*warning: .* set but not used"
"Utilities.vtkexodus2.*warning.*assignment discards qualifiers from pointer target type"
"Utilities.vtkexodus2.*warning.*initialization discards qualifiers from pointer target type"
"Utilities.vtkexodus2.*warning.*assignment discards qualifiers from pointer target type"
"Utilities.vtkexodus2.*warning.*passing argument .* of .* as unsigned due to prototype"
"Utilities.vtkexodus2.*warning.*possible loss of data"
"Uitilties/vtkexodus2.*warning: .* set but not used"
# gcc -Wsign-conversion
"Utilities.vtkexodus2.*warning.*conversion to .* from .* may change the sign of the result"
# gcc -Wconversion
......@@ -254,14 +257,17 @@ SET(CTEST_CUSTOM_WARNING_EXCEPTION
"Utilities.vtkpng.*warning: variable .* might be clobbered by"
"Utilities/vtkjpeg.*warning: conversion to .* from .* may change the sign of the result"
"Utilities/vtkjpeg.*warning: conversion to .* from .* may alter its value"
"Utilities/vtkjpeg.*.warning: .* set but not used"
"Utilities/DICOMParser.*warning: conversion to .* from .* may alter its value"
"Utilities/DICOMParser.*warning: conversion to .* from .* may change the sign of the result"
# gcc -Wsign-conversion
"Utilities/vtkmetaio.*warning: conversion to '.*' from '.*' may change the sign of the result"
# gcc -Wconversion
"Utilities/vtkmetaio.*warning: conversion to '.*' from '.*' may alter its value"
"Uitilties/vtkmetaio/.*warning: .* set but not used"
# gcc -Wsign-conversion
"Utilities/vtkalglib.*warning: conversion to .* from .* may change the sign of the result"
"Uitilties/vtkalglib/.*warning: .* set but not used"
# gcc -Wsign-conversion
"Utilities/ftgl/src/.*warning: conversion to .* from .* may change the sign of the result"
# gcc -Wconversion
......@@ -275,6 +281,8 @@ SET(CTEST_CUSTOM_WARNING_EXCEPTION
"Utilities/mrmpi/.*warning: conversion to .* from .* may change the sign of the result"
# gcc -Wunused-result
"Utilities/mrmpi/.*warning: ignoring return value of .size_t fread.void.. size_t. size_t. FILE.... declared with attribute warn_unused_result"
"Uitilties/vtklibproj4/.*warning: .* set but not used"
)
IF(APPLE)
......
......@@ -136,6 +136,11 @@ IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY)
ADD_EXECUTABLE(TestParallelKMeansStatisticsMPI TestParallelKMeansStatisticsMPI.cxx)
TARGET_LINK_LIBRARIES(TestParallelKMeansStatisticsMPI vtkInfovis vtkParallel ${MPI_LIBRARIES})
# TestRealDataPDescriptiveStatisticsMPI:
# MPI test of parallel descriptive statistics with real data
ADD_EXECUTABLE(TestRealDataPDescriptiveStatisticsMPI TestRealDataPDescriptiveStatisticsMPI.cxx)
TARGET_LINK_LIBRARIES(TestRealDataPDescriptiveStatisticsMPI vtkInfovis vtkParallel ${MPI_LIBRARIES})
IF (VTK_MPIRUN_EXE)
ADD_TEST(TestParallelRandomStatisticsMPI
${VTK_MPIRUN_EXE} ${VTK_MPI_PRENUMPROC_FLAGS} ${VTK_MPI_NUMPROC_FLAG} ${VTK_MPI_MAX_NUMPROCS}
......@@ -164,6 +169,13 @@ IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY)
${CXX_TEST_PATH}/${CXX_TEST_CONFIG}/TestParallelKMeansStatisticsMPI
${VTK_MPI_POSTFLAGS}
)
ADD_TEST(TestRealDataPDescriptiveStatisticsMPI
${VTK_MPIRUN_EXE} ${VTK_MPI_PRENUMPROC_FLAGS} ${VTK_MPI_NUMPROC_FLAG} ${VTK_MPI_MAX_NUMPROCS}
${VTK_MPI_PREFLAGS}
${CXX_TEST_PATH}/${CXX_TEST_CONFIG}/TestRealDataPDescriptiveStatisticsMPI
${VTK_MPI_POSTFLAGS}
)
ENDIF (VTK_MPIRUN_EXE)
ENDIF (VTK_USE_PARALLEL AND VTK_USE_MPI)
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestParallelRandomStatisticsMPI.cxx
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 2008 Sandia Corporation.
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
* license for use of this work by or on behalf of the
* U.S. Government. Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that this Notice and any
* statement of authorship are reproduced on all copies.
*/
// .SECTION Thanks
// Thanks to Philippe Pebay and Ajith Mascarenhas from Sandia National Laboratories
// for implementing this test.
#include <mpi.h>
#include "vtkPDescriptiveStatistics.h"
#include "vtkFloatArray.h"
#include "vtkMath.h"
#include "vtkMPIController.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkStdString.h"
#include "vtkTable.h"
#include "vtkTimerLog.h"
#include "vtkVariantArray.h"
#include "vtksys/CommandLineArguments.hxx"
#include "vtksys/SystemTools.hxx"
struct RealDataDescriptiveStatisticsArgs
{
int nVals;
int* retVal;
int ioRank;
vtkStdString fileName;
int* dataDim;
int* procDim;
int argc;
char** argv;
};
// Calculate the processor id (integer triple), given its rank
void CalculateProcessorId( int *procDim, int rank, int *procId )
{
int procXY = procDim[0] * procDim[1];
procId[2] = rank / procXY;
procId[1] = ( rank - procId[2] * procXY ) / procDim[0];
procId[0] = ( rank - procId[2] * procXY ) % procDim[0];
}
// Calculate the processor rank given its id(integer triple)
int CalculateProcessorRank( int *procDim, int *procId )
{
int rank = procId[2] * procDim[0] * procDim[1] +
procId[1] * procDim[0] + procId[0];
return rank;
}
// Read a block of data bounded by [low, high] from file into buffer.
// The entire data has dimensions dim
void ReadFloatDataBlockFromFile( ifstream& ifs,
int *dim,
int *low,
int *high,
float *buffer )
{
vtkIdType dimXY = dim[0] * dim[1];
vtkIdType dimX = dim[0];
float *pbuffer = buffer;
// Set bounds
vtkIdType bounds[2][3];
bounds[0][0] = ( low[0] < 0 ? 0 : low[0] );
bounds[0][1] = ( low[1] < 0 ? 0 : low[1] );
bounds[0][2] = ( low[2] < 0 ? 0 : low[2] );
bounds[1][0] = ( high[0] >= dim[0] ? dim[0] - 1 : high[0] );
bounds[1][1] = ( high[1] >= dim[1] ? dim[1] - 1 : high[1] );
bounds[1][2] = ( high[2] >= dim[2] ? dim[2] - 1 : high[2] );
vtkIdType rangeX = bounds[1][0] - bounds[0][0] + 1;
vtkIdType sizeX = high[0] - low[0] + 1;
vtkIdType sizeY = high[1] - low[1] + 1;
vtkIdType sizeXY = sizeX * sizeY;
// Next position to start writing
pbuffer += (bounds[0][0] - low[0] );
// Iterate over 'z'
for (int z = low[2]; z <= high[2]; z++)
{
if (z >= bounds[0][2] && z <= bounds[1][2] )
{
vtkIdType offsetZ = z * dimXY;
// Iterate over 'y'.
for (int y = low[1]; y <= high[1]; y++)
{
if (y >= bounds[0][1] && y <= bounds[1][1] )
{
vtkIdType offsetY = y * dimX;
long long offset = offsetZ + offsetY + bounds[0][0];
// Seek to point
ifs.seekg( offset * sizeof(*pbuffer), ios::beg );
// Get a block of rangeX values
ifs.read( reinterpret_cast<char *>( pbuffer ),
rangeX * sizeof(*pbuffer) );
// Proceed to next write position
pbuffer += sizeX;
if ( ifs.fail() || ifs.eof() )
{
vtkGenericWarningMacro("Failed to read data or reached EOF.");
exit( -1 );
}
}
else
{
// Skip one line
pbuffer += sizeX;
}
}
}
else
{
// Skip one plane
pbuffer += sizeXY;
}
}
}
// Given the data dimensions dataDim, the process dimensions procDim, my
// process id myProcId, set the block bounding box myBlockBounds for my data.
// Also open the data file as filestream ifs.
void SetDataParameters( int *dataDim,
int *procDim,
int *myProcId,
const char* fileName,
ifstream& ifs,
int myBlockBounds[2][3] )
{
vtkIdType myDim[3];
myDim[0] = static_cast<int>( ceil( dataDim[0] / ( 1. * procDim[0] ) ) );
myDim[1] = static_cast<int>( ceil( dataDim[1] / ( 1. * procDim[1] ) ) );
myDim[2] = static_cast<int>( ceil( dataDim[2] / ( 1. * procDim[2] ) ) );
// cout << "My data dim = " << myDim[0] << " x " << myDim[1] <<
// " x " << myDim[2] << endl;
// Determine data bounds
myBlockBounds[0][0] = myProcId[0] * myDim[0];
myBlockBounds[0][1] = myProcId[1] * myDim[1];
myBlockBounds[0][2] = myProcId[2] * myDim[2];
vtkIdType mybb0 = myBlockBounds[0][0] + myDim[0] - 1;
vtkIdType cast0 = static_cast<int>( dataDim[0] - 1 );
myBlockBounds[1][0] = ( mybb0 < cast0 ? mybb0 : cast0 );
vtkIdType mybb1 = myBlockBounds[0][1] + myDim[1] - 1;
vtkIdType cast1 = static_cast<int>( dataDim[1] - 1 );
myBlockBounds[1][1] = ( mybb1 < cast1 ? mybb1 : cast1 );
vtkIdType mybb2 = myBlockBounds[0][2] + myDim[2] - 1;
vtkIdType cast2 = static_cast<int>( dataDim[2] - 1 );
myBlockBounds[1][2] = ( mybb2 < cast2 ? mybb2 : cast2 );
// Open file
ifs.open( fileName, ios::in | ios::binary );
if( ifs.fail() )
{
vtkGenericWarningMacro("Error opening file:"
<< fileName
<<".");
exit( -1 );
}
}
// This will be called by all processes
void RealDataDescriptiveStatistics( vtkMultiProcessController* controller, void* arg )
{
// Get test parameters
RealDataDescriptiveStatisticsArgs* args = reinterpret_cast<RealDataDescriptiveStatisticsArgs*>( arg );
*(args->retVal) = 0;
// Get MPI communicator
vtkMPICommunicator* com = vtkMPICommunicator::SafeDownCast( controller->GetCommunicator() );
// Get local rank
int myRank = com->GetLocalProcessId();
int myProcId[3];
CalculateProcessorId( args->procDim, myRank, myProcId );
// Synchronize and start clock
com->Barrier();
vtkTimerLog *timer=vtkTimerLog::New();
timer->StartTimer();
// ************************** Read input data file ****************************
ifstream ifs;
int myBlockBounds[2][3];
SetDataParameters( args->dataDim,
args->procDim,
myProcId,
args->fileName,
ifs,
myBlockBounds );
vtkIdType myDataDim[3];
myDataDim[0] = myBlockBounds[1][0] - myBlockBounds[0][0] + 1;
myDataDim[1] = myBlockBounds[1][1] - myBlockBounds[0][1] + 1;
myDataDim[2] = myBlockBounds[1][2] - myBlockBounds[0][2] + 1;
vtkIdType myDataSize = myDataDim[0] * myDataDim[1] * myDataDim[2];
float* buffer = new float[myDataSize];
ReadFloatDataBlockFromFile( ifs,
args->dataDim,
myBlockBounds[0],
myBlockBounds[1],
buffer );
// ************************** Create input data table *************************
vtkStdString varName( "Chi" );
vtkFloatArray* floatArr = vtkFloatArray::New();
floatArr->SetNumberOfComponents( 1 );
floatArr->SetName( varName );
for ( vtkIdType i = 0; i < myDataSize; ++ i )
{
floatArr->InsertNextValue( buffer[i] );
}
cout << "\n# Cardinality on process "
<< myRank
<< ": "
<< myDataSize
<< "\n";
vtkTable* inputData = vtkTable::New();
inputData->AddColumn( floatArr );
floatArr->Delete();
delete [] buffer;
// ************************** Descriptive Statistics **************************
// Instantiate a parallel descriptive statistics engine and set its input
vtkPDescriptiveStatistics* pcs = vtkPDescriptiveStatistics::New();
pcs->SetInput( vtkStatisticsAlgorithm::INPUT_DATA, inputData );
// Select column of interest
pcs->AddColumn( varName );
// Test (in parallel) with Learn, Derive, and Assess options turned on
pcs->SetLearnOption( true );
pcs->SetDeriveOption( true );
pcs->SetAssessOption( true );
pcs->Update();
// Get output data and meta tables
vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast( pcs->GetOutputDataObject( vtkStatisticsAlgorithm::OUTPUT_MODEL ) );
vtkTable* outputPrimary = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 0 ) );
vtkTable* outputDerived = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 1 ) );
// Synchronize and stop clock
com->Barrier();
timer->StopTimer();
if ( com->GetLocalProcessId() == args->ioRank )
{
cout << "\n## Completed parallel calculation of descriptive statistics (with assessment):\n"
<< " Total sample size: "
<< outputPrimary->GetValueByName( 0, "Cardinality" ).ToInt()
<< " \n"
<< " Wall time: "
<< timer->GetElapsedTime()
<< " sec.\n";
cout << " Calculated the following primary statistics:\n";
for ( vtkIdType r = 0; r < outputPrimary->GetNumberOfRows(); ++ r )
{
cout << " ";
for ( int i = 0; i < outputPrimary->GetNumberOfColumns(); ++ i )
{
cout << outputPrimary->GetColumnName( i )
<< "="
<< outputPrimary->GetValue( r, i ).ToString()
<< " ";
}
cout << "\n";
}
cout << " Calculated the following derived statistics:\n";
for ( vtkIdType r = 0; r < outputDerived->GetNumberOfRows(); ++ r )
{
cout << " ";
for ( int i = 0; i < outputDerived->GetNumberOfColumns(); ++ i )
{
cout << outputDerived->GetColumnName( i )
<< "="
<< outputDerived->GetValue( r, i ).ToString()
<< " ";
}
cout << "\n";
}
}
// Clean up
pcs->Delete();
inputData->Delete();
timer->Delete();
}
//----------------------------------------------------------------------------
int main( int argc, char** argv )
{
// **************************** MPI Initialization ***************************
vtkMPIController* controller = vtkMPIController::New();
controller->Initialize( &argc, &argv );
// If an MPI controller was not created, terminate in error.
if ( ! controller->IsA( "vtkMPIController" ) )
{
vtkGenericWarningMacro("Failed to initialize a MPI controller.");
controller->Delete();
return 1;
}
vtkMPICommunicator* com = vtkMPICommunicator::SafeDownCast( controller->GetCommunicator() );
// Get local rank
int myRank = com->GetLocalProcessId();
// ************************** Find an I/O node ********************************
int* ioPtr;
int ioRank;
int flag;
MPI_Attr_get( MPI_COMM_WORLD,
MPI_IO,
&ioPtr,
&flag );
if ( ( ! flag ) || ( *ioPtr == MPI_PROC_NULL ) )
{
// Getting MPI attributes did not return any I/O node found.
ioRank = MPI_PROC_NULL;
vtkGenericWarningMacro("No MPI I/O nodes found.");
// As no I/O node was found, we need an unambiguous way to report the problem.
// This is the only case when a testValue of -1 will be returned
controller->Finalize();
controller->Delete();
return -1;
}
else
{
if ( *ioPtr == MPI_ANY_SOURCE )
{
// Anyone can do the I/O trick--just pick node 0.
ioRank = 0;
}
else
{
// Only some nodes can do I/O. Make sure everyone agrees on the choice (min).
com->AllReduce( ioPtr,
&ioRank,
1,
vtkCommunicator::MIN_OP );
}
}
if ( myRank == ioRank )
{
cout << "\n# Process "
<< ioRank
<< " will be the I/O node.\n";
}
// Check how many processes have been made available
int numProcs = controller->GetNumberOfProcesses();
if ( myRank == ioRank )
{
cout << "\n# Running test with "
<< numProcs
<< " processes...\n";
}
// **************************** Parse command line ***************************
// If no arguments were provided, terminate in error.
if ( argc < 2 )
{
vtkGenericWarningMacro("No input data arguments were provided.");
controller->Delete();
return 1;
}
// Set default argument values (some of which are invalid, for mandatory parameters)
vtkStdString fileName= "";
vtksys_stl::vector<int> dataDim;
vtksys_stl::vector<int> procDim;
// Initialize command line argument parser
vtksys::CommandLineArguments clArgs;
clArgs.Initialize( argc, argv );
clArgs.StoreUnusedArguments( false );
// Parse input data file name
clArgs.AddArgument("--file-name",
vtksys::CommandLineArguments::SPACE_ARGUMENT,
&fileName, "Name of input data file");
// Parse input data file name
clArgs.AddArgument("--data-dim",
vtksys::CommandLineArguments::MULTI_ARGUMENT,
&dataDim, "Dimensions of the input data");
// Parse process array dimensions
clArgs.AddArgument("--proc-dim",
vtksys::CommandLineArguments::MULTI_ARGUMENT,
&procDim, "Dimensions of the input data");
// If incorrect arguments were provided, terminate in error.
if ( ! clArgs.Parse() )
{
vtkGenericWarningMacro("Incorrect input data arguments were provided.");
return 1;
}
// If no file name was provided, terminate in error.
if ( ! strcmp( fileName.c_str(), "" ) )
{
if ( myRank == ioRank )
{
vtkGenericWarningMacro("No input data file name was provided.");
}
// Terminate cleanly
controller->Finalize();
controller->Delete();
return 1;
}
else
{
if ( myRank == ioRank )
{
cout << "\n# Input data file name: "
<< fileName
<< "\n";
}
}
// If no or insufficient data dimensionality information, terminate in error.
if ( dataDim.size() < 3 )
{
if ( myRank == ioRank )
{
vtkGenericWarningMacro("Only "
<< dataDim.size()
<< "data dimension(s) provided (3 needed).");
}
// Terminate cleanly
controller->Finalize();
controller->Delete();
return 1;
}
else
{
if ( myRank == ioRank )
{
cout << "\n# Data dimensionality: "
<< dataDim.at( 0 )
<< " "
<< dataDim.at( 1 )
<< " "
<< dataDim.at( 2 )
<< "\n";
}
}
// Fill process dimensionality with ones if not provided or incomplete
unsigned int missingDim = 3 - procDim.size();
for ( unsigned int d = 0; d < missingDim; ++ d )
{
procDim.push_back( 1 );
}
// If process dimensionality is inconsistent with total number of processes, terminate in error.
if ( procDim.at( 0 ) * procDim.at( 1 ) * procDim.at( 2 ) != numProcs )
{
if ( myRank == ioRank )
{
vtkGenericWarningMacro("Number of processes: "
<< numProcs
<< " <> "
<< procDim.at( 0 )
<< " * "
<< procDim.at( 1 )
<< " * "
<< procDim.at( 2 )