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); }