/******************************************************************* * * DESCRIPTION: class FlatCoupledCell * * AUTHOR: Amir Barylko & Jorge Beyoglonian * Version 2: Daniel Rodriguez. * * EMAIL: mailto://amir@dc.uba.ar * mailto://jbeyoglo@dc.uba.ar * mailto://drodrigu@dc.uba.ar * * DATE: 27/06/1998 * DATE: 12/11/1999 (v2) * *******************************************************************/ // ** include files **// #include #include "flatcoup.h" // header #include "cellstate.h" // CellState #include "neighval.h" // NeighborhoodValue #include "strutil.h" // lowerCase #include "realfunc.h" // calculateWithQuantum #include "message.h" #include "msgbag.h" // ** private data ** // #define OUT_PORT "out" // ** public ** // inline long *selectPos( long *select, nTupla *dim, const CellPosition &pos, bool verifyIncludes ) { return &(select[ pos.calculateIndex( *dim, verifyIncludes ) ]); } /******************************************************************* * Method: createCells ********************************************************************/ CoupledCell &FlatCoupledCell::createCells( const CellPositionList &n, const CellPositionList &selectList, CellPartition *part ) { //Rami: fictitious port only used to avoid run time error when using message bags // it is used in the messages sent internally by the cells localPort = new Port("neighborChange", this->id()); this->CoupledCell::neighborsList(n); cellState( new CellState( *((nTupla *) &(dimension())), borderWrapped() ) ); register long cantElems = dimension().totalElements(); select = new long[ cantElems ]; xList = new VirtualPortList[ cantElems ]; yList = new VirtualPortList[ cantElems ]; //Rami cout << "creating the cellsMsgs and cellsNeighbors" << endl; cellsMsgs = new MessageBag[cantElems] ; cellsNeighbors = new (NeighborhoodValue*)[cantElems]; // nTupla dimen( dimension() ); register long posi( 0 ); // let's fill the order for ( CellPositionList::const_iterator cursor = selectList.begin(); cursor != selectList.end(); cursor++ ) *(selectPos( select, &dimen, *cursor, true )) = posi++; /////////////////////// // Creates the cells /////////////////////// MASSERTMSG( !dimen.contains(0), "Attempt to create a FlatCoupledCell model with a dimension containing the value 0."); CellPosition counter( dimen.dimension(), 0 ); register bool overflow = false; while (!overflow){ (*cellState())[ counter ] = initialCellValue(); if( find( selectList.begin(), selectList.end(), counter ) == selectList.end()) *(selectPos( select, &dimen, counter, false )) = posi++; //Rami: initializing the neigborhoodValues for all the cells cout << "FlatCoupledCell: initializing neighborhood value for " << counter.print() << endl; cellsNeighbors[counter.calculateIndex(dimen)] = new NeighborhoodValue(*cellState(),neighborsList(),counter); cout << counter.print() << " : " << cellsNeighbors[counter.calculateIndex(dimen)]->get() << endl; // overflow = counter.next( dimen ); } MASSERTMSG( posi == cantElems, "Invalid cell creation!" ); return *this ; } /******************************************************************* * Method: setCellValue ********************************************************************/ CoupledCell &FlatCoupledCell::setCellValue( const CellPosition &pos, const Real &val ) { // CellPosition *cp = (CellPosition *) &pos; // (*cellState())[ *cp ] = val ; CellPosition position = pos; cellsNeighbors[ position.calculateIndex( dimension() ) ]->set(val); return *this ; } /******************************************************************* * Method: localTransition ********************************************************************/ CoupledCell &FlatCoupledCell::setLocalTransition( const CellPosition &pos, const LocalTransAdmin::Function &fn ) { funcZones[ pos ] = fn; return *this ; } /******************************************************************* * Method: initFunction ********************************************************************/ Model &FlatCoupledCell::initFunction() { typedef map< long, CellPosition > SelectList ; SelectList posList ; nTupla dimen( dimension() ); MASSERTMSG( !dimen.contains(0), "Attempt to initialize a FlatCoupledCell model with a dimension containing the value 0."); MASSERTMSG( eventList.empty()== true, "CoupledFlatCell::initFunction : eventList is not empty !"); register bool overflow = false; CellPosition counter( dimen.dimension(), 0 ); while (!overflow){ posList[ *(selectPos( select, &dimen, counter, false )) ] = counter; NextEvent nextEvent; nextEvent.time = Time::Zero; nextEvent.pos = counter; nextEvent.value = cellsNeighbors[counter.calculateIndex(dimen)]->get(); cout << "initFunction: nextEvent.pos " << nextEvent.pos.print() << endl; cout << "FlatCoupledCell::initFunction: have set " << counter.print() << " : " << cellsNeighbors[counter.calculateIndex(dimen)]->get() << endl ; eventList.push_back(nextEvent); overflow = counter.next( dimen ); } cout << "initFunction: The size of the nextEventList is " << eventList.size() << endl; return *this; /* * for( SelectList::iterator cursor = posList.begin(); cursor != posList.end(); cursor ++ ) externalFunction( Time::Zero, cursor->second ); */ } //======================================================================== Model &FlatCoupledCell::outputFunction(const CollectMessage& msg) { Time time = msg.time(); typedef list Influenced; Influenced influenced; nTupla dimen( dimension() ); VirtualPortList::iterator cursor; CellPositionList::const_iterator links; CellPosition aux; register long posCell; cout << " outputFunctions: The sizes of the message bags are : " << endl; CellPosition tempCounter = CellPosition(dimen.dimension(), 0); bool tempOverflow = false; while(!tempOverflow) { cout << tempCounter.print() << " : " << cellsMsgs[tempCounter.calculateIndex(dimen)].size() << endl; tempOverflow = tempCounter.next(dimen); } ExternalMessage* extMsg = new ExternalMessage() ; extMsg->time(time); extMsg->procId(-1); extMsg->port(*localPort); NextEventList::iterator eventCursor = nextEventList().begin(); // while( !eventList.empty() && eventList.front().time == time ) for (; ( eventCursor != nextEventList().end() ) && (eventCursor->time == time) ; eventCursor++) { // NextEvent &nextEvent( eventList.front() ); NextEvent &nextEvent = *eventCursor; extMsg->value( nextEvent.value.value() ); extMsg->senderCellPosition(nextEvent.pos); /*************************************************************/ // let's analize the output // Find the "OUT" port posCell = nextEvent.pos.calculateIndex( dimension() ); for (cursor = yList[posCell].begin(); cursor != yList[posCell].end(); cursor++) if (cursor->first == OUT_PORT) sendOutput( time, *(cursor->second), nextEvent.value.value() ); /*************************************************************/ cout << endl << "neighbors of " << nextEvent.pos.print() << " : " << endl; // let's save the external messages to the local links for (links = neighborsList().begin(); links != neighborsList().end(); links++ ) { aux = nextEvent.pos; aux -= *links; // REVERSE NEIGHBOR LIST // For NORMAL NEIGHBOR LIST do += if ( cellState()->includes(aux) ) { cellState()->calcRealPos(aux); influenced.push_back(aux); } cout << aux.print() << "\t" ; } // CellPosition position = nextEvent.pos; cout << endl; for (Influenced::iterator cursor = influenced.begin(); cursor != influenced.end(); cursor++ ) { cout << "outputFunction: going to send extMsg(" << extMsg->senderCellPosition().print() <<") to " << cursor->print() << endl; (cellsMsgs[ (*cursor).calculateIndex(dimen) ]).add((ExternalMessage*) ( extMsg->clone() ) ) ; } influenced.erase(influenced.begin(), influenced.end()); } tempCounter = CellPosition(dimen.dimension(), 0); tempOverflow = false; while(!tempOverflow) { cout << tempCounter.print() << " : " << cellsMsgs[tempCounter.calculateIndex(dimen)].size() << endl; tempOverflow = tempCounter.next(dimen); } tempCounter = CellPosition(dimen.dimension(), 0); MessageBag::iterator cur ; bool _overflow = false; while(!_overflow) { cout << "outputFunction: printing the message bag contents for " << tempCounter.print() << endl; for (cur = cellsMsgs[tempCounter.calculateIndex(dimen)].begin() ; cur != cellsMsgs[tempCounter.calculateIndex(dimen)].end() ;cur++) { ExternalMessage msg_ =*( (ExternalMessage*)(*cur) ); cout << msg_.senderCellPosition() << " value : " << msg_.value() << endl; } _overflow = tempCounter.next(dimen); } return *this; } Model &FlatCoupledCell::internalFunction(const InternalMessage& msg) { cout << "FlatCoupledCell: received internal message from FlatCellCoordinator @ " << msg.time() << endl; nTupla dimen = dimension(); CellPosition counter = CellPosition(dimen.dimension(),0); register bool overflow = false; while(!overflow) { MessageBag &msgBag = cellsMsgs[counter.calculateIndex(dimen)] ; if ( isImminent(counter, msg.time()) && (msgBag.size() == 0) ) { cout << "going to execute localInternalFunction for " << counter.print() << " @ " << msg.time() << endl; localInternalFunction(counter, msg.time()); } else if ( isImminent(counter, msg.time()) && (msgBag.size() != 0) ) { cout << "going to execute localConfluentFunction for " << counter.print() << " @ " << msg.time() << endl; localConfluentFunction(counter,msg.time(), msgBag); msgBag.eraseAll(); } else if ( !isImminent(counter, msg.time()) && ( msgBag.size() != 0 ) ) { cout << "going to execute localExternalFunction for " << counter.print() << " @ " << msg.time() << endl; localExternalFunction(counter, msgBag); msgBag.eraseAll(); } overflow = counter.next(dimen); } } //********************************************************************************************* Model &FlatCoupledCell::updateNeighborValues(const CellPosition &pos,const MessageBag &msgBag) { nTupla dimen = dimension(); CellPosition position = pos; MessageBag::iterator cursor; VirtualPortList::const_iterator portCursor; cout << "updating neighborhood for " << position.print() << endl; cout << "The size of the message bag is " << msgBag.size() << endl; for (cursor = msgBag.begin(); cursor != msgBag.end() ; cursor++) { ExternalMessage msg = *((ExternalMessage*)(*cursor)); if ((msg.procId() != -1) && (msg.port().name() != "neighborChange") ) // Rami: it must be external message sent by FlatCoordinator { for (portCursor = xList[position.calculateIndex(dimen)].begin(); portCursor != xList[position.calculateIndex(dimen)].end(); portCursor++) { if ( *(portCursor->second) == msg.port() ) this->setLastValuePortIn(position, portCursor->first,msg.value()); } } else if ( (msg.procId() == -1) && (msg.port().name() == "neighborChange") ) // Rami: it must be a message sent internally by the FlatCoupledCell model { cout << "senderCellPosition is " << msg.senderCellPosition().print() << endl; CellPosition otherPosition = msg.senderCellPosition(); CellPosition cp; cp = this->inverseNeighborhood(position, otherPosition); cellsNeighbors[position.calculateIndex(dimen)]->set(cp, msg.value()); } } cout << "printing the neighborhood for " << position.print() << endl; CellPositionList::const_iterator cursor_ = neighborsList().begin(); if ( cursor_ == neighborsList().end() ) cout << "cursor_ == neighborsList() " << endl; for(; cursor_ != neighborsList().end(); cursor_++) cout << cursor_->print() << " : " << cellsNeighbors[position.calculateIndex(dimen)]->get(*cursor_) << "\t" ; cout << endl; return *this; } //********************************************************************************************* //********************************************************************************************* Model &FlatCoupledCell::localConfluentFunction( const CellPosition &pos,const Time &time ,const MessageBag &msgBag) { localInternalFunction( pos, time); localExternalFunction( pos, msgBag); return *this; } /******************************************************************* * Method: internalFunction *******************************************************************/ Model &FlatCoupledCell::localInternalFunction( const CellPosition& pos, const Time &time ) { MASSERTMSG( isImminent(pos, time) == true, "Trying to execute localInternalFunction for non-imminent cells"); nTupla dimen = dimension(); CellPosition position = pos; NextEventList::iterator cursor = nextEventList().begin(); while( cursor != nextEventList().end() ) if ( ( (*cursor).time == time ) && ( (*cursor).pos == position ) ) { cellsNeighbors[ position.calculateIndex(dimen)]->set((*cursor).value); cout << "going to delete: " << (cursor->pos).print() << "," << (cursor->time).asString() << "," << (cursor->value).value() << endl; cursor = nextEventList().erase(cursor); cout << "deleted one event from nextEvent list " << endl; } else cursor++; cout << "FlatCoupledCell: executed localInternalFunction for " << position.print() << endl; return *this; } //******************************************************************************************** bool FlatCoupledCell::isImminent(const CellPosition& pos, const Time& time) { CellPosition position = pos; NextEventList::iterator cursor = eventList.begin(); for (; cursor != eventList.end() ; cursor++) if( ( (*cursor).time == time ) && ( (*cursor).pos == position ) ) return true; if (cursor == eventList.end()) return false; } //******************************************************************************************** /******************************************************************* * Function Name: addInfluence * Description: agrega una influencia entre dos ports ********************************************************************/ Model &FlatCoupledCell::addInfluence( const string &sourceName, const string &sourcePort, const string &destName, const string &destPort ) { MASSERTMSG( sourceName==description() || destName==description(), "Invalid Link!" ); if( sourceName==description() ) { Port &port( port( sourcePort ) ); xList[ CellPosition(destName).calculateIndex( dimension() )].insert( VirtualPortList::value_type( lowerCase(destPort), &port ) ); // Now adds the default function in the port function list setPortInFunction( CellPosition(destName), destPort, DEFAULT_FUNCTION_InPort ); // Now set the last value arrived to the port with a undefined setLastValuePortIn( CellPosition(destName), destPort, Real::tundef ); } else { /************************************************************/ // Now, adds the output ports to the YList Port &port( port( destPort ) ); yList[ CellPosition(sourceName).calculateIndex( dimension() )].insert( VirtualPortList::value_type( lowerCase(sourcePort), &port ) ); /************************************************************/ } return *this ; } /******************************************************************* * Function Name: setPortInFunction * Description: agrega o establece una function para un puerto especifico de una celda ********************************************************************/ void FlatCoupledCell::setPortInFunction( const CellPosition &cellPos, const string &portIn, const string &functionName ) { FlatPortInFunction::iterator cursor = getPortFunction().begin(); register bool salgo = false; // search for the (cellPos, portIn) while ( !salgo && cursor != getPortFunction().end() ) if ( cursor->first.cellPos() == cellPos && cursor->first.inPort() == portIn ) salgo = true; else cursor++; // if not exists if (cursor == getPortFunction().end() ) { CellDescription *cellDesc = new CellDescription; cellDesc->cellPos( cellPos ); cellDesc->inPort( portIn ); getPortFunction()[ *cellDesc ] = functionName; } else // the entry exists { CellDescription cellDesc; cellDesc.cellPos( cellPos ); cellDesc.inPort( portIn ); getPortFunction()[ cellDesc ] = functionName; } } /******************************************************************* * Function Name: getPortInFunction * Description: obtiene el nombre de la function para un puerto especifico de una celda ********************************************************************/ const string &FlatCoupledCell::getPortInFunction( const CellPosition &cellPos, const string &portIn ) { register bool salgo = false; // search for the (cellPos(), portIn) FlatPortInFunction::iterator cursor = getPortFunction().begin(); while (!salgo && cursor != getPortFunction().end()) if ( cursor->first.cellPos() == cellPos && cursor->first.inPort() == portIn ) salgo = true; else cursor++; MASSERTMSG( cursor != getPortFunction().end(), "Invalid reference to the PortIn function: " + portIn); CellDescription cellDesc; cellDesc.cellPos( cellPos ); cellDesc.inPort( portIn ); return getPortFunction()[ cellDesc ]; } /******************************************************************* * Function Name: setLastValuePortIn * Description: agrega o establece el ultimo valor ingresado por un puerto especifico de una celda ********************************************************************/ void FlatCoupledCell::setLastValuePortIn( const CellPosition &cellPos, const string &portIn, const Real &value ) { FlatPortValues::iterator cursor = getPortValues().begin(); register bool salgo = false; // search for the (cellPos, portIn) while (!salgo && cursor != getPortValues().end()) if ( cursor->first.cellPos() == cellPos && cursor->first.inPort() == portIn ) salgo = true; else cursor++; // if not exists if (cursor == getPortValues().end() ) { CellDescription *cellDesc = new CellDescription; cellDesc->cellPos( cellPos ); cellDesc->inPort( portIn ); portValues[ *cellDesc ] = value; } else // the entry exists { CellDescription cellDesc; cellDesc.cellPos( cellPos ); cellDesc.inPort( portIn ); portValues[ cellDesc ] = value; } } /******************************************************************* * Function Name: getInputPortValues * Description: obtiene a partir de la lista de valores de los ports * de todas las celdas, una lista con los valores de los * ports de una celda especifica ********************************************************************/ void FlatCoupledCell::getInputPortValues( PortValues *pv, const CellPosition &cellPos, const string &portIn ) { // search for the cellPos for (FlatPortValues::const_iterator cursor = getPortValues().begin(); cursor != getPortValues().end(); cursor++) if ( cursor->first.cellPos() == cellPos ) (*pv)[ cursor->first.inPort() ] = cursor->second; } /******************************************************************* * Function Name: getOutputPorts * Description: obtiene una lista de los puertos de salida de la celda * en cuestion ********************************************************************/ void FlatCoupledCell::getOutputPorts( VirtualPortList **vpl, const CellPosition &cellPos ) { *vpl = &(yList[ cellPos.calculateIndex( dimension() ) ]); // register long posCell = cellPos.calculateIndex( dimension() ); // for (VirtualPortList::const_iterator cursor = yList[posCell].begin(); cursor != yList[posCell].end(); cursor++) // vpl->insert( VirtualPortList::value_type( cursor->first, cursor->second ) ); } /******************************************************************* * Method: externalFunction ********************************************************************/ //Model &FlatCoupledCell::externalFunction( const Time &time, const CellPosition &pos, bool external, Real mtv, const string &portIn ) Model &FlatCoupledCell::localExternalFunction( const CellPosition &pos, const MessageBag &msgBag) { cout << "started executing localExternalFunction for " << pos.print() << endl; CellPosition position = pos; CellPosition dimen = dimension(); Time delay( defaultDelay()); Time actualTime( msgBag.time() ); Real tv; bool executedLocal = false; MessageBag::iterator cursor ; updateNeighborValues(position, msgBag); cout << "FlatCoupledCell::localExternalFunction: after updateNeighborValues" << endl; for ( cursor = msgBag.begin() ; cursor != msgBag.end(); cursor++) { ExternalMessage msg = *((ExternalMessage*)(*cursor)); if( !executedLocal && msg.procId() != -1) { VirtualPortList::const_iterator portCursor = xList[position.calculateIndex(dimen)].begin(); for(; portCursor != xList[position.calculateIndex(dimen)].end() && ( *(portCursor->second) != msg.port() ); portCursor++) ; string portIn = portCursor->first; string functionName = getPortInFunction( position, portIn ); if (functionName == DEFAULT_FUNCTION_InPort) tv = msg.value(); else { VirtualPortList* vpl = new VirtualPortList; getOutputPorts(&vpl, position); NeighborhoodValue* nVal = cellsNeighbors[position.calculateIndex(dimen)]; PortValues *pValues = new PortValues; getInputPortValues(pValues,position, portIn); tv = SingleLocalTransAdmin::Instance().evaluate(functionName,*nVal,pValues,delay, actualTime,vpl,this, portIn); //delete vpl; delete pValues; } executedLocal = true; } else if ( executedLocal && msg.procId() != -1) { cerr << "At : " << msg.time() << endl; cerr << "Warning: current implementation can Not handle multiple external messages !" ; } } if (!executedLocal) { cout << "Evaluating localExternal Function for " << position.print() << endl; LocalTransAdmin::Function idFn( localTransition() ); FunctionZones::iterator funcCursor = funcZones.begin(); while ( funcCursor->first != pos && funcCursor != funcZones.end() ) funcCursor++; if( funcCursor != funcZones.end() ) idFn = funcCursor->second; VirtualPortList* vpl = new VirtualPortList; getOutputPorts( &vpl, position); cout << "before NeighborhoodValue* nVal for " << position.print() << endl; NeighborhoodValue* nVal = cellsNeighbors[position.calculateIndex(dimen)]; cout << "after NeighborhoodValue* nVal for " << position.print() << endl; tv = SingleLocalTransAdmin::Instance().evaluate( idFn, *nVal, NULL, delay, actualTime, vpl, this ) ; cout << " after evaluating tv for " << position.print() << endl; //delete vpl; // cout << " after deleting vpl for " << position.print() << endl; } cout << " tv : " << tv.value() << " for " << position.print() << endl; ///////////////////////////////////////////////////////////////////// if (UseQuantum().Active()) tv = valueWithQuantum(tv, Real(UseQuantum().Value())); ///////////////////////////////////////////////////////////////////// // nTupla dimen( dimension() ); // Replaced all time + delay with nextTime Time nextTime( msgBag.time() + delay ); NextEventList::iterator eventCursor = nextEventList().begin(); NextEventList::iterator lastFound( nextEventList().end() ); // for (; ( cursor->time < nextTime || ( cursor->time == nextTime && *(selectPos(select, &dimen, cursor->pos, false)) < *(selectPos(select, &dimen, pos, false)) ) ) && cursor != nextEventList().end() ; cursor++ ) for (; (eventCursor->time <= nextTime) && (eventCursor != nextEventList().end()); eventCursor++) if (eventCursor->pos == pos) lastFound = eventCursor; // CellPosition *cp = (CellPosition *) &pos; // Real ltv( lastFound == this->nextEventList().end() ? (*cellState())[ *cp ] : lastFound->value ); Real ltv( lastFound == this->nextEventList().end() ? cellsNeighbors[position.calculateIndex(dimen)]->get() : lastFound->value ); if( tv != ltv ) { NextEvent next; next.time = nextTime; next.pos = position; next.value = tv; eventCursor = nextEventList().insert( eventCursor, next ); eventCursor++; cout << "inserted new event for " << position.print() << " @ " << msgBag.time() << endl; if (inertialDelay() && lastFound != nextEventList().end()) nextEventList().erase( lastFound ); // ESTO ESTA MAL. POR ESO FUE COMENTADO //else if (!inertialDelay()) // DEMORA DE TRANSPORTE // for ( ; cursor != nextEventList().end(); cursor++) // if (cursor->pos == pos) // cursor = nextEventList().erase(cursor); } return *this; } FlatCoupledCell &FlatCoupledCell::printStateValues(const Time &time) { nTupla dimen = dimension(); CellPosition counter = CellPosition(dimen.dimension(), 0); CellPosition center = counter; bool overflow = false; while(!overflow) { ( *cellState() )[counter] = (cellsNeighbors[counter.calculateIndex(dimen)])->get(); overflow = counter.next(dimen); } FlatDebug().Stream() << "Time: " << time << endl; cellState()->print( FlatDebug().Stream() ) ; return *this; } FlatCoupledCell::~FlatCoupledCell() { delete select; delete xList; delete yList; delete localPort; delete[] cellsMsgs; register long totalElements = dimension().totalElements(); for (int i = 0 ; i < totalElements ; i++) delete cellsNeighbors[i]; delete[] cellsNeighbors; } Processor &FlatCoupledCell::createProcessor() { return SingleProcessorAdmin::Instance().generateProcessor(this, localProc()); }