示例#1
0
//! \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]);
  }
}
示例#2
0
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;
}
示例#3
0
//! \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;
}
示例#4
0
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];
      }
    }
  }
 
}
示例#5
0
// 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;

}