/////////////////////////////////////////////////////////////////////////////// /// \brief Loads a texture font from the specified sandwich database. /// /// \param sandwich The database from which to load the TextureFont. /// \param texture_id Identifies the TextureFont to load from the database. /// \param rm The ResourceManager from which to retrieve the texture for the /// font. /// \return A unique_ptr to the font, or an empty unique_ptr if a problem /// occurs during the load. std::unique_ptr<TextureFont> loadTextureFont(sw::Sandwich& sandwich, const Id& id, sw::ResourceManager& rm) { std::unique_ptr<TextureFont> result; try { db::StmtCache& cache = sandwich.getStmtCache(); db::CachedStmt get_font = cache.hold(Id(PBJ_GFX_TEXTURE_FONT_SQLID_LOAD), PBJ_GFX_TEXTURE_FONT_SQL_LOAD); get_font.bind(1, id.value()); if (get_font.step()) { Id texture_id = Id(get_font.getUInt64(0)); F32 cap_height = float(get_font.getDouble(1)); std::vector<TextureFontCharacter> chars; db::CachedStmt get_chars = cache.hold(Id(PBJ_GFX_TEXTURE_FONT_SQLID_LOAD_CHARS), PBJ_GFX_TEXTURE_FONT_SQL_LOAD_CHARS); get_chars.bind(1, id.value()); while (get_chars.step()) { TextureFontCharacter ch; ch.codepoint = get_chars.getInt(0); ch.texture_offset.x = float(get_chars.getDouble(1)); ch.texture_offset.y = float(get_chars.getDouble(2)); ch.texture_dimensions.x = float(get_chars.getDouble(3)); ch.texture_dimensions.y = float(get_chars.getDouble(4)); ch.character_offset.x = float(get_chars.getDouble(5)); ch.character_offset.y = float(get_chars.getDouble(6)); ch.character_advance = float(get_chars.getDouble(7)); chars.push_back(ch); } const Texture& texture = rm.getTexture(sw::ResourceId(sandwich.getId(), texture_id)); result.reset(new TextureFont(texture, cap_height, chars)); } else throw std::runtime_error("Texture not found!"); } catch (const db::Db::error& err) { PBJ_LOG(VWarning) << "Database error while loading texture font!" << PBJ_LOG_NL << " Sandwich ID: " << sandwich.getId() << PBJ_LOG_NL << "TextureFont ID: " << id << PBJ_LOG_NL << " Exception: " << err.what() << PBJ_LOG_NL << " SQL: " << err.sql() << PBJ_LOG_END; } catch (const std::exception& err) { PBJ_LOG(VWarning) << "Exception while loading texture font!" << PBJ_LOG_NL << " Sandwich ID: " << sandwich.getId() << PBJ_LOG_NL << "TextureFont ID: " << id << PBJ_LOG_NL << " Exception: " << err.what() << PBJ_LOG_END; } return result; }
Id generator::id_generator<Generator, Id, GeneratorArgs...>::operator()(const Id &min, const Id &max) const { if (min >= max) return Id::invalid(); Id res = Id(this->generator_(min.value(), max.value())); // Generation if (this->bad() || res < Id::min() || Id::max() < res) return Id::invalid(); return res; }
void testReacVolumeScaling() { Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); Id comptId = shell->doCreate( "CubeMesh", Id(), "cube", 1 ); Id meshId( comptId.value() + 1 ); Id subId = shell->doCreate( "Pool", comptId, "sub", 1 ); Id prdId = shell->doCreate( "Pool", comptId, "prd", 1 ); Id reacId = shell->doCreate( "Reac", comptId, "reac", 1 ); double vol1 = 1e-15; ObjId mid = shell->doAddMsg( "OneToOne", subId, "requestVolume", meshId, "get_volume" ); assert( mid != ObjId() ); mid = shell->doAddMsg( "OneToOne", prdId, "requestVolume", meshId, "get_volume" ); assert( mid != ObjId() ); vector< double > coords( 9, 10.0e-6 ); coords[0] = coords[1] = coords[2] = 0; Field< vector< double > >::set( comptId, "coords", coords ); double volume = Field< double >::get( comptId, "volume" ); assert( doubleEq( volume, vol1 ) ); ObjId ret = shell->doAddMsg( "Single", reacId, "sub", subId, "reac" ); assert( ret != ObjId() ); ret = shell->doAddMsg( "Single", reacId, "prd", prdId, "reac" ); assert( ret != ObjId() ); Field< double >::set( reacId, "Kf", 2 ); Field< double >::set( reacId, "Kb", 3 ); double x = Field< double >::get( reacId, "kf" ); assert( doubleEq( x, 2 ) ); x = Field< double >::get( reacId, "kb" ); assert( doubleEq( x, 3 ) ); ret = shell->doAddMsg( "Single", reacId, "sub", subId, "reac" ); assert( ret != ObjId() ); double conv = 1.0 / ( NA * vol1 ); x = Field< double >::get( reacId, "kf" ); assert( doubleEq( x, 2 * conv ) ); x = Field< double >::get( reacId, "kb" ); assert( doubleEq( x, 3 ) ); ret = shell->doAddMsg( "Single", reacId, "sub", subId, "reac" ); assert( ret != ObjId() ); ret = shell->doAddMsg( "Single", reacId, "prd", prdId, "reac" ); assert( ret != ObjId() ); x = Field< double >::get( reacId, "kf" ); assert( doubleEq( x, 2 * conv * conv ) ); x = Field< double >::get( reacId, "kb" ); assert( doubleEq( x, 3 * conv ) ); shell->doDelete( comptId ); cout << "." << flush; }
void HSolve::addGkEk( Id id, double Gk, double Ek ) { if(isSubSolver_) { if(Gk > 0) { PN2S_Proxy::setValue(id.value(), Gk, pn2s::FIELD::EXT_CURRENT_GK); PN2S_Proxy::setValue(id.value(), Gk * Ek, pn2s::FIELD::EXT_CURRENT_EKGK); } return; } unsigned int index = localIndex( id ); assert( 2 * index + 1 < externalCurrent_.size() ); externalCurrent_[ 2 * index ] += Gk; externalCurrent_[ 2 * index + 1 ] += Gk * Ek; }
void testPoolVolumeScaling() { Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); Id comptId = shell->doCreate( "CylMesh", Id(), "cyl", 1 ); Id meshId( comptId.value() + 1 ); Id poolId = shell->doCreate( "Pool", comptId, "pool", 1 ); ObjId mid = shell->doAddMsg( "OneToOne", ObjId( poolId, 0 ), "requestVolume", ObjId( meshId, 0 ), "get_volume" ); assert( mid != ObjId() ); vector< double > coords( 9, 0.0 ); double x1 = 100e-6; double r0 = 10e-6; double r1 = 5e-6; double lambda = x1; coords[3] = x1; coords[6] = r0; coords[7] = r1; coords[8] = lambda; Field< vector< double > >::set( comptId, "coords", coords ); double volume = Field< double >::get( poolId, "volume" ); assert( doubleEq( volume, PI * x1 * (r0+r1) * (r0+r1) / 4.0 ) ); Field< double >::set( poolId, "n", 400 ); double volscale = 1 / ( NA * volume ); double conc = Field< double >::get( poolId, "conc" ); assert( doubleEq( conc, 400 * volscale ) ); Field< double >::set( poolId, "conc", 500 * volscale ); double n = Field< double >::get( poolId, "n" ); assert( doubleEq( n, 500 ) ); Field< double >::set( poolId, "nInit", 650 ); double concInit = Field< double >::get( poolId, "concInit" ); assert( doubleEq( concInit, 650 * volscale ) ); Field< double >::set( poolId, "concInit", 10 * volscale ); n = Field< double >::get( poolId, "nInit" ); assert( doubleEq( n, 10 ) ); shell->doDelete( comptId ); cout << "." << flush; }
// See what Element::getNeighbors does with 2 sub <----> prd. void testTwoReacGetNeighbors() { Shell* shell = reinterpret_cast< Shell* >( Id().eref().data() ); Id comptId = shell->doCreate( "CubeMesh", Id(), "cube", 1 ); Id meshId( comptId.value() + 1 ); Id subId = shell->doCreate( "Pool", comptId, "sub", 1 ); Id prdId = shell->doCreate( "Pool", comptId, "prd", 1 ); Id reacId = shell->doCreate( "Reac", comptId, "reac", 1 ); ObjId mid = shell->doAddMsg( "OneToOne", subId, "requestVolume", meshId, "get_volume" ); assert( mid != ObjId() ); mid = shell->doAddMsg( "OneToOne", prdId, "requestVolume", meshId, "get_volume" ); assert( mid != ObjId() ); ObjId ret = shell->doAddMsg( "Single", reacId, "sub", subId, "reac" ); assert( ret != ObjId() ); ret = shell->doAddMsg( "Single", reacId, "sub", subId, "reac" ); assert( ret != ObjId() ); ret = shell->doAddMsg( "Single", reacId, "prd", prdId, "reac" ); assert( ret != ObjId() ); vector< Id > pools; unsigned int num = reacId.element()->getNeighbors( pools, Reac::initCinfo()->findFinfo( "toSub" ) ); assert( num == 2 ); assert( pools[0] == subId ); assert( pools[1] == subId ); pools.clear(); num = reacId.element()->getNeighbors( pools, Reac::initCinfo()->findFinfo( "sub" ) ); assert( num == 2 ); assert( pools[0] == subId ); assert( pools[1] == subId ); shell->doDelete( comptId ); cout << "." << flush; }
//////////////////////////////////////////////////////////////////////////////// /// \fn std::unique_ptr<AudioBuffer> loadSound(sw::Sandwich& sandwich, /// const Id& id) /// /// \brief Loads a sound. /// /// \author Ben Crist /// \date 2013-08-22 /// /// \exception std::runtime_error Thrown when a runtime error error /// condition occurs. /// /// \param [in,out] sandwich The sandwich. /// \param id The identifier. /// /// \return The sound. std::unique_ptr<Buffer> loadSound(sw::Sandwich& sandwich, const Id& id) { std::unique_ptr<Buffer> result; try { db::StmtCache& cache = sandwich.getStmtCache(); db::CachedStmt stmt = cache.hold(Id(PBJSQLID_LOAD), PBJSQL_LOAD); stmt.bind(1, id.value()); if (stmt.step()) { const void* data; size_t data_length = stmt.getBlob(0, data); result.reset(new Buffer(static_cast<const ALubyte*>(data), data_length)); } else throw std::runtime_error("Sound not found!"); } catch (const db::Db::error& err) { PBJ_LOG(VWarning) << "Database error while loading sound!" << PBJ_LOG_NL << "Sandwich ID: " << sandwich.getId() << PBJ_LOG_NL << " Sound ID: " << id << PBJ_LOG_NL << " Exception: " << err.what() << PBJ_LOG_NL << " SQL: " << err.sql() << PBJ_LOG_END; } catch (const std::exception& err) { PBJ_LOG(VWarning) << "Exception while loading sound!" << PBJ_LOG_NL << "Sandwich ID: " << sandwich.getId() << PBJ_LOG_NL << " Sound ID: " << id << PBJ_LOG_NL << " Exception: " << err.what() << PBJ_LOG_END; } return result; }
/////////////////////////////////////////////////////////////////////////////// /// \brief Load a set of WindowSettings from a bed. /// /// \details Each WindowSettings Id represents a stack of current and previous /// values. This allows the user to revert to previous settings if /// new settings are tried and not supported. /// /// \param bed The bed to load from. /// \param id The Id of the WindowSettings stack to load. /// /// \ingroup loading WindowSettings loadWindowSettings(bed::Bed& bed, const Id& id) { try { bed::StmtCache& cache = bed.getStmtCache(); bed::CachedStmt& stmt = cache.hold(Id(BE_WND_WINDOW_SETTINGS_SQLID_LOAD), BE_WND_WINDOW_SETTINGS_SQL_LOAD); stmt.bind(1, id.value()); if (stmt.step()) { WindowSettings ws; ws.id.bed = bed.getId(); ws.id.asset = id; ws.mode = static_cast<WindowSettings::Mode>(stmt.getInt(0)); ws.system_positioned = stmt.getBool(1); ws.save_position_on_close = stmt.getBool(2); ws.position.x = stmt.getInt(3); ws.position.y = stmt.getInt(4); ws.size.x = stmt.getInt(5); ws.size.y = stmt.getInt(6); ws.monitor_index = stmt.getInt(7); ws.refresh_rate = stmt.getUInt(8); ws.v_sync = static_cast<WindowSettings::VSyncMode>(stmt.getInt(9)); ws.msaa_level = stmt.getUInt(10); ws.red_bits = stmt.getUInt(11); ws.green_bits = stmt.getUInt(12); ws.blue_bits = stmt.getUInt(13); ws.alpha_bits = stmt.getUInt(14); ws.depth_bits = stmt.getUInt(15); ws.stencil_bits = stmt.getUInt(16); ws.srgb_capable = stmt.getBool(17); ws.use_custom_gamma = stmt.getBool(18); ws.custom_gamma = float(stmt.getDouble(19)); ws.context_version_major = stmt.getUInt(20); ws.context_version_minor = stmt.getUInt(21); ws.forward_compatible_context = stmt.getBool(22); ws.debug_context = stmt.getBool(23); ws.context_profile_type = static_cast<WindowSettings::ContextProfileType>(stmt.getInt(24)); return ws; } else throw std::runtime_error("WindowSettings record not found!"); } catch (const bed::Db::error& err) { BE_LOG(VWarning) << "Database error while loading window settings!" << BE_LOG_NL << " Bed: " << bed.getId() << BE_LOG_NL << "WindowSettings ID: " << id << BE_LOG_NL << " Exception: " << err.what() << BE_LOG_NL << " SQL: " << err.sql() << BE_LOG_END; } catch (const std::runtime_error& err) { BE_LOG(VWarning) << "Exception while loading window settings!" << BE_LOG_NL << " Bed: " << bed.getId() << BE_LOG_NL << "WindowSettings ID: " << id << BE_LOG_NL << " Exception: " << err.what() << BE_LOG_END; } return WindowSettings(); }
/** * Tab controlled by table * A + Tab <===> B * A + B -sumtot--> tot1 * 2B <===> C * * C ---e1Pool ---> D * D ---e2Pool ----> E * * All these are created on /kinetics, a cube compartment of vol 1e-18 m^3 * */ Id makeReacTest() { double simDt = 0.1; double plotDt = 0.1; Shell* s = reinterpret_cast< Shell* >( Id().eref().data() ); Id pools[10]; unsigned int i = 0; // Make the objects. Id kin = s->doCreate( "CubeMesh", Id(), "kinetics", 1 ); Id tab = s->doCreate( "StimulusTable", kin, "tab", 1 ); Id T = pools[i++] = s->doCreate( "BufPool", kin, "T", 1 ); Id A = pools[i++] = s->doCreate( "Pool", kin, "A", 1 ); Id B = pools[i++] = s->doCreate( "Pool", kin, "B", 1 ); Id C = pools[i++] = s->doCreate( "Pool", kin, "C", 1 ); Id D = pools[i++] = s->doCreate( "Pool", kin, "D", 1 ); Id E = pools[i++] = s->doCreate( "Pool", kin, "E", 1 ); Id tot1 = pools[i++] = s->doCreate( "BufPool", kin, "tot1", 1 ); Id sum = s->doCreate( "Function", tot1, "func", 1 ); // Silly that it has to have this name. Id sumInput( sum.value() + 1 ); Id e1Pool = s->doCreate( "Pool", kin, "e1Pool", 1 ); Id e2Pool = s->doCreate( "Pool", kin, "e2Pool", 1 ); Id e1 = s->doCreate( "Enz", e1Pool, "e1", 1 ); Id cplx = s->doCreate( "Pool", e1, "cplx", 1 ); Id e2 = s->doCreate( "MMenz", e2Pool, "e2", 1 ); Id r1 = s->doCreate( "Reac", kin, "r1", 1 ); Id r2 = s->doCreate( "Reac", kin, "r2", 1 ); Id plots = s->doCreate( "Table2", kin, "plots", 7 ); // Connect them up s->doAddMsg( "Single", tab, "output", T, "setN" ); s->doAddMsg( "Single", r1, "sub", T, "reac" ); s->doAddMsg( "Single", r1, "sub", A, "reac" ); s->doAddMsg( "Single", r1, "prd", B, "reac" ); Field< unsigned int >::set( sum, "numVars", 2 ); s->doAddMsg( "Single", A, "nOut", ObjId( sumInput, 0, 0 ), "input" ); s->doAddMsg( "Single", B, "nOut", ObjId( sumInput, 0, 1 ), "input" ); s->doAddMsg( "Single", sum, "valueOut", tot1, "setN" ); s->doAddMsg( "Single", r2, "sub", B, "reac" ); s->doAddMsg( "Single", r2, "sub", B, "reac" ); s->doAddMsg( "Single", r2, "prd", C, "reac" ); s->doAddMsg( "Single", e1, "sub", C, "reac" ); s->doAddMsg( "Single", e1, "enz", e1Pool, "reac" ); s->doAddMsg( "Single", e1, "cplx", cplx, "reac" ); s->doAddMsg( "Single", e1, "prd", D, "reac" ); s->doAddMsg( "Single", e2, "sub", D, "reac" ); s->doAddMsg( "Single", e2Pool, "nOut", e2, "enzDest" ); s->doAddMsg( "Single", e2, "prd", E, "reac" ); // Set parameters. Field< double >::set( A, "concInit", 2 ); Field< double >::set( e1Pool, "concInit", 1 ); Field< double >::set( e2Pool, "concInit", 1 ); Field< string >::set( sum, "expr", "x0+x1" ); Field< double >::set( r1, "Kf", 0.2 ); Field< double >::set( r1, "Kb", 0.1 ); Field< double >::set( r2, "Kf", 0.1 ); Field< double >::set( r2, "Kb", 0.0 ); Field< double >::set( e1, "Km", 5 ); Field< double >::set( e1, "kcat", 1 ); Field< double >::set( e1, "ratio", 4 ); Field< double >::set( e2, "Km", 5 ); Field< double >::set( e2, "kcat", 1 ); vector< double > stim( 100, 0.0 ); double vol = Field< double >::get( kin, "volume" ); for ( unsigned int i = 0; i< 100; ++i ) { stim[i] = vol * NA * (1.0 + sin( i * 2.0 * PI / 100.0 ) ); } Field< vector< double > >::set( tab, "vector", stim ); Field< double >::set( tab, "stepSize", 0.0 ); Field< double >::set( tab, "stopTime", 10.0 ); Field< double >::set( tab, "loopTime", 10.0 ); Field< bool >::set( tab, "doLoop", true ); // Connect outputs for ( unsigned int i = 0; i < 7; ++i ) s->doAddMsg( "Single", ObjId( plots,i), "requestOut", pools[i], "getConc" ); // Schedule it. for ( unsigned int i = 11; i < 18; ++i ) s->doSetClock( i, simDt ); s->doSetClock( 18, plotDt ); /* s->doUseClock( "/kinetics/##[ISA=Reac],/kinetics/##[ISA=EnzBase],/kinetics/##[ISA=SumFunc]", "process", 4 ); s->doUseClock( "/kinetics/##[ISA=PoolBase]", "process", 5 ); s->doUseClock( "/kinetics/##[ISA=StimulusTable]", "process", 4 ); s->doUseClock( "/kinetics/##[ISA=Table]", "process", 8 ); s->doSetClock( 4, simDt ); s->doSetClock( 5, simDt ); s->doSetClock( 8, plotDt ); */ return kin; }
Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests, unsigned int& benchmark ) { unsigned int numCores = getNumCores(); int numNodes = 1; int myNode = 0; bool isInfinite = 0; int opt; benchmark = 0; // Default, means don't do any benchmarks. Cinfo::rebuildOpIndex(); #ifdef USE_MPI /* // OpenMPI does not use argc or argv. // unsigned int temp_argc = 1; int provided; MPI_Init_thread( &argc, &argv, MPI_THREAD_SERIALIZED, &provided ); */ MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &numNodes ); MPI_Comm_rank( MPI_COMM_WORLD, &myNode ); /* if ( provided < MPI_THREAD_SERIALIZED && myNode == 0 ) { cout << "Warning: This MPI implementation does not like multithreading: " << provided << "\n"; } */ // myNode = MPI::COMM_WORLD.Get_rank(); #endif /** * Here we allow the user to override the automatic identification * of processor configuration */ while ( ( opt = getopt( argc, argv, "hiqurn:b:B:" ) ) != -1 ) { switch ( opt ) { case 'i' : // infinite loop, used for multinode debugging, to give gdb something to attach to. isInfinite = 1; break; case 'n': // Multiple nodes numNodes = (unsigned int)atoi( optarg ); break; case 'b': // Benchmark: benchmark = atoi( optarg ); break; case 'B': // Benchmark plus dump data: handle later. break; case 'u': // Do unit tests, pass back. doUnitTests = 1; break; case 'r': // Do regression tests: pass back doRegressionTests = 1; break; case 'q': // quit immediately after completion. quitFlag = 1; break; case 'h': // help default: cout << "Usage: moose -help -infiniteLoop -unit_tests -regression_tests -quit -n numNodes -benchmark [ksolve intFire hhNet msg_<msgType>_<size>]\n"; exit( 1 ); } } if ( myNode == 0 ) { #if 0 cout << "on node " << myNode << ", numNodes = " << numNodes << ", numCores = " << numCores << endl; #endif } Id shellId; Element* shelle = new GlobalDataElement( shellId, Shell::initCinfo(), "root", 1 ); Id clockId = Id::nextId(); assert( clockId.value() == 1 ); Id classMasterId = Id::nextId(); Id postMasterId = Id::nextId(); Shell* s = reinterpret_cast< Shell* >( shellId.eref().data() ); s->setShellElement( shelle ); s->setHardware( numCores, numNodes, myNode ); s->loadBalance(); /// Sets up the Elements that represent each class of Msg. unsigned int numMsg = Msg::initMsgManagers(); new GlobalDataElement( clockId, Clock::initCinfo(), "clock", 1 ); new GlobalDataElement( classMasterId, Neutral::initCinfo(), "classes", 1); new GlobalDataElement( postMasterId, PostMaster::initCinfo(), "postmaster", 1 ); assert ( shellId == Id() ); assert( clockId == Id( 1 ) ); assert( classMasterId == Id( 2 ) ); assert( postMasterId == Id( 3 ) ); // s->connectMasterMsg(); Shell::adopt( shellId, clockId, numMsg++ ); Shell::adopt( shellId, classMasterId, numMsg++ ); Shell::adopt( shellId, postMasterId, numMsg++ ); assert( numMsg == 10 ); // Must be the same on all nodes. Cinfo::makeCinfoElements( classMasterId ); // This will be initialized within the Process loop, and better there // as it flags attempts to call the Reduce operations before ProcessLoop // Qinfo::clearReduceQ( numCores ); // Initialize the ReduceQ entry. // SetGet::setShell(); // Msg* m = new OneToOneMsg( shelle, shelle ); // assert ( m != 0 ); while ( isInfinite ) // busy loop for debugging under gdb and MPI. ; return shellId; }
Id init( int argc, char** argv, Shell* pShell) { unsigned int numCores = getNumCores(); int numNodes = 1; int myNode = 0; Cinfo::rebuildOpIndex(); #ifdef USE_MPI /* // OpenMPI does not use argc or argv. // unsigned int temp_argc = 1; int provided; MPI_Init_thread( &argc, &argv, MPI_THREAD_SERIALIZED, &provided ); */ MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &numNodes ); MPI_Comm_rank( MPI_COMM_WORLD, &myNode ); if ( myNode == 0 ) { cout << "++ On node " << myNode << ", numNodes = " << numNodes << ", numCores = " << numCores << endl; } #endif Id shellId; Element* shelle = new GlobalDataElement( shellId, Shell::initCinfo(), "root", 1 ); Id clockId = Id::nextId(); assert( clockId.value() == 1 ); Id classMasterId = Id::nextId(); Id postMasterId = Id::nextId(); pShell = reinterpret_cast< Shell* >( shellId.eref().data() ); pShell->setShellElement( shelle ); pShell->setHardware( numCores, numNodes, myNode ); pShell->loadBalance(); /// Sets up the Elements that represent each class of Msg. unsigned int numMsg = Msg::initMsgManagers(); new GlobalDataElement( clockId, Clock::initCinfo(), "clock", 1 ); new GlobalDataElement( classMasterId, Neutral::initCinfo(), "classes", 1); new GlobalDataElement( postMasterId, PostMaster::initCinfo(), "postmaster", 1 ); assert ( shellId == Id() ); assert( clockId == Id( 1 ) ); assert( classMasterId == Id( 2 ) ); assert( postMasterId == Id( 3 ) ); Shell::adopt( shellId, clockId, numMsg++ ); Shell::adopt( shellId, classMasterId, numMsg++ ); Shell::adopt( shellId, postMasterId, numMsg++ ); assert( numMsg == 10 ); // Must be the same on all nodes. Cinfo::makeCinfoElements( classMasterId ); return shellId; }