BodyRigid::BodyRigid(const char* name, double const &mass, Mat3x3 const &inertia, Vect3 const &pos, Quat const &q, Vect3 const &vel, Vect3 const &wl, bool const &fixed) : Body(name,pos,q,vel,wl), m_mass(mass), m_inertia(inertia), m_fixed(fixed) { m_appliedForce = Vect3(0,0,0); m_appliedTorque = Vect3(0,0,0); /// initialize kanes method .... TODO site the page number this this shows up on m_sAhat << 0.,0.,0.,0.,0.,0.; m_sFhat << 0.,0.,0.,0.,0.,0.; m_sIhat << 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0; m_n_alpha_t_k << 0,0,0; m_n_a_t_k << 0,0,0; // contact stuff m_stiff = 0; m_damp = 0; m_frict = 0; m_thresh = 0; }
vec3_t *G2Exporter_Surface_GetVertNormal(int iSurfaceIndex, int iVertIndex, int iLODIndex) { static vec3_t v3={0}; memset(v3,0,sizeof(v3)); if (iLODIndex == giNumLODs-1) { // q3data surface... // if (iSurfaceIndex < giNumSurfaces) { // standard surface... // md3SurfaceData_t *pSurfaceData = GetMD3SurfaceData(iSurfaceIndex); if (pSurfaceData) { // this logic is kinda gay, not sure why the *6 etc, but that's how other q3data code works, so... // float **ppVerts = pSurfaceData->verts; memcpy(v3,(vec3_t*) &ppVerts[0][iVertIndex*6+3], sizeof(v3)); { Matrix4 Swap; Swap.Identity(); if (1) { Swap.SetRow(0,Vect3(0.0f,-1.0f,0.0f)); Swap.SetRow(1,Vect3(1.0f,0.0f,0.0f)); } Swap.CalcFlags(); Vect3 v3In((const float *)v3); static Vect3 v3Out; Swap.XFormVect(v3Out,v3In); return (vec3_t*) &v3Out; } } } else { // tag surface... // // I don't think tag-surfaces normals have any meaning for ghoul2, so... // return &v3; } } else { // imported surface... // vec3_t &v3Src = ImportedModel.ImportedLODs[iLODIndex].ImportedSurfaces[ImportedModel.SurfaceIndexRemaps[iSurfaceIndex]].ImportedVerts[iVertIndex].normal; memcpy(v3,v3Src,sizeof(v3)); return &v3; } assert(0); return &v3; }
PANEL(Vect3 P1, Vect3 P2, Vect3 P3, Vect3 P4) { C1 = P1; C2 = P2; C3 = P3; C4 = P4; C1o = C1; C2o = C2; C3o = C3; C4o = C4; edgeX1 = edgeX2 = dF = Vect3(0.0); Sigma = Mu = PhiWakePrev = 0.0; Gamma = Phi = Sigma = Mu = 0.0; Area = MaxDiagonal = Gamma = Vn = MuPrev = GammaPrev = 0.0; Centroid = Vect3(.25 * (C1 + C2 + C3 + C4)); Owner = NULL; OtherBoundarySurface = AttachedProtoWake = SheddingSurface = NULL; Neighb = NULL; Theta = 0.0; isBound = isTop = isWake = false; BoundBC = ID = -1; TRANS.assign(3, Vect3(0.)); PhiPrev = Array <REAL> (4, 0.0); Cloc = Rloc = 0.0; Vfmm = dVFMM_dt = VWakePrev = Vect3(0.); DoubletValidRange2 = ValidRange = 1e32; GetNormal(); }
BodyRigid::BodyRigid( std::string const &name, double const &mass, vector<double> const &inertia, vector<double> const &pos, vector<double> const &q, vector<double> const &vel, vector<double> const &wl, bool const &fixed ): Body(name), m_mass(mass), m_fixed(fixed) { m_inertia <<inertia[0], inertia[1], inertia[2], inertia[3], inertia[4], inertia[5], inertia[6], inertia[7], inertia[8]; Vect3 pos_; pos_ << pos[0], pos[1], pos[2]; Quat q_(q[0], q[1], q[2], q[3]); Vect3 vel_; vel_ << vel[0], vel[1], vel[2]; Vect3 wl_; wl_ << wl[0], wl[1], wl[2]; m_pos = pos_; m_q = q_; m_vel =vel_; m_wl = wl_; m_wldot = Vect3(0,0,0); m_accel = Vect3(0,0,0); m_appliedForce = Vect3(0,0,0); m_appliedTorque = Vect3(0,0,0); /// initialize kanes method .... TODO site the page number this this shows up on m_sAhat << 0.,0.,0.,0.,0.,0.; m_sFhat << 0.,0.,0.,0.,0.,0.; m_sIhat << 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0; m_n_alpha_t_k << 0,0,0; m_n_a_t_k << 0,0,0; // contact stuff m_stiff = 0; m_damp = 0; m_frict = 0; m_thresh = 0; }
void trig_cone(Vect3 centre, Array <Vect3> &X, Array <Vect3> &Omega, REAL magnitude, REAL radius) { for (int x = 1; x <= NX; ++x) { for (int y = 1; y <= NY; ++y) { REAL r = sqrt((centre.x - x)*(centre.x - x)+ (centre.y - y)*(centre.y - y)); if (r / radius < 1) { Omega.push_back(Vect3(0., 0., magnitude * sin((pi * 0.5 * (1 + (r / radius)))))); X.push_back(Vect3(x, y, 0.)); } } } }
void TIME_STEPPER::Euler(FVMCell * cell) { for (int q = 0; q < SYSTEM::NumTransVars; ++q) { cell->TransVars[q] += dt * cell->TransDerivs[q]; cell->TransDerivs[q] = Vect3(0.); } }
void cylinder_dipole(Vect3 centre, Array <Vect3> &X, Array <Vect3> &Omega, REAL offset, REAL amplitude, REAL radius) { REAL c_cone[3] = {centre.x + offset, centre.x - offset, centre.y}; REAL r1 = 0, r2 = 0; for (int x = 1; x <= 300; ++x) { for (int y = 1; y <= 300; ++y) { r1 = sqrt((c_cone[0] - x)*(c_cone[0] - x) + (c_cone[2] - y)*(c_cone[2] - y)); r2 = sqrt((c_cone[1] - x)*(c_cone[1] - x) + (c_cone[2] - y)*(c_cone[2] - y)); if (r1 <= radius) { Omega.push_back(Vect3(0., 0., (0. * amplitude) - amplitude)); X.push_back(Vect3(x, y, 0.)); } if (r2 <= radius) { Omega.push_back(Vect3(0., 0., (0. * amplitude) + amplitude)); X.push_back(Vect3(x, y, 0.)); } } } }
PANEL() { C1 = C2 = C3 = C4 = C1o = C2o = C3o = C4o = NC1 = NC2 = NC3 = NC4 = edgeX1 = edgeX2 = dF = Vect3(0.0); Sigma = Mu = 0.0; Gamma = Phi = PhiWakePrev = 0.0; Area = MaxDiagonal = Sigma = Mu = Gamma = Vn = MuPrev = GammaPrev = 0.0; Centroid = CollocationPoint = Vect3(.25 * (C1 + C2 + C3 + C4)); Owner = NULL; OtherBoundarySurface = AttachedProtoWake = SheddingSurface = NULL; Neighb = NULL; Theta = 0.0; isBound = isTop = isWake = false; BoundBC = ID = -1; TRANS.assign(3,Vect3(0.)); PhiPrev = Array <REAL> (4,0.0); Cloc = Rloc = 0.0; Vfmm = dVFMM_dt = VWakePrev = Vect3(0.); DoubletValidRange2 = ValidRange = 1e32; }
ParticleEmitter::ParticleEmitter( ParticleEmitterDesc p_particleDesc ) { m_particleDesc = p_particleDesc; m_nrOfDeadParticles = 0; for (int i = 0; i < m_particleDesc.nrOfParticles; i++) { m_particleList.push_back(new Particle()); //l_lifeTime is between m_particleDesc.lifeTimeMin and m_particleDesc.lifeTimeMax float l_lifeTime = m_particleDesc.lifeTimeMin + (float)rand()/((float)RAND_MAX/(m_particleDesc.lifeTimeMax-m_particleDesc.lifeTimeMin)); //l_speed is between m_particleDesc.speedMin and m_particleDesc.speedMax float l_speed = m_particleDesc.speedMin + (float)rand()/((float)RAND_MAX/(m_particleDesc.speedMax-m_particleDesc.speedMin)); //Random x,y,z between -1 and 1 double xx = (double)rand()/((double)RAND_MAX*.5) - 1; double yy = (double)rand()/((double)RAND_MAX*.5) - 1; double zz = (double)rand()/((double)RAND_MAX*.5) - 1; //Calculate magnitude of x,y,z double vmag = sqrt((xx*xx)+(yy*yy)+(zz*zz)); //Normalize x,y,z xx = xx/vmag; yy = yy/vmag; zz = zz/vmag; //Voila! Random unit vector! Vect3 l_direction = Vect3((float)xx, (float)yy, (float)zz); //TODO calculate direction depending on what angles are set m_particleList.at(i)->Init(m_particleDesc.position, m_particleDesc.scale, l_direction, m_particleDesc.acceleration, m_particleDesc.startColor, m_particleDesc.endColor, l_lifeTime, l_speed, 0.0f); } m_particleDataList.resize( m_particleList.size()*3 ); glGenVertexArrays( 1, &m_vao ); glBindVertexArray( m_vao ); glGenBuffers( 1, &m_dataBuffer ); glBindBuffer( GL_ARRAY_BUFFER, m_dataBuffer ); glBufferData( GL_ARRAY_BUFFER, m_particleDataList.size() * 3 * sizeof( float ), 0, GL_DYNAMIC_DRAW ); glEnableVertexAttribArray( 0 ); glEnableVertexAttribArray( 1 ); glEnableVertexAttribArray( 2 ); #define BUFFER_OFFSET( i ) ( ( char * )NULL + ( i ) ) glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof( float ), BUFFER_OFFSET( 0 ) ); glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof( float ), BUFFER_OFFSET( 3 * sizeof( float ) ) ); glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof( float ), BUFFER_OFFSET( 6 * sizeof( float ) ) ); glBindVertexArray( 0 ); }
void lamb_dipole(Vect3 centre, Array <Vect3> &X, Array <Vect3> &Omega, REAL amplitude, REAL theta_dipole, REAL radius, REAL a, REAL k) { // Produce a Lamb Dipole, eg // lamb_dipole(Vect3(100, 50, 0), X, OMEGA, 30, pi / 2, 30, 30, 3.81 / 30); REAL U; for (int x = 1; x <= NX; ++x) { for (int y = 1; y <= NY; ++y) { U = 0.; if (x < centre.x) U = -amplitude; if (x > centre.x) U = amplitude; REAL r = sqrt((centre[0] - x)*(centre[0] - x) + (centre[1] - y)*(centre[1] - y)); if (r < radius) { REAL theta = atan2((centre[1] - y)*(centre[1] - y) + 1e-16, (centre[0] - x)*(centre[0] - x) + 1e-16); REAL numerator = gsl_sf_bessel_J1(k * r); REAL denominator = gsl_sf_bessel_J0(k * a); Omega.push_back(Vect3(0.0, 0.0, -U * 2 * k * sin(theta - theta_dipole) * numerator / denominator)); X.push_back(Vect3((REAL) x, (REAL) y, 0.0)); } } } }
Surf2VolMat::Surf2VolMat(const Geometry& geo, const Matrix& points) { std::map<const Domain, Vertices> m_points; unsigned index = 0; // Find the points per domain and generate the indices for the m_points for ( unsigned i = 0; i < points.nlin(); ++i) { const Domain domain = geo.domain(Vect3(points(i, 0), points(i, 1), points(i, 2))); if ( domain.name() == "Air" ) { std::cerr << " Surf2Vol: Point [ " << points.getlin(i); std::cerr << "] is outside the head. Point is dropped." << std::endl; } else { m_points[domain].push_back(Vertex(points(i, 0), points(i, 1), points(i, 2), index++)); } } assemble_Surf2Vol(geo, *this, m_points); }
void Paddle::Render() { m_renderComp->RenderObject(GetBoundingBox(), PADDLE, Vect3(1.0f, 1.0f, 0.0f)); //PADDLE == enum OH REALLY?! }
vec3_t *G2Exporter_Surface_GetVertCoords(int iSurfaceIndex, int iVertIndex, int iLODIndex) { static vec3_t v3={0}; memset(&v3,0,sizeof(v3)); if (iLODIndex == giNumLODs-1) { // q3data surface... // if (iSurfaceIndex < giNumSurfaces) { // standard surface... // md3SurfaceData_t *pSurfaceData = GetMD3SurfaceData(iSurfaceIndex); if (pSurfaceData) { // this logic is kinda gay, not sure why the *6 etc, but that's how other q3data code works, so... // float **ppVerts = pSurfaceData->verts; static vec3_t v3; for (int i=0; i<3; i++) { v3[i] = ppVerts[0][iVertIndex*6+i];// /MD3_XYZ_SCALE; } // return &v3; Matrix4 Swap; Swap.Identity(); if (1) { Swap.SetRow(0,Vect3(0.0f,-1.0f,0.0f)); Swap.SetRow(1,Vect3(1.0f,0.0f,0.0f)); } Swap.CalcFlags(); Vect3 v3In((const float *)v3); static Vect3 v3Out; Swap.XFormVect(v3Out,v3In); return (vec3_t*) &v3Out; } } else { // tag surface... // assert(iVertIndex<3); md3Tag_t *pTag = &g_data.tags[0][iSurfaceIndex - giNumSurfaces]; vec3_t v3New; //#ifdef PERFECT_CONVERSION v3New[0] = pTag->axis[0][iVertIndex] ; v3New[1] = pTag->axis[1][iVertIndex] ; v3New[2] = pTag->axis[2][iVertIndex] ; // don't worry about how this crap works, it just does (arrived at by empirical methods... :-) // // (mega-thanks to Gil as usual) // if (iVertIndex==2) { VectorCopy(pTag->origin,v3); } else if (iVertIndex==1) { v3New[0] = 2.0f * pTag->axis[1][iG2_TRISIDE_MIDDLE]; v3New[1] = -(2.0f * pTag->axis[0][iG2_TRISIDE_MIDDLE]); v3New[2] = 2.0f * pTag->axis[2][iG2_TRISIDE_MIDDLE]; VectorSubtract(pTag->origin,v3New,v3); } else { v3New[0] = pTag->axis[1][iG2_TRISIDE_LONGEST]; v3New[1] = -pTag->axis[0][iG2_TRISIDE_LONGEST]; v3New[2] = pTag->axis[2][iG2_TRISIDE_LONGEST]; VectorSubtract(pTag->origin,v3New,v3); } // return (vec3_t*) &v3; Matrix4 Swap; Swap.Identity(); if (1) { Swap.SetRow(0,Vect3(0.0f,-1.0f,0.0f)); Swap.SetRow(1,Vect3(1.0f,0.0f,0.0f)); } Swap.CalcFlags(); Vect3 v3In((const float *)v3); static Vect3 v3Out; Swap.XFormVect(v3Out,v3In); return (vec3_t*) &v3Out; } } else { // imported surface... // vec3_t &v3Src = ImportedModel.ImportedLODs[iLODIndex].ImportedSurfaces[ImportedModel.SurfaceIndexRemaps[iSurfaceIndex]].ImportedVerts[iVertIndex].vertCoords; memcpy(v3,v3Src,sizeof(v3)); return &v3; } assert(0); return &v3; }
void BodyRigid::forceAccumReset() { m_appliedForce = Vect3(0,0,0); m_appliedTorque = Vect3(0,0,0); }
int ProcNKeys(TxtNode *t,int& foundkeys) { if (t->child) { TxtNode *sib=t->child; if (!sib->text) return 207; int tp=myatoi(sib->text,sib->length); sib=sib->sibling; if (!sib||!sib->text) return 208; int num=myatoi(sib->text,sib->length); sib=sib->sibling; int i; int lastframe=startframe-1; TxtNode *s=sib; for (i=0;i<num;i++) { if (!s||!s->text) return 110; int frame=myatoi(s->text,s->length); if (frame>33000) frame=frame-65536; if (frame<startframe) { assert(!i); lastframe=frame-1; startframe=frame; } if (frame>endframe) endframe=frame; if (frame-startframe>maxmatframe) maxmatframe=frame-startframe; s=s->sibling; if (!s||!s->text) return 212; int junk=myatoi(s->text,s->length); if (junk!=3) return 213; s=s->sibling; if (!s||!s->text) return 216; float x=(float)myatof(s->text,s->length); s=s->sibling; if (!s||!s->text) return 216; float y=(float)myatof(s->text,s->length); s=s->sibling; if (!s||!s->text) return 216; float z=(float)myatof(s->text,s->length); s=s->sibling; int k; if (tp==1) //scale { Vect3 v=Vect3(x,z,y); for (k=lastframe+1;k<=frame;k++) scales[k-startframe]=v; foundkeys|=4; } else if (tp==2) //translation { Vect3 v(x,-z,y); for (k=lastframe+1;k<=frame;k++) { mats[k-startframe].SetRow(3,v); mats[k-startframe].CalcFlags(); } foundkeys|=1; } else if (tp==3) //rotation { Matrix4 tmp; tmp.Rotate(-x*M_PI/180.0f,-y*M_PI/180.0f,-z*M_PI/180.0f); Vect3 t,tt; tmp.GetRow(2,t); t*=-1.0f; tmp.GetRow(1,tt); tmp.SetRow(2,tt); tmp.SetRow(1,t); for (k=0;k<3;k++) { float tt=-tmp[k][2]; tmp[k][2]=tmp[k][1]; tmp[k][1]=tt; } for (k=lastframe+1;k<=frame;k++) { int l; for (l=0;l<3;l++) { tmp.GetRow(l,t); mats[k-startframe].SetRow(l,t); mats[k-startframe].CalcFlags(); } } foundkeys|=2; } lastframe=frame; } } return 0; }
void TIME_STEPPER::DoFMM() { int nt = 100; for (int I = 0; I < BODY::Bodies.size(); ++I) { Array <REAL> times = UTIL::globalLinspace(BODY::Time, BODY::Time + 1.1*dt, nt); // max timestep change permitted is +- 5% Array <Vect3> EulerHist; Vect3 EulerAnglesTplusDT = UTIL::ODE4(BODY::EulerDot, times, EulerHist, BODY::Bodies[I]->EulerAngles, BODY::Bodies[I]->BodyRates); for (int i = 0; i < BODY::Bodies[I]->Faces.size(); ++i) { BODY::Bodies[I]->Faces[i].XP1 = BODY::Bodies[I]->Faces[i].CollocationPoint; Vect3 MinX = BODY::Bodies[I]->Faces[i].CollocationPoint, MaxX = BODY::Bodies[I]->Faces[i].CollocationPoint; for (int t = 0; t < nt; ++t) { Vect3 CGTplusDT = BODY::Bodies[I]->CG0 + times[t] * BODY::Bodies[I]->Velocity; Array <Vect3> TRANS = BODY::ReturnTrans(EulerHist[t]); Vect3 C1 = CGTplusDT + VectMultMatrix(TRANS, BODY::Bodies[I]->Faces[i].C1o - BODY::Bodies[I]->CG0); Vect3 C2 = CGTplusDT + VectMultMatrix(TRANS, BODY::Bodies[I]->Faces[i].C2o - BODY::Bodies[I]->CG0); Vect3 C3 = CGTplusDT + VectMultMatrix(TRANS, BODY::Bodies[I]->Faces[i].C3o - BODY::Bodies[I]->CG0); Vect3 C4 = CGTplusDT + VectMultMatrix(TRANS, BODY::Bodies[I]->Faces[i].C4o - BODY::Bodies[I]->CG0); Vect3 Xp = 0.25 * (C1 + C2 + C3 + C4); BODY::Bodies[I]->Faces[i].XP2 = Xp; MinX = min(MinX, Xp); MaxX = max(MaxX, Xp); } REAL Buffer = 1.0; MaxX += Vect3(Buffer, Buffer, Buffer); MinX -= Vect3(Buffer, Buffer, Buffer); MinX = floor(MinX) - 0.5; MaxX = ceil(MaxX) + 0.5; int DX = int((MaxX.x) - (MinX.x)); int DY = int((MaxX.y) - (MinX.y)); int DZ = int((MaxX.z) - (MinX.z)); BODY::Bodies[I]->Faces[i].Xp = Array < Array < Array <Vect3*> > > (DX, Array < Array < Vect3*> > (DY, Array <Vect3*> (DZ, NULL))); BODY::Bodies[I]->Faces[i].Vp = Array < Array < Array <Vect3*> > > (DX, Array < Array < Vect3*> > (DY, Array <Vect3*> (DZ, NULL))); for (int a = 0; a < DX; ++a) for (int b = 0; b < DY; ++b) for (int c = 0; c < DZ; ++c) { OctreeCapsule C(MinX + Vect3(1.0 * a, 1.0 * b, 1.0 * c), Vect3(0, 0, 0), false); C.toMonitor = true; globalOctree->Root->EvalCapsule(C); // Any nodes which are created in this step are NOT included in the FVM calculation, and can safely be removed after the FMM/Panel vel calcs... BODY::Bodies[I]->Faces[i].Vp[a][b][c] = C.Ptr2CellVelocity; BODY::Bodies[I]->Faces[i].Xp[a][b][c] = C.Ptr2CellPosition; } } } // // for (int i = 0; i < BODY::AllBodyFaces.size(); ++i) { // Vect3 Xp = BODY::AllBodyFaces[i]->CollocationPoint; // { // Vect3 OwnerCG = BODY::AllBodyFaces[i]->Owner->CG; // Vect3 OwnerVel = BODY::AllBodyFaces[i]->Owner->Velocity; // Vect3 OwnerRates = BODY::AllBodyFaces[i]->Owner->BodyRates; // // Vect3 MinX = Xp, MaxX = Xp; // // for (int nt = 1; nt < 100; ++nt) { // Vect3 PanelVel = OwnerVel + OwnerRates.Cross(Xp - OwnerCG); // // OwnerCG += OwnerVel * dt / 100; // // Xp += dt * PanelVel / 100; // // MinX = min(MinX, Xp); // MaxX = max(MaxX, Xp); // } // // // // // REAL Buffer = 1.0; // MaxX += Vect3(Buffer, Buffer, Buffer); // MinX -= Vect3(Buffer, Buffer, Buffer); // // MinX = floor(MinX) - 0.5; // MaxX = ceil(MaxX) + 0.5; // // int DX = int((MaxX.x) - (MinX.x)); // int DY = int((MaxX.y) - (MinX.y)); // int DZ = int((MaxX.z) - (MinX.z)); // // BODY::AllBodyFaces[i]->Xp = Array < Array < Array <Vect3*> > > (DX, Array < Array < Vect3*> > (DY, Array <Vect3*> (DZ, NULL))); // BODY::AllBodyFaces[i]->Vp = Array < Array < Array <Vect3*> > > (DX, Array < Array < Vect3*> > (DY, Array <Vect3*> (DZ, NULL))); // // for (int a = 0; a < DX; ++a) // for (int b = 0; b < DY; ++b) // for (int c = 0; c < DZ; ++c) { // OctreeCapsule C(MinX + Vect3(1.0 * a, 1.0 * b, 1.0 * c), Vect3(0, 0, 0), false); // C.toMonitor = true; // globalOctree->Root->EvalCapsule(C); // // Any nodes which are created in this step are NOT included in the FVM calculation, and can safely be removed after the FMM/Panel vel calcs... // BODY::AllBodyFaces[i]->Vp[a][b][c] = C.Ptr2CellVelocity; // BODY::AllBodyFaces[i]->Xp[a][b][c] = C.Ptr2CellPosition; // } // // // // } // } globalOctree->ResetAllVelsAndFields(); globalOctree->UpdateLists(); globalOctree->GetVels(); }
void TIME_STEPPER::TimeAdvance() { #ifdef USE_SWSS // This is a SWSS // First TIME_STEPPER::RKStep = 0; // t0: Calc FMM and get DT #ifndef NOFMM if (globalSystem->useFMM) DoFMM(); else { for (int i = 0; i < FVMCell::AllCells.size(); ++i) { FVMCell::AllCells[i]->Velocity = globalSystem->unscaledVinf * SYSTEM::GambitScale; } } #else #pragma omp parallel for for (int i = 0; i < FVMCell::AllCells.size(); ++i) { FVMCell::AllCells[i]->Velocity = 0.0; FVMCell::AllCells[i]->VelGrads[0] = FVMCell::AllCells[i]->VelGrads[1] = FVMCell::AllCells[i]->VelGrads[2] = Vect3(0.0); for (int j = 0; j < FVMCell::AllCells.size(); ++j) { Vect3 D = FVMCell::AllCells[j]->Position - FVMCell::AllCells[i]->Position; FVMCell::AllCells[i]->Velocity += UTIL::globalDirectVel(D, FVMCell::AllCells[j]->Omega); directGradMethod(D, FVMCell::AllCells[j]->Omega, FVMCell::AllCells[i]->VelGrads); } } #endif // t0: calculate face velocities due to body globalSystem->GetFaceVels(); // t0: calculate face velocities due to body time_step(); // t0: get panel FMM Vels #ifndef NOFMM if (globalSystem->useBodies) { globalSystem->GetPanelFMMVelocities(dt); // t0: get time derivatives at t0 // t0: advance innter (body) timestep if (TIME_STEPPER::RK2Mode) BODY::BodySubStep(dt / 2.0, globalSystem->NumSubSteps); else BODY::BodySubStep(dt, globalSystem->NumSubSteps); } #endif /* Order of integrations is as follows: * 0) Panel * 1) stretch * 2) diffuse * 3) O2x * 4) O2y * 5) O2z * * * Other sweep is reverse */ // Record initial vals for (int i = 0; i < FVMCell::AllCells.size(); ++i) { FVMCell::AllCells[i]->VelHold = FVMCell::AllCells[i]->Velocity; // this is done in vCollapseVelField FVMCell::AllCells[i]->VelGradsHold = FVMCell::AllCells[i]->VelGrads; // this is done in vCollapseVelField for (int q = 0; q < SYSTEM::NumTransVars; ++q) FVMCell::AllCells[i]->TransVarsHold[q] = FVMCell::AllCells[i]->TransVars[q]; FVMCell::AllCells[i]->OmegaHold = FVMCell::AllCells[i]->Omega; } if (globalSystem->useFMM) { globalOctree->DiffuseZAndAdvance(dt); globalOctree->StretchAndAdvance(dt); globalOctree->DiffuseYAndAdvance(dt); } globalOctree->O2UWxAndAdvance(dt); globalOctree->O2UWyAndAdvance(dt); globalOctree->O2UWzAndAdvance(dt); if (globalSystem->useFMM) globalOctree->DiffuseXAndAdvance(dt); // Second sweep // Reset initial values -- VelHold is still unchanged - can be reused; same with its gradients #ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < FVMCell::AllCells.size(); ++i) { for (int q = 0; q < SYSTEM::NumTransVars; ++q) { FVMCell::AllCells[i]->TransVars0[q] = FVMCell::AllCells[i]->TransVars[q]; FVMCell::AllCells[i]->TransVars[q] = FVMCell::AllCells[i]->TransVarsHold[q]; } FVMCell::AllCells[i]->Velocity = FVMCell::AllCells[i]->VelHold; FVMCell::AllCells[i]->VelGrads = FVMCell::AllCells[i]->VelGradsHold; FVMCell::AllCells[i]->Omega = FVMCell::AllCells[i]->OmegaHold; } if (globalSystem->useFMM) globalOctree->DiffuseXAndAdvance(dt); globalOctree->O2UWzAndAdvance(dt); globalOctree->O2UWyAndAdvance(dt); globalOctree->O2UWxAndAdvance(dt); if (globalSystem->useFMM) { globalOctree->DiffuseYAndAdvance(dt); globalOctree->StretchAndAdvance(dt); globalOctree->DiffuseZAndAdvance(dt); } for (int i = 0; i < FVMCell::AllCells.size(); ++i) { FVMCell::AllCells[i]->Omega = Vect3(0.0); for (int q = 0; q < SYSTEM::NumTransVars; ++q) { Vect3 VarTmp = FVMCell::AllCells[i]->TransVars[q]; FVMCell::AllCells[i]->TransVars [q] = 0.5 * (FVMCell::AllCells[i]->TransVars0[q] + VarTmp); FVMCell::AllCells[i]->Omega += FVMCell::AllCells[i]->TransVars[q]; } } #else // t0: get cell velocities/gradients etc. DoFMM(); // t0: calculate face velocities due to body globalSystem->GetFaceVels(); // t0: calculate timestep length (use last values of panel singularity strengths for body influence) time_step(); // t0: get panel FMM Vels // if (globalSystem->useBodies) // globalSystem->GetPanelFMMVelocities(0.0); // globalSystem->GetFaceVels(); FVMCell::CellDerivs.allocate(SYSTEM::NumTransVars); for (int q = 0; q < SYSTEM::NumTransVars; ++q) { FVMCell::CellDerivs[q] = Array <Vect3> (FVMCell::AllCells.size()); #ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < FVMCell::AllCells.size(); ++i) { FVMCell::CellDerivs[q][i] = FVMCell::AllCells[i]->O2UW(q); FVMCell::CellDerivs[q][i] += FVMCell::AllCells[i]->Stretch(q); // FVMCell::CellDerivs[q][i] += FVMCell::AllCells[i]->Diffuse(q); } #ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < FVMCell::AllCells.size(); ++i) FVMCell::AllCells[i]->TransVars[q] += dt * FVMCell::CellDerivs[q][i]; } #ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < FVMCell::AllCells.size(); ++i) FVMCell::AllCells[i]->NormaliseObliterate(); // Update cell velocities to reflect new cell omegas #ifdef _OPENMP #pragma omp parallel for #endif for (int i = 0; i < FVMCell::AllCells.size(); ++i) FVMCell::AllCells[i]->GetISAVels(); // Now update Panel FMM Vels to reflect new velocities then advance over timestep if (globalSystem->useBodies) { globalSystem->GetPanelFMMVelocities(dt); BODY::BodySubStep(dt, globalSystem->NumSubSteps); } // if (TIME_STEPPER::RK2Mode) { // TIME_STEPPER::RKStep = 1; // // t*: Do the FMM again // DoFMM(); // if (globalSystem->useBodies) { // globalSystem->GetPanelFMMVelocities(dt / 2); // BODY::BodySubStep(dt / 2.0, globalSystem->NumSubSteps); // t = t0 -> t* // // t*: calculate face velocities due to body // } // globalSystem->GetFaceVels(); // // t*: calculate gradients at t* // globalOctree->FVM(); // dom_dt(t*) // // t*: advance to t1 // globalOctree->Integrate(); // t = t0 -> t1 // } #endif // Put the wake in the tree from the bodytimestep if (globalSystem->useBodies) { globalSystem->PutWakesInTree(); } else TIME_STEPPER::SimTime += dt; // Clean up if (!fmod((REAL) n, 25.0)) PruneNow = true; globalOctree->Reset(); }