Esempio n. 1
0
// static function
Id Neutral::child( const Eref& e, const string& name ) 
{
	static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" );
	static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
	static const FuncId pafid = pf2->getFid();
	static const Finfo* cf = neutralCinfo->findFinfo( "childOut" );
	static const SrcFinfo* cf2 = dynamic_cast< const SrcFinfo* >( cf );
	static const BindIndex bi = cf2->getBindIndex();
	
	const vector< MsgFuncBinding >* bvec = e.element()->getMsgAndFunc( bi );

	vector< Id > ret;

	for ( vector< MsgFuncBinding >::const_iterator i = bvec->begin();
		i != bvec->end(); ++i ) {
		if ( i->fid == pafid ) {
			const Msg* m = Msg::getMsg( i->mid );
			assert( m );
			Element* e2 = m->e2();
			if ( e2->getName() == name ) {
				if ( e.dataIndex() == ALLDATA ) {// Child of any index is OK
					return e2->id();
				} else {
					ObjId parent = m->findOtherEnd( m->getE2() );
					// If child is a fieldElement, then all parent indices
					// are permitted. Otherwise insist parent dataIndex OK.
					if ( e2->hasFields() || parent == e.objId() )
						return e2->id();
				}
			}
		}
	}
	return Id();
}
Esempio n. 2
0
void Pool::vRemesh( const Eref& e, const Qinfo* q, 
	double oldvol,
	unsigned int numTotalEntries, unsigned int startEntry, 
	const vector< unsigned int >& localIndices, 
	const vector< double >& vols )
{
	if ( e.index().value() != 0 )
		return;
	/*
	if ( q->addToStructuralQ() )
		return;
		*/
	Neutral* n = reinterpret_cast< Neutral* >( e.data() );
	assert( vols.size() > 0 );
	double concInit = nInit_ / ( NA * oldvol );
	if ( vols.size() != e.element()->dataHandler()->localEntries() )
		n->setLastDimension( e, q, vols.size() );
	// Note that at this point the Pool pointer may be invalid!
	// But we need to update the concs anyway.
	assert( e.element()->dataHandler()->localEntries() == vols.size() );
	Pool* pooldata = reinterpret_cast< Pool* >( e.data() );
	for ( unsigned int i = 0; i < vols.size(); ++i ) {
		pooldata[i].nInit_ = pooldata[i].n_ = concInit * vols[i] * NA;
	}
}
Esempio n. 3
0
OneToAllMsg::OneToAllMsg( MsgId mid, Eref e1, Element* e2 )
	: 
		Msg( mid, e1.element(), e2, OneToAllMsg::managerId_ ),
		i1_( e1.index() )
{
	;
}
Esempio n. 4
0
void HSolve::zombify( Eref hsolve ) const
{
    vector< Id >::const_iterator i;
	vector< ObjId > temp;

    for ( i = compartmentId_.begin(); i != compartmentId_.end(); ++i )
		temp.push_back( ObjId( *i, 0 ) );
    for ( i = compartmentId_.begin(); i != compartmentId_.end(); ++i )
        CompartmentBase::zombify( i->eref().element(),
					   ZombieCompartment::initCinfo(), hsolve.id() );

	temp.clear();
    for ( i = caConcId_.begin(); i != caConcId_.end(); ++i )
		temp.push_back( ObjId( *i, 0 ) );
	// Shell::dropClockMsgs( temp, "process" );
    for ( i = caConcId_.begin(); i != caConcId_.end(); ++i )
        CaConcBase::zombify( i->eref().element(), ZombieCaConc::initCinfo(), hsolve.id() );

	temp.clear();
    for ( i = channelId_.begin(); i != channelId_.end(); ++i )
		temp.push_back( ObjId( *i, 0 ) );
    for ( i = channelId_.begin(); i != channelId_.end(); ++i )
        HHChannelBase::zombify( i->eref().element(),
						ZombieHHChannel::initCinfo(), hsolve.id() );
}
Esempio n. 5
0
unsigned int getReactantVols( const Eref& reac, const SrcFinfo* pools, 
	vector< double >& vols )
{
	static const unsigned int meshIndex = 0;

	const vector< MsgFuncBinding >* mfb = 
		reac.element()->getMsgAndFunc( pools->getBindIndex() );
	unsigned int smallIndex = 0;

	vols.resize( 0 );
	if ( mfb ) {
		for ( unsigned int i = 0; i < mfb->size(); ++i ) {
			double v = 1;
			Element* pool = Msg::getMsg( (*mfb)[i].mid )->e2();
			if ( pool == reac.element() )
				pool = Msg::getMsg( (*mfb)[i].mid )->e1();
			assert( pool != reac.element() );
			Eref pooler( pool, meshIndex );
			if ( pool->cinfo()->isA( "PoolBase" ) ) {
				v = lookupVolumeFromMesh( pooler );
			} else {
				cout << "Error: getReactantVols: pool is of unknown type\n";
				assert( 0 );
			}
			vols.push_back( v );
			if ( v < vols[0] )
				smallIndex = i;
		}
	}
	return smallIndex;
}
Esempio n. 6
0
/* Enzymatic Reaction */
void SbmlReader::setupEnzymaticReaction( const EnzymeInfo & einfo,string name )
{
	static const Cinfo* enzymeCinfo = initEnzymeCinfo();	
	static const Finfo* k1Finfo = enzymeCinfo->findFinfo( "k1" );
	static const Finfo* k2Finfo = enzymeCinfo->findFinfo( "k2" );
	static const Finfo* k3Finfo = enzymeCinfo->findFinfo( "k3" );
	Eref E = ( einfo.enzyme )();
	Element* enzyme_ = Neutral::create( "Enzyme",name,E.id(),Id::scratchId() );//create Enzyme
	Eref complx = einfo.complex(); 
	Eref(enzyme_).add( "enz",E,"reac",ConnTainer::Default ); 
 	Eref(enzyme_).add( "cplx",complx,"reac",ConnTainer::Default ); 
	vector< Id >::const_iterator sub_itr;
	for ( sub_itr = einfo.substrates.begin(); sub_itr != einfo.substrates.end(); sub_itr++ )
	{	Eref S = (*sub_itr)();
		Eref( enzyme_ ).add( "sub",S,"reac",ConnTainer::Default ); 

	}
	vector< Id >::const_iterator prd_itr;
	for ( prd_itr = einfo.products.begin(); prd_itr != einfo.products.end(); prd_itr++ )
	{	Eref P = (*prd_itr)();
		Eref( enzyme_ ).add( "prd",P,"prd",ConnTainer::Default );

	}
	::set< double >( enzyme_, k1Finfo, einfo.k1 );
	::set< double >( enzyme_, k2Finfo, einfo.k2 );
	::set< double >( enzyme_, k3Finfo, einfo.k3 );
	::set< bool >( enzyme_,"mode",0 );
	::set( complx,"destroy" );
}
Esempio n. 7
0
/* create COMPARTMENT  */
map< string,Id > SbmlReader::createCompartment( Id location )
{
	static const Cinfo* kincomptCinfo = initKinComptCinfo();
	static const Finfo* sizeFinfo = kincomptCinfo->findFinfo( "size" );
	static const Finfo* dimensionFinfo = kincomptCinfo->findFinfo( "numDimensions" );
	map< string,Id > idMap;	
	//Id outcompt; //outside compartment	
	map< Id,string > outsideMap;
	map< Id,string > ::iterator iter;
	double msize = 0.0,size=0.0;	
	::Compartment* compt;
	unsigned int num_compts = model_->getNumCompartments();
	//cout << "num of compartments :" << num_compts <<endl;
	for ( unsigned int i = 0; i < num_compts; i++ )
	{
		compt = model_->getCompartment(i);
		std::string id = "";
		if ( compt->isSetId() ){
			id = compt->getId();
		}
		std::string name = "";
		if ( compt->isSetName() ){
			name = compt->getName();
		} 
		std::string outside = "";
		if ( compt->isSetOutside() ){
			outside = compt->getOutside ();
			
		}
		if ( compt->isSetSize() ){
			msize = compt->getSize();
		}
		UnitDefinition * ud = compt->getDerivedUnitDefinition();
		size = transformUnits( msize,ud );
		unsigned int dimension = compt->getSpatialDimensions();
		comptEl_ = Neutral::create( "KinCompt",id, location, Id::scratchId() ); //create Compartment 
		idMap[id] = comptEl_->id(); 
		if ( outside != "" )
			outsideMap[comptEl_->id()] = outside ; 
		if ( size != 0.0 )
		    ::set< double >( comptEl_, sizeFinfo, size );
		if ( dimension != 0 )
			::set< unsigned int >( comptEl_,dimensionFinfo,dimension );		
	}
	for ( iter = outsideMap.begin(); iter != outsideMap.end(); iter++ )
	{
		Eref msid = iter->first();			
		string outside = iter->second;	
		Id outcompt = idMap.find( outside )->second;	
		static const Finfo* outsideFinfo = kincomptCinfo->findFinfo( "outside" );
		static const Finfo* insideFinfo = kincomptCinfo->findFinfo( "inside" );
		msid.dropAll("child"); //delete the connection with old parent ie, /kinetics
		Eref(outcompt() ).add("childSrc",msid,"child",ConnTainer::Default); //create connection with new parent ie.outside compartment
		Eref( msid ).add( outsideFinfo->msg(),outcompt(),insideFinfo->msg(),ConnTainer::Default );
		
	}	
	
	return idMap;
}
Esempio n. 8
0
double GslStoich::getNinit( const Eref& e ) const
{
	unsigned int i = e.index().value();
	unsigned int j = coreStoich()->convertIdToPoolIndex( e.id() );
	assert( i < pools_.size() );
	assert( j < pools_[i].size() );
	return pools_[i].Sinit()[j];
}
Eref SingleMsg::firstTgt( const Eref& src ) const 
{
	if ( src.element() == e1_ )
		return Eref( e2_, i2_, f2_ );
	else if ( src.element() == e2_ )
		return Eref( e1_, i1_ );
	return Eref( 0, 0 );
}
Esempio n. 10
0
void GslStoich::setNinit( const Eref& e, double v )
{
	unsigned int i = e.index().value();
	unsigned int j = coreStoich()->convertIdToPoolIndex( e.id() );
	assert( i < pools_.size() );
	assert( j < pools_[i].size() );
	pools_[i].varSinit()[j] = v;
}
Esempio n. 11
0
/// Utility function to find the size of a pool. We assume one-to-one
/// match between pool indices and mesh indices: that is what they are for.
double lookupVolumeFromMesh( const Eref& e )
{
	ObjId compt = getCompt( e.id() );
	if ( compt == ObjId() )
		return 1.0;
	return LookupField< unsigned int, double >::
			get( compt, "oneVoxelVolume", e.dataIndex() );
}
Eref OneToAllMsg::firstTgt( const Eref& src ) const 
{
	if ( src.element() == e1_ )
		return Eref( e2_, 0 );
	else if ( src.element() == e2_ )
		return Eref( e1_, i1_ );
	return Eref( 0, 0 );
}
/////////////////////////////////////////////////////////////////
// Now test 'get' across nodes.
// Normally the 'get' call is invoked by the parser, which expects a
// value to come back. Note that the return must be asynchronous:
// the parser cannot block since we need to execute MPI polling
// operations on either side.
/////////////////////////////////////////////////////////////////
void testParGet( Id tnId, vector< Id >& testIds )
{
	unsigned int myNode = MuMPI::INTRA_COMM().Get_rank();
	unsigned int numNodes = MuMPI::INTRA_COMM().Get_size();
	Slot parGetSlot = initShellCinfo()->getSlot( "parallel.getSrc" );
	char name[20];
	string sname;
	if ( myNode == 0 ) {
		cout << "\ntesting parallel get" << flush;
	} else {
		sprintf( name, "foo%d", myNode * 2 );
		sname = name;
		set< string >( tnId.eref(), "name", sname );
	}
	MuMPI::INTRA_COMM().Barrier();
	Eref e = Id::shellId().eref();
	Shell* sh = static_cast< Shell* >( e.data() );
	vector< unsigned int > rids( numNodes, 0 );
	vector< string > ret( numNodes );
	unsigned int origSize = sh->freeRidStack_.size();
	ASSERT( origSize > 0 , "Stack initialized properly" );
	if ( myNode == 0 ) {
		for ( unsigned int i = 1; i < numNodes; i++ ) {
			rids[i] = 
				openOffNodeValueRequest< string >( sh, &ret[i], 1 );
			ASSERT( sh->freeRidStack_.size() == origSize - i, "stack in use" );
			sendTo3< Id, string, unsigned int >(
				Id::shellId().eref(), parGetSlot, i - 1,
				testIds[i - 1], "name", rids[i]
			);
		}
	}
	// Here we explicitly do what the closeOffNodeValueRequest handles.
	MuMPI::INTRA_COMM().Barrier();
	// Cycle a few times to make sure all data gets back to node 0
	for ( unsigned int i = 0; i < 5; i++ ) {
		pollPostmaster();
		MuMPI::INTRA_COMM().Barrier();
	}
	
	// Now go through to check all values have come back.
	if ( myNode == 0 ) {
		ASSERT( sh->freeRidStack_.size() == 1 + origSize - numNodes, 
			"Stack still waiting" );
		for ( unsigned int i = 1; i < numNodes; i++ ) {
			sprintf( name, "foo%d", i * 2 );
			sname = name;
			ASSERT( sh->offNodeData_[ rids[i] ].numPending == 0,
				"Pending requests cleared" );
			ASSERT( sh->offNodeData_[ rids[i] ].data == 
				static_cast< void* >( &ret[i] ), "Pointing to strings" );
			ASSERT( ret[ i ] == sname, "All values returned correctly" );
			// Clean up the debris
			sh->offNodeData_[ rids[i] ].data = 0;
			sh->freeRidStack_.push_back( rids[i] );
		}
	}
}
Esempio n. 14
0
/**
 * This is a little tricky because we might be mapping between
 * data entries and field entries here.
 * May wish also to apply to exec operations.
 * At this point, the effect of trying to go between regular
 * data entries and field entries is undefined.
 */
