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; } }
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; }
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 ); }
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 ); }
/** * 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 ); }
/** * 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 ); } }
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; }
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; }
/** * 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 ); }
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; }
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() ); }
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; }
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; } }
SingleMsg::SingleMsg( const Eref& e1, const Eref& e2, unsigned int msgIndex) : Msg( ObjId( managerId_, (msgIndex != 0 ) ? msgIndex: msg_.size() ), e1.element(), e2.element() ), i1_( e1.dataIndex() ), i2_( e2.dataIndex() ), f2_( e2.fieldIndex() ) { if ( msgIndex == 0 ) { msg_.push_back( this ); return; } else if ( msg_.size() <= msgIndex ) { msg_.resize( msgIndex + 1 ); } msg_[ msgIndex ] = this; }
OneToAllMsg::OneToAllMsg( MsgId mid, Eref e1, Element* e2 ) : Msg( mid, e1.element(), e2, OneToAllMsg::managerId_ ), i1_( e1.index() ) { ; }
unsigned int EnzBase::getNumSub( const Eref& e, const Qinfo* q ) const { const vector< MsgFuncBinding >* mfb = e.element()->getMsgAndFunc( toSub()->getBindIndex() ); assert( mfb ); return ( mfb->size() ); }
/** * Here we get the steady-state values for the gate (the 'instant' * calculation) as A_/B_. */ void HHChannel::vReinit( const Eref& er, ProcPtr info ) { g_ = ChanCommon::vGetGbar( er ); Element* e = er.element(); double A = 0.0; double B = 0.0; if ( Xpower_ > 0 ) { assert( xGate_ ); xGate_->lookupBoth( Vm_, &A, &B ); if ( B < EPSILON ) { cout << "Warning: B_ value for " << e->getName() << " is ~0. Check X table\n"; return; } if (!xInited_) X_ = A/B; g_ *= takeXpower_( X_, Xpower_ ); } if ( Ypower_ > 0 ) { assert( yGate_ ); yGate_->lookupBoth( Vm_, &A, &B ); if ( B < EPSILON ) { cout << "Warning: B value for " << e->getName() << " is ~0. Check Y table\n"; return; } if (!yInited_) Y_ = A/B; g_ *= takeYpower_( Y_, Ypower_ ); } if ( Zpower_ > 0 ) { assert( zGate_ ); if ( useConcentration_ ) zGate_->lookupBoth( conc_, &A, &B ); else zGate_->lookupBoth( Vm_, &A, &B ); if ( B < EPSILON ) { cout << "Warning: B value for " << e->getName() << " is ~0. Check Z table\n"; return; } if (!zInited_) Z_ = A/B; g_ *= takeZpower_( Z_, Zpower_ ); } ChanCommon::vSetGk( er, g_ * HHChannelBase::modulation_ ); updateIk(); // Gk_ = g_; // Ik_ = ( Ek_ - Vm_ ) * g_; // Send out the relevant channel messages. // Same for reinit as for process. sendReinitMsgs( er, info ); g_ = 0.0; }
void NSDFWriter::process(const Eref& eref, ProcPtr proc) { if (filehandle_ < 0){ return; } vector < double > uniformData; const Finfo* tmp = eref.element()->cinfo()->findFinfo("requestOut"); const SrcFinfo1< vector < double > *>* requestOut = static_cast<const SrcFinfo1< vector < double > * > * >(tmp); requestOut->send(eref, &uniformData); for (unsigned int ii = 0; ii < uniformData.size(); ++ii){ data_[ii].push_back(uniformData[ii]); } ++steps_; if (steps_ < flushLimit_){ return; } // // TODO this is place holder. Will convert to 2D datasets to // // collect same field from object on same clock // for (unsigned int ii = 0; ii < datasets_.size(); ++ii){ // herr_t status = appendToDataset(datasets_[ii], data_[ii]); // data_[ii].clear(); // } // for (unsigned int ii = 0; ii < events_.size(); ++ii){ // herr_t status = appendToDataset(eventDatasets_[ii], events_[ii]); // } NSDFWriter::flush(); steps_ = 0; }
bool Pool::vGetIsBuffered( const Eref& e ) const { /// We need this explicit check because when the moose class is /// flipped, the internal C++ class isn't. /// Inherited by BufPool. return e.element()->cinfo()->name() == "BufPool"; }
// 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(); }
// static function bool Neutral::isDescendant( Id me, Id ancestor ) { static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); static const FuncId pafid = pf2->getFid(); Eref e = me.eref(); while ( e.element()->id() != Id() && e.element()->id() != ancestor ) { ObjId mid = e.element()->findCaller( pafid ); assert( mid != ObjId() ); ObjId fid = Msg::getMsg( mid )->findOtherEnd( e.objId() ); e = fid.eref(); } return ( e.element()->id() == ancestor ); }
/** * Here we get the steady-state values for the gate (the 'instant' * calculation) as A_/B_. */ void HHChannel2D::reinit( const Eref& er, ProcPtr info ) { g_ = ChanBase::getGbar(); Element* e = er.element(); double A = 0.0; double B = 0.0; if ( Xpower_ > 0 ) { xGate_->lookupBoth( depValue( Xdep0_ ), depValue( Xdep1_ ), &A, &B ); if ( B < EPSILON ) { cout << "Warning: B_ value for " << e->getName() << " is ~0. Check X table\n"; return; } if (!xInited_) X_ = A/B; g_ *= takeXpower_( X_, Xpower_ ); } if ( Ypower_ > 0 ) { yGate_->lookupBoth( depValue( Ydep0_ ), depValue( Ydep1_ ), &A, &B ); if ( B < EPSILON ) { cout << "Warning: B value for " << e->getName() << " is ~0. Check Y table\n"; return; } if (!yInited_) Y_ = A/B; g_ *= takeYpower_( Y_, Ypower_ ); } if ( Zpower_ > 0 ) { zGate_->lookupBoth( depValue( Zdep0_ ), depValue( Zdep1_ ), &A, &B ); if ( B < EPSILON ) { cout << "Warning: B value for " << e->getName() << " is ~0. Check Z table\n"; return; } if (!zInited_) Z_ = A/B; g_ *= takeZpower_( Z_, Zpower_ ); } ChanBase::setGk( g_ ); ChanBase::updateIk(); // Gk_ = g_; // Ik_ = ( Ek_ - Vm_ ) * g_; // Send out the relevant channel messages. // Same for reinit as for process. ChanBase::reinit( er, info ); /* channelOut.send( er, info, Gk_, Ek_ ); // Needed by GHK-type objects permeability.send( er, info, Gk_ ); */ g_ = 0.0; }
vector< ObjId > Neutral::getOutgoingMsgs( const Eref& e ) const { vector< ObjId > ret; unsigned int numBindIndex = e.element()->cinfo()->numBindIndex(); for ( unsigned int i = 0; i < numBindIndex; ++i ) { const vector< MsgFuncBinding >* v = e.element()->getMsgAndFunc( i ); if ( v ) { for ( vector< MsgFuncBinding >::const_iterator mb = v->begin(); mb != v->end(); ++mb ) { ret.push_back( mb->mid ); } } } return ret; }
// // Stage 0: Check if it is a Msg. This is deleted by Msg::deleteMsg( ObjId ) // Stage 1: mark for deletion. This is done by setting cinfo = 0 // Stage 2: Clear out outside-going msgs // Stage 3: delete self and attached msgs, void Neutral::destroy( const Eref& e, int stage ) { if ( e.element()->cinfo()->isA( "Msg" ) ) { Msg::deleteMsg( e.objId() ); return; } vector< Id > tree; Eref er( e.element(), ALLDATA ); unsigned int numDescendants = buildTree( er, tree ); /* cout << "Neutral::destroy: id = " << e.id() << ", name = " << e.element()->getName() << ", numDescendants = " << numDescendants << endl; */ assert( numDescendants == tree.size() ); Element::destroyElementTree( tree ); }
vector< string > Neutral::getMsgDestFunctions( const Eref& e, string field ) const { vector< string > ret( 0 ); const Finfo* finfo = e.element()->cinfo()->findFinfo( field ); const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( finfo ); if ( sf ) { vector< ObjId > tgt; vector< string > func; e.element()->getMsgTargetAndFunctions( e.dataIndex(), sf, tgt, func ); return func; } else { cout << "Warning: Neutral::getMsgDestFunctions: Id.Field '" << e.id().path() << "." << field << "' not found or not a SrcFinfo\n"; } return ret; }
Eref SparseMsg::firstTgt( const Eref& src ) const { if ( matrix_.nEntries() == 0 ) return Eref( 0, 0 ); if ( src.element() == e1_ ) { const unsigned int* fieldIndex; const unsigned int* colIndex; unsigned int n = matrix_.getRow( src.dataIndex(), &fieldIndex, &colIndex ); if ( n != 0 ) { return Eref( e2_, colIndex[0], fieldIndex[0] ); } } else if ( src.element() == e2_ ) { return Eref( e1_, 0 ); } return Eref( 0, 0 ); }
double Neutral::getDt( const Eref& e ) const { int tick = e.element()->getTick(); if ( tick < 0 ) return 0.0; Id clockId( 1 ); return LookupField< unsigned int, double >::get( clockId, "tickDt", tick ); }
void Clock::buildTicks( const Eref& e ) { activeTicks_.resize(0); activeTicksMap_.resize(0); for ( unsigned int i = 0; i < ticks_.size(); ++i ) { if ( ticks_[i] > 0 && e.element()->hasMsgs( processVec()[i]->getBindIndex() ) ) { activeTicks_.push_back( ticks_[i] ); activeTicksMap_.push_back( i ); } } }
// 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() ); }
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()); }