Example #1
0
// streamline advects as far as possible till the boundary or terminates at
// critical points. only two cases will happen: OUT_OF_BOUND & CRITICAL_POINT
int vtCStreamLine::executeInfiniteAdvection(TIME_DIR time_dir,
                                            TIME_DEP time_dep,
                                            vtListSeedTrace& seedTrace,
                                            float& totalStepsize,
                                            vector<float>* vStepsize)
{
	int istat;
	vtParticleInfo* thisSeed;
	PointInfo thisParticle, prevParticle, second_prevParticle, seedInfo;
	vtListParticleIter sIter;
	float dt, dt_estimate, cell_volume, mag, curTime;
	VECTOR3 vel;
	INTEG_ORD integ_ord;

	// initialize
	integ_ord = m_integrationOrder;
	sIter = m_lSeeds.begin();
	thisSeed = *sIter;
	seedInfo = thisSeed->m_pointInfo;
	seedTrace.clear();
	totalStepsize = 0.0;

	// the first point
	seedTrace.push_back(new VECTOR3(seedInfo.phyCoord));
	istat = m_pField->at_phys(seedInfo.fromCell, seedInfo.phyCoord, seedInfo, 
	                          m_fCurrentTime, vel);
	if((fabs(vel[0]) < m_fStationaryCutoff) && 
	   (fabs(vel[1]) < m_fStationaryCutoff) && 
	   (fabs(vel[2]) < m_fStationaryCutoff))
		return CRITICAL_POINT;

	thisParticle = seedInfo;
	curTime = m_fCurrentTime;

	// get the initial stepsize
	cell_volume = m_pField->volume_of_cell(seedInfo.inCell);
	mag = vel.GetMag();
	if(fabs(mag) < 1.0e-6f)
		dt_estimate = 1.0e-5f;
	else
		dt_estimate = pow(cell_volume, (float)0.3333333f) / mag;
	dt = m_fInitialStepSize * dt_estimate;

#ifdef DEBUG
	fprintf(fDebugOut, "****************new particle*****************\n");
	fprintf(fDebugOut, "seed: %f, %f, %f with step size %f\n", 
	        seedInfo.phyCoord[0],seedInfo.phyCoord[1],seedInfo.phyCoord[2],dt);
#endif

	// start to advect
	while(true)
	{
		second_prevParticle = prevParticle;
		prevParticle = thisParticle;

		// take a proper step, also calculates a new step size for the next step
		if(integ_ord == SECOND || integ_ord == FOURTH)
			istat = oneStepGeometric(integ_ord, time_dir, time_dep,
			                         thisParticle, prevParticle, 
			                         second_prevParticle, &curTime, &dt, 
			                         seedTrace.size());
		else if(integ_ord == RK45)
			istat = oneStepEmbedded(integ_ord, time_dir, time_dep,
			                        thisParticle, &curTime, &dt);
		else
			return OUT_OF_BOUND;


		if(istat == OUT_OF_BOUND)			// out of boundary
		{
			// find the boundary intersection point
			VECTOR3 intersectP, startP, endP;
			float oldStepsize, stepSize; 
			oldStepsize = stepSize = dt;
			startP = prevParticle.phyCoord;
			endP = thisParticle.phyCoord;
			m_pField->BoundaryIntersection(intersectP, startP, endP, &stepSize,
			                               oldStepsize);
			totalStepsize += stepSize;
			seedTrace.push_back(new VECTOR3(intersectP));
			if(vStepsize != NULL)
				vStepsize->push_back(stepSize);
			return OUT_OF_BOUND;
		}

		// find the loop
		list<VECTOR3*>::iterator searchIter;
		searchIter = seedTrace.end();
		searchIter--;
		for(; searchIter != seedTrace.begin(); searchIter--)
		{
			if(thisParticle.phyCoord == **searchIter)			// loop
				return CRITICAL_POINT;
		}

		m_pField->at_phys(thisParticle.fromCell, thisParticle.phyCoord, 
		                  thisParticle, m_fCurrentTime, vel);
		seedTrace.push_back(new VECTOR3(thisParticle.phyCoord));
		if(vStepsize != NULL)
			vStepsize->push_back(dt);
		totalStepsize += dt;

#ifdef DEBUG
		fprintf(fDebugOut, "***************advected particle***************\n");
		fprintf(fDebugOut, "pos = (%f, %f, %f), vel = (%f, %f, %f) with step size %f, total step size %f\n", thisParticle.phyCoord[0], thisParticle.phyCoord[1], thisParticle.phyCoord[2], vel[0], vel[1], vel[2], dt, totalStepsize);
#endif

		if(totalStepsize > 4000.0)
		{
			printf("curl\n");
			vel.Set(0.0, 0.0, 0.0);
		}

		if((fabs(vel[0]) < m_fStationaryCutoff) && 
		   (fabs(vel[1]) < m_fStationaryCutoff) && 
		   (fabs(vel[2]) < m_fStationaryCutoff))
			return CRITICAL_POINT;
		if((int)seedTrace.size() > 2)
			adapt_step(second_prevParticle.phyCoord, prevParticle.phyCoord, 
			           thisParticle.phyCoord, &dt);
	}

	return OUT_OF_BOUND;
}
Example #2
0
int vtCStreamLine::computeFieldLine(TIME_DIR time_dir,
									 TIME_DEP time_dep, 
									 vtListSeedTrace& seedTrace,
									 list<float>& stepList,
									 PointInfo& seedInfo)
{
	int istat;
	PointInfo thisParticle;
	double dt, cell_vol, mag; 
	double curTime;
	VECTOR3 vel;
	float totalStepsize = 0.0;
	bool onAdaptive = true;
	int nSetAdaptiveCount = 0;

	// the first particle
	thisParticle = seedInfo;
	
	seedTrace.push_back(new VECTOR3(seedInfo.phyCoord));
	curTime = (double)m_fCurrentTime;
	istat = m_pField->getFieldValue(seedInfo.phyCoord, m_fCurrentTime, vel);
	if(istat == OUT_OF_BOUND)
		return OUT_OF_BOUND;			// the advection is out of boundary
	if(istat == MISSING_VALUE ||((abs(vel[0]) < m_fStationaryCutoff) && (abs(vel[1]) < m_fStationaryCutoff) && (abs(vel[2]) < m_fStationaryCutoff)))
		return CRITICAL_POINT;			// this is critical point
		
	// get the initial step size
	
	cell_vol = m_pField->GetMinCellVolume();
	mag = vel.GetDMag();
	
	dt = m_fInitStepSize * cell_vol / mag;
	
	//Determine the value of mag*dt to project 10 times init size.  
	double maxMagDt = 10.*dt*mag;

	int rollbackCount = 0;
	// start to advect
	
	while(totalStepsize < (float)((m_nMaxsize-1)*m_fSamplingRate))
	{
		bool doingRetrace = false;
		
		int retrace = true;
		
		
		while(retrace)
		{
			retrace = false;
			
			for(int magTry = 0; magTry < 40; magTry++) {
				
				istat = runge_kutta4(time_dir, time_dep, thisParticle, &curTime, dt, maxMagDt);
			
				if (istat != FIELD_TOO_BIG) break;
				//Shrink dt by factor of 10.
				dt = 0.1*dt;

			}
			assert (istat != FIELD_TOO_BIG);
			
			seedTrace.push_back(new VECTOR3(thisParticle.phyCoord));
			stepList.push_back(dt);

			if(istat == OUT_OF_BOUND)			// out of boundary
				return OUT_OF_BOUND;

			m_pField->getFieldValue(thisParticle.phyCoord, m_fCurrentTime, vel);
			
			if((abs(vel[0]) < m_fStationaryCutoff) && (abs(vel[1]) < m_fStationaryCutoff) && (abs(vel[2]) < m_fStationaryCutoff))
				return CRITICAL_POINT;

			totalStepsize += dt;			// accumulation of step size
			nSetAdaptiveCount++;
			
			if((nSetAdaptiveCount == 2) && (onAdaptive == false))
				onAdaptive = true;

			// just generate valid new point
			if(((int)seedTrace.size() > 2)&&(onAdaptive))
			{
				double minStepsize, maxStepsize;
				VECTOR3 thisPhy, prevPhy, second_prevPhy;
				list<VECTOR3*>::iterator pIter = seedTrace.end();
				pIter--;
				thisPhy = **pIter;
				pIter--;
				prevPhy = **pIter;
				pIter--;
				second_prevPhy = **pIter;

				
				mag = vel.GetDMag();
				minStepsize = m_fInitStepSize * cell_vol / mag;
				maxStepsize = m_fMaxStepSize * cell_vol / mag;
				retrace = adapt_step(second_prevPhy, prevPhy, thisPhy, minStepsize, maxStepsize, &dt, onAdaptive);
				if(onAdaptive == false)
					nSetAdaptiveCount = 0;

				assert (rollbackCount < 10000);//If we got here, it's surely an infinite loop!
					
				// roll back and retrace
				//the doingRetrace flag is to stop double retracing (which results in infinite loop!)
				//Note a slightly different approach is in VTTimeVaryingFieldLine.cpp
				if(retrace && !doingRetrace)			
				{
					seedTrace.pop_back();
					seedTrace.pop_back();
					thisParticle.Set(*(seedTrace.back()));
					totalStepsize -= stepList.back();
					stepList.pop_back();
					totalStepsize -= stepList.back();
					stepList.pop_back();
					rollbackCount++;
					doingRetrace = true;
				} else doingRetrace = false;
			}
		}// end of retrace
		//What was the distance advected?
	}// end of advection
	return (OKAY);
}