//! \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]); } }
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]; } } } }
// compute the Discontinuous Galerkin volume terms // fast version void* DGVolume(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 m = f->model.m; 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 nraf[3]={f->interp_param[4], f->interp_param[5], f->interp_param[6]}; const unsigned int sc_npg=npg[0]*npg[1]*npg[2]; int f_interp_param[8]= {f->interp_param[0], f->interp_param[1], f->interp_param[2], f->interp_param[3], f->interp_param[4], f->interp_param[5], f->interp_param[6], f->interp_param[7]}; // loop on the subcells 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 L 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; // compute all of the xref for the subcell double *xref0 = malloc(sc_npg * sizeof(double)); double *xref1 = malloc(sc_npg * sizeof(double)); double *xref2 = malloc(sc_npg * sizeof(double)); double *omega = malloc(sc_npg * sizeof(double)); int *imems = malloc(m * sc_npg * sizeof(int)); int pos=0; for(unsigned int p=0; p < sc_npg; ++p) { double xref[3]; double tomega; ref_pg_vol(f->interp_param+1,offsetL+p,xref,&tomega,NULL); xref0[p] = xref[0]; xref1[p] = xref[1]; xref2[p] = xref[2]; omega[p] = tomega; for(int im=0; im < m; ++im) { imems[pos++] = f->varindex(f_interp_param,ie,offsetL+p,im); } } // loop in the "cross" in the three directions for(int dim0 = 0; dim0 < 3; dim0++){ // point p at which we compute the flux for(int p0 = 0; p0 < npg[0]; p0++){ for(int p1 = 0; p1 < npg[1]; p1++){ for(int p2 = 0; p2 < npg[2]; p2++){ double wL[m],flux[m]; int p[3]={p0,p1,p2}; int ipgL=offsetL+p[0]+npg[0]*(p[1]+npg[1]*p[2]); for(int iv=0; iv < m; iv++){ ///int imemL=f->varindex(f_interp_param,ie,ipgL,iv); wL[iv] = f->wn[imems[m*(ipgL-offsetL)+iv]]; /// big bug !!!! //wL[iv] = f->wn[imemL]; } int q[3]={p[0],p[1],p[2]}; // loop on the direction dim0 on the "cross" for(int iq = 0; iq < npg[dim0]; iq++){ q[dim0]=(p[dim0]+iq)%npg[dim0]; double dphiref[3]={0,0,0}; // compute grad phi_q at glop p dphiref[dim0]=dlag(deg[dim0],q[dim0],p[dim0])*nraf[dim0]; double xrefL[3]={xref0[ipgL-offsetL], xref1[ipgL-offsetL], xref2[ipgL-offsetL]}; double wpgL=omega[ipgL-offsetL]; /* double xrefL[3], wpgL; */ /* ref_pg_vol(f->interp_param+1,ipgL,xrefL,&wpgL,NULL); */ // mapping from the ref glop to the physical glop double dtau[3][3],codtau[3][3],dphiL[3]; Ref2Phy(physnode, xrefL, dphiref, // dphiref -1, // ifa NULL, // xphy dtau, codtau, dphiL, // dphi NULL); // vnds f->model.NumFlux(wL,wL,dphiL,flux); int ipgR=offsetL+q[0]+npg[0]*(q[1]+npg[1]*q[2]); for(int iv=0; iv < m; iv++){ //int imemR=f->varindex(f_interp_param,ie,ipgR,iv); f->dtwn[imems[m*(ipgR-offsetL)+iv]]+=flux[iv]*wpgL; } } // iq } // p2 } // p1 } // p0 } // dim loop free(omega); free(xref0); free(xref1); free(xref2); free(imems); } // icl2 } //icl1 } // icl0 } return NULL; }