Example #1
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);
}