#include #include #include #include #include "OutputManager.h" #include "ATC_Error.h" #include "LammpsInterface.h" using std::ofstream; using std::stringstream; using std::ios_base; using std::setw; using std::string; using std::map; using std::vector; using std::set; namespace ATC { static const int kFieldPrecison = 12; static const int kFieldWidth = kFieldPrecison + 6; static const int kFileNameSize = 26; // HERE <<<< static string tensor_component_names[9] = {"11","12","13", "21","22","23", "31","32","33"}; static string sym_tensor_component_names[6] = {"11","22","33","12","13","23"}; static string vector_component_names[3] = {"_X","_Y","_Z"}; static string list_component_names[26] = {"_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z"}; string* get_component_names(int type) { // HERE <<<< string* componentNames = list_component_names; if (type==VECTOR_OUTPUT) componentNames = vector_component_names; else if (type == SYM_TENSOR_OUTPUT) componentNames = sym_tensor_component_names; else if (type == TENSOR_OUTPUT) componentNames = tensor_component_names; return componentNames; } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- OutputManager::OutputManager(string outputPrefix, set & otypes) : initialized_(false), firstStep_(true), firstGlobalsWrite_(true), writeGlobalsHeader_(true), coordinates_(NULL), connectivities_(NULL), dataType_(POINT), outputPrefix_(outputPrefix), ensightOutput_(otypes.count(ENSIGHT)), textOutput_(otypes.count(GNUPLOT)), fullTextOutput_(otypes.count(FULL_GNUPLOT)), vtkOutput_(otypes.count(VTK)), tensorToComponents_(false), // paraview does not support tensors vectorToComponents_(false), warnTooManyCols_(true) {} //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- OutputManager::OutputManager() : initialized_(false), firstStep_(true), firstGlobalsWrite_(true), writeGlobalsHeader_(true), coordinates_(NULL), connectivities_(NULL), dataType_(POINT), outputPrefix_("NULL"), ensightOutput_(true), textOutput_(false), fullTextOutput_(false), vtkOutput_(false), tensorToComponents_(false), // paraview does not support tensors vectorToComponents_(false) {} //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- OutputManager::~OutputManager() {} //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- void OutputManager::set_option(OutputOption option, bool value) { if (option == OUTPUT_VECTOR_COMPONENTS) vectorToComponents_ = value; else if (option == OUTPUT_TENSOR_COMPONENTS) tensorToComponents_ = value; else throw ATC_Error("unsupported output option"); }; //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- void OutputManager::initialize(string outputPrefix, set & otypes) { if (outputPrefix_ != outputPrefix ) { // new stream with existing object outputPrefix_ = outputPrefix; initialized_ = false; } outputTimes_.clear(); if (otypes.count(ENSIGHT) > 0) ensightOutput_ = true; else ensightOutput_ = false; if (otypes.count(GNUPLOT) > 0) textOutput_ = true; if (otypes.count(FULL_GNUPLOT) > 0) fullTextOutput_ = true; if (otypes.count(VTK) > 0) vtkOutput_ = true; firstStep_ = true; firstGlobalsWrite_ = true; writeGlobalsHeader_ = true; } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- void OutputManager::print_custom_names() { map >::const_iterator itr; string msg = "output custom names:\n"; for (itr = fieldNames_.begin(); itr != fieldNames_.end(); itr++) { string stem = itr->first; vector names = itr->second; for (unsigned int i = 0; i < names.size(); i++) { msg+= stem+" : "+names[i]+"\n"; } } ATC::LammpsInterface::instance()->print_msg_once(msg); } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- // Dump text-based fields to disk for later restart void OutputManager::write_restart_file(string fileName, RESTART_LIST *data) { FILE * fp=NULL; fp=fopen(fileName.c_str(),"wb"); // open RESTART_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { const MATRIX* field_data = iter->second; for (int i = 0; i < field_data->nRows(); ++i) { for (int j = 0; j < field_data->nCols(); ++j) { double x = (*field_data)(i,j); fwrite(&x,sizeof(double),1,fp); } } } fclose(fp); } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- // Read a file corresponding to a write by write_restart_file void OutputManager::read_restart_file(string fileName, RESTART_LIST *data) { FILE * fp=NULL; fp=fopen(fileName.c_str(),"rb"); // open RESTART_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { MATRIX* field_data = iter->second; for (int i = 0; i < field_data->nRows(); ++i) { for (int j = 0; j < field_data->nCols(); ++j) { double myVal; fread(&myVal,sizeof(double),1,fp); (*field_data)(i,j) = myVal; } } } fclose(fp); } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- void OutputManager::write_globals(void) { if ( outputPrefix_ == "NULL") return; string file = outputPrefix_ + ".GLOBALS"; ofstream text; if ( firstGlobalsWrite_ ) text.open(file.c_str(),ios_base::out); else text.open(file.c_str(),ios_base::app); firstGlobalsWrite_ = false; map::iterator iter; // header if ( firstStep_ || writeGlobalsHeader_) { text << "# time:1 "; int index = 2; for (iter = globalData_.begin(); iter != globalData_.end(); iter++) { string name = iter->first; string str; stringstream out; out << ":" << index++; str = out.str(); name.append(str); text.width(kFieldWidth); text << name << " "; } text << '\n'; } writeGlobalsHeader_ = false; // data text.width(kFieldWidth); text << outputTimes_[outputTimes_.size()-1] << " "; for (iter = globalData_.begin(); iter != globalData_.end(); iter++) { double value = iter->second; text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << value << " "; } text << "\n"; } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- void OutputManager::write_geometry(const MATRIX *coordinates, const Array2D *connectivities) { if ( outputPrefix_ == "NULL") throw ATC_Error( "No outputPrefix given."); number_of_nodes_ = coordinates->nCols(); coordinates_ = coordinates; connectivities_ = connectivities; if (ensightOutput_) write_geometry_ensight(); if (textOutput_) write_geometry_text(); initialized_ = true; } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- void OutputManager::write_geometry_ensight(void) { // geometry based on a reference configuration string geom_file_name = outputPrefix_ + ".geo"; // open file FILE * fp=NULL; char buffer[80]; if ( ! initialized_ ) { fp=fopen(geom_file_name.c_str(),"wb"); // open strcpy(buffer,"C Binary"); fwrite(buffer,sizeof(char),80,fp); } else { fp=fopen(geom_file_name.c_str(),"ab"); // append } if (fp == NULL) { throw ATC_Error("can not create Ensight geometry file"); } // write preamble strcpy(buffer,"BEGIN TIME STEP"); fwrite(buffer,sizeof(char),80,fp); strcpy(buffer,"Ensight geometry file"); fwrite(buffer,sizeof(char),80,fp); strcpy(buffer,"description"); fwrite(buffer,sizeof(char),80,fp); strcpy(buffer,"node id assign"); fwrite(buffer,sizeof(char),80,fp); strcpy(buffer,"element id assign"); fwrite(buffer,sizeof(char),80,fp); // per part strcpy(buffer,"part"); fwrite(buffer,sizeof(char),80,fp); int part_number=1; fwrite(&part_number,sizeof(int),1,fp); strcpy(buffer,"description"); fwrite(buffer,sizeof(char),80,fp); const MATRIX & coordinates = *coordinates_; // write coordinates strcpy(buffer,"coordinates"); fwrite(buffer,sizeof(char),80,fp); fwrite(&number_of_nodes_,sizeof(int),1,fp); int number_of_spatial_dimensions = coordinates.nRows(); if (number_of_spatial_dimensions != 3) throw ATC_Error("Ensight writer needs a 3D geometry"); for (int i = 0; i < number_of_spatial_dimensions; ++i) { for (int j = 0; j < number_of_nodes_; ++j) { float x = (float) coordinates(i,j); fwrite(&x,sizeof(float),1,fp); } } // write mesh connectivities or point "connectivities" if (connectivities_) { dataType_ = MESH; int nodes_per_element = connectivities_->nRows(); if (nodes_per_element == 4) { strcpy(buffer,"tetra4"); } else if (nodes_per_element == 8) { strcpy(buffer,"hexa8"); } else if (nodes_per_element == 20) { strcpy(buffer,"hexa20"); } else if (nodes_per_element == 27) { strcpy(buffer,"hexa27"); } else throw ATC_Error("Ensight writer does not recoginize element type"); fwrite(buffer,sizeof(char),80,fp); int number_of_elements = connectivities_->nCols(); fwrite(&number_of_elements,sizeof(int),1,fp); int number_of_nodes_per_element = connectivities_->nRows(); for (int j = 0; j < number_of_elements; ++j) { for (int i = 0; i < number_of_nodes_per_element; ++i) { int inode = (*connectivities_)(i,j) +1; // 1 based numbering fwrite(&inode,sizeof(int),1,fp); } } } else { strcpy(buffer,"point"); fwrite(buffer,sizeof(char),80,fp); int number_of_elements = number_of_nodes_; fwrite(&number_of_elements,sizeof(int),1,fp); for (int j = 0; j < number_of_elements; ++j) { int inode = j +1; // 1 based numbering fwrite(&inode,sizeof(int),1,fp); } } // end per part strcpy(buffer,"END TIME STEP"); fwrite(buffer,sizeof(char),80,fp); fclose(fp); } //----------------------------------------------------------------------------- //* //----------------------------------------------------------------------------- void OutputManager::write_geometry_text(void) { if ( outputPrefix_ == "NULL") return; // geometry based on a reference configuration string geom_file_text = outputPrefix_ + ".XYZ"; // open file ofstream text; text.open(geom_file_text.c_str(),ios_base::out); if (connectivities_) { int number_of_elements = connectivities_->nCols(); int number_of_nodes_per_element = connectivities_->nRows(); for (int j = 0; j < number_of_elements; ++j) { text << "#"; for (int i = 0; i < number_of_nodes_per_element; ++i) { int inode = (*connectivities_)(i,j) +1; // 1 based numbering text << setw(6) << inode; } text << "\n"; } } const MATRIX & coordinates = *coordinates_; int number_of_spatial_dimensions = coordinates.nRows(); for (int j = 0; j < number_of_nodes_; ++j) { text << setw(6) << j+1 << " "; for (int i = 0; i < number_of_spatial_dimensions; ++i) { text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << coordinates(i,j) << " "; } text << "\n"; } text << "\n"; } //----------------------------------------------------------------------------- /** pack "soln" into data */ //----------------------------------------------------------------------------- void OutputManager::write_data(double time, FIELDS *soln, OUTPUT_LIST *data, const int *node_map) { // pack OUTPUT_LIST combined_data; if (soln) { FIELDS::iterator iter; for (iter = soln->begin(); iter != soln->end(); iter++) { FieldName field_index = iter->first; MATRIX* field_data = &((iter->second).set_quantity()); string field_name = field_to_string(field_index); combined_data[field_name] = field_data; } } if (data) { OUTPUT_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { string field_name = iter->first; const MATRIX* field_data = iter->second; combined_data[field_name] = field_data; } } write_data(time, &(combined_data), node_map); }; //----------------------------------------------------------------------------- /** write data */ //----------------------------------------------------------------------------- void OutputManager::write_data(double time, OUTPUT_LIST *data, const int *node_map) { if (! initialized_) { throw ATC_Error("must write geometry before data"); } // store the time step value outputTimes_.push_back(time); if (ensightOutput_) { // write data OUTPUT_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { string field_name = iter->first; const MATRIX* field_data = iter->second; write_data_ensight(field_name, field_data, node_map); } // write dictionary write_dictionary(time,data); } // write text dump if (textOutput_) { write_data_text(data); if (firstStep_ && node_map) { string map_file_text = outputPrefix_ + ".MAP"; ofstream text; text.open(map_file_text.c_str(),ios_base::out); for (int i=0; i< number_of_nodes_ ; i++) { text << node_map[i] << "\n"; } text.close(); } } else if (fullTextOutput_) { write_data_text(data,node_map); } if (vtkOutput_) { write_data_vtk(data); } // global variables if (! globalData_.empty()) write_globals(); if (firstStep_) firstStep_ = false; } //----------------------------------------------------------------------------- /** write (ensight gold format "C" binary) data */ // use "ens_checker" to check binary format //----------------------------------------------------------------------------- void OutputManager::write_data_ensight(string field_name, const MATRIX *field_data, const int *node_map) { int ndof = field_data->nCols(); int col_start = 0; int col_end = ndof; string filenames[kFileNameSize]; int nfiles = 1; filenames[0] = outputPrefix_ + "." + field_name; int type = data_type(ndof); if (use_component_names(type)){ nfiles = ndof; if (nfiles > kFileNameSize) { if (warnTooManyCols_ && ATC::LammpsInterface::instance()->rank_zero()) { warnTooManyCols_ = false; stringstream ss; ss << "WARNING: only writing " << kFileNameSize << " components of " << field_name << " which has " << ndof; ATC::LammpsInterface::instance()->print_msg(ss.str()); } nfiles = kFileNameSize; } string* component_names = get_component_names(type); for (int ifile = 0; ifile < nfiles; ++ifile) { string comp_name; if (! custom_name(field_name,ifile,comp_name)) comp_name = field_name + component_names[ifile]; filenames[ifile] = outputPrefix_ + "." + comp_name; } } for (int ifile = 0; ifile < nfiles; ++ifile) { // for vector/tensor to components if ( nfiles > 1 ) { col_start = ifile; col_end = ifile+1; } // open or append data file string data_file_name = filenames[ifile]; FILE * fp=NULL; if ( outputTimes_.size() == 1 ) { fp=fopen(data_file_name.c_str(),"wb"); // open } else { fp=fopen(data_file_name.c_str(),"ab"); // append } if (fp == NULL) { throw ATC_Error("can not create Ensight data file: "+data_file_name); } // write data char buffer[80]; strcpy(buffer,"BEGIN TIME STEP"); fwrite(buffer,sizeof(char),80,fp); strcpy(buffer,"field name"); fwrite(buffer,sizeof(char),80,fp); // per part strcpy(buffer,"part"); fwrite(buffer,sizeof(char),80,fp); int part_number = 1; fwrite(&part_number,sizeof(int),1,fp); strcpy(buffer,"coordinates"); fwrite(buffer,sizeof(char),80,fp); if (node_map) { for (int j = col_start; j < col_end; ++j) { for (int i = 0; i < number_of_nodes_; ++i) { int inode = node_map[i]; float x = (float) (*field_data)(inode,j); fwrite(&x,sizeof(float),1,fp); } } } else { for (int j = col_start; j < col_end; ++j) { for (int i = 0; i < field_data->nRows(); ++i) { float x = (float) (*field_data)(i,j); fwrite(&x,sizeof(float),1,fp); } } } // end per part strcpy(buffer,"END TIME STEP"); fwrite(buffer,sizeof(char),80,fp); fclose(fp); } } //----------------------------------------------------------------------------- /** write data dict for both text & full_text */ //----------------------------------------------------------------------------- void OutputManager::write_text_data_header(OUTPUT_LIST *data, ofstream & text, int k) { if (data) { OUTPUT_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { string field_name = iter->first; int nrows = iter->second->nRows(); if (!(nrows>0)) { string msg = field_name + " does not have data for output"; throw ATC_Error(msg); } int ncols = iter->second->nCols(); if (ncols > kFileNameSize) { if (ATC::LammpsInterface::instance()->rank_zero()) { stringstream ss; ss << " only writing " << kFileNameSize << " components of " << field_name << " which has " << ncols; ATC::LammpsInterface::instance()->print_msg(ss.str()); } ncols = kFileNameSize; } if (ncols == 1) { string name = field_name; custom_name(field_name,0,name); string str; stringstream out; out <<":"<begin(); if (iter == data->end()) { throw ATC_Error(" no data in output");} const MATRIX* field_data = iter->second; nrows = field_data->nRows(); for (int i = 0; i < nrows; ++i) { text.width(6); text << i << " "; // give an ordinate for gnuplot text.width(10); text << outputTimes_.size() << " "; OUTPUT_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { const MATRIX* field_data = iter->second; int ncols = field_data->nCols(); if (ncols > kFileNameSize) { ncols = kFileNameSize;} for (int j = 0; j < ncols; ++j) { text.width(kFieldWidth); text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << (*field_data)(i,j) << " "; } } text <<"\n"; } text <<"\n"; } //----------------------------------------------------------------------------- /** write data in full text format */ //----------------------------------------------------------------------------- void OutputManager::write_data_text(OUTPUT_LIST *data, const int *node_map) { string data_file_text = outputPrefix_ + ".DATA"; ofstream text; if (firstStep_) text.open(data_file_text.c_str(),ios_base::out); else text.open(data_file_text.c_str(),ios_base::app); // write data label header if (firstStep_) { text.width(6); text << "# index:1" << " "; text.width(6); text << " id:2" << " "; text.width(10); text << " step:3" << " "; text.width(4); text << " x:4" << " "; text.width(4); text << " y:5" << " "; text.width(4); text << " z:6" << " "; write_text_data_header(data,text,7); if (connectivities_) { int number_of_elements = connectivities_->nCols(); int number_of_nodes_per_element = connectivities_->nRows(); text << "# connectivities number_of_elements: " << number_of_elements << " nodes_per_element: " << number_of_nodes_per_element << "\n"; for (int j = 0; j < number_of_elements; ++j) { text << "#"; for (int i = 0; i < number_of_nodes_per_element; ++i) { int inode = (*connectivities_)(i,j) +1; // 1 based numbering text << setw(6) << inode; } text << "\n"; } } } text << "# timestep " << outputTimes_.size() << " : " << outputTimes_[outputTimes_.size()-1] << "\n"; OUTPUT_LIST::iterator iter; iter = data->begin(); if (iter == data->end()) { throw ATC_Error(" no data in output");} int nnodes = coordinates_->nCols(); for (int i = 0; i < nnodes; ++i) { int unode = i; if (node_map) unode = node_map[i]; text.width(6); text << i << " "; text.width(6); text << unode << " "; text.width(10); text << outputTimes_.size() << " "; // coordinates for (int j = 0; j < coordinates_->nRows(); ++j) { text.width(kFieldWidth); text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << (*coordinates_)(j,i) << " "; } // data OUTPUT_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { const MATRIX* field_data = iter->second; int ncols = field_data->nCols(); if (ncols > kFileNameSize) { ncols = kFileNameSize; } for (int j = 0; j < ncols; ++j) { text.width(kFieldWidth); text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << (*field_data)(unode,j) << " "; } } text <<"\n"; } text <<"\n"; } //----------------------------------------------------------------------------- /** write data in vtk text format */ //----------------------------------------------------------------------------- void OutputManager::write_data_vtk(OUTPUT_LIST *data) { string data_file_text = outputPrefix_ + ".vtk"; ofstream text; if (firstStep_) text.open(data_file_text.c_str(),ios_base::out); else throw ATC_Error(" vtk format can not handle multiple steps"); text << "# vtk DataFile Version 3.0\n"; text << "# " << outputPrefix_ << "\n"; text << "ASCII\n"; text << "DATASET UNSTRUCTURED_GRID\n"; // geometry int nnodes = coordinates_->nCols(); text << "POINTS " << nnodes << " float\n"; for (int i = 0; i < nnodes; ++i) { for (int j = 0; j < coordinates_->nRows(); ++j) { text.width(kFieldWidth); text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << (*coordinates_)(j,i) << " "; } text << "\n"; } text << "\n"; int nelems = connectivities_->nCols(); int nodes_per_element = connectivities_->nRows(); text << "CELLS " << nelems << " " << nelems*(nodes_per_element+1) << "\n"; for (int j = 0; j < nelems; ++j) { text << setw(6) << nodes_per_element; for (int i = 0; i < nodes_per_element; ++i) { int inode = (*connectivities_)(i,j); // 0 based numbering text << setw(6) << inode; } text << "\n"; } text << "\n"; int cell_type = 4 ; text << "CELL_TYPES " << nelems << "\n"; for (int j = 0; j < nelems; ++j) { text << cell_type << "\n"; } text << "\n"; // data text << "POINT_DATA " << nnodes << "\n"; text << "\n"; OUTPUT_LIST::iterator iter; for (iter = data->begin(); iter != data->end(); iter++) { string field_name = iter->first; const MATRIX* field_data = iter->second; int ncols = field_data->nCols(); if (ncols == 1) { text << "SCALARS " << field_name << " float\n"; text << "LOOKUP_TABLE default\n"; } else { text << "VECTORS " << field_name << " float\n"; } for (int i = 0; i < nnodes; ++i) { for (int j = 0; j < ncols; ++j) { text.width(kFieldWidth); text << setw(kFieldWidth) << std::scientific << std::setprecision(kFieldPrecison) << (*field_data)(i,j) << " "; } text <<"\n"; } } text <<"\n"; } /** write (ensight gold : ASCII "C" format) dictionary */ void OutputManager::write_dictionary(double time, OUTPUT_LIST *data) { // file names string dict_file_name = outputPrefix_ + ".case"; string geom_file_name = outputPrefix_ + ".geo"; // open file FILE * fp=NULL; if ((fp=fopen(dict_file_name.c_str(),"w")) == NULL) { throw ATC_Error("can not create Ensight case file"); } // write file fprintf(fp,"FORMAT\n"); fprintf(fp,"type: ensight gold\n"); fprintf(fp,"GEOMETRY\n"); if ( dataType_ == POINT) { fprintf(fp,"model: 1 1 %s change_coords_only\n", geom_file_name.c_str()); } else { fprintf(fp,"model: %s\n", geom_file_name.c_str()); } fprintf(fp,"VARIABLE\n"); // data types if (!data) throw ATC_Error("no data for output"); OUTPUT_LIST::iterator iter; int ncols = 0; for (iter = data->begin(); iter != data->end(); iter++) { string field_name = iter->first; string field_file = outputPrefix_ + "." + field_name; const MATRIX* field_data = iter->second; int fieldCols = field_data->nCols(); ncols += fieldCols; int type = data_type(fieldCols); if (use_component_names(type)){ string* component_names = get_component_names(type); int ndof = fieldCols; if (ndof > kFileNameSize) ndof = kFileNameSize; for (int j = 0; j < ndof; ++j) { string comp_name; if (! custom_name(field_name,j,comp_name)) comp_name = field_name + component_names[j]; string comp_file = outputPrefix_ + "." + comp_name; fprintf(fp,"scalar per node: 1 1 %s %s\n", comp_name.c_str(),comp_file.c_str()); } } else if (type == VECTOR_OUTPUT) { fprintf(fp,"vector per node: 1 1 %s %s\n", field_name.c_str(),field_file.c_str()); } else if (type == SYM_TENSOR_OUTPUT) { fprintf(fp,"tensor symm per node: 1 1 %s %s\n", field_name.c_str(),field_file.c_str()); } else if (type == TENSOR_OUTPUT) { fprintf(fp,"tensor asymm per node: 1 1 %s %s\n", field_name.c_str(),field_file.c_str()); } else { fprintf(fp,"scalar per node: 1 1 %s %s\n", field_name.c_str(),field_file.c_str()); } } if (!firstStep_ && ncols != nDataCols_) { throw ATC_Error("number of columns of data has changed: start new output"); } nDataCols_ = ncols; int nsteps = outputTimes_.size(); fprintf(fp,"TIME\n"); fprintf(fp,"time set: 1\n"); fprintf(fp,"number of steps: %10d\n",nsteps); if ( dataType_ == POINT) { fprintf(fp,"filename start number: 0\n"); fprintf(fp,"filename increment: 1\n"); } fprintf(fp,"time values:\n"); for (int j = 0; j < nsteps; ++j) { double t = outputTimes_[j]; fprintf(fp,"%12.5e",t); if ((j+1)%6 == 0) fprintf(fp,"\n"); } fprintf(fp,"\n"); fprintf(fp,"FILE\n"); fprintf(fp,"file set: 1\n"); fprintf(fp,"number of steps: %10d\n",nsteps); fclose(fp); }; } // end ATC namespace