56 #include "../utility/utility.h"
64 extern template herr_t writeScalarAttr(hid_t file_id,
string path,
string value);
65 extern template herr_t writeScalarAttr(hid_t file_id,
string path,
double value);
67 const char*
const EVENTPATH =
"/data/event";
68 const char*
const UNIFORMPATH =
"/data/uniform";
69 const char*
const MODELTREEPATH =
"/model/modeltree";
70 const char*
const MAPUNIFORMSRC =
"/map/uniform";
71 const char*
const MAPEVENTSRC =
"/map/event";
73 string iso_time(time_t * t)
79 timeinfo = std::gmtime(¤t);
81 timeinfo = std::gmtime(t);
83 assert(timeinfo != NULL);
85 strftime(buf, 32,
"%FT%T", timeinfo);
89 const Cinfo * NSDFWriter::initCinfo()
93 "Sets up field elements for event inputs",
94 InputVariable::initCinfo(),
95 &NSDFWriter::getEventInput,
96 &NSDFWriter::setNumEventInputs,
97 &NSDFWriter::getNumEventInputs);
101 "The moose element tree root to be saved under /model/modeltree",
102 &NSDFWriter::setModelRoot,
103 &NSDFWriter::getModelRoot);
107 "Handle process calls. Collects data in buffer and if number of steps"
108 " since last write exceeds flushLimit, writes to file.",
113 "Reinitialize the object. If the current file handle is valid, it tries"
114 " to close that and open the file specified in current filename field.",
117 static Finfo * processShared[] = {
123 "Shared message to receive process and reinit",
124 processShared,
sizeof( processShared ) /
sizeof(
Finfo* ));
126 static Finfo * finfos[] = {
131 static string doc[] = {
132 "Name",
"NSDFWriter",
133 "Author",
"Subhasis Ray",
134 "Description",
"NSDF file writer for saving data."
140 HDF5DataWriter::initCinfo(),
142 sizeof(finfos)/
sizeof(
Finfo*),
144 doc,
sizeof( doc ) /
sizeof(
string ));
149 static const Cinfo * nsdfWriterCinfo = NSDFWriter::initCinfo();
151 NSDFWriter::NSDFWriter(): eventGroup_(-1), uniformGroup_(-1), dataGroup_(-1), modelGroup_(-1), mapGroup_(-1), modelRoot_(
"/")
156 NSDFWriter::~NSDFWriter()
161 void NSDFWriter::close()
163 if (filehandle_ < 0){
168 if (uniformGroup_ >= 0){
169 H5Gclose(uniformGroup_);
172 if (eventGroup_ >= 0){
173 H5Gclose(eventGroup_);
175 if (dataGroup_ >= 0){
176 H5Gclose(dataGroup_);
178 HDF5DataWriter::close();
181 void NSDFWriter::closeUniformData()
183 for (map < string, hid_t>::iterator ii = classFieldToUniform_.begin();
184 ii != classFieldToUniform_.end();
186 if (ii->second >= 0){
187 H5Dclose(ii->second);
198 void NSDFWriter::sortOutUniformSources(
const Eref& eref)
201 classFieldToSrcIndex_.clear();
202 objectField_.clear();
203 objectFieldToIndex_.clear();
209 assert(numTgt == src_.size());
215 for (
unsigned int ii = 0; ii < func_.size(); ++ii){
216 string varname = func_[ii];
217 size_t found = varname.find(
"get");
219 varname = varname.substr(3);
220 if (varname.length() == 0){
223 varname[0] = tolower(varname[0]);
226 assert(varname.length() > 0);
228 string datasetPath = className +
"/"+ varname;
229 classFieldToSrcIndex_[datasetPath].push_back(ii);
230 vars_.push_back(varname);
232 data_.resize(numTgt);
239 void NSDFWriter::openUniformData(
const Eref &eref)
241 sortOutUniformSources(eref);
244 if (uniformGroup_ < 0){
245 uniformGroup_ = require_group(filehandle_, UNIFORMPATH);
249 for (map<
string, vector< unsigned int > >::iterator it = classFieldToSrcIndex_.begin();
250 it != classFieldToSrcIndex_.end();
252 vector< string > tokens;
254 string className = tokens[0];
255 string fieldName = tokens[1];
256 hid_t container = require_group(uniformGroup_, className);
257 vector < string > srclist;
258 hid_t dataset = createDataset2D(container, fieldName.c_str(), it->second.size());
259 classFieldToUniform_[it->first] = dataset;
260 writeScalarAttr<string>(dataset,
"field", fieldName);
268 void NSDFWriter::createUniformMap()
274 hid_t uniformMapContainer = require_group(filehandle_, MAPUNIFORMSRC);
276 for (map<
string, vector < unsigned int > >::iterator ii = classFieldToSrcIndex_.begin();
277 ii != classFieldToSrcIndex_.end(); ++ii){
278 vector < string > pathTokens;
280 string className = pathTokens[0];
281 string fieldName = pathTokens[1];
282 hid_t container = require_group(uniformMapContainer, className);
283 char ** sources = (
char **)calloc(ii->second.size(),
sizeof(
char*));
284 for (
unsigned int jj = 0; jj < ii->second.size(); ++jj){
285 sources[jj] = (
char*)calloc(src_[ii->second[jj]].path().length()+1,
sizeof(char));
286 strcpy(sources[jj],src_[ii->second[jj]].path().c_str());
288 hid_t ds = createStringDataset(container, fieldName, (hsize_t)ii->second.size(), (hsize_t)ii->second.size());
289 hid_t memtype = H5Tcopy(H5T_C_S1);
290 status = H5Tset_size(memtype, H5T_VARIABLE);
292 status = H5Dwrite(ds, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, sources);
294 cout <<
"Write dataset: status=" << status << endl;
297 for (
unsigned int jj = 0; jj < ii->second.size(); ++jj){
301 status = H5DSset_scale(ds,
"source");
302 status = H5DSattach_scale(classFieldToUniform_[ii->first], ds, 0);
303 status = H5DSset_label(classFieldToUniform_[ii->first], 0,
"source");
304 status = H5Dclose(ds);
305 status = H5Tclose(memtype);
309 void NSDFWriter::closeEventData()
311 for (
unsigned int ii = 0; ii < eventDatasets_.size(); ++ii){
312 if (eventDatasets_[ii] >= 0){
313 H5Dclose(eventDatasets_[ii]);
317 eventInputs_.clear();
318 eventDatasets_.clear();
320 eventSrcFields_.clear();
328 void NSDFWriter::openEventData(
const Eref &eref)
330 if (filehandle_ <= 0){
333 for (
unsigned int ii = 0; ii < eventInputs_.size(); ++ii){
335 path << eref.
objId().
path() <<
"/" <<
"eventInput[" << ii <<
"]";
338 const DestFinfo * dest =
static_cast<const DestFinfo*
>(el->cinfo()->findFinfo(
"input"));
339 vector < ObjId > src;
340 vector < string > srcFields;
341 el->getMsgSourceAndSender(dest->
getFid(), src, srcFields);
343 cerr <<
"NSDFWriter::openEventData - only one source can be connected to an eventInput" <<endl;
344 }
else if (src.size() == 1){
345 eventSrcFields_.push_back(srcFields[0]);
346 eventSrc_.push_back(src[0].
path());
347 events_.resize(eventSrc_.size());
349 path << src[0].path() <<
"." << srcFields[0];
350 hid_t dataSet = getEventDataset(src[0].
path(), srcFields[0]);
351 eventDatasets_.push_back(dataSet);
353 cerr <<
"NSDFWriter::openEventData - cannot handle multiple connections at single input." <<endl;
358 void NSDFWriter::createEventMap()
361 hid_t eventMapContainer = require_group(filehandle_, MAPEVENTSRC);
365 for (map<
string, vector < string > >::iterator ii = classFieldToEventSrc_.begin();
366 ii != classFieldToEventSrc_.end();
368 vector < string > pathTokens;
370 string className = pathTokens[0];
371 string fieldName = pathTokens[1];
372 hid_t classGroup = require_group(eventMapContainer, className);
373 hid_t strtype = H5Tcopy(H5T_C_S1);
374 status = H5Tset_size(strtype, H5T_VARIABLE);
376 hid_t ftype = H5Tcreate(H5T_COMPOUND,
sizeof(hvl_t) +
sizeof(hobj_ref_t));
377 status = H5Tinsert(ftype,
"source", 0, strtype);
378 status = H5Tinsert(ftype,
"data",
sizeof(hvl_t), H5T_STD_REF_OBJ);
379 hsize_t dims[1] = {ii->second.size()};
380 hid_t space = H5Screate_simple(1, dims, NULL);
382 hid_t ds = H5Dcreate2(classGroup, fieldName.c_str(), ftype, space,
383 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
384 status = H5Sclose(space);
388 for (
unsigned int jj = 0; jj < ii->second.size(); ++jj){
389 buf->source = ii->second[jj].c_str();
390 char * dsname = (
char*)calloc(256,
sizeof(
char));
391 ssize_t size = H5Iget_name(classFieldToEvent_[ii->first][jj], dsname, 255);
394 dsname = (
char*)calloc(size,
sizeof(
char));
395 size = H5Iget_name(classFieldToEvent_[ii->first][jj], dsname, 255);
397 status = H5Rcreate(&(buf->data), filehandle_, dsname, H5R_OBJECT, -1);
402 hid_t memtype = H5Tcreate(H5T_COMPOUND,
sizeof(
map_type));
403 status = H5Tinsert(memtype,
"source",
404 HOFFSET(
map_type, source), strtype);
405 status = H5Tinsert(memtype,
"data",
406 HOFFSET(
map_type, data), H5T_STD_REF_OBJ);
407 status = H5Dwrite(ds, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf);
409 status = H5Tclose(strtype);
410 status = H5Tclose(ftype);
411 status = H5Tclose(memtype);
412 status = H5Dclose(ds);
424 hid_t NSDFWriter::getEventDataset(
string srcPath,
string srcField)
426 string eventSrcPath = srcPath + string(
"/") + srcField;
427 map< string, hid_t >::iterator it = eventSrcDataset_.find(eventSrcPath);
428 if (it != eventSrcDataset_.end()){
431 ObjId source(srcPath);
435 string path = EVENTPATH + string(
"/") + className + string(
"/") + srcField;
436 hid_t container = require_group(filehandle_, path);
437 stringstream dsetname;
438 dsetname << source.id.value() <<
"_" << source.dataIndex <<
"_" << source.fieldIndex;
439 hid_t dataset = createDoubleDataset(container, dsetname.str().c_str());
440 classFieldToEvent_[className +
"/" + srcField].push_back(dataset);
441 classFieldToEventSrc_[className +
"/" + srcField].push_back(srcPath);
442 status = writeScalarAttr<string>(dataset,
"source", srcPath);
444 status = writeScalarAttr<string>(dataset,
"field", srcField);
446 eventSrcDataset_[eventSrcPath] = dataset;
450 void NSDFWriter::flush()
454 writeScalarAttr<string>(filehandle_,
"tend", iso_time(NULL));
457 for (map< string, hid_t>::iterator it = classFieldToUniform_.begin();
458 it != classFieldToUniform_.end(); ++it){
459 map< string, vector < unsigned int > >::iterator idxit = classFieldToSrcIndex_.find(it->first);
460 if (idxit == classFieldToSrcIndex_.end()){
461 cerr <<
"Error: NSDFWriter::flush - could not find entry for " << it->first <<endl;
464 if (data_.size() == 0 || data_[0].size() == 0){
467 double * buffer = (
double*)calloc(idxit->second.size() * steps_,
sizeof(double));
468 vector< double > values;
469 for (
unsigned int ii = 0; ii < idxit->second.size(); ++ii){
470 for (
unsigned int jj = 0; jj < steps_; ++jj){
471 buffer[ii * steps_ + jj] = data_[idxit->second[ii]][jj];
473 data_[idxit->second[ii]].clear();
476 hid_t filespace = H5Dget_space(it->second);
483 herr_t status = H5Sget_simple_extent_dims(filespace, dims, maxdims);
484 hsize_t newdims[] = {dims[0], dims[1] + steps_};
485 status = H5Dset_extent(it->second, newdims);
487 filespace = H5Dget_space(it->second);
488 hsize_t start[2] = {0, dims[1]};
490 hid_t memspace = H5Screate_simple(2, dims, NULL);
491 H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start, NULL, dims, NULL);
492 status = H5Dwrite(it->second, H5T_NATIVE_DOUBLE, memspace, filespace, H5P_DEFAULT, buffer);
499 for (
unsigned int ii = 0; ii < eventSrc_.size(); ++ii){
500 appendToDataset(getEventDataset(eventSrc_[ii], eventSrcFields_[ii]),
505 HDF5DataWriter::flush();
508 void NSDFWriter::reinit(
const Eref& eref,
const ProcPtr proc)
519 if (filename_.empty()){
520 filename_ =
"moose_data.nsdf.h5";
523 writeScalarAttr<string>(filehandle_,
"created", iso_time(0));
524 writeScalarAttr<string>(filehandle_,
"tstart", iso_time(0));
525 writeScalarAttr<string>(filehandle_,
"nsdf_version",
"1.0");
526 openUniformData(eref);
527 for (map < string, hid_t >::iterator it = classFieldToUniform_.begin();
528 it != classFieldToUniform_.end();
531 writeScalarAttr< double >(it->second,
"tstart", 0.0);
533 writeScalarAttr< double >(it->second,
"dt", proc->
dt);
542 void NSDFWriter::process(
const Eref& eref,
ProcPtr proc)
544 if (filehandle_ < 0){
547 vector < double > uniformData;
550 requestOut->
send(eref, &uniformData);
551 for (
unsigned int ii = 0; ii < uniformData.size(); ++ii){
552 data_[ii].push_back(uniformData[ii]);
555 if (steps_ < flushLimit_){
571 NSDFWriter& NSDFWriter::operator=(
const NSDFWriter& other)
573 eventInputs_ = other.eventInputs_;
574 for ( vector< InputVariable >::iterator
575 i = eventInputs_.begin(); i != eventInputs_.end(); ++i )
577 for (
unsigned int ii = 0; ii < getNumEventInputs(); ++ii){
583 void NSDFWriter::setNumEventInputs(
unsigned int num)
585 unsigned int prevSize = eventInputs_.size();
586 eventInputs_.resize(num);
587 for (
unsigned int ii = prevSize; ii < num; ++ii){
588 eventInputs_[ii].setOwner(
this);
592 unsigned int NSDFWriter::getNumEventInputs()
const
594 return eventInputs_.size();
597 void NSDFWriter::setEnvironment(
string key,
string value)
603 void NSDFWriter::setInput(
unsigned int index,
double value)
605 events_[index].push_back(value);
608 InputVariable* NSDFWriter::getEventInput(
unsigned int index)
610 static InputVariable
dummy;
611 if (index < eventInputs_.size()){
612 return &eventInputs_[index];
614 cout <<
"Warning: NSDFWriter::getEventInput: index: " << index <<
615 " is out of range: " << eventInputs_.size() << endl;
619 void NSDFWriter::setModelRoot(
string value)
624 string NSDFWriter::getModelRoot()
const
630 void NSDFWriter::writeModelTree()
632 vector< string > tokens;
633 ObjId mRoot(modelRoot_);
634 string rootPath = MODELTREEPATH + string(
"/") + mRoot.element()->getName();
635 hid_t rootGroup = require_group(filehandle_, rootPath);
640 deque<hid_t> h5nodeQueue;
641 nodeQueue.push_back(mRoot);
642 h5nodeQueue.push_back(rootGroup);
646 while (nodeQueue.size() > 0){
647 ObjId node = nodeQueue.front();
648 nodeQueue.pop_front();
649 hid_t prev = h5nodeQueue.front();;
650 h5nodeQueue.pop_front();
651 vector < Id > children;
653 for (
unsigned int ii = 0; ii < children.size(); ++ii){
654 string name = children[ii].element()->getName();
656 if (children[ii].
path() ==
"/Msgs"
657 || children[ii].
path() ==
"/clock"
658 || children[ii].
path() ==
"/classes"
659 || children[ii].
path() ==
"/postmaster"){
662 exists = H5Lexists(prev, name.c_str(), H5P_DEFAULT);
664 tmp = H5Gopen2(prev, name.c_str(), H5P_DEFAULT);
666 tmp = H5Gcreate2(prev, name.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
668 writeScalarAttr< string >(tmp,
"uid", children[ii].path());
669 nodeQueue.push_back(children[ii]);
670 h5nodeQueue.push_back(tmp);
672 status = H5Gclose(prev);
char map_type(const std::type_info &t)
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)
unsigned int dataIndex() const
unsigned int getMsgTargetAndFunctions(DataId srcDataId, const SrcFinfo *finfo, vector< ObjId > &tgt, vector< string > &func) const
static void children(const Eref &e, vector< Id > &ret)
Element * element() const
void send(const Eref &er, T arg) const
const Cinfo * cinfo() const
Element * element() const
void tokenize(const string &str, const string &delimiters, vector< string > &tokens)
static A get(const ObjId &dest, const string &field)
const Finfo * findFinfo(const string &name) const
static SrcFinfo1< vector< double > * > * requestOut()