//! \brief compute compute the source term of the collision //! model: electric force + true collisions void VlasovP_Lagrangian_Source(const real* x, const real t, const real* w, real* source, int m) { real E=w[_INDEX_EX]; // electric field real Md[_INDEX_MAX_KIN+1]; real db[_INDEX_MAX_KIN+1]; for(int iv=0;iv<_INDEX_MAX_KIN+1;iv++){ Md[iv]=0; db[iv]=0; } for(int iv=0;iv<_INDEX_MAX_KIN+1;iv++){ source[iv]=0; } // no source on the potential for the moment source[_INDEX_PHI]=0; source[_INDEX_EX]=0; source[_INDEX_RHO]=0; //rho init source[_INDEX_VELOCITY]=0; // u init source[_INDEX_PRESSURE]=0; // p init source[_INDEX_TEMP]=0; // loop on the finite emlements for(int iel=0;iel<_NB_ELEM_V;iel++){ // loop on the local glops for(int kloc=0;kloc<_DEG_V+1;kloc++){ real omega=wglop(_DEG_V,kloc); int kpg=kloc+iel*_DEG_V; Md[kpg]+=omega*_DV; for(int iloc=0;iloc<_DEG_V+1;iloc++){ int ipg=iloc+iel*_DEG_V; source[ipg]+=E*omega*w[kpg]*dlag(_DEG_V,iloc,kloc); if (iloc==kloc) db[ipg]+=E*omega*dlag(_DEG_V,iloc,kloc); } } } // upwinding if (E>0){ source[_INDEX_MAX_KIN]-=E*w[_INDEX_MAX_KIN]; db[_INDEX_MAX_KIN]-=E; } else { source[0]-=-E*w[0]; db[0]-=-E; } for(int iv=0;iv<_INDEX_MAX_KIN+1;iv++){ source[iv]/=Md[iv]; //printf("%f ",source[iv]); } }
real local_kinetic_energy(field *f,real *x, real *w) { real wex[_INDEX_MAX]; real l_ke=0; real t=f->tnow; // loop on the finite emlements for(int iel = 0; iel < _NB_ELEM_V; iel++){ // loop on the local glops for(int iloc = 0; iloc < _DEG_V + 1; iloc++){ real omega = wglop(_DEG_V, iloc); real vi = -_VMAX + iel * _DV + _DV * glop(_DEG_V, iloc); int ipg = iloc + iel * _DEG_V; l_ke += omega * _DV * w[ipg] * vi * vi ; } } return l_ke; }
//! \brief compute square of velocity L2 error //! \param[in] w : values of f at glops //! \param[in] x : point of the mesh //! \param[in] t : time //! \param[in] t : type of L2norm. if type_norm=0 this is the //! numerical solution if type_norm=1 this is the error real L2VelError(field *f, real *x, real *w){ real wex[_INDEX_MAX]; real err2 = 0; real t = f->tnow; f->model.ImposedData(x, t, wex); // loop on the finite emlements for(int iel = 0; iel < _NB_ELEM_V; iel++){ // loop on the local glops for(int iloc = 0; iloc < _DEG_V + 1; iloc++){ real omega = wglop(_DEG_V, iloc); real vi = -_VMAX + iel*_DV + _DV * glop(_DEG_V, iloc); int ipg = iloc + iel * _DEG_V; err2 += omega * _DV * (w[ipg] - wex[ipg]) * (w[ipg] - wex[ipg]); } } return err2; }
void ADERTimeStep(ADERDG* adg) { double dt = adg->dt_small; // first, predict the values of w at an intermediate time step for(int ie = 1;ie <= _NBELEMS_IN; ie++) { Predictor(adg, ie, dt / 2); } // init the derivative to zero for(int ie = 1; ie<= _NBELEMS_IN; ie++) { for(int i = 0; i < _NGLOPS; i++) { for(int iv = 0; iv < _M; iv++) { adg->dtw[ie][i][iv]=0; } } } // impose the exact values on boundary left and right cells double x = adg->face[0]; double t = adg->tnow + dt / 2 ; ExactSol(x, t, adg->wpred[0][_D]); // _D = last point of left cell x = adg->face[_NBFACES-1]; // 0 = first point of right cell ExactSol(x, t, adg->wpred[_NBELEMS_IN + 1][0]); // compute the face flux terms // loop on the faces for(int i = 0; i < _NBFACES; i++){ double *wL, *wR; double flux[_M]; int ie = i; wL = adg->wpred[ie][_D]; // _D = last point of left cell wR = adg->wpred[ie+1][0]; // 0 = first point of right cell NumFlux(wL, wR, flux); for (int k = 0; k < _M; k++){ adg->dtw[ie][_D][k] -= flux[k]; adg->dtw[ie+1][0][k] += flux[k]; } } // compute the volume terms for(int ie = 1; ie<= _NBELEMS_IN; ie++){ double h = adg->face[ie] - adg->face[ie-1]; // loop on the glops i for(int i = 0; i < _NGLOPS; i++){ // integration weight double omega = wglop(_D, i) * h; // flux at glop i double flux[_M]; NumFlux(adg->wpred[ie][i], adg->wpred[ie][i], flux); // loop on the basis functions j for(int j = 0; j < _D+1; j++){ // derivative of basis function j at glop i double dd = dlag(_D, j, i) / h; for (int k = 0; k < _M; k++){ adg->dtw[ie][j][k] += omega * dd * flux[k]; } } } } // divide by the mass matrix for(int ie = 1; ie<= _NBELEMS_IN; ie++){ double h = adg->face[ie] - adg->face[ie-1]; for(int i = 0; i < _NGLOPS; i++){ double omega = wglop(_D, i) * h; for (int k = 0; k < _M; k++){ adg->dtw[ie][i][k] /= omega; } } } // update wnext and // copy wnext into wnow for the next time step for(int ie = 1; ie<= _NBELEMS_IN; ie++){ for(int i = 0; i < _NGLOPS; i++){ for(int iv = 0; iv < _M; iv++){ adg->wnext[ie][i][iv] = adg->wnow[ie][i][iv] + dt * adg->dtw[ie][i][iv]; adg->wnow[ie][i][iv] = adg->wnext[ie][i][iv]; } } } }
// inter-subcell fluxes void* DGSubCellInterface(void* mc){ MacroCell* mcell = (MacroCell*) mc; Field* f= mcell->field; // loop on the elements for (int ie=mcell->first_cell;ie<mcell->last_cell_p1;ie++){ // get the physical nodes of element ie double physnode[20][3]; for(int inoloc=0;inoloc<20;inoloc++){ int ino=f->macromesh.elem2node[20*ie+inoloc]; physnode[inoloc][0]=f->macromesh.node[3*ino+0]; physnode[inoloc][1]=f->macromesh.node[3*ino+1]; physnode[inoloc][2]=f->macromesh.node[3*ino+2]; } const int nraf[3]={f->interp_param[4], f->interp_param[5], f->interp_param[6]}; const int deg[3]={f->interp_param[1], f->interp_param[2], f->interp_param[3]}; const int npg[3] = {deg[0]+1, deg[1]+1, deg[2]+1}; const int m = f->model.m; // loop on the subcells //#pragma omp parallel for collapse(3) for(int icL0 = 0; icL0 < nraf[0]; icL0++){ for(int icL1 = 0; icL1 < nraf[1]; icL1++){ for(int icL2 = 0; icL2 < nraf[2]; icL2++){ int icL[3]={icL0,icL1,icL2}; // get the left subcell id int ncL=icL[0]+nraf[0]*(icL[1]+nraf[1]*icL[2]); // first glop index in the subcell int offsetL=npg[0]*npg[1]*npg[2]*ncL; // sweeping subcell faces in the three directions for(int dim0 = 0; dim0 < 3; dim0++){ // compute the subface flux only // if we do not touch the subcell boundary // along the current direction dim0 if (icL[dim0] != nraf[dim0]-1) { int icR[3]={icL[0],icL[1],icL[2]}; // The right cell index corresponds to an increment in // the dim0 direction icR[dim0]++; int ncR=icR[0]+nraf[0]*(icR[1]+nraf[1]*icR[2]); int offsetR=npg[0]*npg[1]*npg[2]*ncR; // FIXME: write only write to L-values (and do both // faces) to parallelise better. const int altdim1[3]={1,0,0}; const int altdim2[3]={2,2,1}; // now loop on the left glops of the subface //int dim1=(dim0+1)%3, dim2=(dim0+2)%3; int dim1=altdim1[dim0], dim2=altdim2[dim0]; int iL[3]; iL[dim0] = deg[dim0]; for(iL[dim2] = 0; iL[dim2] < npg[dim2]; iL[dim2]++){ for(iL[dim1] = 0; iL[dim1] < npg[dim1]; iL[dim1]++){ // find the right and left glops volume indices int iR[3] = {iL[0],iL[1],iL[2]}; iR[dim0] = 0; int ipgL=offsetL+iL[0]+(deg[0]+1)*(iL[1]+(deg[1]+1)*iL[2]); int ipgR=offsetR+iR[0]+(deg[0]+1)*(iR[1]+(deg[1]+1)*iR[2]); //printf("ipgL=%d ipgR=%d\n",ipgL,ipgR); // Compute the normal vector for integrating on the // face double vnds[3]; { double xref[3], wpg3; ref_pg_vol(f->interp_param+1,ipgL,xref,&wpg3,NULL); // mapping from the ref glop to the physical glop double dtau[3][3],codtau[3][3]; Ref2Phy(physnode, xref, NULL, // dphiref -1, // ifa NULL, // xphy dtau, codtau, NULL, // dphi NULL); // vnds // we compute ourself the normal vector because we // have to take into account the subcell surface double h1h2=1./nraf[dim1]/nraf[dim2]; vnds[0] = codtau[0][dim0]*h1h2; vnds[1] = codtau[1][dim0]*h1h2; vnds[2] = codtau[2][dim0]*h1h2; } // numerical flux from the left and right state and // normal vector double wL[m],wR[m],flux[m]; for(int iv=0; iv < m; iv++){ int imemL=f->varindex(f->interp_param,ie,ipgL,iv); int imemR=f->varindex(f->interp_param,ie,ipgR,iv); wL[iv] = f->wn[imemL]; wR[iv] = f->wn[imemR]; } f->model.NumFlux(wL,wR,vnds,flux); // subcell ref surface glop weight double wpg = wglop(deg[dim1],iL[dim1]) * wglop(deg[dim2],iL[dim2]); /* printf("vnds %f %f %f flux %f wpg %f\n", */ /* vnds[0],vnds[1],vnds[2], */ /* flux[0],wpg); */ // finally distribute the flux on the two sides for(int iv=0; iv < m; iv++){ int imemL = f->varindex(f->interp_param, ie, ipgL, iv); int imemR = f->varindex(f->interp_param, ie, ipgR, iv); f->dtwn[imemL] -= flux[iv] * wpg; f->dtwn[imemR] += flux[iv] * wpg; } } // face yhat loop } // face xhat loop } // endif internal face } // dim loop } // subcell icl2 loop } // subcell icl1 loop } // subcell icl0 loop } // macro elem loop return NULL; }