//------------------------------------------------------------
// $Id: volumeSet.cc,v 1.1.1.1 1999/11/25 06:26:10 yamauchi Exp $
//------------------------------------------------------------
// 	volume set (objectSetClass から) 
//	(M\pi)^2 
//
//	volume を PE で保持する際に利用するクラス。
//	引数に空間(大域的な空間ではない。このクラスの管理する大きさの
//	配列の index。このクラスは PE のトポロジなどは知らない) の 
//	index を与えるとその空間に属する物体の配列が得られる
// 	実装は空間と速度のトレードオフで変化する予定
//	まずは1次元の配列による
//	objectSet と似ているので template 化を考えるべきだったか? 
//	1998/2/9
//	Copyright (C) 1998 YAMAUCHI Hitoshi 山内 斉
//------------------------------------------------------------
#include "volumeSet.h"
#include "ProcObj.h"

void VolumeSetClass::
init(const IntVec3& aLocalTotalSpcNum)
{
    const int localSpcNumX = aLocalTotalSpcNum.get(IntVec3::X);
    const int localSpcNumY = aLocalTotalSpcNum.get(IntVec3::Y);
    const int localSpcNumZ = aLocalTotalSpcNum.get(IntVec3::Z);
    if((localSpcNumX <= 0) || (localSpcNumY <= 0) || (localSpcNumZ <= 0))
    {
	cerr << "Error! : illegal number of spaces VolumeSetClass::init"
	    << aLocalTotalSpcNum << endl;
	commMpi2_exit(1);
    }
    this->delElems();
    
    this->mpVolList = new SLList < VolumeClass * > [localSpcNumX * 
						    localSpcNumY * 
						    localSpcNumZ];	    
    this->mLocalSpcNum = aLocalTotalSpcNum;
}

/**------------------------------------------------------------
 *  3 dim の index で指定した場所のリストに pVol を加える
 * 	@param a3dIdx  部分空間位置 = spcpos
 *	@param pVol    volume へのポインタ
 *------------------------------------------------------------*/
void VolumeSetClass::
add(const IntVec3& a3dIdx, VolumeClass* pVol)
{
    IntVec3 innerIdx = GpPE->getLocalIdxFromSpcPos(a3dIdx);
    assert(this->localIdxOK(innerIdx) == YES);
    int idx = this->getLocalIdxFromLocalXYZ(innerIdx.get(IntVec3::X),
				innerIdx.get(IntVec3::Y),
				innerIdx.get(IntVec3::Z));
    this->mpVolList[idx].append(pVol);
}

/**------------------------------------------------------------
 *  3 dim の index で指定した場所の volume list を返す
 * 	@param a3dIdx  部分空間位置 spcpos
 *------------------------------------------------------------*/
SLList < VolumeClass * > *VolumeSetClass::
getList(const IntVec3& a3dIdx)
{
    IntVec3 innerIdx = GpPE->getLocalIdxFromSpcPos(a3dIdx);
    assert(this->localIdxOK(innerIdx) == YES);
    int idx = this->getLocalIdxFromLocalXYZ(innerIdx.get(IntVec3::X),
					    innerIdx.get(IntVec3::Y),
					    innerIdx.get(IntVec3::Z));
    return(&(this->mpVolList[idx]));
}

/**------------------------------------------------------------
 *  全ての要素を一つの List として返す．
 *	for(int i = 0; i < aVolumeSet.getTotalLocalSpaceNum(); i++)
 *      {      aVolumeSet.getList(i);	}
 *  のようにすると全ての空間のリストを調べられる
 *
 * 	@param idx  内部表現の配列の index
 *------------------------------------------------------------*/
void VolumeSetClass::
getAllElementAsList(SLList < VolumeClass * > * pRetList)
{
    for(int i = 0; i < this->getTotalLocalSpaceNum(); i++)
    {
	SLList < VolumeClass * > *pPtrcpy = this->getListAs1DimArray(i);
	for(Pix p = pPtrcpy->first(); p != NULL; pPtrcpy->next(p))
	{
	    pRetList->append((*pPtrcpy)(p));
	}
    } 
}


/**------------------------------------------------------------
 *  内部表現の 1 次元配列の index で指定した場所の volume list を返す
 *  これはこの volumeSet に対して全体を見たい時に有用
 *  たとえば，
 *	for(int i = 0; i < aVolumeSet.getTotalLocalSpaceNum(); i++)
 *      {      aVolumeSet.getList(i);	}
 *  のようにすると全ての空間のリストを調べられる
 *
 * 	@param idx  内部表現の配列の index
 *------------------------------------------------------------*/
SLList < VolumeClass * > *VolumeSetClass::
getListAs1DimArray(int idx)
{
    assert((0 <= idx) && (idx < this->getTotalLocalSpaceNum()));
    return(&(this->mpVolList[idx]));
}


/**------------------------------------------------------------
 *  総保持空間数 : 保持している部分空間の数
 *	これは allocation 法によっては担当空間よりも大きい場合がある
 *------------------------------------------------------------*/
int VolumeSetClass::
getTotalLocalSpaceNum(void) const
{
    int axis[3];
    this->mLocalSpcNum.getAsArray(axis);

    return(axis[0] * axis[1] * axis[2]);
}


void VolumeSetClass::
print(void)
{
    for(int z = 0; z < this->mLocalSpcNum.get(IntVec3::Z); z++)
    {
	for(int y = 0; y < this->mLocalSpcNum.get(IntVec3::Y); y++)
	{
	    for(int x = 0; x < this->mLocalSpcNum.get(IntVec3::X); x++)
	    {
		int idx = getLocalIdxFromLocalXYZ(x, y, z);
		if(!(this->mpVolList[idx].empty()))
		{
		    cout << "DEBUG: spcpos " << 
			(this->mpVolList[idx].front())->getSubVolumeSpcPos()
			    << ", id = ";
		    Pix pix;
		    SLList < VolumeClass * > &vlist = this->mpVolList[idx];
		    for(pix = vlist.first(); pix != NULL; vlist.next(pix))
		    {
			cout << vlist(pix)->getID() << " ";
			vlist(pix)->print();
			// vlist(pix)->outVolumeAsPPM(); 確認
		    }
		    cout << "." << endl;
		}
	    }
	}
    }
}
