Patch to NewField/PrintField.h
Dave Nystrom
wdn at lanl.gov
Tue Oct 16 22:13:40 UTC 2001
Below is a copy of a patched version of NewField/PrintField.h from the Blanca
branch. Could someone add the changes to the Blanca branch of Pooma2. It
adds a couple of update and blockAndEvaluate calls necessary for running in
parallel.
Thanks,
Dave Nystrom email: wdn at lanl.gov
LANL X-3 phone: 505-667-7913 fax: 505-665-3046
--------------------------NewField/PrintField.h-----------------------------
// -*- C++ -*-
// ACL:license
// ----------------------------------------------------------------------
// This software and ancillary information (herein called "SOFTWARE")
// called POOMA (Parallel Object-Oriented Methods and Applications) is
// made available under the terms described here. The SOFTWARE has been
// approved for release with associated LA-CC Number LA-CC-98-65.
//
// Unless otherwise indicated, this SOFTWARE has been authored by an
// employee or employees of the University of California, operator of the
// Los Alamos National Laboratory under Contract No. W-7405-ENG-36 with
// the U.S. Department of Energy. The U.S. Government has rights to use,
// reproduce, and distribute this SOFTWARE. The public may copy, distribute,
// prepare derivative works and publicly display this SOFTWARE without
// charge, provided that this Notice and any statement of authorship are
// reproduced on all copies. Neither the Government nor the University
// makes any warranty, express or implied, or assumes any liability or
// responsibility for the use of this SOFTWARE.
//
// If SOFTWARE is modified to produce derivative works, such modified
// SOFTWARE should be clearly marked, so as not to confuse it with the
// version available from LANL.
//
// For more information about POOMA, send e-mail to pooma at acl.lanl.gov,
// or visit the POOMA web page at http://www.acl.lanl.gov/pooma/.
// ----------------------------------------------------------------------
// ACL:license
//-----------------------------------------------------------------------------
// Classes:
// PrintField - information and routines used to print out a
// Field to a stream.
//-----------------------------------------------------------------------------
#ifndef POOMA_NEWFIELD_PRINTFIELD_H
#define POOMA_NEWFIELD_PRINTFIELD_H
//-----------------------------------------------------------------------------
// Overview:
//
// PrintField
// - Extract the elements of a Field and print out the
// contents to a stream with some nice formatting. The user can select
// how many elements to print per line, the precision, format, etc.
// This is done by constructing an PrintField, and calling the
// 'print' method with the stream to print to and the field to print.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes:
//-----------------------------------------------------------------------------
#include "Utilities/PAssert.h"
#include <iomanip>
//-----------------------------------------------------------------------------
// Forward References:
//-----------------------------------------------------------------------------
class PrintField;
//-----------------------------------------------------------------------------
//
// Full Description:
//
// PrintField is a utility program for ConstField and Field object, used
// to print (nicely) the contents of an field to a provided stream. All
// the data in the field will be printed in ascii format; if you want to
// display just a portion of an field, take a view of the field and give
// that to the print() method.
//
// CONSTRUCTING A PrintField:
// --------------------------
// When you construct a PrintField, you can give it several format parameters
// to control how to display the field. These parameters are, in the
// order they are given in the constructor (all have default values):
//
// domain width: the number of spaces that will be used to print out domain
// numbers. If it is 3, say, then domains will be printed like
// [003:008]
// - query setting with "domainWidth()"
// - change setting with "setDomainWidth(int newval)"
//
// data width: the number of spaces, total, used to print out data values.
// - query setting with "dataWidth()"
// - change setting with "setDataWidth(int newval)"
//
// data precision: the number of digits past the decimal point displayed
// when data values are printed
// - query setting with "dataPrecision()"
// - change setting with "setDataPrecision(int newval)"
//
// carriage return: if this value is < 0, then for each row of values from
// the field, no carriage return is printed until the end
// of the row. If this number is > 0, it represents the
// maximum number of values that will be printed before a
// return. Only the first set of numbers for a row of
// the field will have a domain prefix included.
// - query setting with "carReturn()"
// - change setting with "setCarReturn(int newval)"
//
// scientific notation: a boolean flag, if true numbers are printed using
// scientific notation, e.g. 10e-14
// - query setting with "scientific()"
// - change setting with "setScientific(bool newflag)"
//
// data spacing: the number of spaces to print between values
// - query setting with "spacing()"
// - change setting with "setSpacing(int newval)"
//
// PRINTING FIELDE OBJECTS WITH A PrintField:
// -----------------------------------------
// PrintField is not templated, so that you can reuse the same formatter
// for different fields. It has one templated member function 'print':
//
// template<class S, class A>
// void print(S &s, const A &a) const
//
// where 'S' must be an object with an ostream-like interface (such as
// cout, or an Inform object), and 'A' must be an object with a Field
// interface. 'print' will take data from A and print it to the stream
// using the current format settings.
//
// 1-D fields just have the one row printed, perhaps on multiple lines
// if carReturn is > 0. 2-D fields are printed as a table, with each
// line prefixed by the domain it includes. For example:
// [00:02][00] = 0 0 0
// [00:02][01] = 0 0 0
// prints the values for [0:2][0:1] of a 2D field. 3-D and higher arrays
// have a sequence of 2-D slices printed for them, each slice separated
// by a line indicating which slice it is, and a separator. Example:
// [0:2:1][0:3:1][2]:
// ----------------------------------------------------
// [00:02][00][02] = 0 0 0
// [00:02][01][02] = 0 0 0
// [00:02][02][02] = 0 0 0
// [00:02][03][02] = 0 0 0
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Open POOMA namespace:
//-----------------------------------------------------------------------------
// namespace POOMA {
//-----------------------------------------------------------------------------
// PerformPrintField struct: a simple wrapper around the templated 'print'
// method of PrintField. This is here as a workaround to a Metrowerks
// problem that prevents having templated member functions defined as
// out-of-line. This struct defines one static method 'print', which
// prints an field to a stream (the two template parameters). The Dim
// parameter is used to specialize this to the case of a 1D domain. This is
// called by the 'print' templated member function of PrintField.
//-----------------------------------------------------------------------------
template<class S, class A, int Dim>
struct PerformPrintField
{
static void print(const PrintField &, S &, const A &);
};
template<class S, class A>
struct PerformPrintField<S, A, 1>
{
static void print(const PrintField &, S &, const A &);
};
//-----------------------------------------------------------------------------
// PrintAarry class declaration
//-----------------------------------------------------------------------------
class PrintField
{
public:
//============================================================
// Constructors.
//============================================================
//------------------------------------------------------------
// Construct an PrintField object with an field, and the settings for
// how the field should be printed.
PrintField(int domainWidth = 3, int dataWidth = 10,
int dataPrecision = 4, int carReturn = -1,
bool scientific = false, int spacing = 1)
: domainwidth_m(domainWidth), datawidth_m(dataWidth),
dataprecision_m(dataPrecision), carreturn_m(carReturn),
spacing_m(spacing), scientific_m(scientific)
{
PAssert(domainwidth_m > 0);
PAssert(datawidth_m > 0);
PAssert(dataprecision_m > 0);
PAssert(spacing_m >= 0);
}
//------------------------------------------------------------
// Copy constructor.
PrintField(const PrintField &a)
: domainwidth_m(a.domainwidth_m), datawidth_m(a.datawidth_m),
dataprecision_m(a.dataprecision_m), carreturn_m(a.carreturn_m),
scientific_m(a.scientific_m)
{
}
//============================================================
// Destructor.
//============================================================
~PrintField()
{
}
//============================================================
// PrintField print methods.
//============================================================
//------------------------------------------------------------
// print this field to the given stream. This just invokes a
// static method in an external class in order to get around a
// Metrowerks bug.
template<class S, class A>
void print(S &s, const A &a) const
{
int n = a.numSubFields();
if (n == 0)
{
PerformPrintField<S,A,A::dimensions>::print(*this, s, a);
}
else
{
for (int i = 0; i < n; i++)
{
s << "subfield #" << i << ":\n"<< "-------------\n";
print(s, a[i]);
}
}
}
//============================================================
// PrintField format settings accessors.
//============================================================
//------------------------------------------------------------
// get/set the number of places used to print out domain numbers
int domainWidth() const
{
return domainwidth_m;
}
void setDomainWidth(int val)
{
domainwidth_m = val;
PAssert(domainwidth_m > 0);
}
//------------------------------------------------------------
// get/set the number of places used to print out field data values
int dataWidth() const
{
return datawidth_m;
}
void setDataWidth(int val)
{
datawidth_m = val;
PAssert(datawidth_m > 0);
}
//------------------------------------------------------------
// get/set the precision of the field data values
int dataPrecision() const
{
return dataprecision_m;
}
void setDataPrecision(int val)
{
dataprecision_m = val;
PAssert(dataprecision_m > 0);
}
//------------------------------------------------------------
// get/set the number of carriage returns used
int carReturn() const
{
return carreturn_m;
}
void setCarReturn(int val)
{
carreturn_m = val;
}
//------------------------------------------------------------
// get/set the flag indicating whether to use scientific notation
bool scientific() const
{
return scientific_m;
}
void setScientific(bool val)
{
scientific_m = val;
}
//------------------------------------------------------------
// get/set the number of spaces between numbers
int spacing() const
{
return spacing_m;
}
void setSpacing(int val)
{
spacing_m = val;
PAssert(spacing_m >= 0);
}
private:
//------------------------------------------------------------
// The width for domain numbers.
int domainwidth_m;
//------------------------------------------------------------
// The width for field element values.
int datawidth_m;
//------------------------------------------------------------
// The precision of the field element values.
int dataprecision_m;
//------------------------------------------------------------
// How long before a carriage return is printed.
int carreturn_m;
//------------------------------------------------------------
// The number of spaces between values.
int spacing_m;
//------------------------------------------------------------
// Should scientific notation be used?
bool scientific_m;
};
//-----------------------------------------------------------------------------
// PerformPrintField print method definition.
// print takes data from an field, and prints it nicely to a stream.
// S is a template parameter for an ostream-like object.
// A is a template parameter for a Field-like object.
// This is the 1-D specialized case.
//-----------------------------------------------------------------------------
template<class S, class A>
void
PerformPrintField<S,A,1>::print(const PrintField &p, S &s, const A &a)
{
// make sure this is the right function
CTAssert(A::dimensions == 1);
// Output should update the field before printing. John Hall
a.update();
Pooma::blockAndEvaluate();
// determine the domain and domain-iterator type in the given field
typedef typename A::Domain_t Domain_t;
typedef typename Domain_t::const_iterator Iterator_t;
// create an iterator over the domain of the field
Iterator_t griditer = a.domain().begin();
Iterator_t enditer = a.domain().end();
// print out the prefix
s << "[";
if (a.domain()[0].first() < 0)
s.fill(' ');
else
s.fill('0');
s.width(p.domainWidth());
s << a.domain()[0].first() << ":";
if (a.domain()[0].last() < 0)
s.fill(' ');
else
s.fill('0');
s.width(p.domainWidth());
s << a.domain()[0].last() << "] = ";
s.fill(' ');
// loop over the elements, printing out values as necessary
int i, printed = 0;
while (griditer != enditer)
{
// determine the number of spaces to print first
int spacing = 0;
if (printed > 0)
{
spacing = p.spacing();
if (p.carReturn() >= 0 && printed >= p.carReturn())
{
s << "\n";
spacing = 2*p.domainWidth() + 6;
printed = 0;
}
}
// print out spaces
for (i=0; i < spacing; ++i)
s << " ";
// print the number
if (p.scientific())
s.setf(std::ios::scientific);
s.precision(p.dataPrecision());
s.width(p.dataWidth());
s << a.read(*griditer);
// increment iterator and counter
++griditer;
++printed;
}
// print final newline when done
s << "\n";
}
//-----------------------------------------------------------------------------
// PerformPrintField print method definition.
// print takes data from an field, and prints it nicely to a stream.
// S is a template parameter for an ostream-like object.
// A is a template parameter for a Field-like object.
// This is the N-D general case, for N > 1. It prints out 2D 'slices' for
// the first two dimensions, and loops over the other dimensions.
//-----------------------------------------------------------------------------
template<class S, class A, int Dim>
void
PerformPrintField<S,A,Dim>::print(const PrintField &p, S &s, const A &a)
{
int i, j, k;
// make sure this is the right function
CTAssert(A::dimensions == Dim && Dim > 1);
// Output should update the field before printing. John Hall
a.update();
Pooma::blockAndEvaluate();
// determine the domain and domain-iterator type in the given field
typedef typename A::Domain_t Domain_t;
typedef typename Domain_t::Element_t Element_t;
typedef typename Domain_t::const_iterator Iterator_t;
// create an iterator over the domain of the field
Iterator_t griditer = a.domain().begin();
Iterator_t enditer = a.domain().end();
// get 1-D domains info for the first two dimensions, and use these sizes
// to determine how to do the inner dimensional loops
Element_t x0 = a.domain()[0].first();
Element_t x1 = a.domain()[0].last();
Element_t xs = a.domain()[0].stride();
Element_t y0 = a.domain()[1].first();
Element_t y1 = a.domain()[1].last();
Element_t ys = a.domain()[1].stride();
// Start looping over all the elements. We can stop printing when
// we hit the end of the griditer. We print out 2D slices, and for
// higher dimensions, we print out a line saying which slice is coming
// up next, for example:
// [1:5:1][2:8:1][2][4][0]:
// -------------------------------------------
while (griditer != enditer)
{
// print out the higher-dim size statement, if necessary
if (Dim > 2)
{
s << '\n' << a.domain()[0] << a.domain()[1];
for (i=2; i < Dim; ++i)
s << "[" << (*griditer)[i].first() << "]";
s << ":" << '\n';
s << "----------------------------------------------------\n";
}
// loop over all the elements of the next 2D slice now
for (j=y0; j <= y1; j += ys)
{
// print out the prefix for the next 2D slice line
s << "[";
if (x0 < 0)
s.fill(' ');
else
s.fill('0');
s.width(p.domainWidth());
s << x0 << ":";
if (x1 < 0)
s.fill(' ');
else
s.fill('0');
s.width(p.domainWidth());
s << x1 << "]";
for (i=1; i < Dim; ++i)
{
s << "[";
if ((*griditer)[i].first() < 0)
s.fill(' ');
else
s.fill('0');
s.width(p.domainWidth());
s << (*griditer)[i].first() << "]";
}
s.fill(' ');
s << " = ";
// print all the values along this 1-D strip
int printed = 0;
for (i=x0; i <= x1; i += xs)
{
// determine the number of spaces to print first
int spacing = 0;
if (printed > 0)
{
spacing = p.spacing();
if (p.carReturn() >= 0 && printed >= p.carReturn())
{
s << '\n';
spacing = (Dim + 1)*(p.domainWidth() + 2) + 4;
printed = 0;
}
}
// print out spaces
for (k=0; k < spacing; ++k)
s << ' ';
// print the number
if (p.scientific())
s.setf(std::ios::scientific);
s.precision(p.dataPrecision());
s.width(p.dataWidth());
s << a.read(*griditer);
// increment iterator and counter
++griditer;
++printed;
}
// print final newline when done with this line
s << '\n';
}
}
}
// } // namespace Pooma
#endif // POOMA_NEWFIELD_PRINTFIELD_H
// ACL:rcsinfo
// ----------------------------------------------------------------------
// $RCSfile: PrintField.h,v $ $Author: oldham $
// $Revision: 1.3 $ $Date: 2001/03/29 18:17:32 $
// ----------------------------------------------------------------------
// ACL:rcsinfo
More information about the pooma-dev
mailing list