// This is a user-supplied routine that sets the the boundary conditions // void SetBndValues_Unst(const mesh& Mesh, dTensor3* q, dTensor3* aux) { int meqn = q->getsize(2); int kmax = q->getsize(3); int maux = aux->getsize(2); int NumElems = Mesh.get_NumElems(); int NumPhysElems = Mesh.get_NumPhysElems(); int NumGhostElems = Mesh.get_NumGhostElems(); int NumNodes = Mesh.get_NumNodes(); int NumPhysNodes = Mesh.get_NumPhysNodes(); int NumEdges = Mesh.get_NumEdges(); // ---------------------------------------- // Loop over each ghost cell element and // place the correct information into // these elements // ---------------------------------------- for (int i=1; i<=NumGhostElems; i++) { int j = Mesh.get_ghost_link(i); for (int m=1; m<=meqn; m++) for (int k=1; k<=kmax; k++) { q->set(i+NumPhysElems,m,k, 0.0 ); } } }
// This is a user-supplied routine that sets the the boundary conditions // // The default routine for the 4D Vlasov code is to apply zero boundary // conditions in configuration space. This routine is identical to the one // found in the unst branch of the 2D DoGPack code, and *should* be setting // periodic boundary conditions. // void SetBndValues_Unst(const mesh& Mesh, dTensor3* q, dTensor3* aux) { // problem information (If this were to be pulled from DogParams, these // numbers would NOT be correct! The reason is that each quadrature point // was actually saved as a separate "equation") const int meqn = q->getsize(2); const int kmax = q->getsize(3); const int maux = aux->getsize(2); // Mesh information const int NumElems = Mesh.get_NumElems(); const int NumPhysElems = Mesh.get_NumPhysElems(); const int NumGhostElems = Mesh.get_NumGhostElems(); const int NumNodes = Mesh.get_NumNodes(); const int NumPhysNodes = Mesh.get_NumPhysNodes(); const int NumEdges = Mesh.get_NumEdges(); // ---------------------------------------- // Loop over each ghost cell element and // place the correct information into // these elements // ---------------------------------------- for (int i=1; i<=NumGhostElems; i++) { int j = Mesh.get_ghost_link(i); for (int m=1; m<=meqn; m++) for (int k=1; k<=kmax; k++) { q->set(i+NumPhysElems, m, k, q->get(j, m, k) ); } } }
// // Output basic mesh information to screen // void ScreenOutput(const mesh& Mesh) { // Compute mesh quality parameters double totalarea = Mesh.get_area_prim(1); double maxarea = Mesh.get_area_prim(1); double minarea = Mesh.get_area_prim(1); for (int i=2; i<=Mesh.get_NumPhysElems(); i++) { double tmp = Mesh.get_area_prim(i); totalarea = totalarea + tmp; if (tmp < minarea) { minarea = tmp; } if (tmp > maxarea) { maxarea = tmp; } } double minAngle = 180.0; for (int i=1; i<=Mesh.get_NumPhysElems(); i++) { const int i1 = Mesh.get_tnode(i,1); const int i2 = Mesh.get_tnode(i,2); const int i3 = Mesh.get_tnode(i,3); point v12, v23, v31; v12.x = Mesh.get_node(i2,1) - Mesh.get_node(i1,1); v12.y = Mesh.get_node(i2,2) - Mesh.get_node(i1,2); v23.x = Mesh.get_node(i3,1) - Mesh.get_node(i2,1); v23.y = Mesh.get_node(i3,2) - Mesh.get_node(i2,2); v31.x = Mesh.get_node(i1,1) - Mesh.get_node(i3,1); v31.y = Mesh.get_node(i1,2) - Mesh.get_node(i3,2); double angle1 = acos((v12.x*-v31.x+v12.y*-v31.y) /(sqrt(v12.x*v12.x+v12.y*v12.y)*sqrt(v31.x*v31.x+v31.y*v31.y))); double angle2 = acos((v23.x*-v12.x+v23.y*-v12.y) /(sqrt(v23.x*v23.x+v23.y*v23.y)*sqrt(v12.x*v12.x+v12.y*v12.y))); double angle3 = acos((v31.x*-v23.x+v31.y*-v23.y) /(sqrt(v31.x*v31.x+v31.y*v31.y)*sqrt(v23.x*v23.x+v23.y*v23.y))); if ((angle1*180/pi) < minAngle) { minAngle = angle1*180/pi; } if ((angle2*180/pi) < minAngle) { minAngle = angle2*180/pi; } if ((angle3*180/pi) < minAngle) { minAngle = angle3*180/pi; } } // Output summary of results to screen printf("\n"); printf(" SUMMARY OF RESULTS:\n"); printf(" -------------------\n"); printf(" Number of Elements: %8i\n",Mesh.get_NumElems()); printf(" Number of Physical Elements: %8i\n",Mesh.get_NumPhysElems()); printf(" Number of Ghost Elements: %8i\n",Mesh.get_NumGhostElems()); printf(" Number of Nodes: %8i\n",Mesh.get_NumNodes()); printf(" Number of Physical Nodes: %8i\n",Mesh.get_NumPhysNodes()); printf(" Number of Boundary Nodes: %8i\n",Mesh.get_NumBndNodes()); printf(" Number of Edges: %8i\n",Mesh.get_NumEdges()); printf(" Number of Boundary Edges: %8i\n",Mesh.get_NumBndEdges()); printf("\n"); printf(" Total Area Covered: %24.16e\n",totalarea); printf(" Area Ratio: small/large: %24.16e\n",minarea/maxarea); printf(" Angle Ratio: minAngle/60: %24.16e\n",minAngle/60.0); printf("\n"); }
// This file should be identical to DogSolveRK_Unst, with the exception that all // output printing statements are silenced. // // Advance the solution qold to qnew over time interval tstart to tend. // // All local information is allocated within this function. The only part // that gets shared are time values passed through dogStateUnst2. This class // should be modified to accept the state variable, q and aux in place of only // containing time information as is currently the case. (-DS) double DogSolveRK_Unst_Quiet( const dTensor2* vel_vec, const mesh& Mesh, const edge_data_Unst& EdgeData, dTensor3& aux, dTensor3& qold, dTensor3& qnew, const double tstart, const double tend, DogStateUnst2& dogStateUnst2) { const int mx = qnew.getsize(1); const int meqn = qnew.getsize(2); const int kmax = qnew.getsize(3); const int maux = aux.getsize(2); const double* cflv = dogParams.get_cflv(); const int nv = dogParams.get_nv(); RKinfo rk; SetRKinfo(dogParams.get_time_order(),rk); // define local variables int n_step = 0; double t = tstart; double dt = dogStateUnst2.get_initial_dt(); const double CFL_max = cflv[1]; const double CFL_target = cflv[2]; double cfl = 0.0; double dtmin = dt; double dtmax = dt; const int NumElems = Mesh.get_NumElems(); // Number of total elements in mesh const int NumNodes = Mesh.get_NumNodes(); // Number of nodes in mesh const int NumEdges = Mesh.get_NumEdges(); // Number of edges in mesh dTensor3 qstar(NumElems,meqn,kmax); dTensor3 q1(NumElems,meqn,kmax); dTensor3 q2(NumElems,meqn,kmax); dTensor3 auxstar(NumElems,maux,kmax); dTensor3 Lstar(NumElems,meqn,kmax); dTensor3 Lold(NumElems,meqn,kmax); dTensor3 auxold(NumElems,maux,kmax); dTensor1 smax(NumEdges); void L2Project_Unst( const dTensor2* vel_vec, const int istart, const int iend, const int QuadOrder, const int BasisOrder_qin, const int BasisOrder_auxin, const int BasisOrder_fout, const mesh& Mesh, const dTensor3* qin, const dTensor3* auxin, dTensor3* fout, void (*Func)(const dTensor2* vel_vec, const dTensor2&,const dTensor2&, const dTensor2&,dTensor2&)); // JUNK here: void AuxFuncWrapper( const dTensor2* vel_vec, const dTensor2& xpts, const dTensor2& NOT_USED_1, const dTensor2& NOT_USED_2, dTensor2& auxvals); const int space_order = dogParams.get_space_order(); if( maux > 0 ) { printf("WARNING: maux = %d should be zero for Vlasov routines.", maux); printf(" Modify parameters.ini to remove this warning\n" ); L2Project_Unst(vel_vec,1,NumElems, space_order,space_order,space_order,space_order, Mesh,&qnew,&aux,&aux,&AuxFuncWrapper); } // Set initialize qstar and auxstar values qstar.copyfrom(qold); auxstar.copyfrom(aux); // Runge-Kutta time stepping while (t<tend) { // initialize time step int m_accept = 0; n_step = n_step + 1; // check if max number of time steps exceeded if( n_step > nv ) { eprintf(" Error in DogSolveRK_Unst.cpp: " " Exceeded allowed # of time steps \n" " n_step = %d\n" " nv = %d\n\n", n_step, nv); } // copy qnew into qold qold.copyfrom(qnew); auxold.copyfrom(aux); // keep trying until we get a dt that does not violate CFL condition while (m_accept==0) { // set current time double told = t; if (told+dt > tend) { dt = tend - told; } t = told + dt; // TODO - this needs to be performed at the 'local' level dogStateUnst2.set_time ( told ); dogStateUnst2.set_dt ( dt ); // Set initial maximum wave speed to zero smax.setall(0.); // Take a full time step of size dt switch ( dogParams.get_time_order() ) { case 1: // First order in time (1-stage) // ----------------------------------------------- // Stage #1 (the only one in this case) rk.mstage = 1; BeforeStep_Unst(dt,Mesh,aux,qnew); ConstructL_Unst(told, vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux, qnew, Lstar, qnew); AfterStep_Unst(dt,Mesh,aux,qnew); // ----------------------------------------------- break; case 2: // Second order in time (2-stages) // ----------------------------------------------- // Stage #1 rk.mstage = 1; dogStateUnst2.set_time(told); BeforeStep_Unst(dt,Mesh,aux,qnew); ConstructL_Unst(told,vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax); UpdateSoln_Unst( rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage), dt, Mesh, aux, qnew, Lstar, qstar); AfterStep_Unst(dt, Mesh, auxstar, qstar); // ------------------------------------------------ // Stage #2 rk.mstage = 2; dogStateUnst2.set_time(told+dt); BeforeStep_Unst(dt, Mesh, auxstar, qstar); ConstructL_Unst(told+1.0*dt, vel_vec, Mesh, EdgeData, aux, qstar, Lstar, smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage), rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage), dt, Mesh, auxstar, qstar, Lstar, qnew); AfterStep_Unst(dt, Mesh, aux, qnew); // ------------------------------------------------ break; case 3: // Third order in time (3-stages) // qnew = alpha1 * qstar + alpha2 * qnew + beta * dt * L( qstar ) // alpha1 = 1.0 // alpha2 = 0.0 // beta = 1.0 // ------------------------------------------------ // Stage #1 rk.mstage = 1; dogStateUnst2.set_time(told); BeforeStep_Unst(dt,Mesh,aux,qnew); ConstructL_Unst(told, vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax); Lold.copyfrom(Lstar); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux,qnew,Lstar,qstar); AfterStep_Unst(dt,Mesh,aux,qstar); // ------------------------------------------------- // alpha1 = 0.75 // alpha2 = 0.25 // beta = 0.25 // Stage #2 rk.mstage = 2; dogStateUnst2.set_time(told+0.5*dt); BeforeStep_Unst(dt,Mesh,aux,qstar); ConstructL_Unst(told+dt, vel_vec,Mesh,EdgeData,aux,qstar,Lstar,smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux,qnew,Lstar,qstar); AfterStep_Unst(dt,Mesh,aux,qstar); // -------------------------------------------------- // alpha1 = 2/3 // alpha2 = 1/3 // beta = 2/3 // Stage #3 rk.mstage = 3; dogStateUnst2.set_time(told+dt); BeforeStep_Unst(dt,Mesh,auxstar,qstar); ConstructL_Unst(told+0.5*dt,vel_vec,Mesh,EdgeData,auxstar,qstar,Lstar,smax); UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage), rk.beta->get(rk.mstage),dt,Mesh,aux,qstar,Lstar,qnew); AfterStep_Unst(dt,Mesh,aux,qnew); // -------------------------------------------------- break; default: unsupported_value_error(dogParams.get_time_order()); } // compute cfl number cfl = GetCFL_Unst(dt,Mesh,aux,smax); // output time step information // if (dogParams.get_verbosity()>0) // { // printf(" In DogSolveRK_Quiet: DogSolve2D ... Step %5d" // " CFL =%6.3f" // " dt =%11.3e" // " t =%11.3e\n", // n_step, cfl, dt, t); // } // choose new time step if (cfl>0.0) { dt = Min(dogParams.get_max_dt(), dt*CFL_target/cfl); dtmin = Min(dt,dtmin); dtmax = Max(dt,dtmax); } else { dt = dogParams.get_max_dt(); } // see whether to accept or reject this step if (cfl<=CFL_max) // accept { m_accept = 1; dogStateUnst2.set_time(t); // do any extra work // AfterFullTimeStep_Unst(dogStateUnst2.get_dt(),Mesh, // auxold,qold,Lold,aux,qnew); } else //reject { t = told; dogStateUnst2.set_time(told); // if( dogParams.get_verbosity() > 0 ) // { // printf("DogSolve2D rejecting step..." // "CFL number too large\n"); // } // copy qold into qnew qnew.copyfrom(qold); aux.copyfrom(auxold); // after reject function // AfterReject_Unst(Mesh,dt,aux,qnew); } } } // printf(" Finished! t = %2.3e and nsteps = %d\n", t, n_step ); // set initial time step for next call to DogSolveRK dogStateUnst2.set_initial_dt(dt); void DeleteRKInfo(RKinfo& rk); DeleteRKInfo(rk); return cfl; }