/*
Copyright (C) 2000-2004
Code contributed by Greg Collecutt, Joseph Hope and Paul Cochrane
This file is part of xmds.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
$Id: xmdsvectorelement.cc,v 1.20 2005/10/18 23:33:16 joehope Exp $
*/
/*! @file xmdsvectorelement.cc
@brief Vector element parsing classes and methods
More detailed explanation...
*/
#include<xmlbasics.h>
#include<dom3.h>
#include<xmdsutils.h>
#include<xmdsclasses.h>
// ******************************************************************************
// ******************************************************************************
// xmdsVectorElement public
// ******************************************************************************
// ******************************************************************************
extern bool debugFlag;
long nxmdsVectorElements=0; //!< The number of xmds vector elements
enum {
ASCII = 1,
BINARY = 2
};
// ******************************************************************************
xmdsVectorElement::xmdsVectorElement(
const xmdsSimulation *const yourSimulation,
const bool& yourVerboseMode,
const xmdsField *const yourField) :
xmdsVector(yourField),
xmdsElement(yourSimulation,yourVerboseMode) {
if(debugFlag) {
nxmdsVectorElements++;
printf("xmdsVectorElement::xmdsVectorElement\n");
printf("nxmdsVectorElements=%li\n",nxmdsVectorElements);
}
};
// ******************************************************************************
xmdsVectorElement::~xmdsVectorElement() {
if(debugFlag) {
nxmdsVectorElements--;
printf("xmdsVectorElement::~xmdsVectorElement\n");
printf("nxmdsVectorElements=%li\n",nxmdsVectorElements);
}
};
// ******************************************************************************
void xmdsVectorElement::processElement(
const Element *const yourElement) {
if(debugFlag) {
printf("xmdsVectorElement::processElement\n");
}
list<XMLString> anXMLStringList;
XMLString anXMLString;
if(verbose()) {
printf("Processing vector element ...\n");
}
// ************************************
// find name
getAssignmentStrings(yourElement,"name",1,1,anXMLStringList);
const xmdsVector* possibleTwin;
if(field()->getVector(*anXMLStringList.begin(),possibleTwin)) {
sprintf(errorMessage(),"a vector of name '%s' already exists in this field",anXMLStringList.begin()->c_str());
throw xmdsException(yourElement,errorMessage());
}
setName(*anXMLStringList.begin());
if(verbose()) {
printf("vector name is '%s'\n",name()->c_str());
}
// ************************************
// find type
getAssignmentStrings(yourElement,"type",0,1,anXMLStringList);
if(anXMLStringList.size()==1) {
if(*anXMLStringList.begin()=="complex") {
setVectorType(COMPLEX);
if(verbose()) {
printf("vector type is 'complex'\n");
}
}
else if(*anXMLStringList.begin()=="double") {
setVectorType(DOUBLE);
if(verbose()) {
printf("vector type is 'double'\n");
}
}
else {
}
}
else {
setVectorType(COMPLEX);
printf("vector type defaulting to 'complex'\n");
}
// ************************************
// find components
getAssignmentStrings(yourElement,"components",1,0,anXMLStringList);
if(anXMLStringList.size()==0) {
throw xmdsException(yourElement,"No vector components specified!");
}
setComponents(anXMLStringList);
if(verbose()) {
for(unsigned long i=0; i<nComponents(); i++) {
printf("adding vector component '%s'\n",componentName(i)->c_str());
}
}
// ************************************
// find 'filename'
getAssignmentStrings(yourElement,"filename",NOT_REQD,1,anXMLStringList);
if(anXMLStringList.size()==1) {
// we have a filename assignent
getAttributeStrings(yourElement,"filename","format",NOT_REQD,anXMLString);
myInputFileFormat = ASCII; // the default value
if (anXMLString != EMPTY_STRING) {
// a format attribute has been set
if (anXMLString == "binary") {
myInputFileFormat = BINARY;
}
else if (anXMLString == "bin") {
myInputFileFormat = BINARY;
}
else if (anXMLString == "ascii") {
myInputFileFormat = ASCII;
}
else if (anXMLString == "text") {
myInputFileFormat = ASCII;
}
else if (anXMLString == "txt") {
myInputFileFormat = ASCII;
}
else {
throw xmdsException(yourElement,
"Warning: Unknown file format attribute value in 'filename' tag\nI expected either 'binary' or 'ascii'.");
}
}
myFileName=*anXMLStringList.begin();
if(verbose()) {
printf("vector initialisation from file '%s'\n",myFileName.c_str());
}
setInitialSpace(0);
}
else {
// initialisation from code
if(verbose()) {
printf("initialisation from user code\n");
}
setInitialSpace(0);
if(field()->geometry()->nDims()>0) {
// ************************************
// find space
list<bool> aSpaceList;
getAssignmentBools(yourElement,"fourier_space",0,field()->geometry()->nDims(),aSpaceList);
if(aSpaceList.size() == 0) {
printf("Initialisation space for vector '%s' defaulting to x-space.\n",name()->c_str());
}
else {
list<bool>::const_iterator pBool = aSpaceList.begin();
for(unsigned long i=0;i<field()->geometry()->nDims();i++) {
if(verbose()) {
if(*pBool) {
printf("initialisation will be performed with dimension #%li in fourier space\n",i+1);
}
else {
printf("initialisation will be performed with dimension #%li in normal space\n",i+1);
}
}
pBool++;
}
setInitialSpace(spaceList2ULong(aSpaceList));
}
}
// ************************************
// find vectors
getAssignmentStrings(yourElement,"vectors",0,0,myVectorNamesList);
field()->processVectors(myVectorNamesList,initialSpace());
// ************************************
// find code
myCode=*yourElement->textContent(0);
// check for non-white space charaters in code:
if(myCode.isAllWhiteSpace()) {
throw xmdsException(yourElement,"No initialisation code defined!");
}
if(verbose()) {
printf("initialisation code loaded\n");
}
}
};
// ******************************************************************************
// ******************************************************************************
// xmdsVectorElement private
// ******************************************************************************
// ******************************************************************************
// ******************************************************************************
void xmdsVectorElement::writeInitialiseRoutine(
FILE *const outfile) const {
if(debugFlag) {
printf("xmdsVectorElement::writeInitialise\n");
}
const unsigned long nDims = field()->geometry()->nDims();
const char *const fieldName = field()->name()->c_str();
const char *const vectorName = name()->c_str();
fprintf(outfile,
"// *************************\n"
"void _%s_%s_initialise() {\n\n",
fieldName,
vectorName);
if(myFileName.length()>0) {
// initialisation from file
if(myInputFileFormat == ASCII) {
fprintf(outfile,
"FILE* infile = fopen(\"%s\",\"r\");\n"
"\n"
"if (infile==0) {\n"
"\t printf(\"Error opening file '%s' for initialisation of vector '%s'\\n\");\n"
"\t exit(255);\n"
"\t }\n"
"\n"
"unsigned long _i0=0;\n"
"\n",
myFileName.c_str(),
myFileName.c_str(),
vectorName);
if(simulation()->parameters()->usempi&!simulation()->parameters()->stochastic) {
//forwarding to "ranks' point in file. Slow but safe
fprintf(outfile,"double _garbage=0.0;\n");
fprintf(outfile,"for(unsigned long _i0=0;_i0<(_%s_size/_%s_lattice0)*_%s_%s_ncomponents*local_x_start;_i0++){\n",fieldName,fieldName,fieldName,vectorName);
if(vectorType()==COMPLEX) {
fprintf(outfile,"\t if(fscanf(infile,\"%%lf %%lf\",&_garbage,&_garbage) != 2) \n");
}
else if(vectorType()==DOUBLE) {
fprintf(outfile,"\t if(fscanf(infile,\"%%lf\",&_garbage) != 1) \n");
}
fprintf(outfile,
"\t\t printf(\"Rank %%i Error forwarding '%s' from file '%s': either bad float format or insufficient data\\n\",rank);\n",vectorName,
myFileName.c_str());
fprintf(outfile,"}\n");
fprintf(outfile,"\n");
fprintf(outfile,"while(_i0<total_local_size*_%s_%s_ncomponents) {\n",
fieldName,
fieldName,
vectorName);
}
else{
fprintf(outfile,"while(_i0<_%s_size*_%s_%s_ncomponents) {\n",
fieldName,
fieldName,
vectorName);
}
if(vectorType()==COMPLEX) {
fprintf(outfile,"\t if(fscanf(infile,\"%%lf %%lf\",&_%s_%s[_i0].re,&_%s_%s[_i0].im) != 2) {\n",
fieldName,vectorName,fieldName,vectorName);
}
else if(vectorType()==DOUBLE) {
fprintf(outfile,"\t if(fscanf(infile,\"%%lf\",&_%s_%s[_i0]) != 1) {\n",fieldName,vectorName);
}
fprintf(outfile,
"\t\t printf(\"Error loading '%s' from file '%s': either bad float format or insufficient data\\n\");\n",vectorName,
myFileName.c_str());
if(simulation()->parameters()->usempi&!simulation()->parameters()->stochastic)
fprintf(outfile,"\t\t _i0=total_local_size*_%s_%s_ncomponents;\n",
fieldName,
vectorName);
else
fprintf(outfile,"\t\t _i0=_%s_size*_%s_%s_ncomponents;\n",
fieldName,
fieldName,
vectorName);
/* This next line kills the program at this point.
We may or may not want to do this, although I just had a user
request that the program not continue past this error. (Wasted time)
Reverting is as simple as deleting the next line. (JJH) */
fprintf(outfile,"\t\t exit(255);\n"
"\t }\n"
"\t _i0++;\n"
"}\n"
"\n"
"fclose(infile);\n");
}
else if (myInputFileFormat == BINARY) {
fprintf(outfile,
"FILE* infile = fopen(\"%s\",\"rb\");\n"
"\n"
"if (infile==0) {\n"
"\t printf(\"Error opening file '%s' for initialisation of vector '%s'\\n\");\n"
"\t return;\n"
"\t }\n"
"\n",
myFileName.c_str(),
myFileName.c_str(),
vectorName);
if(vectorType()==COMPLEX) {
// We are cutting the temporary variable due to stack overflow. Why was this done this way originally?
// fprintf(outfile,"\t complex _tempInput[_%s_size*_%s_%s_ncomponents];\n",
// fieldName,fieldName,vectorName);
// fprintf(outfile,"\t fread(&_tempInput, sizeof(complex), _%s_size*_%s_%s_ncomponents, infile);\n",
// fieldName,fieldName,vectorName);
fprintf(outfile,"\t fread(_%s_%s, sizeof(complex), _%s_size*_%s_%s_ncomponents, infile);\n",fieldName,vectorName,
fieldName,fieldName,vectorName);
// fprintf(outfile,"\t _%s_%s = _tempInput;\n",fieldName,vectorName);
}
else if(vectorType()==DOUBLE) {
// fprintf(outfile,"\t double _tempInput[_%s_size*_%s_%s_ncomponents];\n",
// fieldName,fieldName,vectorName);
// fprintf(outfile,"\t fread(&_tempInput, sizeof(double), _%s_size*_%s_%s_ncomponents, infile);\n",
// fieldName,fieldName,vectorName);
fprintf(outfile,"\t fread(_%s_%s, sizeof(double), _%s_size*_%s_%s_ncomponents, infile);\n",fieldName,vectorName,
fieldName,fieldName,vectorName);
// fprintf(outfile,"\t _%s_%s = _tempInput;\n",fieldName,vectorName);
}
fprintf(outfile,
"\n"
"fclose(infile);\n");
}
else {
// something must have really screwed up to get here...
throw xmdsException("For some reason the input file is neither ascii nor binary...\nHow did we get here??");
}
}
else {
// initialisation from code
if(simulation()->parameters()->stochastic) {
fprintf(outfile,"const double _var = 1.0");
for(unsigned long i=0;i<nDims;i++) {
if(space(i)) {
fprintf(outfile,"/_%s_dk%li",fieldName,i);
}
else {
fprintf(outfile,"/_%s_dx%li",fieldName,i);
}
}
fprintf(outfile,";\n");
fprintf(outfile,"double *_noises = new double[_n_noises];\n");
if(simulation()->parameters()->errorCheck) {
fprintf(outfile,"double *_noises2 = new double[_n_noises];\n");
}
fprintf(outfile,"\n");
}
field()->vectors2space(outfile,initialSpace(),myVectorNamesList,"");
list<XMLString> vectorNameList = myVectorNamesList;
vectorNameList.push_back(*name());
field()->openLoops(outfile,initialSpace(),vectorNameList);
char indent[64];
for(unsigned long i=0;i<nDims;i++) {
indent[i]=0x09;
}
indent[nDims]=0;
if(simulation()->parameters()->stochastic) {
if(simulation()->parameters()->errorCheck) {
fprintf(outfile,"%s_make_noises(_gen1,_var/2,_noises,_n_noises);\n",indent);
fprintf(outfile,"%s_make_noises(_gen2,_var/2,_noises2,_n_noises);\n",indent);
fprintf(outfile,"%sfor(unsigned long _s0=0;_s0<_n_noises;_s0++)\n",indent);
fprintf(outfile,"%s _noises[_s0] += _noises2[_s0];\n",indent);
fprintf(outfile,"\n");
}
else {
fprintf(outfile,"%s_make_noises(_gen,_var,_noises,_n_noises);\n",indent);
fprintf(outfile,"\n");
}
}
fprintf(outfile,"// ********** Code from vector element***********\n");
fprintf(outfile,"%s\n",myCode.c_str());
fprintf(outfile,"// **********************************************\n");
fprintf(outfile,"\n");
field()->closeLoops(outfile,initialSpace(),vectorNameList);
if (simulation()->parameters()->stochastic) {
fprintf(outfile, " delete[] _noises;\n");
if (simulation()->parameters()->errorCheck) {
fprintf(outfile, " delete[] _noises2;\n");
}
}
}
if(needsFFTWRoutines()) {
fprintf(outfile,"\n");
fprintf(outfile,"_%s_%s_space=%li;\n",field()->name()->c_str(),name()->c_str(),initialSpace());
}
fprintf(outfile,"}\n");
fprintf(outfile,"\n");
};
syntax highlighted by Code2HTML, v. 0.9.1