Exemple #1
0
// get the min and max value for all time steps
int Solution::GetMinMaxValueAll(VECTOR3& minVal, VECTOR3& maxVal)
{
	minVal = m_pMinValue[0];
	maxVal = m_pMaxValue[0];

	for(int tFor = 1; tFor < m_nTimeSteps; tFor++)
	{
		if(minVal.GetMag() > m_pMinValue[tFor].GetMag())
			minVal = m_pMinValue[tFor];

		if(maxVal.GetMag() < m_pMaxValue[tFor].GetMag())
			maxVal = m_pMaxValue[tFor];
	}

	return 1;
}
Exemple #2
0
float FieldData::getFieldMag(float point[3])
{
	VECTOR3 pos(point[0],point[1],point[2]);
	VECTOR3 vel;

	int rc = pField->getFieldValue( pos, (float)timeStep, vel);
	if (rc < 0) 
		return -1.f;

	return vel.GetMag();
}
Exemple #3
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;
}
Exemple #4
0
int vtCStreamLine::computeFieldLine(TIME_DIR time_dir,
                                    INTEG_ORD integ_ord,
                                    TIME_DEP time_dep, 
                                    vtListSeedTrace& seedTrace,
                                    PointInfo& seedInfo)
{
	int count = 0, istat;
	PointInfo thisParticle, prevParticle, second_prevParticle;
	PointInfo third_prevParticle;
	float dt, dt_estimate, dt_attempt, mag, curTime, prevCurTime;
	VECTOR3 vel;
	float cell_volume;

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

	thisParticle = seedInfo;

	seedTrace.push_back(new VECTOR3(seedInfo.phyCoord));
	curTime = m_fCurrentTime;
	count++;

	// get the initial stepsize
	// this method was taken from the paper "Interactive Time-Dependent
	// Particle Tracing Using Tetrahedral Decomposition", by Kenwright and Lane
	dt = m_fInitialStepSize;
	if(m_adaptStepSize)
	{
		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(count < m_nMaxsize)
	{
		third_prevParticle = second_prevParticle;
		second_prevParticle = prevParticle;
		prevParticle = thisParticle;
		prevCurTime = curTime;
		dt_attempt = dt;

		// 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, count);
		else if(integ_ord == RK45)
			istat = oneStepEmbedded(integ_ord, time_dir, time_dep,
			                        thisParticle, &curTime, &dt);

#ifdef DEBUG
		fprintf(fDebugOut, "point: %f, %f, %f with step size %f\n", 
		        thisParticle.phyCoord[0], thisParticle.phyCoord[1], 
		        thisParticle.phyCoord[2], dt);
#endif

		// check if the step failed
		if(istat == FAIL)
		{
			if(!m_adaptStepSize)
			{
				// can't change the step size, so advection just ends
				return OKAY;
			}
			else if(dt_attempt == m_fMinStepSize)
			{
				// tried to take a step with the min step size, 
				// can't go any further
				return OKAY;
			}
			else
			{
				// try to retake the step with a smaller step size
				dt = dt_attempt*0.1;
				if(dt < m_fMinStepSize)
					dt = m_fMinStepSize;
				thisParticle = prevParticle;
				prevParticle = second_prevParticle;
				second_prevParticle = third_prevParticle;
				curTime = prevCurTime;
				continue;
			}
		}

		seedTrace.push_back(new VECTOR3(thisParticle.phyCoord));
		count++;

		if(!m_adaptStepSize)
		{
			// change step size to prevously used, since the oneStep methods
			// will change the value of dt
			dt = dt_attempt;
		}

		// check if point is outside real bounds 
		// (bounds not counting ghost cells)
		if(!m_pField->IsInRealBoundaries(thisParticle))
		{
			return OUT_OF_BOUND;
		}

		// check if point is at critical point
		m_pField->at_phys(thisParticle.fromCell, thisParticle.phyCoord, 
		                  thisParticle, m_fCurrentTime, vel);
		if((fabs(vel[0]) < m_fStationaryCutoff) && 
		   (fabs(vel[1]) < m_fStationaryCutoff) && 
		   (fabs(vel[2]) < m_fStationaryCutoff))
		{
			return CRITICAL_POINT;
		}
	}

	return OKAY;
}
Exemple #5
0
//////////////////////////////////////////////////////////////////////////
// Compute streamlines.
// output
//	listSeedTraces: For each seed, return a list keeping the trace it
//					advects
//////////////////////////////////////////////////////////////////////////
//New version, uses FlowLineData instead of points array to write results of advection.
void vtCStreamLine::computeStreamLine(float curTime, FlowLineData* container){
	m_fCurrentTime = curTime;

	vtListParticleIter sIter;
	int istat;
	int seedNum = 0;
	for(sIter = m_lSeeds.begin(); sIter != m_lSeeds.end(); ++sIter)
	{
		vtParticleInfo* thisSeed = *sIter;
		if(thisSeed->itsValidFlag == 1)			// valid seed
		{
			if(m_itsTraceDir & BACKWARD_DIR)
			{
				vtListSeedTrace* backTrace;
				list<float>* stepList;
				backTrace = new vtListSeedTrace;
				stepList = new list<float>;
				istat = computeFieldLine(BACKWARD, STEADY, *backTrace, *stepList, thisSeed->m_pointInfo);
				SampleFieldline(container, seedNum, BACKWARD, backTrace, stepList, true, istat );
				delete backTrace;
				delete stepList;
			} else {
				//must be pure forward, set start point
				container->setFlowStart(seedNum, 0);
			}
			if(m_itsTraceDir & FORWARD_DIR)
			{
				vtListSeedTrace* forwardTrace;
				list<float>* stepList;
				forwardTrace = new vtListSeedTrace;
				stepList = new list<float>;
				istat = computeFieldLine(FORWARD,STEADY, *forwardTrace, *stepList, thisSeed->m_pointInfo);
				SampleFieldline(container, seedNum, FORWARD, forwardTrace, stepList, true, istat);
				delete forwardTrace;
				delete stepList;
			} else {
				//Must be pure backward, establish end of flowline: 
				container->setFlowEnd(seedNum, 0);
			}
		}
		else                // out of data region.  Just mark seed as end, don't advect.
        {
			float x = thisSeed->m_pointInfo.phyCoord.x();
			float y = thisSeed->m_pointInfo.phyCoord.y();
			float z = thisSeed->m_pointInfo.phyCoord.z();
			container->setFlowPoint(seedNum, 0, x,y,z);
			if(container->getMaxLength(BACKWARD) > 0)
				container->setFlowPoint(seedNum, -1, END_FLOW_FLAG,0.f,0.f);
			if(container->getMaxLength(FORWARD) > 0) 
				container->setFlowPoint(seedNum, 1, END_FLOW_FLAG,0.f,0.f);
			
			if (container->doSpeeds()){
				PointInfo pointInfo;
				VECTOR3 nodeData;
				float t = m_pField->GetStartTime();

				pointInfo.phyCoord.Set(x,y,z);	
				m_pField->getFieldValue(pointInfo.phyCoord, t, nodeData);
				container->setSpeed(seedNum, 0, nodeData.GetMag()/m_pField->getTimeScaleFactor());
			}
			container->setFlowStart(seedNum, 0);
			container->setFlowEnd(seedNum, 0);
        }

		seedNum++;
	}
}
int vtCTimeVaryingFieldLine::advectParticle(INTEG_ORD int_order, 
					    vtParticleInfo& initialPoint,
					    float initialTime,
					    float finalTime,
					    vtListTimeSeedTrace& seedTrace)
{  
	int count = 0, istat, res;
	PointInfo seedInfo;
	PointInfo thisParticle, prevParticle, second_prevParticle;
	PointInfo third_prevParticle;
	float dt, dt_attempt, dt_estimate, cell_volume, mag, curTime, prevCurTime;
	VECTOR3 vel;

	// the first particle
	seedInfo = initialPoint.m_pointInfo;
	res = m_pField->at_phys(seedInfo.fromCell, seedInfo.phyCoord, seedInfo,
	                        initialTime, vel);
	if(res == OUT_OF_BOUND)  {
		return OUT_OF_BOUND;
	}
	if((fabs(vel[0]) < m_fStationaryCutoff) && 
	   (fabs(vel[1]) < m_fStationaryCutoff) &&
	   (fabs(vel[2]) < m_fStationaryCutoff)) {
		return CRITICAL_POINT;
	}

	thisParticle = seedInfo;
	VECTOR4 *p = new VECTOR4; 
	(*p)[0] = seedInfo.phyCoord[0]; 
	(*p)[1] = seedInfo.phyCoord[1]; 
	(*p)[2] = seedInfo.phyCoord[2]; 
	(*p)[3] = initialTime; 
	seedTrace.push_back(p); 
	curTime = initialTime;
	count++;

	// get the initial stepsize
	dt = m_fInitialStepSize;
	if(m_adaptStepSize)
	{
		switch(m_pField->GetCellType())
		{
		case CUBE:
			dt = dt_estimate = m_fInitialStepSize;
			break;

		case TETRAHEDRON:
			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 = dt_estimate;
			break;

		default:
			break;
		}
	}

	// start to advect
	while(count < m_nMaxsize)
	{
		third_prevParticle = second_prevParticle;
		second_prevParticle = prevParticle;
		prevParticle = thisParticle;
		prevCurTime = curTime;
		dt_attempt = dt;

		if(int_order == SECOND || int_order == FOURTH)
			istat = oneStepGeometric(int_order, m_timeDir, UNSTEADY,
									 thisParticle, prevParticle,
			                         second_prevParticle, &curTime, &dt, count);
		else if(int_order == RK45)
			istat = oneStepEmbedded(int_order, m_timeDir, UNSTEADY,
			                        thisParticle, &curTime, &dt);
		
		// check if the step failed
		if(istat == FAIL)
		{
			if(!m_adaptStepSize)
			{
				// can't change the step size, so advection just ends
				return OKAY;
			}
			if(dt_attempt == m_fMinStepSize)
			{
				// tried to take a step with the min step size, but failed,
				// can't go any further
				return OKAY;
			}
			else
			{
				// try to retake the step with a smaller step size
				dt = dt_attempt * 0.1;
				if(dt < m_fMinStepSize)
					dt = m_fMinStepSize;
				thisParticle = prevParticle;
				prevParticle = second_prevParticle;
				second_prevParticle = third_prevParticle;
				curTime = prevCurTime;
				continue;
			}
		}

		VECTOR4 *p = new VECTOR4; 
		(*p)[0] = thisParticle.phyCoord[0]; 
		(*p)[1] = thisParticle.phyCoord[1]; 
		(*p)[2] = thisParticle.phyCoord[2]; 
		(*p)[3] = curTime; 
		seedTrace.push_back(p); 
		count++;

		if(!m_adaptStepSize)
		{
			// change step size to previously used, since the oneStep methods
			// will change the value of dt
			dt = dt_attempt;
		}

		// check if point is outside real bounds 
		// (bounds not counting ghost cells)
		if(!m_pField->IsInRealBoundaries(thisParticle, curTime))
		{
			return OUT_OF_BOUND;
		}

		// check if point is at critical point
		m_pField->at_phys(thisParticle.fromCell, thisParticle.phyCoord, 
		                  thisParticle, curTime, vel);
		if((fabs(vel[0]) < m_fStationaryCutoff) && 
		   (fabs(vel[1]) < m_fStationaryCutoff) && 
		   (fabs(vel[2]) < m_fStationaryCutoff))
			return CRITICAL_POINT;
	}

	return OKAY;
}
//////////////////////////////////////////////////////////////////////////
// advect the particle until it goes out of boundary or vel = 0
// return back the track of advection
//////////////////////////////////////////////////////////////////////////
int vtCTimeVaryingFieldLine::advectParticle(INTEG_ORD int_order, 
                                            vtParticleInfo& initialPoint,
                                            float initialTime,
                                            float finalTime,
                                            vtListSeedTrace& seedTrace)
{  
	int count = 0, istat, res;
	PointInfo seedInfo;
	PointInfo thisParticle, prevParticle, second_prevParticle;
	float dt, dt_estimate, cell_volume, mag, curTime;
	VECTOR3 vel;

	// the first particle
	seedInfo = initialPoint.m_pointInfo;
	res = m_pField->at_phys(seedInfo.fromCell, seedInfo.phyCoord, seedInfo, 
	                        initialTime, vel);
	if(res == OUT_OF_BOUND){
		return OUT_OF_BOUND;
	}
	if((fabs(vel[0]) < m_fStationaryCutoff) && 
	   (fabs(vel[1]) < m_fStationaryCutoff) && 
	   (fabs(vel[2]) < m_fStationaryCutoff)) {
	  return CRITICAL_POINT;
	}

	thisParticle = seedInfo;
	seedTrace.push_back(new VECTOR3(seedInfo.phyCoord));
	curTime = initialTime;
	count++;

	// get the initial stepsize
	switch(m_pField->GetCellType())
	{
	case CUBE:
		dt = dt_estimate = m_fInitialStepSize;
		break;

	case TETRAHEDRON:
		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 = dt_estimate;
		break;

	default:
		break;
	}

	// start to advect
	while(count < m_nMaxsize)
	{
		second_prevParticle = prevParticle;
		prevParticle = thisParticle;

		if(int_order == SECOND || int_order == FOURTH)
			istat = oneStepGeometric(int_order, m_timeDir, UNSTEADY,
			                         thisParticle, prevParticle, 
			                         second_prevParticle, &curTime, &dt, count);
		else if(int_order == RK45)
			istat = oneStepEmbedded(int_order, m_timeDir, UNSTEADY,
			                        thisParticle, &curTime, &dt);
		else
			return OUT_OF_BOUND;

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

		m_pField->at_phys(thisParticle.fromCell, thisParticle.phyCoord, 
		                  thisParticle, curTime, vel);
		if((fabs(vel[0]) < m_fStationaryCutoff) && 
		   (fabs(vel[1]) < m_fStationaryCutoff) && 
		   (fabs(vel[2]) < m_fStationaryCutoff)) {
			return CRITICAL_POINT;			// arrives at a critical point
		}
		else
		{
			seedTrace.push_back(new VECTOR3(thisParticle.phyCoord));
			count++;
		}

		if((curTime < m_pField->GetMinTimeStep()) || 
		   (curTime > m_pField->GetMaxTimeStep())) {
			return OUT_OF_BOUND;
		}
	}

	return OKAY;
}