sandbox/cselcuk/BasiliskGrainsCouplingFunctions.h

    Helper functions for interfacing Basilisk/Grains3D

    void printBasiliskDataStructure (struct BasiliskDataStructure * b) {
      printf("Grains nparticles = %lu\n", b->particlessize);
      
      /* Geometric aspect */
      printf("Grains radius = %f\n", b->rayon);
      printf("Grains center.x = %f\n", b->centreX);
      printf("Grains center.y = %f\n", b->centreY);
      printf("Grains center.z = %f\n", b->centreZ);
      printf("Grains ncorners = %d\n", b->ncorners);
    
    
      /* Coordinates of the corners, number of faces and their numerotation */
    
      printf("Grains allPoints = %lu\n", b->allPoints);
      printf("Grains allFaces = %lu\n", b->allFaces);
    
      for (int i = 0; i < (b->allPoints); i ++) {
    
    # if dimension == 2
        printf ("Grains Coordinates of point %d is (%f,%f)\n", i, b->PointsCoord[i][0],b->PointsCoord[i][1]);
        
    # elif dimension ==3
    
        printf ("Grains Coordinates of point %d is (%f,%f,%f)\n", i, b->PointsCoord[i][0], b->PointsCoord[i][1], b->PointsCoord[i][2]);
    # endif
      } 
       
      /* Velocities */
      printf("Grains U.x = %f\n", b->vitesseTX);
      printf("Grains U.y = %f\n", b->vitesseTY);
      printf("Grains U.z = %f\n", b->vitesseTZ);
      
      printf("Grains w.x = %f\n", b->vitesseRX);
      printf("Grains w.y = %f\n", b->vitesseRY);
      printf("Grains w.z = %f\n", b->vitesseRZ);
    
      /* Physical properties */
      printf ("Grains mass = %f\n", b->masse);
      printf ("Grains rho_s = %f\n", b->masseVol);
      for (int k = 0; k < 6; k++) {
          printf ("Grains inertia = %g\n", b->inertie[k]);
        }
    }
    
    void UpdateParticlesBasilisk (struct BasiliskDataStructure * b, particle * p, const int m) {
    
      int r;
      for (int k = 0; k < m; k++) {
        
    #if _MPI
    
        MPI_Bcast (&(b[k].particlessize), 1, MPI_INT, 0, MPI_COMM_WORLD);
    
        /* Geometric aspect */
        MPI_Bcast (&(b[k].centreX), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].centreY), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].centreZ), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].rayon), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].ncorners), 1, MPI_INT, 0, MPI_COMM_WORLD);
    
        /* Coordinates of the corners, number of faces and their numerotation */
        MPI_Bcast (&(b[k].allPoints), 1, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].allFaces), 1, MPI_INT, 0, MPI_COMM_WORLD);
    
        r = b[k].allPoints;
      
        /* Allocate the structure in the other threads (Grains is serial) */
        if (pid() > 0) {
          b[k].PointsCoord = (double **) malloc (r*sizeof(double *));
    #if dimension == 2 
          for (int i = 0; i < r; i++) 
    	b[k].PointsCoord[i] = (double *) malloc (2 * sizeof(double));
    #elif dimension == 3
          for (int i = 0; i < r; i++) 
    	b[k].PointsCoord[i] = (double *) malloc (3 * sizeof(double));
    #endif
        }
    
        for (int i = 0; i < r; i++) {
          MPI_Bcast (&(b[k].PointsCoord[i][0]), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
          MPI_Bcast (&(b[k].PointsCoord[i][1]), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    #if dimension ==3
          MPI_Bcast (&(b[k].PointsCoord[i][2]), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    #endif
        }
    
        /* Allocate the structures in the other threads (Grains is serial) */
        r = b[k].allFaces;
        if (pid() > 0) {
          b[k].FacesIndex = (long int **) malloc (r * sizeof(long int *));
          b[k].numPointsOnFaces = (long int *) malloc (r * sizeof(long int));
        }
    
        /* Broadcast-allocate-broadcast */
        for (int i = 0; i < r; i++) {
          MPI_Bcast (&(b[k].numPointsOnFaces[i]), 1, MPI_LONG, 0, MPI_COMM_WORLD);
          int rr = b[k].numPointsOnFaces[i];
          if (pid() > 0)
    	b[k].FacesIndex[i] = (long int *)malloc(rr * sizeof(long int));
          MPI_Barrier (MPI_COMM_WORLD);
    
          for (int j = 0; j < rr; j++)
    	MPI_Bcast (&(b[k].FacesIndex[i][j]), 1, MPI_LONG, 0, MPI_COMM_WORLD);
        }
    
        /* Velocities */
        MPI_Bcast (&(b[k].vitesseTX), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].vitesseTY), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].vitesseTZ), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].vitesseRX), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].vitesseRY), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].vitesseRZ), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    
        /* Physical properties */
        MPI_Bcast (&(b[k].masseVol), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        MPI_Bcast (&(b[k].masse), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        for (int i = 0; i < 6; i++)
          MPI_Bcast (&(b[k].inertie[i]), 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    #endif
    
     
        /* Geometric aspect */ 
        GeomParameter gg; 
        coord cc = {0., 0., 0.};
        cc.x = b[k].centreX;
        cc.y = b[k].centreY;
        cc.z = b[k].centreZ;
        gg.center = cc;
        gg.radius = b[k].rayon;
        gg.ncorners = b[k].ncorners;
        gg.allPoints = b[k].allPoints;
        gg.allFaces = b[k].allFaces;
    
        /* We need the coordinates of the corners for a cube */
    
        /* Allocate on all threads */
        r = gg.ncorners;
        gg.cornersCoord = (double **) malloc (r*sizeof(double *));
        
    #if dimension == 2 
        for (int i = 0; i < r; i++) 
          gg.cornersCoord[i] = (double *) malloc (2 * sizeof(double));
    #elif dimension == 3
        for (int i = 0; i < r; i++) 
          gg.cornersCoord[i] = (double *) malloc (3 * sizeof(double));
    #endif
    
        int ndim = 0;
        for (int i = 0; i < r; i++) {
    #if dimension == 2 
          ndim  = 2; 
    #elif dimension == 3
          ndim = 3;
    #endif
          for (int j = 0; j < ndim; j++) {
    	  gg.cornersCoord[i][j] = b[k].PointsCoord[i][j];
          }
        }
    
        /* We need the indices of the corners for a cube */
        /* Allocate */
        r = gg.allFaces;
        
        gg.cornersIndex = (long int **) malloc (r * sizeof(long int *));
        gg.numPointsOnFaces = (long int *) malloc (r * sizeof(long int));
        
        for (int i = 0; i < r; i++) {
          int rr = b[k].numPointsOnFaces[i];
          gg.cornersIndex[i] = (long int *) malloc (rr * sizeof(long int));
          gg.numPointsOnFaces[i] = rr;
          for (int j = 0; j < rr; j++) {
    	gg.cornersIndex[i][j] = b[k].FacesIndex[i][j];
          }
        }
        
        p[k].g = gg;
        
    #if DLM_Moving_particle    
        /* Velocities */
        cc.x = b[k].vitesseTX;
        cc.y = b[k].vitesseTY;
        cc.z = b[k].vitesseTZ;
    
    #if TRANSLATION
        /* Save the previous translational velocity before updating */
        p[k].Unm1 = p[k].U;
        p[k].U = cc;
    #endif
        cc.x = b[k].vitesseRX;
        cc.y = b[k].vitesseRY;
        cc.z = b[k].vitesseRZ;
    
    #if ROTATION
        /* Save the previous angular velocity before updating */
        p[k].wnm1 = p[k].w;
        p[k].w = cc;
    #endif
    #endif
        
        /* Physical properties */
        p[k].M = b[k].masse;
        p[k].rho_s = b[k].masseVol;
        p[k].Vp = (p[k].M)/(p[k].rho_s);
    
        /* Inertia tensor: Ggrains store them as */
        /* inertie[0] = Ixx; */
        /* inertie[1] = Ixy; */
        /* inertie[2] = Ixz; */
        /* inertie[3] = Iyy; */
        /* inertie[4] = Iyz; */
        /* inertie[5] = Izz; */
    
        /* Basilisk stores these as */
        /* Ip[0] = Ixx */
        /* Ip[1] = Iyy */
        /* Ip[2] = Izz */
        /* Ip[3] = Ixy */
        /* Ip[4] = Ixz */
        /* Ip[5] = Iyz */
          
        /* Ixx */
        p[k].Ip[0] = b[k].inertie[0];
        /* Iyy */
        p[k].Ip[1] = b[k].inertie[3];
        /* Izz */
        p[k].Ip[2] = b[k].inertie[5];
        /* Ixy */
        p[k].Ip[3] = b[k].inertie[1];
        /* Ixz */
        p[k].Ip[4] = b[k].inertie[2];
        /* Iyz */
        p[k].Ip[5] = b[k].inertie[4];
      }
    }
    
    
    void UpdateBasiliskStructure (struct BasiliskDataStructure * b, particle * p, const int m) {
    
      coord U = {0., 0., 0.};
      coord w = {0., 0., 0.};
      
      for (int k = 0; k < m; k++) {
    #if DLM_Moving_particle
    #if TRANSLATION
        U = p[k].U;
    #endif
    #if ROTATION
        w = p[k].w;
    #endif
    #endif
        b[k].vitesseTX = U.x;
        b[k].vitesseTY = U.y;
        b[k].vitesseTZ = U.z;
        b[k].vitesseRX = w.x;
        b[k].vitesseRY = w.y;
        b[k].vitesseRZ = w.z;   
      }
    }
    
    
    void unallocateBasiliskDataStructure(struct BasiliskDataStructure * b, const int m) {
    
      double * c;
      
      for (int k = 0; k < m; k++) {
        /* Unallocate fields of BasiliskDataStructure that are no longer needed (we transferred everything on the particles structure */
        /* printf("addresse of b[k].PointsCoord = %p\n", (void *) b[k].PointsCoord); */
        
        for (signed long int i = 0; i < b[k].allPoints; i++) {
          c = b[k].PointsCoord[i];
          /* printf("addresse of b[k].PointsCoord[i] = %p\n",(void *) b[k].PointsCoord[i]); */
          /* printf("c = %p\n",(void *) c); */
          if(c)
    	free(c);
        }
    
        /* printf("ok free(b[k].PointsCoord[i]) on thread %d\n",pid()); */
        free(b[k].PointsCoord);
    
        /* printf("ok free(b[k].PointsCoord) on thread %d\n",pid()); */
        
        for (signed long int i = 0; i < b[k].allFaces; i++) {
          free(b[k].FacesIndex[i]);
        }
        /* printf("ok free(b[k].FaceIndex[i]) on thread %d\n",pid()); */
        free(b[k].FacesIndex);
        free(b[k].numPointsOnFaces);
      }
    
    }