Eref OneToOneDataIndexMsg::firstTgt( const Eref& src ) const
{
	if ( src.element() == e1_ ) {
		return Eref( e2_, src.dataIndex(), 0 );
	} else if ( src.element() == e2_ ) {
		return Eref( e1_, src.dataIndex() );
	}
	return Eref( 0, 0 );
}
Esempio n. 15
0
void Synapse::addSpike( const Eref& e, double time )
{
	static bool report = false;
	static unsigned int tgtDataIndex = 0;
	// static unsigned int tgtFieldIndex = 0;
	if ( report && e.dataIndex() == tgtDataIndex ) {
		cout << "	" << time << "," << e.fieldIndex();
	}
	handler_->addSpike( e.fieldIndex(), time + delay_, weight_ );
}
Esempio n. 16
0
void GslStoich::setN( const Eref& e, double v )
{
	unsigned int i = e.index().value(); // Later: Handle node location.
	unsigned int j = coreStoich()->convertIdToPoolIndex( e.id() );
	assert( i < pools_.size() );
	assert( j < pools_[i].size() );
	pools_[i].varS()[j] = v;
	assert( i < y_.size() );
	assert( j < y_[i].size() );
	y_[i][j] = v;
}
Esempio n. 17
0
vector< string > Neutral::getDestFields( const Eref& e ) const
{
	unsigned int num = e.element()->cinfo()->getNumDestFinfo();
	vector< string > ret( num );
	for ( unsigned int i = 0; i < num; ++i ) {
		const Finfo *f = e.element()->cinfo()->getDestFinfo( i );
		assert( f );
		ret[i] = f->name();
	}
	return ret;
}
Esempio n. 18
0
/**
 * setIsBuffered is a really nasty operation, made possible only because
 * BufPool is derived from Pool and has no other fields.
 * It uses a low-level replaceCinfo call to just change the 
 * identity of the Cinfo used, leaving everything else as is.
 */
