Beispiel #1
0
void RobustPhy2Ref(real physnode[20][3], real xphy[3], real xref[3]) 
{
#define _ITERNEWTON 8
#define _NTHETA 5

  real dtau[3][3], codtau[3][3];
  real dxref[3], dxphy[3],xphy0[3];
  int ifa =- 1;
  

  // construct a point xphy0 for which we know the inverse map
  xref[0] = 0.5;
  xref[1] = 0.5;
  xref[2] = 0.5;

  Ref2Phy(physnode, xref, 0,ifa, xphy0,0,0,0,0);


  // homotopy path
  // theta=0 -> xphy0
  // theta=1 -> xphy
  real dtheta=1./_NTHETA;

  for(int itheta=0;itheta<=_NTHETA;itheta++){
    //printf("itheta=%d\n",itheta);
    real theta=itheta*dtheta;
    // intermediate point to find
    real xphy1[3];
    for(int ii=0;ii<3;ii++){
      xphy1[ii]=theta*xphy[ii]+(1-theta)*xphy0[ii];
    }
  

    for(int iter = 0; iter < _ITERNEWTON; ++iter) {
      Ref2Phy(physnode, xref, 0,ifa, dxphy, dtau, codtau, 0,0);
      dxphy[0] -= xphy1[0];
      dxphy[1] -= xphy1[1];
      dxphy[2] -= xphy1[2];
      real det = dot_product(dtau[0], codtau[0]);
      //assert(det > 0);

      for(int ii = 0; ii < 3; ii ++ ) {
	dxref[ii] = 0;
	for(int jj = 0; jj < 3; jj ++ ) {
	  dxref[ii] += codtau[jj][ii] * dxphy[jj];
	}
	xref[ii] -= dxref[ii] / det;
      }
      //printf("iter= %d dxref=%f %f %f xref=%f %f %f\n",iter,dxref[0],dxref[1],dxref[2],xref[0],xref[1],xref[2]);
    }
  }

}
Beispiel #2
0
void GeomRef2Phy(Geom* g) 
{
  Ref2Phy(g->physnode, g->xref, g->dphiref,
          g->ifa, g->xphy, g->dtau, g->codtau,
          g->dphi, g->vnds);
  g->det 
    = g->codtau[0][0] * g->dtau[0][0] 
    + g->codtau[0][1] * g->dtau[0][1]
    + g->codtau[0][2] * g->dtau[0][2];
}
Beispiel #3
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 #4
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 #5
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 #6
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 #7
0
void Phy2Ref(real physnode[20][3], real xphy[3], real xref[3]) 
{
#define ITERNEWTON 10

  real dtau[3][3], codtau[3][3];
  real dxref[3], dxphy[3];
  int ifa =- 1;
  xref[0] = 0.5;
  xref[1] = 0.5;
  xref[2] = 0.5;

  real *codtau0 = codtau[0];
  real *codtau1 = codtau[1];
  real *codtau2 = codtau[2];

  for(int iter = 0; iter < ITERNEWTON; ++iter) {
    Ref2Phy(physnode, xref, 0,ifa, dxphy, dtau, codtau, 0,0);
    dxphy[0] -= xphy[0];
    dxphy[1] -= xphy[1];
    dxphy[2] -= xphy[2];
    real overdet = 1.0 / dot_product(dtau[0], codtau[0]);
    //assert(overdet > 0);

    for(int ii = 0; ii < 3; ii ++ ) {
      dxref[ii] = 0;
        dxref[ii] 
	  += codtau0[ii] * dxphy[0] 
	  +  codtau1[ii] * dxphy[1] 
	  +  codtau2[ii] * dxphy[2];
      xref[ii] -= dxref[ii] * overdet;
    }
  }

  /* real eps = 1e-2;  // may be to constraining... */
  /* assert(xref[0] < 1 + eps && xref[0] > -eps); */
  /* assert(xref[1] < 1 + eps && xref[1] > -eps); */
  /* assert(xref[2] < 1 + eps && xref[2] > -eps); */
}
Beispiel #8
0
// Detect if the mesh is 2D and then permut the nodes so that the z
// direction coincides in the reference or physical frame
void Detect2DMacroMesh(MacroMesh *m)
{
  m->is2d = true;

  // Do not permut the node if the connectivity is already built
  if(m->elem2elem != NULL)
    printf("Cannot permute nodes before building connectivity\n");
  assert(m->elem2elem == 0);

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

    // We decide that the mesh is 2D if the middles of the elements
    // have a constant z coordinate equal to 0.5
    real zmil = 0;
    for(int inoloc = 0; inoloc < 20; inoloc++) {
      zmil += physnode[inoloc][2];
    }
    zmil /= 20;
    //printf("zmil: %f\n", zmil);

    if(fabs(zmil-0.5) > 1e-6) {
      // The mesh is not 2d
      m->is2d = false;
      return;
    }
  }

  // TODO: if the mesh is not 2D, then assert constraints on nraf[2]
  // and deg[2].

  printf("Detection of a 2D mesh\n");
  for(int ie = 0; ie < m->nbelems; ie++) {
    // get the physical nodes of 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];
    }
    // If the mesh is 2d permut the nodes in order that the z^ and z
    // axis are the same

    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} };

    // Rotation of the cube around the origin at most two rotations
    // are needed to put the cube in a correct position
    for(int irot = 0; irot < 2; irot++) {
      // compute the normal to face 4
      real vnds[3], dtau[3][3], codtau[3][3];
      Ref2Phy(physnode,
	      face_centers[4],
	      NULL, 4, // dphiref,ifa
	      NULL, dtau,
	      codtau, NULL, vnds); // codtau,dphi,vnds

      real d = norm(vnds);
      // If the normal is not up or down we have to permut the nodes
      if(fabs(vnds[2] / d) < 0.9) {
	printf("irot=%d rotating the element %d\n", irot, ie);
	int oldnum[20];
	int newnum[20] = {1, 5, 6, 2, 4, 8, 7, 3, 11, 9, 
			  10, 17, 18, 13, 19, 12, 16, 14, 20, 15};
	for(int inoloc = 0; inoloc < 20; inoloc++) {
	  newnum[inoloc]--;
	  oldnum[inoloc] = m->elem2node[20 * ie + inoloc];
	}
	// Rotate the node numbering
	for(int inoloc = 0; inoloc < 20; inoloc++) {
	  m->elem2node[20 * ie + inoloc] = oldnum[newnum[inoloc]];
	}
	// Get the rotated node coordinates
	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];
	}

      }
    }

  }

}
Beispiel #9
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 #10
0
void PlotParticles(PIC* pic,MacroMesh *m)
{
  // FIXME: the output filenames should be specified.
  // FIXME: the output files should be closed at some point.
  
  FILE * gmshfile;
  FILE * gnufile;
  gmshfile = fopen("partplot.msh", "w" );
  gnufile = fopen("partplot.dat", "w" );

  float x,y,z,vx,vy,vz;
  fprintf(gmshfile, "$MeshFormat\n2.2 0 %d\n", (int) sizeof(real));
  fprintf(gmshfile, "$EndMeshFormat\n$Nodes\n%d\n", pic->nbparts);
  /* fic << "$MeshFormat"<<endl; */
  /* fic << "2 0 8" << endl; */
  /* fic << "$EndMeshFormat"<<endl; */
  /* fic << "$Nodes" << endl; */
  
  /* fic << NbPart <<endl;       */
  /* cout << "NbPartFinal " << NbPart << endl; */

  for(int i=0;i<pic->nbparts;i++) {

    int ie=pic->old_cell_id[i];
    
    
    // Get the physical nodes of 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];
    }
   
    real xphy[3];
    Ref2Phy(physnode, // phys. nodes
	    &(pic->xv[6*i]), // xref
	    NULL, -1, // dpsiref, ifa
	    xphy, NULL, // xphy, dtau
	    NULL, NULL, NULL); // codtau, dpsi, vnds

    
    /* x=pic->xv[6*i+0]; */
    /* y=pic->xv[6*i+1]; */
    /* z=pic->xv[6*i+2]; */

    x=xphy[0];
    y=xphy[1];
    z=xphy[2];

    vx=pic->xv[6*i+3];
    vy=pic->xv[6*i+4];
    vz=pic->xv[6*i+5];
    fprintf(gmshfile,"%d %f %f %f \n",i+1,x,y,z);
    /* fic << i+1 << " "<<x<<" "<<y<<" "<<0<<endl;	 */
    fprintf(gnufile,"%f %f %f %f %f %f  \n",x,y,z,vx,vy,vz);
  }
  
  fprintf(gmshfile, "$EndNodes\n");
  //fic << "$EndNodes"<<endl;

  fclose(gmshfile);
  fclose(gnufile);

}
Beispiel #11
0
// 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;


}
Beispiel #12
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;
}
Beispiel #13
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;

}
Beispiel #14
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 #15
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 #16
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 #17
0
// Detect if the mesh is 1D and then permut the nodes so that the y,z
// direction coincides in the reference or physical frame
void Detect1DMacroMesh(MacroMesh* m){
  m->is1d = true;

  // do not permut the node if the connectivity
  // is already built
  if (m->elem2elem != NULL)
    printf("Cannot permut nodes before building connectivity\n");
  assert(m->elem2elem == 0);

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

    // we decide that the mesh is 1D if the 
    // middles of the elements have a constant y,z 
    // coordinate equal to 0.5
    real zmil = 0;
    real ymil = 0;
    for(int inoloc = 0; inoloc < 20; inoloc++){
      zmil += physnode[inoloc][2];
      ymil += physnode[inoloc][1];
    }
    zmil /= 20;
    ymil /= 20;
    // the mesh is not 1d
    if (fabs(zmil-0.5)>1e-6 || fabs(ymil-0.5)>1e-6) {
      printf("The mesh is not 1D zmil=%f ymil=%f\n",zmil,ymil);
      m->is1d=false;
      return;
    }
  }

  printf("Detection of a 1D mesh\n");

  printf("Check now hexahedrons orientation\n");
  for(int ie = 0; ie < m->nbelems; ++ie){
    // get the physical nodes of 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];
    }

    // face centers coordinates in the ref frame
    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},
    };

    // compute the normal to face 1
    real vnds[3], dtau[3][3], codtau[3][3];
    Ref2Phy(physnode,
	    face_centers[1],
	    NULL, 1, // dphiref,ifa
	    NULL, dtau,
	    codtau, NULL, vnds); // codtau,dphi,vnds

    real d = sqrt((vnds[0] - 1) * (vnds[0] - 1) 
		+ vnds[1] * vnds[1]
		+ vnds[2] * vnds[2]);

    // if the mesh is not 1D exit
    assert(d<1e-6);
  }
}
Beispiel #18
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 #19
0
// Build other connectivity arrays
void BuildConnectivity(MacroMesh* m) 
{
  printf("Build connectivity...\n");

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

  printf("bounds: %f, %f, %f, %f, %f, %f\n",
	 bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);

  printf("bounds: %f, %f, %f, %f, %f, %f\n",
	 m->xmin[0],m->xmax[0],
	 m->xmin[1],m->xmax[1],
	 m->xmin[2],m->xmax[2]
	 );
  // Build a list of faces each face is made of four corners of the
  // hexaedron mesh
  Face4Sort *face = malloc(6 * sizeof(Face4Sort) * m->nbelems);
  build_face(m, face);
  build_elem2elem(m, face);
  free(face);

  build_node2elem(m);

  // check
  /* for(int ie = 0;ie<m->nbelems;ie++) { */
  /*   for(int ifa = 0;ifa<6;ifa++) { */
  /*     printf("elem=%d face=%d, voisin=%d\n", */
  /* 	     ie,ifa,m->elem2elem[ifa+6*ie]); */
  /*   } */
  /* } */
    
  if(m->is2d) suppress_zfaces(m);
  if(m->is1d) {
    suppress_zfaces(m);
    suppress_yfaces(m);
  }


  // update connectivity if the mesh is periodic
  // in some directions

  real diag[3][3]={1,0,0,
		   0,1,0,
		   0,0,1};

  for (int ie = 0; ie < m->nbelems; 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];
    }
    for(int ifa = 0; ifa < 6; ifa++) {
      if (m->elem2elem[6 * ie + ifa] < 0){
	real xpgref[3],xpgref_in[3];
	int ipgf=0;
	int param2[7]={0,0,0,1,1,1,0};
	ref_pg_face(param2, ifa, ipgf, xpgref, NULL, xpgref_in);
	real dtau[3][3],xpg_in[3];
	real codtau[3][3],vnds[3]={0,0,0};
	Ref2Phy(physnode,
		xpgref_in,
		NULL, ifa, // dpsiref,ifa
		xpg_in, dtau,
		codtau, NULL, vnds); // codtau,dpsi,vnds
	Normalize(vnds);
	vnds[0]=fabs(vnds[0]);
	vnds[1]=fabs(vnds[1]);
	vnds[2]=fabs(vnds[2]);
	int dim=0;
	while(Dist(vnds,diag[dim]) > 1e-2 && dim<3) dim++;
	//assert(dim < 3);
	//printf("xpg_in_before=%f\n",xpg_in[dim]);
	if (dim < 3 && m->period[dim]  > 0){
	  //if (xpg_in[dim] > m->period[dim]){
          if (xpg_in[dim] > m->xmax[dim]){
	    xpg_in[dim] -= m->period[dim];
	    //printf("xpg_in_after=%f\n",xpg_in[dim]);
	  }
	  //else if (xpg_in[dim] < 0){
          else if (xpg_in[dim] < m->xmin[dim]){
	    xpg_in[dim] += m->period[dim];
	    //printf("xpg_in_after=%f\n",xpg_in[dim]);
	  }
	  else {
            //printf("xpg_in=%f\n",xpg_in[dim]);
	    assert(1==2);
	  }
	  m->elem2elem[6 * ie + ifa] = NumElemFromPoint(m,xpg_in,NULL);
	  /* printf("ie=%d ifa=%d numelem=%d vnds=%f %f %f xpg_in=%f %f %f \n", */
	  /* 	 ie,ifa,NumElemFromPoint(m,xpg_in,NULL), */
	  /* 	 vnds[0],vnds[1],vnds[2], */
	  /* 	 xpg_in[0],xpg_in[1],xpg_in[2]); */
	}
      }
    }
  }

  // now, update the face2elem connectivity (because elem2elem has changed)
  for(int ifa = 0; ifa < m->nbfaces; ifa++) {
    int ieL = m->face2elem[4 * ifa + 0];
    int locfaL = m->face2elem[4 * ifa + 1];
    int ieR = m->face2elem[4 * ifa + 2];
    int locfaR = m->face2elem[4 * ifa + 3];

    int ieR2=m->elem2elem[6 * ieL + locfaL];

    if (ieR != ieR2){
      assert(ieR == -1);
      int opp[6]={2,3,0,1,5,4};
      if (locfaL == 0 || locfaL == 1 || locfaL == 4) {
	m->face2elem[4 * ifa + 2] = ieR2;
	m->face2elem[4 * ifa + 3] = opp[locfaL];
      } else {
	// mark the face for suppression
	m->face2elem[4 * ifa + 0] = -1;
      }
    }
  }

  suppress_double_faces(m);

  

  //assert(1==5);
  free(bounds);

  m->connec_ok = true;

