ObjId OneToOneDataIndexMsg::findOtherEnd( ObjId f ) const { if ( f.element() == e1() ) return ObjId( e2()->id(), f.dataIndex ); else if ( f.element() == e2() ) return ObjId( e1()->id(), f.dataIndex ); return ObjId( 0, BADINDEX ); }
void EndoMesh::setSurround( const Eref& e, ObjId v ) { if ( !v.element()->cinfo()->isA( "ChemCompt" ) ) { cout << "Warning: 'surround' may only be set to an object of class 'ChemCompt'\n"; cout << v.path() << " is of class " << v.element()->cinfo()->name() << endl; return; } surround_ = v; parent_ = reinterpret_cast< const MeshCompt* >( v.data() ); }
ObjId OneToAllMsg::findOtherEnd( ObjId f ) const { if ( f.element() == e1() ) { if ( f.dataIndex == i1_ ) return ObjId( e2()->id(), 0 ); } else if ( f.element() == e2() ) { return ObjId( e1()->id(), i1_ ); } return ObjId( 0, BADINDEX ); }
/** Populates the vector of event data buffers (vectors), vector of event source objects, vector of event source fields and the vector of event datasets by querying the messages on InputVariables. */ void NSDFWriter::openEventData(const Eref &eref) { if (filehandle_ <= 0){ return; } for (unsigned int ii = 0; ii < eventInputs_.size(); ++ii){ stringstream path; path << eref.objId().path() << "/" << "eventInput[" << ii << "]"; ObjId inputObj = ObjId(path.str()); Element * el = inputObj.element(); const DestFinfo * dest = static_cast<const DestFinfo*>(el->cinfo()->findFinfo("input")); vector < ObjId > src; vector < string > srcFields; el->getMsgSourceAndSender(dest->getFid(), src, srcFields); if (src.size() > 1){ cerr << "NSDFWriter::openEventData - only one source can be connected to an eventInput" <<endl; } else if (src.size() == 1){ eventSrcFields_.push_back(srcFields[0]); eventSrc_.push_back(src[0].path()); events_.resize(eventSrc_.size()); stringstream path; path << src[0].path() << "." << srcFields[0]; hid_t dataSet = getEventDataset(src[0].path(), srcFields[0]); eventDatasets_.push_back(dataSet); } else { cerr <<"NSDFWriter::openEventData - cannot handle multiple connections at single input." <<endl; } } }
void Shell::doMove( Id orig, ObjId newParent ) { if ( orig == Id() ) { cout << "Error: Shell::doMove: Cannot move root Element\n"; return; } if ( newParent.element() == 0 ) { cout << "Error: Shell::doMove: Cannot move object to null parent \n"; return; } if ( Neutral::isDescendant( newParent, orig ) ) { cout << "Error: Shell::doMove: Cannot move object to descendant in tree\n"; return; } const string& name = orig.element()->getName(); if ( Neutral::child( newParent.eref(), name ) != Id() ) { stringstream ss; ss << "Shell::doMove: Object with same name already present: '" << newParent.path() << "/" << name << "'. Move failed."; warning( ss.str() ); return; } SetGet2< Id, ObjId >::set( ObjId(), "move", orig, newParent ); // innerMove( orig, newParent ); }
void Shell::recvGet( const Eref& e, const Qinfo* q, PrepackedBuffer pb ) { if ( myNode_ == 0 ) { if ( gettingVector_ ) { ObjId tgt = q->src(); // unsigned int linearIndex = q->src().eref().index().value(); unsigned int linearIndex = tgt.element()->dataHandler()->linearIndex( tgt.dataId ); if ( linearIndex >= getBuf_.size() ) { if ( linearIndex >= getBuf_.capacity() ) getBuf_.reserve( linearIndex * 2 ); getBuf_.resize( linearIndex + 1 ); } assert ( linearIndex < getBuf_.size() ); double*& c = getBuf_[ linearIndex ]; c = new double[ pb.dataSize() ]; memcpy( c, pb.data(), pb.dataSize() * sizeof( double ) ); // cout << myNode_ << ":" << q->threadNum() << ": Shell::recvGet[" << linearIndex << "]= (" << pb.dataSize() << ", " << *c << ")\n"; } else { assert ( getBuf_.size() == 1 ); double*& c = getBuf_[ 0 ]; c = new double[ pb.dataSize() ]; memcpy( c, pb.data(), pb.dataSize() * sizeof( double ) ); handleAck( 0, OkStatus ); } ++numGetVecReturns_; } }
// Utility function: return the compartment in which the specified // object is located. // Simply traverses the tree toward the root till it finds a // compartment. Pools use a special msg, but this works for reacs too. ObjId getCompt( Id id ) { ObjId pa = Neutral::parent( id.eref() ).id; if ( pa == ObjId() ) return pa; else if ( pa.element()->cinfo()->isA( "ChemCompt" ) ) return pa; return getCompt( pa ); }
/// non-static func. Returns the Id found by traversing the specified path. ObjId Shell::doFind( const string& path ) const { if ( path == "/" || path == "/root" ) return ObjId(); ObjId curr; vector< string > names; vector< unsigned int > indices; bool isAbsolute = chopPath( path, names, indices ); assert( names.size() == indices.size() ); if ( !isAbsolute ) curr = cwe_; for ( unsigned int i = 0; i < names.size(); ++i ) { if ( names[i] == "." ) { } else if ( names[i] == ".." ) { curr = Neutral::parent( curr.eref() ); } else { ObjId pa = curr; curr = Neutral::child( curr.eref(), names[i] ); if ( curr == ObjId() ) // Neutral::child returned Id(), ie, bad. return ObjId( 0, BADINDEX ); if ( curr.element()->hasFields() ) { curr.dataIndex = pa.dataIndex; curr.fieldIndex = indices[i]; } else { curr.dataIndex = indices[i]; if ( curr.element()->numData() <= curr.dataIndex ) return ObjId( 0, BADINDEX ); } } } assert( curr.element() ); if ( curr.element()->numData() <= curr.dataIndex ) return ObjId( 0, BADINDEX ); if ( curr.fieldIndex > 0 && !curr.element()->hasFields() ) return ObjId( 0, BADINDEX ); return curr; }
ObjId SparseMsg::findOtherEnd( ObjId f ) const { if ( f.element() == e1() ) { const unsigned int* entry; const unsigned int* colIndex; unsigned int num = matrix_.getRow( f.dataIndex, &entry, &colIndex ); if ( num > 0 ) { // Return the first matching entry. return ObjId( e2()->id(), colIndex[0] ); } return ObjId( 0, BADINDEX ); } else if ( f.element() == e2() ) { // Bad! Slow! Avoid! vector< unsigned int > entry; vector< unsigned int > rowIndex; unsigned int num = matrix_.getColumn( f.dataIndex, entry, rowIndex ); if ( num > 0 ) { // Return the first matching entry. return ObjId( e1()->id(), DataId( rowIndex[0] ) ); } } return ObjId( 0, BADINDEX ); }
bool Shell::innerMove( Id orig, ObjId newParent ) { static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" ); static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); static const FuncId pafid = pf2->getFid(); static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" ); assert( !( orig == Id() ) ); assert( !( newParent.element() == 0 ) ); ObjId mid = orig.element()->findCaller( pafid ); Msg::deleteMsg( mid ); Msg* m = new OneToAllMsg( newParent.eref(), orig.element(), 0 ); assert( m ); if ( !f1->addMsg( pf, m->mid(), newParent.element() ) ) { cout << "move: Error: unable to add parent->child msg from " << newParent.element()->getName() << " to " << orig.element()->getName() << "\n"; return 0; } return 1; }
/** * Static utility function. Attaches child element to parent element. * Must only be called from functions executing in parallel on all nodes, * as it does a local message addition * MsgIndex is needed to be sure that the same msg identifies parent-child * connection on all nodes. */ bool Shell::adopt( ObjId parent, Id child, unsigned int msgIndex ) { static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" ); // static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); // static const FuncId pafid = pf2->getFid(); static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" ); assert( !( child.element() == 0 ) ); assert( !( child == Id() ) ); assert( !( parent.element() == 0 ) ); Msg* m = new OneToAllMsg( parent.eref(), child.element(), msgIndex ); assert( m ); // cout << myNode_ << ", Shell::adopt: mid = " << m->mid() << ", pa =" << parent << "." << parent()->getName() << ", kid=" << child << "." << child()->getName() << "\n"; if ( !f1->addMsg( pf, m->mid(), parent.element() ) ) { cout << "move: Error: unable to add parent->child msg from " << parent.element()->getName() << " to " << child.element()->getName() << "\n"; return 0; } return 1; }
ObjId Neutral::parent( ObjId oid ) { static const Finfo* pf = neutralCinfo->findFinfo( "parentMsg" ); static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf ); static const FuncId pafid = pf2->getFid(); if ( oid.id == Id() ) { cout << "Warning: Neutral::parent: tried to take parent of root\n"; return Id(); } ObjId mid = oid.element()->findCaller( pafid ); assert( mid != ObjId() ); ObjId pa = Msg::getMsg( mid )->findOtherEnd( oid ); return pa; }
/** * This is the version used by the parser. Acts as a blocking, * serial-like interface to a potentially multithread, multinode call. * Returns the new Id index upon success, otherwise returns Id(). * The data of the new Element is not necessarily allocated at this point, * that can be deferred till the global Instantiate or Reset calls. * Idea is that the model should be fully defined before load balancing. * */ Id Shell::doCreate( string type, ObjId parent, string name, unsigned int numData, NodePolicy nodePolicy, unsigned int preferredNode ) { #ifdef ENABLE_LOGGER clock_t t = clock(); #endif const Cinfo* c = Cinfo::find( type ); if ( !isNameValid( name ) ) { stringstream ss; ss << "Shell::doCreate: bad character in name'" << name << "'. No Element created"; warning( ss.str() ); return Id(); } if ( c ) { if ( c->banCreation() ) { stringstream ss; ss << "Shell::doCreate: Cannot create an object of class '" << type << "' because it is an abstract base class or a FieldElement.\n"; warning( ss.str() ); return Id(); } Element* pa = parent.element(); if ( !pa ) { stringstream ss; ss << "Shell::doCreate: Parent Element'" << parent << "' not found. No Element created"; warning( ss.str() ); return Id(); } if ( Neutral::child( parent.eref(), name ) != Id() ) { stringstream ss; ss << "Shell::doCreate: Object with same name already present: '" << parent.path() << "/" << name << "'. No Element created"; warning( ss.str() ); return Id(); } // Get the new Id ahead of time and pass to all nodes. Id ret = Id::nextId(); NodeBalance nb( numData, nodePolicy, preferredNode ); // Get the parent MsgIndex ahead of time and pass to all nodes. unsigned int parentMsgIndex = OneToAllMsg::numMsg(); SetGet6< string, ObjId, Id, string, NodeBalance, unsigned int >::set( ObjId(), // Apply command to Shell "create", // Function to call. type, // class of new object parent, // Parent ret, // id of new object name, // name of new object nb, // Node balance configuration parentMsgIndex // Message index of child-parent msg. ); // innerCreate( type, parent, ret, name, numData, isGlobal ); #ifdef ENABLE_LOGGER logger.creationTime.push_back((float(clock() - t)/CLOCKS_PER_SEC)); #endif return ret; } else { stringstream ss; ss << "Shell::doCreate: Class '" << type << "' not known. No Element created"; warning( ss.str() ); } #ifdef ENABLE_LOGGER logger.creationTime.push_back((float(clock() - t)/CLOCKS_PER_SEC)); #endif return Id(); }