Particle_Index ParticleMovementHandler_FindFreeSlotAndPrepareForInsertion( ParticleCommHandler* self )
{
	Particle_Index	lParticle_I = 0;

	if ( self->shadowParticlesLeavingMeUnfilledCount > 0 ) {
		Journal_DPrintfL( self->debug, 3, "Still %d holes available from "
			"particles leaving via shadow cells\n-> free slot to add into is %d\n",
			self->shadowParticlesLeavingMeUnfilledCount,
			self->shadowParticlesLeavingMeIndices[self->currShadowParticleLeavingMeIndex]);
			
		lParticle_I = self->shadowParticlesLeavingMeIndices[self->currShadowParticleLeavingMeIndex];

		self->currShadowParticleLeavingMeIndex++;
		self->shadowParticlesLeavingMeUnfilledCount--;
	}
	else if ( self->particlesOutsideDomainUnfilledCount ) {
		Journal_DPrintfL( self->debug, 3, "Still %d holes available from "
			"particles leaving domain direct\n-> free slot to add into is %d\n", 
			self->particlesOutsideDomainUnfilledCount,
			self->particlesOutsideDomainIndices[self->currParticleLeavingMyDomainIndex]);

		lParticle_I = self->particlesOutsideDomainIndices[self->currParticleLeavingMyDomainIndex];

		self->currParticleLeavingMyDomainIndex++;
		self->particlesOutsideDomainUnfilledCount--;
	}
	else {
		Journal_DPrintfL( self->debug, 3, "No holes left from leaving "
			"particles\n-> slot to insert into is end of array %d\n", 
			self->swarm->particleLocalCount );
		lParticle_I = self->swarm->particleLocalCount;
		/*
		if ( self->swarm->particleLocalCount == self->swarm->particlesArraySize ) {
			Journal_DPrintfL( self->debug, 3, "Particles array memory used up "
				"-> increasing from %d entries by %d\n",
				self->swarm->particlesArraySize, self->swarm->particlesArrayDelta );
			self->swarm->particlesArraySize += self->swarm->particlesArrayDelta;
			self->swarm->particles = Memory_Realloc_Array_Bytes(
				self->swarm->particles,
				self->swarm->particleExtensionMgr->finalSize,
				self->swarm->particlesArraySize );
		}
		*/
		self->swarm->particleLocalCount++;
		Swarm_Realloc( self->swarm );
	}

	return lParticle_I;
}
예제 #2
0
PyObject* GeneralSwarm_AddParticlesFromCoordArray( void* swarm, Index count, Index dim, double* array )
{
    GeneralSwarm* self  = (GeneralSwarm*)swarm;
    unsigned* cellArray = Memory_Alloc_Array( unsigned, count, "GeneralSwarm_AddParticlesFromCoordArray_CellArray" );
    GlobalParticle localParticle;
    GlobalParticle* particle = &localParticle;
    int cellLocalCount  = self->cellLocalCount;
    int oldParticleCount = self->particleLocalCount;
    int ii;
    int totsLocalParticles=0;
    
    // find which particles are local. we do this to avoid swarm reallocs.
    for (ii=0; ii<count; ii++) {
        memcpy(&(particle->coord), array + dim*ii, dim*sizeof(double));
        cellArray[ii] = CellLayout_CellOf( self->cellLayout, particle );
        if( cellArray[ii] < cellLocalCount )
            totsLocalParticles++;

    }
    // alloc particle local index array (to be returned)
    int* partLocalIndex = Memory_Alloc_Array( int, count, "GeneralSwarm_AddParticlesFromCoordArray_CellArray" );
    // ok, lets add them to the swarm, now that we know how many are required
    self->particleLocalCount += totsLocalParticles;
    Swarm_Realloc( self );
    int newPartIndex = oldParticleCount;
    for (ii=0; ii<count; ii++) {
        if( cellArray[ii] < cellLocalCount ){
            particle = (GlobalParticle*)Swarm_ParticleAt( self, newPartIndex );
            memcpy(&(particle->coord), array + dim*ii, dim*sizeof(double));
            Swarm_AddParticleToCell( swarm, cellArray[ii], newPartIndex );
            partLocalIndex[ii] = newPartIndex;
            newPartIndex++;
        } else {
            partLocalIndex[ii] = -1;
        }
    }
 
    /* create numpy array to return */
    npy_intp dims[1] = { count };
    PyObject* pyobj = PyArray_New(&PyArray_Type, 1, dims, NPY_INT, NULL, (void*)partLocalIndex, sizeof(int), 0, NULL);
    /* enable the owndata flag.. this tells numpy to dealloc the data when it is finished with it */
#if NPY_API_VERSION < 0x00000007
    (((PyArrayObject*)pyobj)->flags) = NPY_ARRAY_OWNDATA;
#else
    PyArray_ENABLEFLAGS((PyArrayObject*)pyobj, NPY_ARRAY_OWNDATA);
#endif
    return pyobj;
}
예제 #3
0
int GeneralSwarm_AddParticle( void* swarm, Index dim, double xI, double xJ, double xK )
{
    GeneralSwarm* self  = (GeneralSwarm*)swarm;
    GlobalParticle localParticle;
    GlobalParticle* particle = &localParticle;
    unsigned cell;
    int newPartIndex; 


   /* If the location is not local, return immediately with index value -1 */
      
   particle->coord[ I_AXIS ] = xI;
   particle->coord[ J_AXIS ] = xJ;
   if(dim == 3)
      particle->coord[ K_AXIS ] = xK;

   cell = CellLayout_CellOf( self->cellLayout, particle );
   if( cell >= self->cellLocalCount )
      return (-1);

   /* Otherwise we allocate the particle to the Swarm and return the new index */

   newPartIndex = self->particleLocalCount;

   self->particleLocalCount ++;
   Swarm_Realloc( self );

   particle = (GlobalParticle*)Swarm_ParticleAt( self, newPartIndex );

   particle->coord[ I_AXIS ] = xI;
   particle->coord[ J_AXIS ] = xJ;
   if(dim==3)
      particle->coord[ K_AXIS ] = xK;

   Swarm_AddParticleToCell( self, cell, newPartIndex );

   return(newPartIndex);
    
}
void ParticleMovementHandler_FillRemainingHolesInLocalParticlesArray( ParticleCommHandler* self )
{
	Particle_Index		prevParticlesArraySize = self->swarm->particlesArraySize;
	Particle_Index		numHolesToFill;
	Particle_InCellIndex	cParticle_I;
	StandardParticle*	oldPtrToMovedParticle;
	Cell_LocalIndex		owningCell;
	Particle_Index		indexToInsertAt;
	Particle_Index*		leavingParticlesArray = NULL;
	Index			currLeavingParticleArrayEntry = 0;
	Index			highestLeavingParticleArrayEntry;
	Index			leavingParticlesUnfilledCount = 0;
	Particle_Index		highestLeavingParticleIndex;
	Particle_Index		candidateParticleToMove;
	Bool			finishedFlag = False;
	Bool			mergedArrayCreated = False;
	Particle_Index		prevParticleCount = self->swarm->particleLocalCount;
	
	Journal_DPrintf( self->debug, "In %s():\n", __func__ );
	Stream_IndentBranch( Swarm_Debug );

	numHolesToFill = self->particlesOutsideDomainUnfilledCount + self->shadowParticlesLeavingMeUnfilledCount;
	if ( numHolesToFill == 0 ) {
		Journal_DPrintfL( self->debug, 2, "No holes to fill -> nothing to do, returning.\n" );
		Stream_UnIndentBranch( Swarm_Debug );
		return;
	}
	#if DEBUG
	if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
		ParticleMovementHandler_PrintParticleSlotsYetToFill( self );
	}	
	#endif

	/* work out the list we have to iterate over: */
	if ( self->shadowParticlesLeavingMeUnfilledCount && !self->particlesOutsideDomainUnfilledCount ) {
		Journal_DPrintfL( self->debug, 2, "Particles have only left via shadow cells -> no need to merge lists\n" );
		leavingParticlesArray = &self->shadowParticlesLeavingMeIndices[self->currShadowParticleLeavingMeIndex];
	}
	else if ( self->particlesOutsideDomainUnfilledCount && !self->shadowParticlesLeavingMeUnfilledCount ) {
		Journal_DPrintfL( self->debug, 2, "Particles have only left domain directly -> no need to merge lists\n" );
		leavingParticlesArray = &self->particlesOutsideDomainIndices[self->currParticleLeavingMyDomainIndex];
	} 
	else {
		Journal_DPrintfL( self->debug, 2, "Particles have left both via shadow cells and domain directly -> merge lists\n" );
		leavingParticlesArray = ParticleMovementHandler_MergeListsOfUnfilledParticleSlots( self );
		mergedArrayCreated = True;
	}

	/* Ok: while there are holes left to fill, find the highest candidate, move it, and reduce the count. */
	Journal_DPrintfL( self->debug, 2, "Starting run through the %d particles to fill:\n", numHolesToFill );
	Stream_IndentBranch( Swarm_Debug );

	currLeavingParticleArrayEntry = 0;
	highestLeavingParticleArrayEntry = numHolesToFill-1;
	leavingParticlesUnfilledCount = numHolesToFill;

	while ( leavingParticlesUnfilledCount > 0 ) {

		indexToInsertAt = leavingParticlesArray[currLeavingParticleArrayEntry];
		Journal_DPrintfL( self->debug, 3, "Attempting to fill leaving slot %d (at particle index %d):\n",
			currLeavingParticleArrayEntry, indexToInsertAt );

		Stream_Indent( self->debug );

		/* This is where we work out the index of which particle to move into the free slot.
		 * We Start from the end of the particles array, then decrement by 1 until we find a candidate that
		 * hasn't itself already left. 
		 * We also need to consider the possibility that every candidate higher than the current index
		 * has also left, in which case we are done, and finish the while process. 
		 * See the ParticleCommHandler Twiki page for diagrams illustrating this algorithm.
		 */

		candidateParticleToMove = self->swarm->particleLocalCount-1;
		highestLeavingParticleIndex = leavingParticlesArray[highestLeavingParticleArrayEntry];
		Journal_DPrintfL( self->debug, 3, "Searching for highest particle that hasn't also moved:\n" );
		Stream_Indent( self->debug );	

		while ( candidateParticleToMove == leavingParticlesArray[highestLeavingParticleArrayEntry] ) {
			/* Check if that was the last candidate particle above the current one: */
			/* This test needs to be at the top of this loop to handle the case where we have one
			particle that's leaving */

			if ( candidateParticleToMove <= indexToInsertAt ) {
				Journal_DPrintfL( self->debug, 3, "** No more particles above current "
					"hole %d to fill: we're done. **\n", indexToInsertAt );
				/* Need the line below to mark the fact we failed to fill the current indexToInsertAt hole */
				self->swarm->particleLocalCount--;
				finishedFlag = True;
				break;
			}

			Journal_DPrintfL( self->debug, 3, "Candidate particle %d has also left...\n",
				candidateParticleToMove );

			highestLeavingParticleArrayEntry--;
			highestLeavingParticleIndex = leavingParticlesArray[highestLeavingParticleArrayEntry];
			leavingParticlesUnfilledCount--;
			self->swarm->particleLocalCount--;
			candidateParticleToMove--;
		}	
		Stream_UnIndent( self->debug );	

		if ( True == finishedFlag ) {
			/* We must have hit the "no more candidate particles" criterion in the search loop, so
			 * quit trying to fill empty holes entirely. */
			Stream_UnIndent( self->debug );
			break;
		}

		Journal_DPrintfL( self->debug, 3, "Highest valid particle found at index %d:\n",
			candidateParticleToMove );
		Journal_DFirewall( (candidateParticleToMove > indexToInsertAt), Swarm_Error,
			"Error in %s: Empty hole filling\nalgorithm has stuffed up somehow,"
			" since particle to be moved %d is <= slot to insert into %d.\n",
			__func__, candidateParticleToMove, indexToInsertAt );
		Stream_Indent( self->debug );	

		Journal_DPrintfL( self->debug, 3, "Copying particle data from %d to %d\n",
			candidateParticleToMove, indexToInsertAt );
		Swarm_CopyParticleWithinSwarm( self->swarm, indexToInsertAt, candidateParticleToMove );

		/* update the cell that the moved particle lives in to have the correct index into the
		 * particle array for it. */
		oldPtrToMovedParticle = Swarm_ParticleAt( self->swarm, candidateParticleToMove );
		owningCell = oldPtrToMovedParticle->owningCell;
		cParticle_I = Swarm_GetParticleIndexWithinCell( self->swarm, owningCell, candidateParticleToMove );
		Journal_DPrintfL( self->debug, 3, "Updating owning cell: (Cell %d, PIC index %d) now -> p.i. %d\n",
			owningCell, cParticle_I, indexToInsertAt );
		self->swarm->cellParticleTbl[owningCell][cParticle_I] = indexToInsertAt;


		Stream_UnIndent( self->debug );	

		/* update the counters/indices */
		currLeavingParticleArrayEntry++;
		leavingParticlesUnfilledCount--;
		self->swarm->particleLocalCount--;

		Stream_UnIndent( self->debug );
	}
	Stream_UnIndentBranch( Swarm_Debug );

	/* we only need to free the array of leaving particle slots if its a new merged list */
	if ( mergedArrayCreated == True ) {
		Memory_Free( leavingParticlesArray );
	}

	/* ------------------------- */
	Journal_DPrintfL( self->debug, 2, "Local particle count reduced from %d to %d\n", prevParticleCount,
		self->swarm->particleLocalCount );

	/* Update the memory allocated to the particles array if particle count has reduced significantly */
	while ( self->swarm->particlesArraySize > self->swarm->particleLocalCount + self->swarm->particlesArrayDelta ) {
		self->swarm->particlesArraySize -= self->swarm->particlesArrayDelta;
	}
	if ( self->swarm->particlesArraySize < prevParticlesArraySize ) {
		Journal_DPrintfL( self->debug, 2, "Reducing particles array entries from %d to %d\n",
			prevParticlesArraySize, self->swarm->particlesArraySize );
		Swarm_Realloc( self->swarm );
		/*
		self->swarm->particles = Memory_Realloc_Array_Bytes(
			self->swarm->particles,
			self->swarm->particleExtensionMgr->finalSize,
			self->swarm->particlesArraySize );
		*/
	}	

	Stream_UnIndentBranch( Swarm_Debug );
}
예제 #5
0
void _GlobalParticleLayout_InitialiseParticles( void* particleLayout, void* _swarm )
{
	GlobalParticleLayout*	self = (GlobalParticleLayout*)particleLayout;
	Swarm*			swarm = (Swarm*)_swarm;
	GlobalParticle*         particle = NULL;
	Particle_Index		lParticle_I=0;
	Particle_Index		newParticle_I=0;
	Cell_Index		cell_I;
	Particle_Index          globalParticlesInitialisedCount=0;
	Stream*                 errorStream = Journal_Register( Error_Type, self->type );

	Journal_DPrintf( self->debug, "In %s(): for ParticleLayout \"%s\" (of type %s):\n",
		__func__, self->name, self->type );
	Stream_IndentBranch( Swarm_Debug );

	Journal_DPrintf( self->debug, "For each of the %u total global requested particles, "
		"generating a particle, and checking if it's in this processor's domain. If so, "
		"adding it to the appropriate local cell.\n", self->totalInitialParticles );
	Stream_IndentBranch( Swarm_Debug );

	while( newParticle_I < self->totalInitialParticles ) {
		
		particle = (GlobalParticle*)Swarm_ParticleAt( swarm, lParticle_I );
		GlobalParticleLayout_InitialiseParticle( self, swarm, newParticle_I, particle );
		/* Work out which cell the new particle is in */
		/* First specify the particle doesn't have an owning cell yet, so as
		not to confuse the search algorithm if its an irregular cell/mesh layout */
		particle->owningCell = swarm->cellDomainCount;

		cell_I = CellLayout_CellOf( swarm->cellLayout, particle );

		/* If we found a further particle inside our domain, add it to a cell */
		if ( cell_I < swarm->cellLocalCount ) {
			Journal_DPrintfL( self->debug, 3, "global particle %u at (%.2f,%.2f,%.2f) inside local cell %u\n"
				"adding it to cell and saving it as local particle %u.\n",
				newParticle_I, particle->coord[0], particle->coord[1], particle->coord[2],
				cell_I, lParticle_I );
				
			Stream_IndentBranch( Swarm_Debug );
			/* Add it to that cell */
			Swarm_AddParticleToCell( swarm, cell_I, lParticle_I );
			lParticle_I++;
			swarm->particleLocalCount++;
			Swarm_Realloc( swarm );
			Stream_UnIndentBranch( Swarm_Debug );
		}
		else {
			Journal_DPrintfL( self->debug, 4, "global particle %u at (%.2f,%.2f,%.2f) outside this proc's domain:\n"
				"ignoring.\n", newParticle_I, particle->coord[0], particle->coord[1], particle->coord[2] );
		}		
				
		newParticle_I++;
	}

	Stream_UnIndentBranch( Swarm_Debug );

	/* Do a test to make sure that the total particles assigned across all processors ==
		totalInitialParticles count */
	MPI_Allreduce( &swarm->particleLocalCount, &globalParticlesInitialisedCount, 1, MPI_UNSIGNED, MPI_SUM, swarm->comm );
	Journal_Firewall( globalParticlesInitialisedCount == self->totalInitialParticles, errorStream,
		"Error - in %s() - for GlobalParticleLayout \"%s\", of type %s: after initialising particles, "
		"actual global count of particles initialised was %u, whereas requested global total "
		"totalInitialParticles was %u. If actual is < requested, it means some particles were not "
		"identified by any processor as inside their domain. If actual > requested, it means that "
		"some particles were identified by _multiple_ processors as belonging to their domain. Both "
		"these states are erroneous.\n",
		__func__, self->name, self->type, globalParticlesInitialisedCount, self->totalInitialParticles );

	Stream_UnIndentBranch( Swarm_Debug );
}