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