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