/* #ifdef _PERIOD */
/*   assert(m->is1d); // TODO : generalize to 2D */
/*   assert(m->nbelems==1);  */
/*   // faces 1 and 3 point to the same unique macrocell */
/*   m->elem2elem[1+6*0]=0; */
/*   m->elem2elem[3+6*0]=0; */
/* #endif */
  
}
Beispiel #20
0
void PushParticles(field *f,PIC* pic){

  for(int i=0;i<pic->nbparts;i++) {
    

    // jacobian of tau at the particle
    real physnode[20][3];
    int ie=pic->cell_id[i];
    if (ie >=0) {
      real w[f->model.m];
      InterpField(f,pic->cell_id[i],&(pic->xv[6*i]),w);

      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];
      
      real xphy[3];
      Ref2Phy(physnode, // phys. nodes
	      &(pic->xv[6*i]), // xref
	      NULL, -1, // dpsiref, ifa
	      xphy, dtau, // xphy, dtau
	      codtau, NULL, NULL); // codtau, dpsi, vnds
      real det = dot_product(dtau[0], codtau[0]);
      
      
      //printf("w=%f %f %f %f\n",w[0],w[1],w[2],w[3]);
      
      // 2D motion
      
      real vref[3];
      pic->xv[6*i+3+0] +=pic->dt * (w[0]+w[2]*pic->xv[6*i+4]);
      pic->xv[6*i+3+1] +=pic->dt * (w[1]-w[2]*pic->xv[6*i+3]);
      pic->xv[6*i+3+2] +=0;


      for(int ii=0;ii<3;ii++){
	vref[ii]=0;
	for(int jj=0;jj<3;jj++){
	  vref[ii] += codtau[jj][ii] * pic->xv[6*i+3+jj] / det ;
	}
      }

      // TO DO: check if the particle is in a new element
      pic->xv[6*i+0]+=pic->dt * vref[0];
      pic->xv[6*i+1]+=pic->dt * vref[1];
      pic->xv[6*i+2]+=pic->dt * vref[2];

      bool is_out = (pic->xv[6*i+0] < 0 || pic->xv[6*i+0] > 1) ||
	(pic->xv[6*i+1] < 0 || pic->xv[6*i+1] > 1)  ||
	(pic->xv[6*i+2] < 0 || pic->xv[6*i+2] > 1);
      
      //is_out = false;

      if (is_out) {
	Ref2Phy(physnode, // phys. nodes
		&(pic->xv[6*i]), // xref
		NULL, -1, // dpsiref, ifa
		xphy, NULL, // xphy, dtau
		NULL, NULL, NULL); // codtau, dpsi, vnds
	int old=pic->cell_id[i];
	printf("oldref=%f %f %f \n",pic->xv[6*i+0],
	       pic->xv[6*i+1],pic->xv[6*i+2]);
	pic->cell_id[i]= NumElemFromPoint(&(f->macromesh),
					  xphy,
					  &(pic->xv[6*i]));
	if (pic->cell_id[i] != -1) pic->old_cell_id[i]=pic->cell_id[i]; 
	printf("newref=%f %f %f \n",pic->xv[6*i+0],
	       pic->xv[6*i+1],pic->xv[6*i+2]);
	printf("change elem: %d -> %d \n",old,pic->cell_id[i]);
      }

    

    } // if ie >= 0
  }
  

}
Beispiel #21
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];
      }
    }

  }
    
};