// See if any particles have changed elements
// Stop if off the grid
// throws CommonException()
void ResetElementsTask::Execute(void)
{
	// update feedback damping now if needed
	bodyFrc.UpdateAlpha(timestep,mtime);
	
	// how many patches?
	int totalPatches = fmobj->GetTotalNumberOfPatches();
	
#ifdef PARALLEL_RESET
	// initialize error
	CommonException *resetErr = NULL;

	// parallel over patches
#pragma omp parallel
	{
        // thread for patch pn
		int pn = GetPatchNumber();
        
		try
		{	// resetting all element types
			for(int block=FIRST_NONRIGID;block<=FIRST_RIGID_BC;block++)
			{	// get first material point in this block
				MPMBase *mptr = patches[pn]->GetFirstBlockPointer(block);
				MPMBase *prevMptr = NULL;		// previous one of this type in current patch
				while(mptr!=NULL)
				{	int status = ResetElement(mptr);
					
					if(status==LEFT_GRID)
					{	// particle has left the grid
						mptr->IncrementElementCrossings();
						
						// enter warning only if this particle did not leave the grid before
						if(!mptr->HasLeftTheGridBefore())
						{	int result = warnings.Issue(fmobj->warnParticleLeftGrid,-1);
							if(result==REACHED_MAX_WARNINGS || result==GAVE_WARNING)
							{
#pragma omp critical (output)
								{	mptr->Describe();
								}
								// abort if needed
								if(result==REACHED_MAX_WARNINGS)
								{	char errMsg[100];
									sprintf(errMsg,"Too many particles have left the grid\n  (plot x displacement to see last one).");
									mptr->origpos.x=-1.e6;
									throw CommonException(errMsg,"ResetElementsTask::Execute");
								}
							}
							
							// set this particle has left the grid once
							mptr->SetHasLeftTheGridBefore(TRUE);
						}
						
						// bring back to the previous element
						ReturnToElement(mptr);
					}
					
					else if(status==NEW_ELEMENT && totalPatches>1)
					{	// did it also move to a new patch?
						int newpn = mpmgrid.GetPatchForElement(mptr->ElemID());
						if(pn != newpn)
						{	if(!patches[pn]->AddMovingParticle(mptr,patches[newpn],prevMptr))
							{	throw CommonException("Out of memory storing data for particle changing patches","ResetElementsTask::Execute");
							}
						}
					}
					
					else if(status==LEFT_GRID_NAN)
					{
#pragma omp critical (output)
						{	cout << "# Particle has left the grid and position is nan" << endl;
							mptr->Describe();
						}
						throw CommonException("Particle has left the grid and position is nan","ResetElementsTask::Execute");
					}
					
					// next material point and update previous particle
					prevMptr = mptr;
					mptr = (MPMBase *)mptr->GetNextObject();
				}
			}
		}
		catch(CommonException& err)
        {   if(resetErr==NULL)
			{
#pragma omp critical (error)
				resetErr = new CommonException(err);
			}
		}
		catch(std::bad_alloc&)
        {   if(resetErr==NULL)
			{
#pragma omp critical (error)
				resetErr = new CommonException("Memory error","ResetElementsTask::Execute");
			}
		}
		catch(...)
        {   if(resetErr==NULL)
			{
#pragma omp critical (error)
				resetErr = new CommonException("Unexepected error","ResetElementsTask::Execute");
			}
		}
	}

	// throw now if was an error
	if(resetErr!=NULL) throw *resetErr;
    
	// reduction phase moves the particles
	for(int pn=0;pn<totalPatches;pn++)
		patches[pn]->MoveParticlesToNewPatches();
	
#else
	
	int status;
	MPMBase *mptr,*prevMptr,*nextMptr;
	for(int pn=0;pn<totalPatches;pn++)
	{	for(int block=FIRST_NONRIGID;block<=FIRST_RIGID_BC;block++)
		{	// get first material point in this block
			mptr = patches[pn]->GetFirstBlockPointer(block);
			prevMptr = NULL;		// previous one of this type in current patch
			while(mptr!=NULL)
			{	status = ResetElement(mptr);
				
				if(status==LEFT_GRID)
				{	// particle has left the grid
					mptr->IncrementElementCrossings();
				
					// enter warning only if this particle did not leave the grid before
					if(!mptr->HasLeftTheGridBefore())
					{	int result = warnings.Issue(fmobj->warnParticleLeftGrid,-1);
						if(result==REACHED_MAX_WARNINGS || result==GAVE_WARNING)
						{	mptr->Describe();
							// abort if needed
							if(result==REACHED_MAX_WARNINGS)
							{	char errMsg[100];
								sprintf(errMsg,"Too many particles have left the grid\n  (plot x displacement to see last one).");
								mptr->origpos.x=-1.e6;
								throw CommonException(errMsg,"ResetElementsTask::Execute");
							}
						}
						
						// set this particle has left the grid once
						mptr->SetHasLeftTheGridBefore(TRUE);
					}
				
					// bring back to the previous element
					ReturnToElement(mptr);
				}
				
				else if(status==NEW_ELEMENT && totalPatches>1)
				{	int newpn = mpmgrid.GetPatchForElement(mptr->ElemID());
					if(pn != newpn)
					{	// next material point read before move this particle
						nextMptr = (MPMBase *)mptr->GetNextObject();
						
						// move particle mptr
						patches[pn]->RemoveParticleAfter(mptr,prevMptr);
						patches[newpn]->AddParticle(mptr);
						
						// next material point is now after the prevMptr, which stays the same, which may be NULL
						mptr = nextMptr;
						continue;
					}
				}
				
				else if(status==LEFT_GRID_NAN)
				{	cout << "# Particle has left the grid and position is nan" << endl;
					mptr->Describe();
					throw CommonException("Particle has left the grid and position is nan","ResetElementsTask::Execute");
				}
				
				// next material point and update previous particle
				prevMptr = mptr;
				mptr = (MPMBase *)mptr->GetNextObject();
			}
		}
	}
#endif
}
// See if any particles have changed elements
// Stop if off the grid
void ResetElementsTask::Execute(void)
{
	CommonException *resetErr = NULL;
	
	// update feedback damping now if needed
	bodyFrc.UpdateAlpha(timestep,mtime);

	// This block should be made parallel
	// But when do so, need method to move particle  between patches while keeping threads independent
	int totalPatches = fmobj->GetTotalNumberOfPatches();
	
	int status;
	MPMBase *mptr,*prevMptr,*nextMptr;
	for(int pn=0;pn<totalPatches;pn++)
	{	for(int block=FIRST_NONRIGID;block<=FIRST_RIGID_BC;block++)
		{	// get first material point in this block
			mptr = patches[pn]->GetFirstBlockPointer(block);
			prevMptr = NULL;		// previous one of this type in current patch
			while(mptr!=NULL)
			{	status = ResetElement(mptr);
				
				if(status==LEFT_GRID)
				{	// particle has left the grid
					mptr->IncrementElementCrossings();
				
					// enter warning only if this particle did not leave the grid before
					if(!mptr->HasLeftTheGridBefore())
					{	if(warnings.Issue(fmobj->warnParticleLeftGrid,-1)==REACHED_MAX_WARNINGS)
						{	// print message and log error
							if(resetErr==NULL)
							{	mptr->Describe();
								char errMsg[100];
								sprintf(errMsg,"Too many particles have left the grid\n  (plot x displacement to see last one).");
								mptr->origpos.x=-1.e6;
								resetErr = new CommonException(errMsg,"ResetElementsTask::Execute");
								throw *resetErr;
							}
						}
						
						// set this particle has left the grid once
						mptr->SetHasLeftTheGridBefore(TRUE);
					}
				
					// bring back to the previous element
					ReturnToElement(mptr);
				}
				
				else if(status==NEW_ELEMENT && totalPatches>1)
				{	int newpn = mpmgrid.GetPatchForElement(mptr->ElemID());
					if(pn != newpn)
					{	// next material point read before move this particle
						nextMptr = (MPMBase *)mptr->GetNextObject();
						
						// move particle mptr
						patches[pn]->RemoveParticleAfter(mptr,prevMptr);
						patches[newpn]->AddParticle(mptr);
						
						// next material point is now after the prevMptr, which stays the same, which may be NULL
						mptr = nextMptr;
						continue;
					}
				}
				
				else if(status==LEFT_GRID_NAN)
				{	cout << "# Particle has left the grid and position is nan" << endl;
					mptr->Describe();
					resetErr = new CommonException("Particle has left the grid and position is nan","ResetElementsTask::Execute");
					throw *resetErr;
				}
				
				// next material point and update previous particle
				prevMptr = mptr;
				mptr = (MPMBase *)mptr->GetNextObject();
			}
		}
	}
	
	// if error occurred then throw it
	if(resetErr) throw *resetErr;
}
	inline void ResetField(TInt aFieldId) {ResetElement(aFieldId);}