Beispiel #1
0
// display the field on screen
void DisplayField(Field* f){
  //int param[8]={f->model.m,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
 
  printf("Display field...\n");
  for(int ie=0;ie<f->macromesh.nbelems;ie++){
    printf("elem %d\n",ie);
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      double xref[3],wpg;
      ref_pg_vol(f->interp_param+1,ipg,xref,&wpg,NULL);

      printf("Gauss point %d %f %f %f \n",ipg,xref[0],xref[1],xref[2]);
      printf("dtw= ");
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	printf("%f ",f->dtwn[imem]);
      }
      printf("\n");
      printf("w= ");
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	printf("%f ",f->wn[imem]);
      }
      printf("\n");
    }
  }



};
Beispiel #2
0
int TestFieldDG(void){

  int test = (1==1);

  Field f;
  f.model.m=1; // only one conservative variable
  f.model.NumFlux=TransportNumFlux;
  f.model.BoundaryFlux=TestTransportBoundaryFlux;
  f.model.InitData=TestTransportInitData;
  f.model.ImposedData=TestTransportImposedData;
  f.varindex=GenericVarindex;

  f.interp.interp_param[0]=1;  // _M
  f.interp.interp_param[1]=2;  // x direction degree
  f.interp.interp_param[2]=2;  // y direction degree
  f.interp.interp_param[3]=2;  // z direction degree
  f.interp.interp_param[4]=1;  // x direction refinement
  f.interp.interp_param[5]=1;  // y direction refinement
  f.interp.interp_param[6]=1;  // z direction refinement


  ReadMacroMesh(&(f.macromesh),"test/testcube.msh");
  BuildConnectivity(&(f.macromesh));

  PrintMacroMesh(&(f.macromesh));
  //AffineMapMacroMesh(&(f.macromesh));
  PrintMacroMesh(&(f.macromesh));


  InitField(&f);
  CheckMacroMesh(&(f.macromesh),f.interp.interp_param+1);


  dtField(&f);
  
  DisplayField(&f);  

  int yes_compare = 1;
  int no_compare = 0;

  PlotField(0,no_compare,&f,"visu.msh");
  PlotField(0,yes_compare,&f,"error.msh");

  // test the time derivative with the exact solution
  for(int i=0;i<f.model.m * f.macromesh.nbelems * 
	NPG(f.interp.interp_param+1);i++){
    test = test && fabs(4*f.wn[i]-pow(f.dtwn[i],2))<1e-2;
    assert(test);
  }
  
  return test;



};
Beispiel #3
0
int TestfieldDG()
{
  int test = true;

  field f;
  init_empty_field(&f);
  
  f.model.cfl = 0.05;
  f.model.m = 1; // only one conservative variable
  f.model.NumFlux = TransNumFlux;
  f.model.BoundaryFlux = TestTransBoundaryFlux;
  f.model.InitData = TestTransInitData;
  f.model.ImposedData = TestTransImposedData;
  f.model.Source = NULL;
  f.varindex = GenericVarindex;

  f.interp.interp_param[0] = 1; // _M
  f.interp.interp_param[1] = 2; // x direction degree
  f.interp.interp_param[2] = 2; // y direction degree
  f.interp.interp_param[3] = 2; // z direction degree
  f.interp.interp_param[4] = 2; // x direction refinement
  f.interp.interp_param[5] = 2; // y direction refinement
  f.interp.interp_param[6] = 2; // z direction refinement

  ReadMacroMesh(&(f.macromesh), "../test/testcube2.msh");
  //ReadMacroMesh(&(f.macromesh),"test/testmacromesh.msh");
  BuildConnectivity(&(f.macromesh));

  PrintMacroMesh(&(f.macromesh));
  //AffineMapMacroMesh(&(f.macromesh));
  PrintMacroMesh(&(f.macromesh));

  real tnow = 0.0;
  
  Initfield(&f);
  CheckMacroMesh(&(f.macromesh), f.interp.interp_param + 1);

  dtfield(&f, tnow, f.wn, f.dtwn);
  
  Displayfield(&f);

  /* Plotfield(0, false, &f, NULL, "visu.msh"); */
  /* Plotfield(0, true, &f, "error", "error.msh"); */

  // Test the time derivative with the exact solution
  int *raf = f.interp.interp_param + 4;
  int *deg = f.interp.interp_param + 1;
  for(int i = 0; i < f.model.m * f.macromesh.nbelems * NPG(raf, deg); i++){
    test = test && fabs(4 * f.wn[i] - pow(f.dtwn[i], 2)) < 1e-2;
    printf("i=%d err=%f \n",i,4 * f.wn[i] - pow(f.dtwn[i], 2));
    assert(test);
  }
  
  return test;
};
Beispiel #4
0
void RK2StVenantLin(Field* f,double tmax){
  printf("RK2StVenantLin\n");
  double vmax=sqrt(const_g*H0); // to be changed for another model !!!!!!!!!
  double cfl=0.2/vmax;

  double dt = cfl * f->hmin / vmax;
  int itermax=tmax/dt;
  int freq=(1 >= itermax/10)? 1 : itermax/10;
  //int param[8]={f->model.m,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
  int sizew=f->macromesh.nbelems * f->model.m * NPG(f->interp_param+1);

  int iter=0;

  while(f->tnow<tmax){
    if (iter%freq==0)
      printf("t=%f iter=%d/%d dt=%f\n",f->tnow,iter,itermax,dt);
    // predictor
    dtField(f);

#ifdef _OPENMP
#pragma omp parallel for
#endif
    for(int iw=0;iw<sizew;iw++){
      f->wnp1[iw]=f->wn[iw]+ dt/2 * f->dtwn[iw]; 
    }
    //exchange the field pointers 
    double *temp;
    temp=f->wnp1;
    f->wnp1=f->wn;
    f->wn=temp;

    // corrector
    f->tnow+=dt/2;
    dtField(f);
#ifdef _OPENMP
#pragma omp parallel for
#endif
    for(int iw=0;iw<sizew;iw++){
      f->wnp1[iw]+=dt*f->dtwn[iw];
    }
    f->tnow+=dt/2;
    iter++;
    //exchange the field pointers 
    temp=f->wnp1;
    f->wnp1=f->wn;
    f->wn=temp;

  }
  printf("t=%f iter=%d/%d dt=%f\n",f->tnow,iter,itermax,dt);

}
Beispiel #5
0
// TODO: do not store all diagnotics for all time, but instead just
// append to the output file.
void Energies(field *f, real *w, real k_energy, real e_energy, real t_energy) {
  
  k_energy = 0;
  e_energy = 0;
  t_energy = 0;

  for (int ie = 0; ie < f->macromesh.nbelems; ie++){
    // get the physical nodes of element ie
    real 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];
    }

    // loop on the glops (for numerical integration)
    for(int ipg = 0; ipg < NPG(f->interp_param + 1); ipg++){
      real xpgref[3], xphy[3], wpg;
      real dtau[3][3], codtau[3][3];//,xpg[3];
      // get the coordinates of the Gauss point
      ref_pg_vol(f->interp_param + 1, ipg, xpgref, &wpg, NULL);
      Ref2Phy(physnode, // phys. nodes
	      xpgref,  // xref
	      NULL,-1, // dpsiref,ifa
	      xphy,dtau,  // xphy,dtau
	      codtau,NULL,NULL); // codtau,dpsi,vnds
      real det
	= dtau[0][0] * codtau[0][0]
	+ dtau[0][1] * codtau[0][1]
	+ dtau[0][2] * codtau[0][2]; 
      real wn[f->model.m];
      for(int iv = 0; iv < _INDEX_MAX + 1; iv++){ 
	int imem = f->varindex(f->interp_param, ie, ipg, iv);
	wn[iv] = w[imem];
      }
      // get the exact value
      k_energy += local_kinetic_energy(f, xphy, wn) * wpg * det;
      e_energy += wn[_MV+1] * wn[_MV+1] * wpg * det;      
    }
  }   
  
  t_energy = 0.5 * (e_energy + k_energy);
  
  f->Diagnostics[f->iter_time] = 0.5 * k_energy;
  f->Diagnostics[f->iter_time + f->itermax] = 0.5 * e_energy;
  f->Diagnostics[f->iter_time + 2 * f->itermax] = t_energy;
}
Beispiel #6
0
// compute the normalized L2 distance with the imposed data
double L2error(Field* f){

  //int param[8]={f->model.m,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
  double error=0;
  double moy=0; // mean value
  //#pragma omp parallel for
  for (int ie=0;ie<f->macromesh.nbelems;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];
    }

    // loop on the glops (for numerical integration)
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      double xpgref[3],xphy[3],wpg;
      double dtau[3][3],codtau[3][3];//,xpg[3];
      // get the coordinates of the Gauss point
      ref_pg_vol(f->interp_param+1,ipg,xpgref,&wpg,NULL);
      Ref2Phy(physnode, // phys. nodes
	      xpgref,  // xref
	      NULL,-1, // dpsiref,ifa
	      xphy,dtau,  // xphy,dtau
	      codtau,NULL,NULL); // codtau,dpsi,vnds
      double det
	= dtau[0][0] * codtau[0][0]
	+ dtau[0][1] * codtau[0][1]
	+ dtau[0][2] * codtau[0][2]; 
      double w[f->model.m],wex[f->model.m];
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	w[iv]=f->wn[imem];
      }
      // get the exact value
      f->model.ImposedData(xphy,f->tnow,wex);
      for(int iv=0;iv<f->model.m;iv++){
        error+=pow(w[iv]-wex[iv],2)*wpg*det;
        moy+=pow(w[iv],2)*wpg*det;
      }
    }
  }
  return sqrt(error)/sqrt(moy);
}
Beispiel #7
0
// apply division by the mass matrix
void* DGMass(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];
    }
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){

      double dtau[3][3],codtau[3][3],xpgref[3],wpg;
      ref_pg_vol(f->interp_param+1,ipg,xpgref,&wpg,NULL);
      Ref2Phy(physnode, // phys. nodes
	      xpgref,  // xref
	      NULL,-1, // dpsiref,ifa
	      NULL,dtau,  // xphy,dtau
	      codtau,NULL,NULL); // codtau,dpsi,vnds
      double det
	= dtau[0][0]*codtau[0][0]
	+ dtau[0][1]*codtau[0][1]
	+ dtau[0][2]*codtau[0][2];
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	f->dtwn[imem]/=(wpg*det);
      }
    }
  }

  return NULL;


}
Beispiel #8
0
// time integration by a second order Runge-Kutta algorithm
//  with memory copy instead of pointers exchange 
void RK2Copy(Field* f,double tmax){

  double vmax=1; // to be changed for another model !!!!!!!!!
  double cfl=0.05;

  double dt = cfl * f->hmin / vmax;

  //int param[8]={f->model.m,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
  int sizew=f->macromesh.nbelems * f->model.m * NPG(f->interp_param+1);
 
  int iter=0;

  while(f->tnow<tmax){
    printf("t=%f iter=%d dt=%f\n",f->tnow,iter,dt);
    // predictor
    dtField(f);
    for(int iw=0;iw<sizew;iw++){
      f->wnp1[iw]=f->wn[iw]+ dt/2 * f->dtwn[iw]; 
    }
    //exchange the field pointers 
    for(int iw=0;iw<sizew;iw++){
      double temp=f->wn[iw];
      f->wn[iw]=f->wnp1[iw];
      f->wnp1[iw]=temp;
    }
    // corrector
    f->tnow+=dt/2;
    dtField(f);
    for(int iw=0;iw<sizew;iw++){
      f->wnp1[iw]+=dt*f->dtwn[iw];
    }
    f->tnow+=dt/2;
    iter++;
    //exchange the field pointers 
    for(int iw=0;iw<sizew;iw++){
      f->wn[iw]=f->wnp1[iw];
    }
 
  }
}
Beispiel #9
0
real L2_Kinetic_error(field* f){
  real error = 0;

  for (int ie = 0; ie < f->macromesh.nbelems; ie++){
    // get the physical nodes of element ie
    real 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];
    }

    // loop on the glops (for numerical integration)
    for(int ipg = 0; ipg < NPG(f->interp_param + 1); ipg++){
      real xpgref[3], xphy[3], wpg;
      real dtau[3][3], codtau[3][3];//,xpg[3];
      // get the coordinates of the Gauss point
      ref_pg_vol(f->interp_param + 1, ipg, xpgref, &wpg, NULL);
      Ref2Phy(physnode, // phys. nodes
	      xpgref,  // xref
	      NULL, -1, // dpsiref,ifa
	      xphy, dtau,  // xphy,dtau
	      codtau, NULL, NULL); // codtau,dpsi,vnds
      real det
	= dtau[0][0] * codtau[0][0]
	+ dtau[0][1] * codtau[0][1]
	+ dtau[0][2] * codtau[0][2]; 
      real w[f->model.m];
      for(int iv = 0;iv < f->model.m; iv++){
	int imem = f->varindex(f->interp_param, ie, ipg, iv);
	w[iv] = f->wn[imem];
      }
      // get the exact value
      error += L2VelError(f, xphy, w) * wpg * det;
    }
  }
  return sqrt(error);
}
Beispiel #10
0
void AccumulateParticles(void *fv, real *w)
{
  field *f = fv;
  PIC *pic = f->pic;

  int *raf = f->interp_param + 4;
  int *deg = f->interp_param + 1;
  
  int npg = NPG(raf, deg);
    
  for(int ie = 0; ie < f->macromesh.nbelems; ie++){
    MacroCell *mcell = f->mcell + ie;
    
    for(int ipg = 0; ipg < npg; ipg++){
      int iv = 4;
      int imem = f->varindex(f->interp_param, ipg, iv) + mcell->woffset;
      f->wn[imem]=0;
      iv = 5;
      imem = f->varindex(f->interp_param, ipg, iv) + mcell->woffset;
      f->wn[imem]=0;
      iv = 6;
      imem = f->varindex(f->interp_param, ipg, iv) + mcell->woffset;
      f->wn[imem]=0;
    } 

  }
  
  for(int i=0;i<pic->nbparts;i++) {
    
    int ie=pic->old_cell_id[i];

    // https://xkcd.com/292/
    // FIXME: remove goto
    if (ie < 0) goto nexti;

    MacroCell *mcell = f->mcell + ie;
    
    int npg=NPG(raf, deg);
    real 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];
    }
    real dtau[3][3], codtau[3][3];
    Ref2Phy(physnode, // phys. nodes
	    pic->xv + 6 * i, // xref
	    NULL, -1, // dpsiref, ifa
	    NULL, dtau, // xphy, dtau
	    codtau, NULL, NULL); // codtau, dpsi, vnds
    real det = dot_product(dtau[0], codtau[0]);

    for(int ib=0;ib < npg;ib++){
      real wpg;
      int *raf = f->interp_param + 4;
      int *deg = f->interp_param + 1;
      ref_pg_vol(raf, deg, ib, NULL, &wpg, NULL);
      //printf("det=%f wpg=%f \n", det, wpg);
      wpg *= det;
      real psi;
      psi_ref(f->interp_param+1,ib,pic->xv + 6*i,&psi,NULL);

      int iv = 6;  // rho index
      int imem = f->varindex(f->interp_param, ib, iv) + mcell->woffset;
      w[imem] += psi / wpg * pic->weight;
 
      iv = 4;  // j1 index
      imem = f->varindex(f->interp_param, ib, iv) + mcell->woffset;
      w[imem] += pic->xv[6 * i + 3] * psi / wpg * pic->weight;

      iv = 5;  // j2 index
      imem = f->varindex(f->interp_param, ib, iv) + mcell->woffset;
      w[imem] += pic->xv[6 * i + 4] * psi / wpg * pic->weight;
    }
    
  nexti:  
    assert(1==1);
  }
}
Beispiel #11
0
void CheckMacroMesh(MacroMesh *m, int *param) {
  Geom g;
  real face_centers[6][3]={ {0.5,0.0,0.5},
			    {1.0,0.5,0.5},
			    {0.5,1.0,0.5},
			    {0.0,0.5,0.5},
			    {0.5,0.5,1.0},
			    {0.5,0.5,0.0} };

  //real *bounds = malloc(6 * sizeof(real));
  //macromesh_bounds(m, bounds);

  /* real refnormal[6][3]={{0,-1,0},{1,0,0}, */
  /* 			  {0,1,0},{-1,0,0}, */
  /* 			  {0,0,1},{0,0,-1}}; */

  assert(m->connec_ok);

  for(int ie = 0; ie < m->nbelems; ie++) {
    // Load geometry for macro element ie:
    for(int inoloc = 0; inoloc < 20; inoloc++) {
      int ino = m->elem2node[20 * ie + inoloc];
      g.physnode[inoloc][0] = m->node[3 * ino + 0];
      g.physnode[inoloc][1] = m->node[3 * ino + 1];
      g.physnode[inoloc][2] = m->node[3 * ino + 2];
    }

    // Test that the ref_ipg function is compatible with ref_pg_vol
    //int param[7]={_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
    for(int ipg = 0; ipg < NPG(param); ipg++) {
      real xref1[3], xref_in[3];
      real wpg;
      ref_pg_vol(param, ipg, xref1, &wpg, xref_in);
      memcpy(g.xref, xref1, sizeof(g.xref));

      g.ifa = 0;
      GeomRef2Phy(&g);
      GeomPhy2Ref(&g);

      // if(param[4]==1 && param[5]==1 && param[6]==1) {
      //printf("ipg %d ipg2 %d xref %f %f %f\n",ipg,
      //	     ref_ipg(param,xref_in),xref_in[0],xref_in[1],xref_in[2]);

      // Ensure that the physical coordinates give the same point:
      assert(ipg == ref_ipg(param, xref_in));

      //}
    }

    // middle of the element
    g.xref[0] = 0.5;
    g.xref[1] = 0.5;
    g.xref[2] = 0.5;

    GeomRef2Phy(&g);
    real xphym[3];
    memcpy(xphym, g.xphy, sizeof(xphym));

    for(int ifa = 0; ifa < 6; ifa++) {
      // Middle of the face
      memcpy(g.xref, face_centers[ifa], sizeof(g.xref));
      g.ifa = ifa;
      GeomRef2Phy(&g);
      // Check volume  orientation
      assert(g.det > 0);

      real vec[3] = {g.xphy[0] - xphym[0],
		     g.xphy[1] - xphym[1],
		     g.xphy[2] - xphym[2]};

      // Check face orientation
      assert(0 < dot_product(g.vnds, vec));

      // Check compatibility between face and volume numbering
      for(int ipgf = 0; ipgf < NPGF(param, ifa); ipgf++) {

        // Get the coordinates of the Gauss point
        real xpgref[3];
	{
	  real wpg;
	  ref_pg_face(param, ifa, ipgf, xpgref, &wpg, NULL);
	}
        
	// Recover the volume gauss point from the face index
	int ipgv = param[6];
	real xpgref2[3];
	{
	  real wpg2;
	  ref_pg_vol(param, ipgv, xpgref2, &wpg2, NULL);
	}

        if(m->is2d) { // in 2D do not check upper and lower face
          if(ifa < 4)
            assert(Dist(xpgref, xpgref2) < 1e-11);
        }
	else if (m->is1d){
	  if (ifa==1 || ifa==3) {
	    assert(Dist(xpgref,xpgref2)<1e-11);
	  }
	}
	// in 3D check all faces
	else { // in 3D check all faces
	  if(Dist(xpgref, xpgref2) >= 1e-11) {
	    printf("ERROR: face and vol indices give different rev points:\n");
	    printf("ipgv: %d\n", ipgv);
	    printf("ipgf: %d\n", ipgf);
	    printf("ifa: %d\n", ifa);
	    printf("xpgref:%f %f %f\n", xpgref[0], xpgref[1], xpgref[2]);
	    printf("xpgref2:%f %f %f\n", xpgref2[0], xpgref2[1], xpgref2[2]);
	  }
          assert(Dist(xpgref, xpgref2) < 1e-11);
        }

      }
    }
  }

  // Check that the faces are defined by the same mapping with
  // opposite normals
  for (int ie = 0; ie < m->nbelems; ie++) {
    // int param[8]={1,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
    // Get the geometry for the macro element ie
    real physnode[20][3];
    for(int inoloc = 0; inoloc < 20; inoloc++) {
      int ino = m->elem2node[20 * ie + inoloc];
      physnode[inoloc][0] = m->node[3 * ino + 0];
      physnode[inoloc][1] = m->node[3 * ino + 1];
      physnode[inoloc][2] = m->node[3 * ino + 2];
    }

    // Loop on the 6 faces
    for(int ifa = 0; ifa < 6; ifa++) {
      // Loop on the glops (numerical integration) of the face ifa
      for(int ipgf = 0; ipgf < NPGF(param, ifa); ipgf++) {

	// Get the right elem or the boundary id
	int ieR = m->elem2elem[6 * ie + ifa];
	// If the right element exists and is not
	// the left element (may arrive in periodic cases)
  	if(ieR >= 0 && ieR != ie) {
	  // Get the coordinates of the Gauss point from the
	  // face-local point index and the point slightly inside the
	  // macrocell.
	  real xpgref[3], xpgref_in[3];
	  ref_pg_face(param, ifa, ipgf, xpgref, NULL, xpgref_in);
	  //ref_pg_face(param, ifa, ipgf, xpgref, NULL, NULL);
	  int ipg=param[6];

/* #ifdef _PERIOD */
/* 	  assert(m->is1d); // TODO: generalize to 2d */
/* 	  if (xpgref_in[0] > _PERIOD) xpgref_in[0] -= _PERIOD; */
/* 	  if (xpgref_in[0] < 0) xpgref_in[0] += _PERIOD; */
/* #endif */


	  // Compute the position of the point and the face normal.
	  real xpg[3], vnds[3];
	  {
	    real dtau[3][3];
	    real codtau[3][3];
	    Ref2Phy(physnode,
		    xpgref,
		    NULL, ifa, // dpsiref,ifa
		    xpg, dtau,
		    codtau, NULL, vnds); // codtau,dpsi,vnds
	  }
          
	  // Compute the "slightly inside" position
	  real xpg_in[3];
	  Ref2Phy(physnode,
		  xpgref_in,
		  NULL, ifa, // dpsiref,ifa
		  xpg_in, NULL,
		  NULL, NULL, NULL); // codtau,dpsi,vnds
	  PeriodicCorrection(xpg_in,m->period);

	  // Load the geometry of the right macrocell
	  real physnodeR[20][3];
	  for(int inoloc = 0; inoloc < 20; inoloc++) {
	    int ino = m->elem2node[20 * ieR + inoloc];
	    physnodeR[inoloc][0] = m->node[3 * ino + 0];
	    physnodeR[inoloc][1] = m->node[3 * ino + 1];
	    physnodeR[inoloc][2] = m->node[3 * ino + 2];
	  }

  	  // Find the corresponding point in the right elem
  	  real xpgrefR_in[3];//,xpgrefR[3];
	  Phy2Ref(physnodeR, xpg_in, xpgrefR_in);
	  //Phy2Ref(physnodeR, xpg, xpgrefR);
	  int ipgR = ref_ipg(param, xpgrefR_in);
	  
	  // search the id of the face in the right elem
	  // special treatment if the mesh is periodic
	  // and contains only one elem (then ie==ieR)
	  int neighb_count=0;
	  for(int ifaR=0;ifaR<6;ifaR++){
	    if (m->elem2elem[6*ieR+ifaR] == ie) {
	      for(int ipgfR = 0; ipgfR < NPGF(param, ifaR); ipgfR++) {
		real xpgrefR[3];
		ref_pg_face(param, ifaR, ipgfR, xpgrefR, NULL, NULL);
		if (param[6] == ipgR){
		  real xpgR[3];
		  real vndsR[3];
		  {
		    ref_pg_vol(param, ipgR, xpgrefR, NULL, NULL);
		    real dtauR[3][3], codtauR[3][3];
		    Ref2Phy(physnodeR,
			    xpgrefR,
			    NULL, ifaR, // dphiref, ifa
			    xpgR, dtauR,
			    codtauR, NULL, vndsR); // codtau, dphi, vnds
		  }
		  // Ensure that the normals are opposite
		  // if xpg and xpgR are close
		  /* printf("xpg:%f %f %f\n", xpg_in[0], xpg_in[1], xpg_in[2]); */
		  /* printf("vnds: %f %f %f vndsR: %f %f %f \n", */
		  /* 	 vnds[0],vnds[1],vnds[2], */
		  /* 	 vndsR[0],vndsR[1],vndsR[2]); */
		  /* printf("xpgR:%f %f %f\n", xpgR[0], xpgR[1], xpgR[2]); */
		  assert(fabs(vnds[0] + vndsR[0]) < 1e-8);
		  assert(fabs(vnds[1] + vndsR[1]) < 1e-8);
		  assert(fabs(vnds[2] + vndsR[2]) < 1e-8);
		  neighb_count++;
		}

	      }
	    }
	  }
	  //printf("neighb=%d\n",neighb_count);
	  assert(neighb_count == 1);
	}
      }
    }
  }

  //free(bounds);
}
Beispiel #12
0
// compute the Discontinuous Galerkin volume terms
// slow version
void DGVolumeSlow(Field* f){

  // assembly of the volume terms
  // loop on the elements
  //#pragma omp parallel for
  for (int ie=0;ie<f->macromesh.nbelems;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];
    }

    // mass matrix
    double masspg[NPG(f->interp_param+1)];
    // loop on the glops (for numerical integration)
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      double xpgref[3],wpg;
      // get the coordinates of the Gauss point
      ref_pg_vol(f->interp_param+1,ipg,xpgref,&wpg,NULL);

      // get the value of w at the gauss point
      double w[f->model.m];
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	w[iv]=f->wn[imem];
      }
      // loop on the basis functions
      for(int ib=0;ib<NPG(f->interp_param+1);ib++){
	// gradient of psi_ib at gauss point ipg
	double dpsiref[3],dpsi[3];
	double dtau[3][3],codtau[3][3];//,xpg[3];
	grad_psi_pg(f->interp_param+1,ib,ipg,dpsiref);
	Ref2Phy(physnode, // phys. nodes
		xpgref,  // xref
		dpsiref,-1, // dpsiref,ifa
		NULL,dtau,  // xphy,dtau
		codtau,dpsi,NULL); // codtau,dpsi,vnds
	// remember the diagonal mass term
	if (ib == ipg){
	  double det
	    = dtau[0][0] * codtau[0][0]
	    + dtau[0][1] * codtau[0][1]
	    + dtau[0][2] * codtau[0][2];
	  masspg[ipg]=wpg*det;
	}
	// int_L F(w,w,grad phi_ib )
	double flux[f->model.m];
	f->model.NumFlux(w,w,dpsi,flux);

	for(int iv=0;iv<f->model.m;iv++){
	  int imem=f->varindex(f->interp_param,ie,ib,iv);
	  f->dtwn[imem]+=flux[iv]*wpg;
	}
      }
    }

    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      // apply the inverse of the diagonal mass matrix
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	(f->dtwn[imem])/=masspg[ipg];
      }
    }

  }

  

}
Beispiel #13
0
void InitField(Field* f){

  //int param[8]={f->model.m,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
  double w[f->model.m];
  double xpg[3];
  double xref[3],omega;
  double physnode[20][3];

  f->is2d = false;

  // a copy for avoiding too much "->"
  for(int ip=0;ip<8;ip++){
    f->interp_param[ip]=f->interp.interp_param[ip];
  }

  int nmem=f->model.m * f->macromesh.nbelems * 
    NPG(f->interp_param+1);
  printf("allocate %d doubles\n",nmem);
  f->wn=malloc(nmem * sizeof(double));
  assert(f->wn);	       
  f->wnp1=malloc(nmem * sizeof(double));
  assert(f->wnp1);	       
  f->dtwn=malloc(nmem * sizeof(double));
  assert(f->dtwn);	       

  f->tnow=0;

  for(int ie=0;ie<f->macromesh.nbelems;ie++){
    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];
    }
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      ref_pg_vol(f->interp_param+1, ipg, xref, &omega,NULL);
      double dtau[3][3];
      Ref2Phy(physnode,
	      xref,
	      0,-1, // dphiref,ifa
              xpg,dtau,  
	      NULL,NULL,NULL); // codtau,dphi,vnds
      // check the reverse transform at all the GLOPS
      double xref2[3];
      Phy2Ref(physnode,xpg,xref2);
      assert(Dist(xref,xref2) < 1e-8);
      
      f->model.InitData(xpg,w);
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	f->wn[imem]=w[iv];
      }
    }
  }

  // compute cfl parameter min_i vol_i/surf_i
  f->hmin=1e10;

  for (int ie=0;ie<f->macromesh.nbelems;ie++){
    double vol=0,surf=0;
    // 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];
    }
    // loop on the glops (for numerical integration)
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      double xpgref[3],wpg;
      // get the coordinates of the Gauss point
      ref_pg_vol(f->interp_param+1,ipg,xpgref,&wpg,NULL);
      double codtau[3][3],dtau[3][3];
      Ref2Phy(physnode, // phys. nodes
	      xpgref,  // xref
	      NULL,-1, // dpsiref,ifa
	      NULL,dtau,  // xphy,dtau
	      codtau,NULL,NULL); // codtau,dpsi,vnds
      double det
	= dtau[0][0] * codtau[0][0]
	+ dtau[0][1] * codtau[0][1]
	+ dtau[0][2] * codtau[0][2];
      vol+=wpg*det;
    }
    for(int ifa=0;ifa<6;ifa++){
      // loop on the faces
      for(int ipgf=0;ipgf<NPGF(f->interp_param+1,ifa);ipgf++){
	double xpgref[3],wpg;
	//double xpgref2[3],wpg2;
	// get the coordinates of the Gauss point
	ref_pg_face(f->interp_param+1,ifa,ipgf,xpgref,&wpg,NULL);
	double vnds[3];
	double codtau[3][3],dtau[3][3];
	Ref2Phy(physnode,
		xpgref,
		NULL,ifa, // dpsiref,ifa
		NULL,dtau,
		codtau,NULL,vnds); // codtau,dpsi,vnds
	surf+=sqrt(vnds[0]*vnds[0]+vnds[1]*vnds[1]+vnds[2]*vnds[2])*wpg;
      }
    }    
    f->hmin = f->hmin < vol/surf ? f->hmin : vol/surf;

  }

  // now take into account the polynomial degree and the refinement
  int maxd=f->interp_param[1];
  maxd = maxd > f->interp_param[2] ? maxd : f->interp_param[2];
  maxd = maxd > f->interp_param[3] ? maxd : f->interp_param[3];
  
  f->hmin/=((maxd+1)*f->interp_param[4]);

  printf("hmin=%f\n",f->hmin);

};
Beispiel #14
0
// save the results in the gmsh format
// typplot: index of the plotted variable
// int compare == true -> compare with the exact value
void PlotField(int typplot,int compare,Field* f,char* filename){

  const int hexa64ref[3*64]={
    0,0,3,
    3,0,3,
    3,3,3,
    0,3,3,
    0,0,0,3,0,0,3,3,0,0,3,0,
    1,0,3,2,0,3,0,1,3,0,2,3,0,0,2,0,0,1,3,1,3,3,2,3,
    3,0,2,3,0,1,2,3,3,1,3,3,3,3,2,3,3,1,0,3,2,0,3,1,
    1,0,0,2,0,0,0,1,0,0,2,0,3,1,0,3,2,0,2,3,0,1,3,0,
    1,1,3,1,2,3,2,2,3,2,1,3,1,0,2,2,0,2,2,0,1,1,0,1,
    0,1,2,0,1,1,0,2,1,0,2,2,3,1,2,3,2,2,3,2,1,3,1,1,
    2,3,2,1,3,2,1,3,1,2,3,1,1,1,0,2,1,0,2,2,0,1,2,0,
    1,1,2,2,1,2,2,2,2,1,2,2,1,1,1,2,1,1,2,2,1,1,2,1};

  int* elem2nodes = f->macromesh.elem2node;
  double* node = f->macromesh.node;


  FILE * gmshfile;
  gmshfile = fopen( filename, "w" );

  // data plots
  //int param[8]={f->model.m,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};
  int nraf[3]={f->interp_param[4],f->interp_param[5],f->interp_param[6]};
  // refinement size in each direction
  double hh[3]={1./nraf[0],1./nraf[1],1./nraf[2]};

  int npgv = NPG(f->interp_param+1);
  int nnodes = 20;

  double physnode[nnodes][3];
  double Xr[3];
  double Xphy[3];

  // header
  fprintf(gmshfile,"$MeshFormat\n2.2 0 %d\n",(int) sizeof(double));
  //int one=1;
  //fwrite((char*) &one,sizeof(int),1,gmshfile);
  fprintf(gmshfile,"$EndMeshFormat\n$Nodes\n%d\n",
	  f->macromesh.nbelems*nraf[0]*nraf[1]*nraf[2]*64);

  int nb_plotnodes=f->macromesh.nbelems*nraf[0]*nraf[1]*nraf[2]*64;
  double* value=malloc(nb_plotnodes*sizeof(double));
  assert(value);
  int nodecount=0;
  // nodes
  for(int i=0;i<f->macromesh.nbelems;i++){
    // get the nodes of element L
    for(int ino=0;ino<nnodes;ino++){
      int numnoe=elem2nodes[nnodes*i+ino];
      for(int ii=0;ii<3;ii++){
        physnode[ino][ii]=node[3*numnoe+ii];
      }
    }
    // loop on the macro elem subcells
    int icL[3];
    // loop on the subcells
    for(icL[0]=0;icL[0]<nraf[0];icL[0]++){
      for(icL[1]=0;icL[1]<nraf[1];icL[1]++){
	for(icL[2]=0;icL[2]<nraf[2];icL[2]++){
	  // get the left subcell id
	  // first glop index in the subcell
	  //int offsetL=(deg[0]+1)*(deg[1]+1)*(deg[2]+1)*ncL;
	  
	  for(int ino=0;ino<64;ino++){
	    Xr[0]=(double) (hexa64ref[3*ino+0]) / 3;
	    Xr[1]=(double) (hexa64ref[3*ino+1]) / 3;
	    Xr[2]=(double) (hexa64ref[3*ino+2]) / 3;
	    
	    Xr[0] = icL[0]*hh[0]+ Xr[0] * hh[0];
	    Xr[1] = icL[1]*hh[1]+ Xr[1] * hh[1];
	    Xr[2] = icL[2]*hh[2]+ Xr[2] * hh[2];

	    for(int ii=0;ii<3;ii++){
	      assert(Xr[ii]<1+1e-10 && Xr[ii]>-1e-10);
	    }
	    
	    Ref2Phy(physnode,
		    Xr,
		    NULL,
		    -1,
		    Xphy,
		    NULL,
		    NULL,
		    NULL,
		    NULL);

	    double Xplot[3];
	    Xplot[0]=Xphy[0];
	    Xplot[1]=Xphy[1];
	    Xplot[2]=Xphy[2];

	    value[nodecount]=0;
	    double testpsi=0;
	    for(int ib=0;ib<npgv;ib++){
	      double psi;
	      psi_ref_subcell(f->interp_param+1,icL, ib, Xr, &psi, NULL);
	      testpsi+=psi;
	      int vi = f->varindex(f->interp_param, i, ib, typplot);
	      value[nodecount] += psi * f->wn[vi];
	    }
	    assert(fabs(testpsi-1)<1e-10);

	    // compare with an
	    // exact solution
	    if (compare){
	      double wex[f->model.m];
	      f->model.ImposedData(Xphy,f->tnow,wex);
	      value[nodecount] -= wex[typplot];
	    }
	    nodecount++;


	    // fwrite((char*) &nnoe,sizeof(int),1,gmshfile);
	    // fwrite((char*) &(Xplot[0]),sizeof(double),1,gmshfile);
	    // fwrite((char*) &(Xplot[1]),sizeof(double),1,gmshfile);
	    // fwrite((char*) &(Xplot[2]),sizeof(double),1,gmshfile);
	    fprintf(gmshfile,"%d %f %f %f\n",nodecount,Xplot[0],Xplot[1],Xplot[2]);
	    
	  }
	}
      }
    }
  }

  fprintf(gmshfile,"$EndNodes\n");


  // elements
  fprintf(gmshfile,"$Elements\n");
  fprintf(gmshfile,"%d\n",f->macromesh.nbelems*nraf[0]*nraf[1]*nraf[2]);



  int elm_type=92;
  //int num_elm_follow=f->macromesh.nbelems;
  int num_tags=0;

  // fwrite((char*) &elm_type,sizeof(int),1,gmshfile);
  // fwrite((char*) &num_elm_follow,sizeof(int),1,gmshfile);
  // fwrite((char*) &num_tags,sizeof(int),1,gmshfile);

  for(int i=0;i<f->macromesh.nbelems;i++){

    // loop on the macro elem subcells
    int icL[3];
    // loop on the subcells
    for(icL[0]=0;icL[0]<nraf[0];icL[0]++){
      for(icL[1]=0;icL[1]<nraf[1];icL[1]++){
	for(icL[2]=0;icL[2]<nraf[2];icL[2]++){
	  // get the subcell id
	  int ncL=icL[0]+nraf[0]*(icL[1]+nraf[1]*icL[2]);
	  // first glop index in the subcell
	  //int offsetL=(deg[0]+1)*(deg[1]+1)*(deg[2]+1)*ncL;

	  // global subcell id
	  int numelem=ncL+i*nraf[0]*nraf[1]*nraf[2]+1;
	  //fwrite((char*) &numelem,sizeof(int),1,gmshfile);
	  fprintf(gmshfile,"%d ",numelem);
	  fprintf(gmshfile,"%d ",elm_type);
	  fprintf(gmshfile,"%d ",num_tags);
    
    
	  for(int ii=0;ii<64;ii++){
	    int numnoe=64*(i*nraf[0]*nraf[1]*nraf[2]+ncL) + ii +1;
	    //fwrite((char*) &numnoe,sizeof(int),1,gmshfile);
	    fprintf(gmshfile,"%d ",numnoe);
	  }
	  fprintf(gmshfile,"\n");
	}
      }
    }
  }
  
  fprintf(gmshfile,"$EndElements\n");

  // now display data
    
  fprintf(gmshfile,"$NodeData\n");
  fprintf(gmshfile,"1\n");
  fprintf(gmshfile,"\"Field %d\"\n",typplot);
  
  double t = 0;

  fprintf(gmshfile,"1\n%f\n3\n0\n1\n",t);

  fprintf(gmshfile,"%d\n",nb_plotnodes);

    
  for(int ino=0;ino<nb_plotnodes;ino++){

    //fwrite(const void *ptr, size_t size_of_elements,
    // size_t number_of_elements, FILE *a_file);
    //fwrite((char*) &nodenumber, sizeof(int),1,gmshfile);
    //fwrite((char*) &value, sizeof(double),1,gmshfile);
    //fprintf(gmshfile,"%d %f\n",nodenumber,value);
    fprintf(gmshfile,"%d %f\n",ino+1,value[ino]);      

  }
    
  /* for(int i=0;i<f->macromesh.nbelems;i++){ */
  /*   for(int ino=0;ino<20;ino++){ */
  /* 	int numnoe=elem2nodes[nnodes*i+ino]; */
  /* 	for(int ii=0;ii<3;ii++){ */
  /* 	  physnode[ino][ii]=node[3*numnoe+ii]; */
  /* 	} */
  /*   } */
      
  /*   // data at the eight nodes */
  /*   for(int ii=0;ii<64;ii++){ */
  /* 	int nodenumber=64*i + ii +1; */
	
  /* 	Xr[0]=(double) (hexa64ref[3*ii+0]) / 3; */
  /* 	Xr[1]=(double) (hexa64ref[3*ii+1]) / 3; */
  /* 	Xr[2]=(double) (hexa64ref[3*ii+2]) / 3; */
	
  /* 	Ref2Phy(physnode, */
  /* 		Xr, */
  /* 		NULL, */
  /* 		-1, */
  /* 		Xphy, */
  /* 		NULL, */
  /* 		NULL, */
  /* 		NULL, */
  /* 		NULL); */
	

  /* 	double value=0; */
  /* 	for(int ib=0;ib<npgv;ib++){ */
  /* 	  double psi; */
  /* 	  psi_ref(f->interp_param+1, ib, Xr, &psi, NULL); */
	  
  /* 	  int vi = f->varindex(f->interp_param, i, ib, typplot); */
  /* 	  value += psi * f->wn[vi]; */
  /* 	} */

  /* 	// compare with an */
  /* 	// exact solution */
  /*     if (compare){ */
  /*       double wex[f->model.m]; */
  /*       f->model.ImposedData(Xphy,f->tnow,wex); */
  /*       value -= wex[typplot]; */
  /*     } */


  /* 	//fwrite(const void *ptr, size_t size_of_elements, */
  /* 	// size_t number_of_elements, FILE *a_file); */
  /* 	//fwrite((char*) &nodenumber, sizeof(int),1,gmshfile); */
  /* 	//fwrite((char*) &value, sizeof(double),1,gmshfile); */
  /* 	//fprintf(gmshfile,"%d %f\n",nodenumber,value); */
  /* 	fprintf(gmshfile,"%d %f\n",nodenumber,value); */
  /*   } */

  /* } */

  fprintf(gmshfile,"\n$EndNodeData\n");

    
  fclose(gmshfile);
 
  free(value);

}
Beispiel #15
0
// apply the Discontinuous Galerkin approximation for computing
// the time derivative of the field
void dtFieldSlow(Field* f){

  // interpolation params
  // warning: this is ugly, but the last
  // parameter is used for computing the volume
  // GLOP index from the face GLOP index...
  // ugly too: the first parameter is not used by all
  // utilities. we have sometimes to jump over : pass param+1
  // instead of param...
  //int param[8]={f->model.m,_DEGX,_DEGY,_DEGZ,_RAFX,_RAFY,_RAFZ,0};


  // init to zero the time derivative
  int sizew=0;
  //#pragma omp parallel for
  for(int ie=0;ie<f->macromesh.nbelems;ie++){
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	f->dtwn[imem]=0;
        sizew++;
      }
    }
  }
  assert(sizew==f->macromesh.nbelems * f->model.m * NPG(f->interp_param+1));

  // assembly of the surface terms
  // loop on the elements
  //#pragma omp parallel for
  for (int ie=0;ie<f->macromesh.nbelems;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];
    }

    // loop on the 6 faces
    // or four faces for 2d computations
    int nbfa=6;
    if (f->is2d) nbfa=4;
    for(int ifa=0;ifa<nbfa;ifa++){
      // get the right elem or the boundary id
      int ieR=f->macromesh.elem2elem[6*ie+ifa];
      double physnodeR[20][3];
      if (ieR >= 0) {
      	for(int inoloc=0;inoloc<20;inoloc++){
      	  int ino=f->macromesh.elem2node[20*ieR+inoloc];
      	  physnodeR[inoloc][0]=f->macromesh.node[3*ino+0];
      	  physnodeR[inoloc][1]=f->macromesh.node[3*ino+1];
      	  physnodeR[inoloc][2]=f->macromesh.node[3*ino+2];
      	}
      }
      
      // loop on the glops (numerical integration)
      // of the face ifa
      for(int ipgf=0;ipgf<NPGF(f->interp_param+1,ifa);ipgf++){
  	double xpgref[3],xpgref_in[3],wpg;
  	//double xpgref2[3],wpg2;
  	// get the coordinates of the Gauss point
	// and coordinates of a point slightly inside the
	// opposite element in xref_in
  	ref_pg_face(f->interp_param+1,ifa,ipgf,xpgref,&wpg,xpgref_in);

  	// recover the volume gauss point from
  	// the face index
  	int ipg=f->interp_param[7];
  	// get the left value of w at the gauss point
  	double wL[f->model.m],wR[f->model.m];
  	for(int iv=0;iv<f->model.m;iv++){
  	  int imem=f->varindex(f->interp_param,ie,ipg,iv);
  	  wL[iv]=f->wn[imem];
  	}
  	// the basis functions is also the gauss point index
  	int ib=ipg;
  	// normal vector at gauss point ipg
  	double dtau[3][3],codtau[3][3],xpg[3];
  	double vnds[3];
  	Ref2Phy(physnode,
  		xpgref,
  		NULL,ifa, // dpsiref,ifa
  		xpg,dtau,
  		codtau,NULL,vnds); // codtau,dpsi,vnds
  	double flux[f->model.m];
  	if (ieR >=0) {  // the right element exists
  	  // find the corresponding point in the right elem
	  double xpg_in[3];
	  Ref2Phy(physnode,
		  xpgref_in,
		  NULL,ifa, // dpsiref,ifa
		  xpg_in,dtau,
		  codtau,NULL,vnds); // codtau,dpsi,vnds
  	  double xref[3];
	  Phy2Ref(physnodeR,xpg_in,xref);
  	  int ipgR=ref_ipg(f->interp_param+1,xref);
	  double xpgR[3],xrefR[3],wpgR;
	  ref_pg_vol(f->interp_param+1, ipgR, xrefR, &wpgR,NULL);
	  Ref2Phy(physnodeR,
		  xrefR,
		  NULL,-1, // dphiref,ifa
		  xpgR,NULL,  
		  NULL,NULL,NULL); // codtau,dphi,vnds
	  assert(Dist(xpgR,xpg)<1e-10);
  	  for(int iv=0;iv<f->model.m;iv++){
  	    int imem=f->varindex(f->interp_param,ieR,ipgR,iv);
  	    wR[iv]=f->wn[imem];
  	  }
  	  // int_dL F(wL,wR,grad phi_ib )
  	  f->model.NumFlux(wL,wR,vnds,flux);

  	}
  	else { //the right element does not exist
  	  f->model.BoundaryFlux(xpg,f->tnow,wL,vnds,flux);
  	}
  	for(int iv=0;iv<f->model.m;iv++){
  	  int imem=f->varindex(f->interp_param,ie,ib,iv);
  	  f->dtwn[imem]-=flux[iv]*wpg;
  	}
	
      }

    }
  }

  // assembly of the volume terms
  // loop on the elements
  //#pragma omp parallel for
  for (int ie=0;ie<f->macromesh.nbelems;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];
    }

    // mass matrix
    double masspg[NPG(f->interp_param+1)];
    // loop on the glops (for numerical integration)
    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      double xpgref[3],wpg;
      // get the coordinates of the Gauss point
      ref_pg_vol(f->interp_param+1,ipg,xpgref,&wpg,NULL);

      // get the value of w at the gauss point
      double w[f->model.m];
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	w[iv]=f->wn[imem];
      }
      // loop on the basis functions
      for(int ib=0;ib<NPG(f->interp_param+1);ib++){
	// gradient of psi_ib at gauss point ipg
	double dpsiref[3],dpsi[3];
	double dtau[3][3],codtau[3][3];//,xpg[3];
	grad_psi_pg(f->interp_param+1,ib,ipg,dpsiref);
	Ref2Phy(physnode, // phys. nodes
		xpgref,  // xref
		dpsiref,-1, // dpsiref,ifa
		NULL,dtau,  // xphy,dtau
		codtau,dpsi,NULL); // codtau,dpsi,vnds
	// remember the diagonal mass term
	if (ib == ipg){
	  double det
	    = dtau[0][0] * codtau[0][0]
	    + dtau[0][1] * codtau[0][1]
	    + dtau[0][2] * codtau[0][2];
	  masspg[ipg]=wpg*det;
	}
	// int_L F(w,w,grad phi_ib )
	double flux[f->model.m];
	f->model.NumFlux(w,w,dpsi,flux);

	for(int iv=0;iv<f->model.m;iv++){
	  int imem=f->varindex(f->interp_param,ie,ib,iv);
	  f->dtwn[imem]+=flux[iv]*wpg;
	}
      }
    }

    for(int ipg=0;ipg<NPG(f->interp_param+1);ipg++){
      // apply the inverse of the diagonal mass matrix
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(f->interp_param,ie,ipg,iv);
	(f->dtwn[imem])/=masspg[ipg];
      }
    }

  }
    
};
int TestfieldSubCellDGVol()
{
  int test = true;

  field f;
  init_empty_field(&f);

  f.model.cfl = 0.05;
  f.model.m = 1; // only one conservative variable
  f.model.NumFlux = TransNumFlux;
  f.model.BoundaryFlux = TestTransBoundaryFlux;
  f.model.InitData = TestTransInitData;
  f.model.ImposedData = TestTransImposedData;
  f.varindex = GenericVarindex;

  f.interp.interp_param[0] = 1; // _M
  f.interp.interp_param[1] = 2; // x direction degree
  f.interp.interp_param[2] = 2; // y direction degree
  f.interp.interp_param[3] = 2; // z direction degree
  f.interp.interp_param[4] = 2; // x direction refinement
  f.interp.interp_param[5] = 2; // y direction refinement
  f.interp.interp_param[6] = 1; // z direction refinement

  ReadMacroMesh(&f.macromesh, "../test/testcube.msh");
  //ReadMacroMesh(&f.macromesh,"test/testdisque.msh");
  BuildConnectivity(&f.macromesh);

  PrintMacroMesh(&f.macromesh);
  //AffineMapMacroMesh(&f.macromesh);
  PrintMacroMesh(&f.macromesh);
  
  Initfield(&f);
  CheckMacroMesh(&f.macromesh, f.interp.interp_param + 1);

  real tnow = 0.0;
  
  for(int ie = 0;ie < f.macromesh.nbelems; ie++)
    DGMacroCellInterfaceSlow((void*) (f.mcell+ie), &f, f.wn, f.dtwn);
  for(int ie = 0; ie < f.macromesh.nbelems; ie++) {
    DGSubCellInterface((void*) (f.mcell+ie), &f, f.wn, f.dtwn);
    DGVolume((void*) (f.mcell+ie), &f, f.wn, f.dtwn);
    DGMass((void*) (f.mcell+ie), &f, f.dtwn);
    DGSource((void*) (f.mcell+ie), &f, tnow, f.wn, f.dtwn);
  }

  /* DGMacroCellInterfaceSlow(&f); */
  /* DGSubCellInterface(&f); */
  /* DGVolume(&f); */
  /* DGMass(&f); */
  
  Displayfield(&f);  

  /* Plotfield(0, false, &f, NULL, "visu.msh"); */
  /* Plotfield(0, true, &f, "error", "error.msh"); */

  // test the time derivative with the exact solution
  int *raf = f.interp.interp_param + 4;
  int *deg = f.interp.interp_param + 1;
  for(int i=0;
      i < f.model.m * f.macromesh.nbelems * NPG(raf, deg);
      i++) {
    test = test && fabs(4 * f.wn[i] - pow(f.dtwn[i] , 2)) < 1e-2;
    assert(test);
  }
  
  return test;
}
Beispiel #17
0
int TestPoisson(void) {

  bool test = true;

  field f;
  init_empty_field(&f);
  
  int vec=1;

  // num of conservative variables f(vi) for each vi, phi, E, rho, u,
  // p, e (ou T)
  f.model.m=_MV+6; 
  f.vmax = _VMAX; // maximal wave speed
  f.model.NumFlux = VlasovP_Lagrangian_NumFlux;
  f.model.Source = VlasovP_Lagrangian_Source;
   //f.model.Source = NULL;
  
  f.model.BoundaryFlux = TestPoisson_BoundaryFlux;
  f.model.InitData = TestPoisson_InitData;
  f.model.ImposedData = TestPoisson_ImposedData;
 
  f.varindex = GenericVarindex;
  f.pre_dtfield = NULL;
  f.update_after_rk = NULL; 
    
    
  f.interp.interp_param[0] = f.model.m;  // _M
  f.interp.interp_param[1] = 3;  // x direction degree
  f.interp.interp_param[2] = 0;  // y direction degree
  f.interp.interp_param[3] = 0;  // z direction degree
  f.interp.interp_param[4] = 32;  // x direction refinement
  f.interp.interp_param[5] = 1;  // y direction refinement
  f.interp.interp_param[6] = 1;  // z direction refinement
  // read the gmsh file
  ReadMacroMesh(&(f.macromesh),"../test/testcube.msh");
  // try to detect a 2d mesh
  //bool is1d=Detect1DMacroMesh(&(f.macromesh));
  Detect1DMacroMesh(&(f.macromesh));
  bool is1d=f.macromesh.is1d;
  assert(is1d);

  // mesh preparation
  BuildConnectivity(&(f.macromesh));

  PrintMacroMesh(&(f.macromesh));
  //assert(1==2);
  //AffineMapMacroMesh(&(f.macromesh));
 
  // prepare the initial fields
  Initfield(&f);
  f.nb_diags=0;
  
  // prudence...
  CheckMacroMesh(&(f.macromesh),f.interp.interp_param+1);

  printf("cfl param =%f\n",f.hmin);

  // time derivative
  //dtField(&f);
  //DisplayField(&f);
  //assert(1==2);
  // apply the DG scheme
  // time integration by RK2 scheme 
  // up to final time = 1.
 
  /*Compute_electric_field(&f);

  // check the gradient on every glop
  for(int ie=0;ie<f.macromesh.nbelems;ie++){
    printf("elem %d\n",ie);
    for(int ipg=0;ipg<NPG(f.interp_param+1);ipg++){
      real xref[3],wpg;
      ref_pg_vol(f.interp_param+1,ipg,xref,&wpg,NULL);
      printf("Gauss point %d %f %f %f \n",ipg,xref[0],xref[1],xref[2]);
      int imem=f.varindex(f.interp_param,ie,ipg,_MV+1);
      printf("gradphi exact=%f gradphinum=%f\n",1-2*xref[0],f.wn[imem]);
      test=test && (fabs(f.wn[imem]-(1-2*xref[0]))<1e-10);
    }
    }*/

  //Computation_charge_density(f);
  
  SolvePoisson1D(&f,f.wn,1,0.0,0.0,LU,NONE);

  // check the gradient given by the poisson solver
  for(int ie=0;ie<f.macromesh.nbelems;ie++){
    MacroCell *mcell = f.mcell + ie;

    for(int ipg=0;ipg<NPG(mcell->raf, mcell->deg);ipg++){
      real xref[3],wpg;
      int *raf = f.interp_param+4;
      int *deg = f.interp_param+1;
      ref_pg_vol(raf, deg, ipg, xref, &wpg, NULL);
      //printf("Gauss point %d %f %f %f \n",ipg,xref[0],xref[1],xref[2]);
      int imem=f.varindex(f.interp_param, ipg, _MV + 1) + mcell->woffset;
      // printf("gradphi exact=%f gradphinum=%f rap=%f\n",
      //1-2*xref[0],f.wn[imem],(1-2*xref[0])/f.wn[imem]);
      real tolerance;
      if(sizeof(real) == sizeof(double))
	tolerance = 1e-8;
      else
	tolerance = 1e-4;

      test=test && (fabs(f.wn[imem]-(-1+2*xref[0])) < tolerance);
    }
  }
  return test;
}
Beispiel #18
0
// compute the Discontinuous Galerkin inter-macrocells boundary terms
void* DGMacroCellInterface(void* mc){

  MacroCell* mcell = (MacroCell*) mc;

  Field* f= mcell->field;

  int iparam[8];
  for(int ip=0;ip<8;ip++) iparam[ip]=f->interp_param[ip];
    
  // init to zero the time derivative
  for (int ie=mcell->first_cell;ie<mcell->last_cell_p1;ie++){
    for(int ipg=0;ipg<NPG(iparam+1);ipg++){
      for(int iv=0;iv<f->model.m;iv++){
	int imem=f->varindex(iparam,ie,ipg,iv);
	f->dtwn[imem]=0;
      }
    }
  }
  //assert(sizew==f->macromesh.nbelems * f->model.m * NPG(iparam+1));

  // assembly of the surface terms
  // 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];
    }

    // loop on the 6 faces
    // or four faces for 2d computations
    int nbfa=6;
    if (f->is2d) nbfa=4;
    for(int ifa=0;ifa<nbfa;ifa++){
      // get the right elem or the boundary id
      int ieR=f->macromesh.elem2elem[6*ie+ifa];
      double physnodeR[20][3];
      if (ieR >= 0) {
      	for(int inoloc=0;inoloc<20;inoloc++){
      	  int ino=f->macromesh.elem2node[20*ieR+inoloc];
      	  physnodeR[inoloc][0]=f->macromesh.node[3*ino+0];
      	  physnodeR[inoloc][1]=f->macromesh.node[3*ino+1];
      	  physnodeR[inoloc][2]=f->macromesh.node[3*ino+2];
      	}
      }


      // loop on the glops (numerical integration)
      // of the face ifa
      for(int ipgf=0;ipgf<NPGF(f->interp_param+1,ifa);ipgf++){
	//      for(int ipgf=0;ipgf<NPGF(iparam+1,ifa);ipgf++){ // FIXME?

  	double xpgref[3],xpgref_in[3],wpg;
  	//double xpgref2[3],wpg2;
  	// get the coordinates of the Gauss point
	// and coordinates of a point slightly inside the
	// opposite element in xref_in
  	ref_pg_face(iparam+1,ifa,ipgf,xpgref,&wpg,xpgref_in);

  	// recover the volume gauss point from
  	// the face index
  	int ipg=iparam[7];
  	// get the left value of w at the gauss point
  	double wL[f->model.m],wR[f->model.m];
  	for(int iv=0;iv<f->model.m;iv++){
  	  int imem=f->varindex(iparam,ie,ipg,iv);
  	  wL[iv]=f->wn[imem];
  	}
  	// the basis functions is also the gauss point index
  	int ib=ipg;
  	// normal vector at gauss point ipg
  	double dtau[3][3],codtau[3][3],xpg[3];
  	double vnds[3];
  	Ref2Phy(physnode,
  		xpgref,
  		NULL,ifa, // dpsiref,ifa
  		xpg,dtau,
  		codtau,NULL,vnds); // codtau,dpsi,vnds
  	double flux[f->model.m];
  	if (ieR >=0) {  // the right element exists
  	  // find the corresponding point in the right elem
	  double xpg_in[3];
	  Ref2Phy(physnode,
		  xpgref_in,
		  NULL,ifa, // dpsiref,ifa
		  xpg_in,dtau,
		  codtau,NULL,vnds); // codtau,dpsi,vnds
  	  double xref[3];
	  Phy2Ref(physnodeR,xpg_in,xref);
  	  int ipgR=ref_ipg(iparam+1,xref);
	  double xpgR[3],xrefR[3],wpgR;
	  ref_pg_vol(iparam+1, ipgR, xrefR, &wpgR,NULL);
	  Ref2Phy(physnodeR,
		  xrefR,
		  NULL,-1, // dphiref,ifa
		  xpgR,NULL,  
		  NULL,NULL,NULL); // codtau,dphi,vnds

	  assert(Dist(xpgR,xpg)<1e-10);
  	  for(int iv=0;iv<f->model.m;iv++){
  	    int imem=f->varindex(iparam,ieR,ipgR,iv);
  	    wR[iv]=f->wn[imem];
  	  }
  	  // int_dL F(wL,wR,grad phi_ib )
  	  f->model.NumFlux(wL,wR,vnds,flux);

   
  	}
  	else { //the right element does not exist
  	  f->model.BoundaryFlux(xpg,f->tnow,wL,vnds,flux);
  	}
  	for(int iv=0;iv<f->model.m;iv++){
  	  int imem=f->varindex(iparam,ie,ib,iv);
  	  f->dtwn[imem]-=flux[iv]*wpg;
  	}
	
      }

    }
  }

  return NULL;
}