/*------------------------------------------------------------
 * $Id: PE.cc,v 1.8.2.4 2000/06/28 16:09:57 yamauchi Exp $ 
 *------------------------------------------------------------
 *	PE.cc Processing Element
 *	1996/3/22
 *	Copyright (C) YAMAUCHI Hitoshi 山内 斉
 *	1997/1/21
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "PE.h"
#include "PEStat.h"
#include "config.h"
#include "mpi2communication.h"
#include "Option.h"
#include "volumeFuncs.h"
#include "mpi2_funcs.h"
#include "ProfileMon.h"		// for profiling monitor

class VolumeClass;

//------------------------------------------------------------
// output message functions
//------------------------------------------------------------
void PEoutVerboseMes(int rank, const char *pMes)
{
    if(Option::getInstance()->getVerboseMode() == YES)
    {
	cout << genHd(VERBOSEHEAD, rank) << " " << pMes << endl;
    }
}

void PEoutVerboseMes(const IntVec3& PEid, const char *pMes)
{
    if(Option::getInstance()->getVerboseMode() == YES)
    {
	cout << genHd(VERBOSEHEAD, PEid) << " " << pMes << endl;
    }
}

void PEoutDebugMes(int rank, const char *pMes)
{
    if(Option::getInstance()->getDebugMode() == YES)
    {
	cout << genHd(DEBUGHEAD, rank) << " " << pMes << endl;
    }
}

//------------------------------------------------------------
// 統計情報の出力
//------------------------------------------------------------
void PEClass::
printStatInfo(const char *pStageName)
{
    const char* pMes = genHd(NORMALHEAD, this->getMyRank());
    this->mGStat.print(pMes);
    this->mNIUnit.printStat(pMes, pStageName);
}



//------------------------------------------------------------
// PE
//------------------------------
YorN PEClass::
isRayInValidSpace(const Ray *pOneRay, int pos)
{
    if(this->isDealSpace(pOneRay->getSpcPos()) == NO)
    {	
	cout << "Error! : PE [" << this->getMyRank() << "] get illegal "
	    "ray which has illegal spcpos : call pos " << pos << endl;
	pOneRay->print("Error! ");
	pOneRay->printDDA("Error! ");
	commMpi2_exit(1);
	return(NO);
    }else
    {
	return(YES);	
    }
}


//------------------------------
// 送信操作
//------------------------------
YorN PEClass::
flushSendRaysBuffer(void)
{
    if(this->mNIUnit.flushSendRaysBuff() == YES)
    {
	this->toBusy();
	return(YES);
    }else
    {
	return(NO);
    }
}

//------------------------------
// 受信操作
//------------------------------
void PEClass::
recvRays(void)
{
    if(this->mNIUnit.recvRays() == YES)
    {
	this->toBusy();
    }
}

//------------------------------
// set a ray to the Network Interface Unit
//------------------------------
void PEClass::
setRayToNI(Ray* pRay)
{
    assert(pRay->isOK());
    IntVec3 PEid = 
    	this->mNIUnit.mpSpc2PE->getPEIDfromSpcPos(pRay->getSpcPos());
    const int toPERank = this->getRank(PEid);
    if(toPERank == this->mMyRank)
    {
	this->setRayPtrToThisPE(pRay);
    }else
    {
	this->mNIUnit.sendRays(pRay, toPERank);
    }
}

//------------------------------------------------------------
// 輝度情報の送信
//------------------------------
void PEClass::
insertIntensityIntoBuffer(Ray *pRay)
{
    int scrX = pRay->getScreenPosX();
    int scrY = pRay->getScreenPosY();
    assert(scrX >= 0);
    assert(scrY >= 0);
    const Vector3 color = pRay->getColor();

    if((color.get(Vector3::X) > 0.0) ||
       (color.get(Vector3::Y) > 0.0) ||
       (color.get(Vector3::Z) > 0.0))
    {
	if(Option::getInstance()->getDebugMode() == YES)
	{
#ifdef TRACE_RAY
	    cout << genHd(DEBUGHEAD, this->getMyRank()) << "send FB ray " 
	    	<< pRay->getID() << endl;
#endif
	}
	IntensityClass *pIntensity = new IntensityClass(scrX, scrY, color);
	this->mNIUnit.sendIntensity(pIntensity);
    }
}


//------------------------------
// initRankNID 
//------------------------------
void PEClass::
initRankNID(void)
{
    int myrank = SysStat::getInstance()->getMyRank();
    IntVec3 pe = this->mSysInfo.getPEDim();
    const int PEx = pe.get(IntVec3::X);
    const int PEy = pe.get(IntVec3::Y);

    int idx, idy, idz;
    idz = myrank / (PEx * PEy);
    idy = (myrank - (idz * (PEx * PEy))) / PEx;    
    idx = myrank - (idy * PEx) - (idz * (PEx * PEy));
    IntVec3 id(idx, idy, idz);

    this->mID = id;
    this->mMyRank = myrank;
}


//------------------------------
// PE と PE の各ユニットの初期化
//------------------------------
void PEClass::
initInternalUnits(void)
{
    this->initRankNID();
    this->initSpc2PE();
    Vector3 partmin = this->mSpcParam.getPartVolumeMin();

    int idxMin[3], idxMax[3];
    for(int i = 0; i < 3; i++)
    {
	idxMin[i] = (this->mSpcParam.getMinDefSpcIdx()).get(i);
	idxMax[i] = (this->mSpcParam.getMaxDefSpcIdx()).get(i);
    }

    int frustum_base_square_edge = this->mViewData.getFrustumResX();
    this->mFrustum.init(frustum_base_square_edge);

    this->mDDAUnit.
	initWithoutObjInSpcMap(partmin, 
			       this->mSpcParam.getCellLen(),
			       idxMin, idxMax,
			       this->mSysInfo.getRayPropSkipMethod(),
			       this->mSysInfo.getSystemNetworkType());

    // for PRC method
    this->mPRCUnit.
	initWithoutObjInSpcMap(partmin, 
			       this->mSpcParam.getCellLen(),
			       idxMin, idxMax,
			       this->mSysInfo.getRayPropSkipMethod(),
			       this->mSysInfo.getSystemNetworkType());
}


//------------------------------
// 全ての object と material が分配されたので
// 内部で利用しやすいように変形する。
//------------------------------
void PEClass::
getHavingSubSpcNum(int subspcNumInThisPE[])
{
    int subdivnum   = this->mSpcParam.getSubDivNum();
    subspcNumInThisPE[0] = subdivnum;
    subspcNumInThisPE[1] = subdivnum;
    subspcNumInThisPE[2] = subdivnum;

    if(this->mSysInfo.getAllocationScheme() != Random_Alloc)
    {
	IntVec3 PEdim   = this->mSysInfo.getPEDim();
	assert((subdivnum % PEdim.get(IntVec3::X) == 0) && 
	       (subdivnum % PEdim.get(IntVec3::Y) == 0) && 
	       (subdivnum % PEdim.get(IntVec3::Z) == 0));

	subspcNumInThisPE[0] = subdivnum / PEdim.get(IntVec3::X);
	subspcNumInThisPE[1] = subdivnum / PEdim.get(IntVec3::Y);
	subspcNumInThisPE[2] = subdivnum / PEdim.get(IntVec3::Z);
    }else
    {
	// random alloc では各 PE の保持するだけの local な部分空間を
	// 圧縮して持つことが難しいので分割数だけ持つ
    }
}    

void PEClass::
initObjectSet(void)
{
    int subspcInPE[3];
    this->getHavingSubSpcNum(subspcInPE);
    
    int ***objNumInSubSpc = new int**[subspcInPE[0]];
    int ii, jj;
    for(ii = 0; ii < subspcInPE[0]; ii++)
    {
	objNumInSubSpc[ii] = new int* [subspcInPE[1]];
	for(jj = 0; jj < subspcInPE[1]; jj++)
	{
	    objNumInSubSpc[ii][jj] = new int[subspcInPE[2]];
	}
    }
    int x, y, z;
    for(x = 0; x < subspcInPE[0]; x++) // init counter
    {
	for(y = 0; y < subspcInPE[1]; y++)
	{
	    for(z = 0; z < subspcInPE[2]; z++)
	    {
		objNumInSubSpc[x][y][z] = 0;
	    }
	}
    }

    Pix pix;
    for(pix = this->mObjList.first(); pix != NULL;  this->mObjList.next(pix))
    {
	const IntVec3 localSpc = 
	    this->mNIUnit.mpSpc2PE->getLocalIdxFromSpcPos(this->mObjList(pix)->
							  getSpcPos());
	int lsubx = localSpc.get(IntVec3::X);
	int lsuby = localSpc.get(IntVec3::Y);
	int lsubz = localSpc.get(IntVec3::Z);
	objNumInSubSpc[lsubx][lsuby][lsubz]++;
    }
    
    if(Option::getInstance()->getVerboseMode() == YES)
    {
	cout << genHd(VERBOSEHEAD, this->getID()) 
	     << "One PE allocated subspace [" << subspcInPE[0] << "][" 
	     << subspcInPE[1] << "][" << subspcInPE[2] << "]" << endl; 
    }

    this->mObjectSet.init(IntVec3(subspcInPE[0], subspcInPE[1],subspcInPE[2]));
    for(x = 0; x < subspcInPE[0]; x++) 
    {
	for(y = 0; y < subspcInPE[1]; y++)
	{
	    for(z = 0; z < subspcInPE[2]; z++)
	    {
		//----- debug 
		//static IntVec3 localIdx;
		//localIdx.set(x, y, z);
		//cout << "// PE [" << this->getMyRank() << "] set localIdx "
		//    << localIdx << ", length " << objNumInSubSpc[x][y][z] 
		//	<< endl;
		//----- debug 
		this->mObjectSet.
			setLengthWithLocalIdx(IntVec3(x, y, z), 
					      objNumInSubSpc[x][y][z]); 
	    }
	}
    }
    for(pix = this->mObjList.first(); pix != NULL;  this->mObjList.next(pix))
    {
	const IntVec3 sp = this->mObjList(pix)->getSpcPos();
	this->mObjectSet.add(sp, this->mObjList(pix));
    }
    for(ii = 0; ii < subspcInPE[0]; ii++)
    {
	for(jj = 0; jj < subspcInPE[1]; jj++)
	{
	    delete [] objNumInSubSpc[ii][jj];
	}
	delete [] objNumInSubSpc[ii];
    }
}


//------------------------------
// initialize object and material set
//------------------------------
void PEClass::
initObjectMaterialSet(void)
{
    // object 
    //----- DEBUG from
    ElapsedTimerClass etimer; 	
    etimer.start();
    //----- DEBUG to
    this->initObjectSet();
    //----- DEBUG from 
    etimer.stop();		
    outPEEtime(" for initialize object set.", etimer);
    //----- DEBUG to

    // material 
    int matLenMax = this->mMatList.length();
    assert(matLenMax >= 0);
    if(matLenMax == 0)
    {
	PEoutVerboseMes(this->getID(), "No material and geometry");
	return;
    }
    
    this->mMaterialSet.init();
    this->mMaterialSet.setLength(matLenMax);
    Pix pix;
    int i;
    for(pix = this->mMatList.first(), i = 0; 
	pix != NULL; 
	this->mMatList.next(pix), i++)
    {
	assert(i < matLenMax);
	this->mMaterialSet.set(&(this->mMatList(pix)), i);
    }
    
    if(Option::getInstance()->getVerboseMode() == YES)
    {
	cout << genHd(VERBOSEHEAD, this->getID()) << "inited {obj|mat} "
		"set done. obj = " << this->mObjList.length() << 
		", mat = " << this->mMatList.length() << endl;
    }
    
    if(Option::getInstance()->getDebugMode() == YES)    
    {
	const char *pH = genHd(DEBUGHEAD, this->getMyRank());
	cout << pH << "'T' PE has space, '.' PE has not space" << endl;
	int x, y, z;
	for(z = 0; z < this->mSpcParam.getSubDivNum(); z++)
	{
	    for(y = 0; y < this->mSpcParam.getSubDivNum(); y++)
	    {
		cout << pH;
		for(x = 0; x < this->mSpcParam.getSubDivNum(); x++)
		{
		    if(this->mID == 
		       (this->mNIUnit).mpSpc2PE->
		       getPEIDfromSpcPos(IntVec3(x, y, z))) 
		    {
			cout << "T"; // 担当空間
		    }else
		    {
			cout << "."; // 担当していない空間
		    }
		}
		cout << endl;
	    }
	    cout << endl;
	}
    }
}

//------------------------------
// 受信した物体の情報を出力する
//------------------------------
void PEClass::
outRecvObjectInfo(void)
{
    cout << NORMALHEAD << " PE : r " << this->getMyRank();
    cout << " : object diststat : num " << this->mObjList.length();
    
    // 総空間数
    int 	numberOfTotalSpace 	= -1;
    double 	average			= -1.0;
    double      variance		= -1.0;
    int		noObjectSpaces		= -1;
    double  	noObjSpaceAverage	= -1.0;
    double	noObjSpaceVariance	= -1.0; 
    
    this->mObjectSet.getStat(&numberOfTotalSpace,
			     &average,	      	 &variance,	      
			     &noObjectSpaces,   
			     &noObjSpaceAverage, &noObjSpaceVariance); 
    cout << " spc " << numberOfTotalSpace;
    cout << " av "  << average << " V " << variance;
    cout << " noObj " << noObjectSpaces;
    cout << " NObjav " << noObjSpaceAverage << " NV " << noObjSpaceVariance;
    cout << endl;
}

//------------------------------
// global load balancing を行なう
//------------------------------
void PEClass::
globalLoadBalance(void)
{
    if(this->mSendingRayStopComToHost == YES)
    {
	if(this->mRayPtrQueue.length() < this->mSysInfo.getResumeRayNums())
	{
	    PEStatClass *pPEstat = new PEStatClass();
	    pPEstat->setResumeGenRay(this->getMyRank());
	    
	    this->mNIUnit.mSendPEStatBuf.
	    	enqNewedObjwithMaySend(pPEstat, 
				       SysStat::getInstance()->getHostRank());
	    this->mSendingRayStopComToHost = NO;
// 	    cout << "DEBUG suspend r = " << this->getMyRank() << ", " << 
// 		this->mRayPtrQueue.length() << "/" << 
// 		    this->mSysInfo.getResumeRayNums() << endl;
	}
    }else
    {
	if(this->mRayPtrQueue.length() > this->mSysInfo.getSuspendRayNums())
	{
	    PEStatClass *pPEstat = new PEStatClass();
	    pPEstat->setStopGenRay(this->getMyRank());

	    this->mNIUnit.mSendPEStatBuf.
	    	enqNewedObjwithMaySend(pPEstat, 
				       SysStat::getInstance()->getHostRank());
	    this->mSendingRayStopComToHost = YES;
// 	    cout << "DEBUG suspend r = " << this->getMyRank() << ", " << 
// 		this->mRayPtrQueue.length() << "/" << 
// 		    this->mSysInfo.getSuspendRayNums() << endl;
	}
    }
}

//------------------------------------------------------------
// radiosity and ray-tracing common code
//------------------------------------------------------------
void PEClass::
toBusy(void)
{
    if(this->mIsIdle == YES)
    {
#ifndef REDUCE_VERBOSE_INFO
	if(Option::getInstance()->getOutPEmove() == YES)
	{		
	    cout << "// ## PE [" << this->getMyRank() << "]: B" << endl;
	}
#endif
	this->mIsIdle = NO;
	pm_change_stat(PC_proc_ray_e);
	this->sendHostToThisPEIsBusy(YES);
    }
}

//------------------------------
// if busy then change to idle and send idle status to Host
//------------------------------
void PEClass::
toIdle(void)
{
    if(this->mIsIdle == NO)
    {
#ifndef REDUCE_VERBOSE_INFO
	if(Option::getInstance()->getOutPEmove() == YES)
	{	
	    cout << "// ## PE[" << this->getMyRank() << "]:I" << endl;
	}
#endif
	this->mIsIdle = YES; 
	pm_change_stat(PC_idle_e);
	this->sendHostToThisPEIsBusy(NO);
    }
}

//------------------------------------------------------------
// 交差点が担当部分空間内部に存在するのか?
//------------------------------------------------------------
YorN PEClass::
checkHitPosIsInThisSpcPos(const Vector3& hitpoint, const IntVec3& spcidx) const
{
    const Vector3 partvolMin(this->mSpcParam.getPartVolumeMin());
    const double  celllen = this->mSpcParam.getCellLen();
    for(int i = 0; i < 3; i++)
    {
	if(((int)((hitpoint.get(i) - partvolMin.get(i)) / celllen)) != 
	   spcidx.get(i))
	{
	    return(NO);
	}
    }
    return(YES);
}

//------------------------------
// ray tracing or radiosity 終了か 
//------------------------------
#ifdef FOR_STANDALONE	
YorN PEClass::
isMultiPassStageEnd(void)
{     			
    if((this->mRayPtrQueue.empty() 	== Q_NOT_EMPTY) || // 1
       (this->mRadPatchQueue.empty()	== Q_NOT_EMPTY) || // 2
       (this->mRayTrFRGUnit.canGenerateNextRay() == YES))  // 3
    {
	return(NO);
    }else
    {
	return(YES);	    
    }
}
#endif

//------------------------------
// host にこの PE の状態を伝える
//------------------------------
void PEClass::
sendHostToThisPEIsBusy(YorN IsThisPEBusy)
{
    PEStatClass *pPEstat = new PEStatClass();
    if(IsThisPEBusy == YES)
    {
	pPEstat->setBusy(this->getMyRank());
    }else
    {
	pPEstat->setIdle(this->getMyRank());	
    }

    this->mNIUnit.mSendPEStatBuf.
    	enqNewedObjwithMaySend(pPEstat, SysStat::getInstance()->getHostRank());
}

//------------------------------
// host から command を受信し、解釈する。
//------------------------------
int PEClass::
probNgetHostCommand(void)
{
    this->mNIUnit.recvHostComm();
    if(this->mHostCommRecvQueue.length() == 0)
    {
	return(HOSTCOM_ELSE_e);
    }
    
    assert(this->mHostCommRecvQueue.length() > 0);
    HostCommClass *pHc = this->mHostCommRecvQueue.deq();
    HostCommClass hcomm = (*pHc);
    delete pHc;	

    switch(hcomm.getCommand())
    {
    case HOSTCOM_End_Radiosity_e: 
	this->mIsMultiPassStageOver = YES;
	break;
	
    case HOSTCOM_End_PrepareShading_e: 	
	this->mIsPrepareShadingOver = YES;
	break;
	
    case HOSTCOM_End_Raytrace_e: 	
	this->mIsMultiPassStageOver = YES;
	break;
	
    case HOSTCOM_Issue_BarrierSync_e: 	
	// now do nothing
	break;
	
    case HOSTCOM_Suspend_GenNewRays_e: // 大域負荷分散
	this->mIsStopGenNewRay = YES;
	break;
	
    case HOSTCOM_Resume_GenNewRays_e: // 大域負荷分散
	this->mIsStopGenNewRay = NO;
	break;

    case HOSTCOM_Send_Patch_Descriptions_e: // ホストからのパッチ情報の送信要求
	{
	    this->sendOutRadioResultToHost();
	}
	break;
	
    default:
	cout << "Internal Error! : PE:: r " << this->getMyRank() << 
	    "PEClass::getHostCommand received illegal host command" << endl;
	this->exitprog();
	break;
    }

    if(Option::getInstance()->getDebugMode() == YES)
    {
	cout << genHd(DEBUGHEAD, this->getMyRank()) << "get " << 
		(hcomm.toString()) << endl;
    }
    
    return(hcomm.getCommand());
}

//------------------------------
// 物体が或る空間に存在するか : radiosity, ray-tracing 共通
//------------------------------
YorN  PEClass::
isObjectInSpc(const IntVec3 &spcpos)
{
    switch(this->mSysInfo.getRayPropSkipMethod())
    {
    case NoSkip_rayprop:
    case SobokuSkip_rayprop:
	return(this->mDDAUnit.isObject(spcpos));
	break;

    case ProximityClouds_rayprop:
	return((this->mPRCUnit.isObject(spcpos) == 0) ? NO : YES);
	break;
	
    default:
	cout << "Internal Error! : PEClass::isObjectInSpc : illegal "
		"skip method." << endl;
	this->exitprog();
	return(NO);
	break;
    }

    cout << "Internal Error! : never Reach Here: PEClass::isObjectInSpc()" 
    	 << endl;
    this->exitprog();
    return(NO);			// AIX warn without this return
}


//------------------------------------------------------------
// public functions
//------------------------------------------------------------
PEClass::
PEClass(void)
{
    //------------------------------
    // system, hardware, rendering parameters
    //------------------------------
    this->mID 		= IllegalPEID;
    this->mMyRank	= -1;
    //     this->mSysinfo;	
    //     this->mViewData;
    //     this->mSpcParam;

    //------------------------------
    // ray generator for radiosity delta-radiosity 
    //------------------------------
    this->mpHemiCube 	= NULL;
    this->mppRadiosityRays	= NULL;

    //------------------------------
    // ray generator for ray-tracing 
    //------------------------------
    // 	   this->mRayTrFRGUnit;

    //------------------------------
    // Local memory contents of this PE 
    //------------------------------
    //	   this->mObjList;
    //     this->mObjectSet;	
    // 	   this->mVolList;  
    //     this->mVolSet;    
    //	   this->mMatList;
    //     this->mMaterialSet;	
    //     this->mRayPtrQueue;
    //     this->mRadPatchQueue;
    //     this->mIntVerPtrQueue;

    //------------------------------
    // DDA 部分
    //------------------------------
    // 	   this->mDDAUnit;
    //     this->mNIUnit;

    //------------------------------
    // processor status 
    //------------------------------
    this->mIsMultiPassStageOver = NO;
    this->mIsPrepareShadingOver = NO;
    this->mIsIdle		= NO; // 最初は Busy
    this->mIsStopGenNewRay	= NO; // ray 発生を停止中
    this->mSendingRayStopComToHost = NO; // ray 停止の要求は最初なし

    //------------------------------
    // for PRC method
    //------------------------------
    // this->mPRCUnit;	       NIN

#ifdef COUNT_SKIP_SPACE		// herehere
    this->mSkipSpcOfRays	= 0.0;
    this->mTravSpcOfRays	= 0.0;
#endif
}

//------------------------------
// destruct PE
//------------------------------
PEClass::
~PEClass(void)
{
}

//------------------------------
// この PE の serial ID を得る
//------------------------------
int PEClass::
getMyRank(void) const
{
    assert(this->mMyRank >= 0);
    assert(this->mMyRank < SysStat::getInstance()->getCommSize());    
    
    return(this->mMyRank);
}

//------------------------------
// get Rank (hostComputerClass:: にもある)
//    PE の id から serial ID を得る
//------------------------------
int PEClass::
getRank(const IntVec3& PEid) const
{
    int rank = 
	this->mSysInfo.getPEDim().get(IntVec3::X) * 
	 (PEid.get(IntVec3::Z) * this->mSysInfo.getPEDim().get(IntVec3::Y)
	  + PEid.get(IntVec3::Y)) + PEid.get(IntVec3::X);
    return(rank);
}

//------------------------------
// set view data 
//------------------------------
void PEClass::
setViewData(const ViewDataClass& aViewdata)
{
    this->mViewData = aViewdata;
}

//------------------------------------------------------------
// set and delete objects and materials
//------------------------------------------------------------
void PEClass::
addOneMaterial(materialClass *pMat)
{
    cout << "NIN PEClass::addOneMaterial" << (*pMat) << endl;
}

void PEClass::
addOneObject(objBaseClass *pObj)
{
    cout << "NIN PEClass::addOneObject" << endl;    
    pObj = NULL;
}

//------------------------------
// prepare shading operartion
//------------------------------
void PEClass::
doPrepareShading(void)
{
    ProfileMon::getInstance()->startStage(ProfileMon::ProfSt_prepareShading);
    switch(this->mSysInfo.getShadingScheme())
    {
    case FlatShading:
	// flat shading ではすることはない
	break;
    case GouroudShading:
	this->initPrepareShadingStage(); // stage の処理 start
	this->prepareGouroudShading();
	this->finalizePrepareShadingStage();
	break;
    default:
	cout << "Error!: I don't know such shading scheme. " << 
	    this->mSysInfo.getShadingScheme() << endl;
	this->exitprog();
    }
    ProfileMon::getInstance()->endStage(ProfileMon::ProfSt_prepareShading);
}


//------------------------------
// 全体のバリア同期 : host は time out あり失敗すると exit
//------------------------------
void PEClass::
barrierSync(void)
{
    static int syncID = 0;	// 何回目の barrierSync かを示す
    pm_change_area(PA_sync_wait_e);

    // 同期命令発行
    commMpi2_Barrier();
    pm_change_area(PA_sync_done_e);    
    syncID++;
}    

//------------------------------------------------------------
// print out routine
//------------------------------------------------------------
void PEClass::
printSysInfo(const char *pHead)
{
    cout << pHead << "----- sysinfo ----- PE ID = " << this->mID << endl;
    this->mSysInfo.print(pHead);
    cout << pHead << "----- view data" << endl;	
    this->mViewData.print(pHead);
    cout << pHead << "----- space paramater" << endl;	
    this->mSpcParam.print(pHead);
}

void PEClass::
printObjects(const char *pHead)
{
    cout << pHead << "----- object ----- PE ID = " << this->mID << endl;
    Pix i;
    for(i = this->mObjList.first(); i != NULL; this->mObjList.next(i))
    {
	cout << pHead << " ";
	this->mObjList(i)->print("// -");
    }
}

void PEClass::
printMaterials(const char *pHead)
{
    cout << pHead << "----- material ----- PE ID = " << this->mID << endl;
    Pix i;
    for(i = this->mMatList.first(); i != NULL; this->mMatList.next(i))
    {
	cout << pHead << " " << this->mMatList(i) << endl;
    }
}

//------------------------------
// 空間情報を出力(各 PE は skip のために全空間分持っている)
//------------------------------
void PEClass::
printObjInSpcMap(const char *pHead)
{
    cout << pHead << "----- obj in subspace map ----- PE ID = " << 
	this->mID << endl;

    char buf[256];
    sprintf(buf, "%s PE:: %d", pHead, mMyRank);

    // tokunaga changed
    switch(this->mSysInfo.getRayPropSkipMethod())
    {
    case NoSkip_rayprop:
    case SobokuSkip_rayprop:
	printObjInSpcMapCommon(buf, this->mDDAUnit.mObjInSpcMap);
	break;
    case ProximityClouds_rayprop:
	printObjInSpcMapCommon(buf, this->mPRCUnit.mObjInSpcMap);
	break;
    default:
	cout << "Error! : can't print objects in subspace map."<< endl;
	this->exitprog();
	break;
    }
}


//------------------------------
// この PE の担当空間か
//------------------------------
YorN PEClass::
isDealSpace(const IntVec3& spcpos) const
{
    if(this->mID == this->mNIUnit.mpSpc2PE->getPEIDfromSpcPos(spcpos))
    {
 	return(YES);
    }else
    {
	return(NO);
    }
}
  
//------------------------------
// initSpc2PE
//------------------------------
void PEClass::
initSpc2PE(void)
{
    if(this->mID == IllegalPEID)
    {
	cerr << "Error! : this PE has not initialized ID, yet " << 
	    this->mID << endl;
	this->exitprog();
    }

    switch(this->mSysInfo.getAllocationScheme())
    {
    case Block_Alloc:
    {
	spc2PEBlockClass *pTmpSpc2PE = new spc2PEBlockClass;
	pTmpSpc2PE->init(this->mSysInfo.getPEDim(), 
			 this->mSpcParam.getSubDivNum(),
			 this->mID);
	this->mNIUnit.mpSpc2PE = pTmpSpc2PE;
    }
	break;

    case Distributed_Alloc:
    {
	spc2PEDistributeClass *pTmpSpc2PE = new spc2PEDistributeClass;
	pTmpSpc2PE->init(this->mSysInfo.getPEDim(), 
			 this->mSpcParam.getSubDivNum(),
			 this->mID);
	this->mNIUnit.mpSpc2PE = pTmpSpc2PE;	
    }
	break;	

    case Skewed_Alloc:
    {
	spc2PESkewClass *pTmpSpc2PE = new spc2PESkewClass;
	pTmpSpc2PE->init(this->mSysInfo.getPEDim(), 
			 this->mSpcParam.getSubDivNum(),
			 this->mID);
	this->mNIUnit.mpSpc2PE = pTmpSpc2PE;
    }
	break;

    case Random_Alloc:
    {
	spc2PERandomClass *pTmpSpc2PE = new spc2PERandomClass;
	pTmpSpc2PE->init(this->mSysInfo.getPEDim(), 
			 this->mSpcParam.getSubDivNum(),
			 this->mID);
	this->mNIUnit.mpSpc2PE = pTmpSpc2PE;
    }
	break;

    default:
	cerr << "Error! : no such allocation scheme PEClass::init" << endl;
	this->exitprog();
	break;
    }
}