void Pool::vSetIsBuffered( const Eref& e, bool v )
{
	static const Cinfo* bufPoolCinfo = Cinfo::find( "BufPool" );
	if (vGetIsBuffered( e ) == v)
		return;
	if (v) {
		e.element()->replaceCinfo( bufPoolCinfo );
	} else {
		e.element()->replaceCinfo( poolCinfo );
	}
}
/**
 * This is a little tricky because we might be mapping between
 * data entries and field entries here.
 * May wish also to apply to exec operations.
 * At this point, the effect of trying to go between regular
 * data entries and field entries is undefined.
 */
Eref OneToOneMsg::firstTgt( const Eref& src ) const 
{
	if ( src.element() == e1_ ) {
		if ( e2_->hasFields() )
			return Eref( e2_, i2_, src.dataIndex() );
		else 
			return Eref( e2_, src.dataIndex(), 0 );
	} else if ( src.element() == e2_ ) {
		return Eref( e1_, src.dataIndex() );
	}
	return Eref( 0, 0 );
}
Esempio n. 20
0
vector< Id > Neutral::getNeighbors( const Eref& e, string field ) const
{
	vector< Id > ret;
	const Finfo* finfo = e.element()->cinfo()->findFinfo( field );
	if ( finfo )
		e.element()->getNeighbors( ret, finfo );
	else
		cout << "Warning: Neutral::getNeighbors: Id.Field '" << 
				e.id().path() << "." << field <<
				"' not found\n";
	return ret;
}
Esempio n. 21
0
/*
*  get Assignment Rule
*/
void SbmlReader::getRules()
{
	unsigned int nr = model_->getNumRules();
	//cout<<"no of rules:"<<nr<<endl;
	for ( unsigned int r = 0;r < nr;r++ )
	{
		Rule * rule = model_->getRule(r);
		//cout << "rule :" << rule->getFormula() << endl;
		bool assignRule = rule->isAssignment();
		//cout << "is assignment :" << assignRule << endl;
		if ( assignRule ){
			string rule_variable = rule->getVariable();
			//cout << "variable :" << rule_variable << endl;
			map< string,Eref >::iterator v_iter;
			map< string,Eref >::iterator m_iter;
			v_iter = elmtMap_.find( rule_variable );
			if ( v_iter != elmtMap_.end() ){
				
				Eref rVariable = elmtMap_.find(rule_variable)->second;
				const ASTNode * ast = rule->getMath();
				vector< string > ruleMembers;
				ruleMembers.clear();
				printMembers( ast,ruleMembers );
				for ( unsigned int rm = 0; rm < ruleMembers.size(); rm++ )
				{
					m_iter = elmtMap_.find( ruleMembers[rm] );	
					if ( m_iter != elmtMap_.end() ){				
						Eref rMember = elmtMap_.find(ruleMembers[rm])->second;				
						rMember.add( "nSrc",rVariable,"sumTotal",ConnTainer::Default ); 
					}
					else{
						cerr << "SbmlReader::getRules: Assignment rule member is not a species" << endl;
						errorFlag_ = true;
					}	
				}
			}
			else{
				cerr << "SbmlReader::getRules: for now Assignment rule for parameter/compartment is not handled" << endl;
				errorFlag_ = true;
			}
		}
		bool rateRule = rule->isRate();
		if ( rateRule ){
			cout << "warning : for now Rate Rule is not handled " << endl;
			errorFlag_ = true;
		}
		bool  algebRule = rule->isAlgebraic(); 
		if ( algebRule ){
			cout << "warning: for now Algebraic Rule is not handled" << endl;
			errorFlag_ = true;
		}
	}
}
Esempio n. 22
0
vector< ObjId > Neutral::getIncomingMsgs( const Eref& e ) const
{
	vector< ObjId > ret;
	const vector< ObjId >& msgIn = e.element()->msgIn();

	for (unsigned int i = 0; i < msgIn.size(); ++i ) {
		const Msg* m = Msg::getMsg( msgIn[i] );
			assert( m );
			if ( m->e2() == e.element() )
				ret.push_back( m->mid() );
	}
	return ret;
}
Esempio n. 23
0
void HSolve::zombify( Eref hsolve ) const
{
	vector< Id >::const_iterator i;
	
	for ( i = compartmentId_.begin(); i != compartmentId_.end(); ++i )
		ZombieCompartment::zombify( hsolve.element(), i->eref().element() );
	
	for ( i = caConcId_.begin(); i != caConcId_.end(); ++i )
		ZombieCaConc::zombify( hsolve.element(), i->eref().element() );
	
	for ( i = channelId_.begin(); i != channelId_.end(); ++i )
		ZombieHHChannel::zombify( hsolve.element(), i->eref().element() );
}
Esempio n. 24
0
unsigned int Neutral::buildTree( const Eref& e, vector< Id >& tree )
	const 
{
	unsigned int ret = 1;
	Eref er( e.element(), ALLDATA );
	vector< Id > kids = getChildren( er );
	sort( kids.begin(), kids.end() );
	kids.erase( unique( kids.begin(), kids.end() ), kids.end() );
	for ( vector< Id >::iterator i = kids.begin(); i != kids.end(); ++i )
		ret += buildTree( i->eref(), tree );
	tree.push_back( e.element()->id() );
	return ret;
}
Esempio n. 25
0
// vRemesh: All the work is done by the message from the compartment to the
// Stoich. None of the ZPools is remeshed directly. However, their
// DataHandlers need updating.
void ZPool::vRemesh( const Eref& e, const Qinfo* q, 
	double oldvol,
	unsigned int numTotalEntries, unsigned int startEntry, 
	const vector< unsigned int >& localIndices, 
	const vector< double >& vols )
{
	;
	if ( e.index().value() != 0 )
		return;
	Neutral* n = reinterpret_cast< Neutral* >( e.data() );
	if ( vols.size() != e.element()->dataHandler()->localEntries() )
		n->setLastDimension( e, q, vols.size() );
}
Esempio n. 26
0
OneToOneDataIndexMsg::OneToOneDataIndexMsg(
				const Eref& e1, const Eref& e2,
				unsigned int msgIndex )
	: Msg( ObjId( managerId_, (msgIndex != 0) ? msgIndex: msg_.size() ),
					e1.element(), e2.element() )
{
	if ( msgIndex == 0 ) {
		msg_.push_back( this );
	} else {
		if ( msg_.size() <= msgIndex )
			msg_.resize( msgIndex + 1 );
		msg_[ msgIndex ] = this;
	}
}
Esempio n. 27
0
void HHGate::setTableA( const Eref& e, vector< double > v )
{
  if ( v.size() < 2 ) {
    cout << "Warning: HHGate::setTableA: size must be >= 2 entries on "
	 << e.id().path() << endl;
    return;
  }
  if ( checkOriginal( e.id(), "tableA" ) ) {
    isDirectTable_ = 1;
    A_ = v;
    unsigned int xdivs = A_.size() - 1;
    invDx_ = static_cast< double >( xdivs ) / ( xmax_ - xmin_ );
  }
}
Esempio n. 28
0
void HHGate::setMinfinity( const Eref& e, vector< double > val )
{
  if ( val.size() != 5 ) {
    cout << "Error: HHGate::setMinfinity on " << e.id().path() <<
      ": Number of entries on argument vector should be 5, was " <<
      val.size() << endl;
    return;
  }
  if ( checkOriginal( e.id(), "mInfinity" ) ) {
    mInfinity_ = val;
    updateAlphaBeta();
    updateTables();
  }
}
Esempio n. 29
0
void HHGate::setAlpha( const Eref& e, vector< double > val )
{
  if ( val.size() != 5 ) {
    cout << "Error: HHGate::setAlpha on " << e.id().path() <<
      ": Number of entries on argument vector should be 5, was " <<
      val.size() << endl;
    return;
  }
  if ( checkOriginal( e.id(), "alpha" ) ) {
    alpha_ = val;
    updateTauMinf();
    updateTables();
  }
}
Esempio n. 30
0
void HDF5DataWriter::reinit(const Eref & e, ProcPtr p)
{
    steps_ = 0;
    for (unsigned int ii = 0; ii < data_.size(); ++ii){
        H5Dclose(datasets_[ii]);
    }
    data_.clear();
    src_.clear();
    func_.clear();
    datasets_.clear();
    unsigned int numTgt = e.element()->getMsgTargetAndFunctions(e.dataIndex(),
                                                                requestOut(),
                                                                src_,
                                                                func_);
    assert(numTgt ==  src_.size());
    // TODO: what to do when reinit is called? Close the existing file
    // and open a new one in append mode? Or keep adding to the
    // current file?
    if (filename_.empty()){
        filename_ = "moose_data.h5";
    }
    if (filehandle_ > 0 ){
        close();
    }
    if (numTgt == 0){
        return;
    }
    openFile();
    for (unsigned int ii = 0; ii < src_.size(); ++ii){
        string varname = func_[ii];
        size_t found = varname.find("get");
        if (found == 0){
            varname = varname.substr(3);
            if (varname.length() == 0){
                varname = func_[ii];
            } else {
                // TODO: there is no way we can get back the original
                // field-name case. tolower will get the right name in
                // most cases as field names start with lower case by
                // convention in MOOSE.
                varname[0] = tolower(varname[0]);
            }
        }
        assert(varname.length() > 0);
        string path = src_[ii].path() + "/" + varname;
        hid_t dataset_id = getDataset(path);
        datasets_.push_back(dataset_id);
    }
    data_.resize(src_.size());
}