Esempio n. 1
0
/*
	* Read the previous FFD simulation data in a format of standard output
	*
	* @param para Pointer to FFD parameters
	* @param var Pointer to FFD simulation variables
	*
	* @return 0 if no error occurred
	*/
int read_ffd_data(PARA_DATA *para, REAL **var) {
  int i,j, k;
  int imax = para->geom->imax;
  int jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  char string[400];

  if((file_old_ffd=fopen(para->inpu->old_ffd_file_name,"r"))==NULL) {
    sprintf(msg, "ffd_data_reader.c: Can not open file \"%s\".",
            para->inpu->old_ffd_file_name);
    ffd_log(msg, FFD_ERROR);
    return 1;
  }

  FOR_ALL_CELL
   fgets(string, 400, file_old_ffd);
   sscanf(string,"%lf%lf%lf%lf%lf%lf", &var[VX][IX(i,j,k)], &var[VY][IX(i,j,k)],
          &var[VZ][IX(i,j,k)], &var[TEMP][IX(i,j,k)],
          &var[Xi1][IX(i,j,k)], &var[IP][IX(i,j,k)]);
  END_FOR

  fclose(file_old_ffd);
  sprintf(msg, "read_ffd_data(): Read previous ffd simulation data file %s.",
          para->inpu->old_ffd_file_name);
  ffd_log(msg, FFD_NORMAL);
  return 0;
} /* End of read_ffd_data()*/
///////////////////////////////////////////////////////////////////////////////
/// Compare the area of boundaries
///
///\param para Pointer to FFD parameters
///\param var Pointer to the FFD simulaiton variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int compare_boundary_area(PARA_DATA *para, REAL **var, int **BINDEX) {
  int i, j;
  REAL *A0 = para->bc->AWall, *A1 = para->cosim->para->are;

  ffd_log("compare_boundary_area(): "
          "Start to compare the area of solid surfaces.",
          FFD_NORMAL);
  for(i=0; i<para->bc->nb_wall; i++) {
    j = para->bc->wallId[i];
    if(fabs(A0[i]-A1[j])<SMALL) {
      sprintf(msg, "\t%s has the same area of %f[m2]",
        para->bc->wallName[i], A0[i]);
      ffd_log(msg, FFD_NORMAL);
    }
    else {
      sprintf(msg, 
              "compare_boundary_area(): Area of surface %s are different: "
              "Modelica (%f[m2]) and FFD (%f[m2])",
              para->bc->wallName[i], A1[j], A0[i]);
      ffd_log(msg, FFD_ERROR);
      return 1;
    }
  }

  return 0;
} // End of compare_boundary_area()
Esempio n. 3
0
///////////////////////////////////////////////////////////////////////////////
/// TDMA solver for 1D array
///
///\param ap Pointer to coefficient for center
///\param ae Pointer to coefficient for east
///\param aw Pointer to coefficient for west
///\param b Pointer to b
///\param psi Pointer to variable
///\param LENGTH Length of the array
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int TDMA_1D(REAL *ap, REAL *ae, REAL *aw, REAL *b, REAL *psi,
             int LENGTH) {
  REAL *P, *Q;
  int i;

  P = (REAL *)malloc(LENGTH * sizeof(REAL));
  if(P==NULL) {
    ffd_log("TDMA_1D(): Could not allocate memory for P.", FFD_ERROR);
    return 1;
  }
  Q = (REAL *)malloc(LENGTH * sizeof(REAL));
  if(Q==NULL) {
    ffd_log("TDMA_1D(): Could not allocate memory for Q.", FFD_ERROR);
    return 1;
  }
  for(i=1; i<=LENGTH-1; i++) {
    P[i] = ae[i] / (ap[i] - aw[i]*P[i-1]);
    Q[i] = (b[i] + aw[i]*Q[i-1]) / (ap[i] - aw[i]*P[i-1]);
  }

  for(i=LENGTH-1; i>=1; i--)
    psi[i] = P[i]*psi[i+1] + Q[i];

  free(P);
  free(Q);
  return 0;
} /* end of TDMA_1D() */
Esempio n. 4
0
///////////////////////////////////////////////////////////////////////////////
/// Read the file to identify the block cells in space
///
/// The default name used by SCi is zeroone.dat. The user can change the file
/// name and give the new name in the FFD input file *.ffd.
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int read_sci_zeroone(PARA_DATA *para, REAL **var, int **BINDEX) {
  int i, j, k;
  int delcount=0;
  int mark;
  int imax = para->geom->imax;
  int jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int index = para->geom->index;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  REAL *flagp = var[FLAGP];

  if( (file_params=fopen(para->inpu->block_file_name,"r")) == NULL ) {
    sprintf(msg, "read_sci_input():Could not open file \"%s\"!\n",
            para->inpu->block_file_name);
    ffd_log(msg, FFD_ERROR);
    return 1;
  }

  sprintf(msg, "read_sci_input(): start to read block information from \"%s\".",
          para->inpu->block_file_name);
  ffd_log(msg, FFD_NORMAL);

  for(k=1;k<=kmax;k++)
    for(j=1;j<=jmax;j++)
      for(i=1;i<=imax;i++) {
        fscanf(file_params,"%d" ,&mark);

        // mark=1 block cell;mark=0 fluid cell

        if(mark==1) {
          flagp[IX(i,j,k)] = SOLID;
          BINDEX[0][index] = i;
          BINDEX[1][index] = j;
          BINDEX[2][index] = k;
          index++;
        }
        delcount++;

        if(delcount==25) {
          fscanf(file_params,"\n");
          delcount=0;
        }
      }

  fclose(file_params);
  para->geom->index=index;

  sprintf(msg, "read_sci_input(): end of reading zeroone.dat.");
  ffd_log(msg, FFD_NORMAL);

  return 0;
} // End of read_sci_zeroone()
Esempio n. 5
0
///////////////////////////////////////////////////////////////////////////////
/// Allcoate memory for variables
///
///\param para Pointer to FFD parameters
///
///\return No return needed
///////////////////////////////////////////////////////////////////////////////
int allocate_memory (PARA_DATA *para) {

  int nb_var, i;
  int size = (geom.imax+2) * (geom.jmax+2) * (geom.kmax+2);

  /****************************************************************************
  | Allocate memory for variables
  ****************************************************************************/
  nb_var = C2BC+1;
  var       = (REAL **) malloc ( nb_var*sizeof(REAL*) );
  if(var==NULL) {
    ffd_log("allocate_memory(): Could not allocate memory for var.",
            FFD_ERROR);
    return 1;
  }

  for(i=0; i<nb_var; i++) {
    var[i] = (REAL *) calloc(size, sizeof(REAL));
    if(var[i]==NULL) {
      sprintf(msg, 
              "allocate_memory(): Could not allocate memory for var[%d]", i);
      ffd_log(msg, FFD_ERROR);
      return 1;
    }
  }

  /****************************************************************************
  | Allocate memory for boundary cells
  | BINDEX[0]: i of global coordinate in IX(i,j,k)
  | BINDEX[1]: j of global coordinate in IX(i,j,k)
  | BINDEX[2]: k of global coordinate in IX(i,j,k)
  | BINDEX[3]: Fixed temperature or fixed heat flux
  | BINDEX[4]: Boundary ID to identify which boundary it belongs to
  ****************************************************************************/
  BINDEX = (int **)malloc(5*sizeof(int*));
  if(BINDEX==NULL) {
    ffd_log("allocate_memory(): Could not allocate memory for BINDEX.",
            FFD_ERROR);
    return 1;
  }

  for(i=0; i<5; i++) {
    BINDEX[i] = (int *) malloc(size*sizeof(int));
    if(BINDEX[i]==NULL) {
      sprintf(msg, 
              "allocate_memory(): Could not allocate memory for BINDEX[%d]", i);
      ffd_log(msg, FFD_ERROR);
      return 1;
    }
  }
  return 0;
} // End of allocate_memory()
Esempio n. 6
0
///////////////////////////////////////////////////////////////////////////////
/// Calculate convective heat transfer coefficient divided by 
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param i I-index of the cell
///\param j J-index of the cell
///\param k K-index of the cell
///\param D distance from the cell center to the wall
///
///\return Mass flow difference divided by the outflow area
///////////////////////////////////////////////////////////////////////////////
REAL h_coef(PARA_DATA *para, REAL **var, int i, int j, int k, REAL D) {
  REAL h, kapa; 
  REAL nu = para->prob->nu;

  switch(para->prob->tur_model) {
    case LAM:
      kapa = nu; 
      break;
    case CONSTANT:
      kapa = (REAL)101.0 * nu;
      break;
    case CHEN:
      kapa = nu + nu_t_chen_zero_equ(para, var, i, j, k);
      break;
    default:
      sprintf(msg, "h_coef(): Value (%d) for para->prob->tur_model"
              "was not correct.", para->prob->tur_model);
      ffd_log(msg, FFD_ERROR);
  }
  h = para->prob->Cp * para->prob->rho * para->prob->alpha * kapa 
    / (nu * D);

  return h;

} // End of h_coef()
Esempio n. 7
0
///////////////////////////////////////////////////////////////////////////////
/// Solver for equations
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param var_type Variable type
///\param Pointer to variable
///
///\return 0 if not error occurred
///////////////////////////////////////////////////////////////////////////////
int equ_solver(PARA_DATA *para, REAL **var, int var_type, REAL *psi) {
  REAL *flagp = var[FLAGP], *flagu = var[FLAGU],
       *flagv = var[FLAGV], *flagw = var[FLAGW];
  int flag = 0;

  switch(var_type) {
    case VX:
      Gauss_Seidel(para, var, flagu, psi);
      break;
    case VY:
      Gauss_Seidel(para, var, flagv, psi);
      break;
    case VZ:
      Gauss_Seidel(para, var, flagw, psi);
      break;
    case TEMP:
    case IP:
    case Xi1:
    case Xi2:
    case C1:
    case C2:
      Gauss_Seidel(para, var, flagp, psi);
      break;
    default:
      sprintf(msg, "equ_solver(): Solver for variable type %d is not defined.", 
              var_type);
      ffd_log(msg, FFD_ERROR);
      flag = 1;
      break;
  }

  return flag;
}// end of equ_solver
Esempio n. 8
0
/******************************************************************************
  Write data that will be read by other program
******************************************************************************/
int write_cosimulation_data(PARA_DATA *para, REAL **var)
{
  int i;
  int imax = para->geom->imax, jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);

  ffdSharedData data;


  /*--------------------------------------------------------------------------
  | The following code is to be modified by the users
  --------------------------------------------------------------------------*/
  for(i=0; i<3; i++)
    data.number[i] = var[VX][IX(1,1,1)] + i;

  data.status = 1;
  data.t = para->mytime->t;

  strcpy(data.message, "This is FFD data\0");

  if(write_to_shared_memory(&data))
    exit(1);
  else
    ffd_log("cosimulation.c: write data to shared memory.", FFD_NORMAL);

  return 0;
} // End of write_cosimulation_data()
Esempio n. 9
0
/******************************************************************************
  Read the data send from the other program
******************************************************************************/
int read_cosimulation_data(PARA_DATA *para, REAL **var)
{
  int j, k;
  int imax = para->geom->imax, jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  otherSharedData data;
  REAL feak[1];

  if(read_from_shared_memory(&data))
    exit(1);
  else
    ffd_log("cosimulation.c: read data from shared memory.", FFD_NORMAL);

  feak[0] = data.arr[0];

  /*--------------------------------------------------------------------------
  | The following code is to be modified by the users
  --------------------------------------------------------------------------*/
  for(j=0; j<=jmax+1; j++)
    for(k=0; k<=kmax+1; k++)
      var[TEMPBC][IX(imax+1,j,k)]= feak[0];

   
  printf("\ntime=%f, status=%d\n", data.t, data.status);
  printf("arr[0]=%f, arr[1]=%f, arr[2]=%f\n", data.arr[0], data.arr[1], data.arr[2]);

   //printf("message=%s\n",data.message); 

  return 0;
} // End of read_cosimulation_data()
///////////////////////////////////////////////////////////////////////////////
/// Initialize the parameters 
///
///\param para Pointer to FFD parameters
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int initialize(PARA_DATA *para) {
  // Define the default value for parameter
  set_default_parameter(para);

  // Overwrite the default values using user defined values
  if(read_parameter(para)) {
    ffd_log("initialize(): Failed to read paramter file.", FFD_ERROR);
    return 1;
  }

  /*---------------------------------------------------------------------------
  | Output the help information 
  ---------------------------------------------------------------------------*/
  if(para->outp->version==DEMO) {
    printf("\n\nHow to use this demo:\n\n" );
    printf("\t Switch Windows: \n");
    printf("\t\tVelocity: key '1'\n");
    printf("\t\tContaminant: key '2'\n");
    printf("\t\tTemperature: key '3'\n");
    printf("\t Add densities with the right mouse button\n");
    printf("\t Add velocities with the left mouse button\n");
    printf("\t Increase the inlet velocity with 'F' or 'f' key\n");
    printf("\t Decrease the inlet velocity with 'S' or 's' key\n");
    printf("\t Increase the BC temperature with 'H' or 'h' key\n");
    printf("\t Decrease the BC temperature with 'C' or 'c' key\n" );
    printf("\t Clear the simulation by pressing the '0' key\n" );
    printf("\t Quit by pressing the 'q' key\n" );
  }

  return 0;
} // End of initialize( )
Esempio n. 11
0
///////////////////////////////////////////////////////////////////////////////
/// Calculate the velocity
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
/////////////////////////////////////////////////////////////////////////////// 
int vel_step(PARA_DATA *para, REAL **var,int **BINDEX) {
  REAL *u  = var[VX],  *v  = var[VY],    *w  = var[VZ];
  REAL *u0 = var[TMP1], *v0 = var[TMP2], *w0 = var[TMP3];
  int flag = 0;

  flag = advect(para, var, VX, 0, u0, u, BINDEX);
  if(flag!=0) {
    ffd_log("vel_step(): Could not advect for velocity X.", FFD_ERROR);
    return flag;
  }

  flag = advect(para, var, VY, 0, v0, v, BINDEX);
  if(flag!=0) {
    ffd_log("vel_step(): Could not advect for velocity Y.", FFD_ERROR);
    return flag;
  }

  flag = advect(para, var, VZ, 0, w0, w, BINDEX); 
  if(flag!=0) {
    ffd_log("vel_step(): Could not advect for velocity Z.", FFD_ERROR);
    return flag;
  }

  flag = diffusion(para, var, VX, 0, u, u0, BINDEX);
  if(flag!=0) {
    ffd_log("vel_step(): Could not diffuse velocity X.", FFD_ERROR);
    return flag;
  }

  flag = diffusion(para, var, VY, 0, v, v0, BINDEX);
  if(flag!=0) {
    ffd_log("vel_step(): Could not diffuse velocity Y.", FFD_ERROR);
    return flag;
  }

  flag = diffusion(para, var, VZ, 0, w, w0, BINDEX); 
  if(flag!=0) {
    ffd_log("vel_step(): Could not diffuse velocity Z.", FFD_ERROR);
    return flag;
  }

  flag = project(para, var,BINDEX);
  if(flag!=0) {
    ffd_log("vel_step(): Could not project velocity.", FFD_ERROR);
    return flag;
  }

  if(para->bc->nb_outlet!=0) flag = mass_conservation(para, var,BINDEX);
  if(flag!=0) {
    ffd_log("vel_step(): Could not conduct mass conservation correction.",
            FFD_ERROR);
    return flag;
  }

  return flag;
} // End of vel_step( )
///////////////////////////////////////////////////////////////////////////////
/// Write the instantaneous value of variables in Tecplot format
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param name Pointer to the filename
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int write_unsteady(PARA_DATA *para, REAL **var, char *name){
  int i,j,k;
  int imax=para->geom->imax, jmax=para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  REAL *u = var[VX], *v = var[VY], *w = var[VZ], *p = var[IP];
  REAL  *d = var[TRACE];
  REAL *T = var[TEMP];
  char *filename;
  FILE *datafile;

  /****************************************************************************
  | Allocate memory for filename
  | Length of filename should be sizeof(ActualName) + 1
  | Using sizeof(ActualName) will cause memory fault in free(filename)
  ****************************************************************************/
  filename = (char *) malloc((strlen(name)+5)*sizeof(char));
  if(filename==NULL) {
    ffd_log("write_unsteady(): Failed to allocate memory for file name", 
            FFD_ERROR); 
    return 1;
  }

  strcpy(filename, name);
  strcat(filename, ".plt");

  // Open output file
  if((datafile=fopen(filename,"w"))==NULL) {
    sprintf(msg, "write_unsteady(): Failed to open file %s.", filename);
    ffd_log(msg, FFD_ERROR);
    return 1;
  }

  FOR_ALL_CELL
    fprintf( datafile, "%f\t%f\t%f\t",u[IX(i,j,k)], v[IX(i,j,k)], w[IX(i,j,k)]);
    fprintf( datafile, "%f\t%f\t%f\n",T[IX(i,j,k)], d[IX(i,j,k)], p[IX(i,j,k)]);
  END_FOR

  sprintf(msg, "write_unsteady(): Wrote the unsteady data file %s.", filename);
  ffd_log(msg, FFD_NORMAL);

  free(filename);
  fclose(datafile);
  return 0;
} //write_unsteady()
Esempio n. 13
0
///////////////////////////////////////////////////////////////////////////////
/// Calculate the temperature
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int temp_step(PARA_DATA *para, REAL **var, int **BINDEX) {
  REAL *T = var[TEMP], *T0 = var[TMP1];
  int flag = 0;

  flag = advect(para, var, TEMP, 0, T0, T, BINDEX); 
  if(flag!=0) {
    ffd_log("temp_step(): Could not advect temperature.", FFD_ERROR);
    return flag;
  }

  flag = diffusion(para, var, TEMP, 0, T, T0, BINDEX);
  if(flag!=0) {
    ffd_log("temp_step(): Could not diffuse temperature.", FFD_ERROR);
    return flag;
  }

  return flag;
} // End of temp_step( )
Esempio n. 14
0
///////////////////////////////////////////////////////////////////////////////
/// Entrance of calculating diffusion equation
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param var_type Type of variable
///\param index Index of trace substance or species
///\param psi Pointer to the variable at current time step
///\param psi0 Pointer to the variable at previous time step
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int diffusion(PARA_DATA *para, REAL **var, int var_type, int index,
               REAL *psi, REAL *psi0, int **BINDEX) {
  int flag = 0;

  /****************************************************************************
  | Define the coeffcients for diffusion euqation
  ****************************************************************************/
  flag = coef_diff(para, var, psi, psi0, var_type, index, BINDEX);
  if(flag!=0) {
    ffd_log("diffsuion(): Could not calculate coefficents for "
            "diffusion equation.", FFD_ERROR);
    return flag;
  }

  // Solve the equations
  equ_solver(para, var, var_type, psi);

  // Define B.C.
  set_bnd(para, var, var_type, index, psi, BINDEX);

  // Check residual
  if(para->solv->check_residual==1) {
    switch(var_type) {
      case VX:
        sprintf(msg, "diffusion(): Residual of VX is %f",
                check_residual(para, var, psi));
        ffd_log(msg, FFD_NORMAL);
        break;
      case VY:
        sprintf(msg, "diffusion(): Residual of VY is %f",
                check_residual(para, var, psi));
        ffd_log(msg, FFD_NORMAL);
        break;
      case VZ:
        sprintf(msg, "diffusion(): Residual of VZ is %f",
                check_residual(para, var, psi));
        ffd_log(msg, FFD_NORMAL);
        break;
      case TEMP:
        sprintf(msg, "diffusion(): Residual of T is %f",
                check_residual(para, var, psi));
        ffd_log(msg, FFD_NORMAL);
        break;
      case TRACE:
        sprintf(msg, "diffusion(): Residual of Trace %d is %f",
                index, check_residual(para, var, psi));
        ffd_log(msg, FFD_NORMAL);
        break;
      default:
        sprintf(msg, "diffusion(): No sovler for varibale type %d", 
                var_type);
        ffd_log(msg, FFD_ERROR);
        flag = 1;
    }
  }
       
  return flag;
} // End of diffusion( )
Esempio n. 15
0
///////////////////////////////////////////////////////////////////////////////
/// Calculate the contaminant concentration
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
/////////////////////////////////////////////////////////////////////////////// 
int den_step(PARA_DATA *para, REAL **var, int **BINDEX) {
  REAL *den, *den0 = var[TMP1];
  int i, flag = 0;

  /****************************************************************************
  | Solve the species
  ****************************************************************************/
  for(i=0; i<para->bc->nb_Xi; i++) {
    if(para->outp->version==DEBUG) {
      sprintf(msg, "den_step(): start to solve Xi%d", i+1);
      ffd_log(msg, FFD_NORMAL);
    }
    den = var[Xi1+i];
    flag = advect(para, var, Xi1+i, i, den0, den, BINDEX);
    if(flag!=0) {
      sprintf(msg, "den_step(): Could not advect species %d", i+1);
      ffd_log(msg, FFD_ERROR);
      return flag;
    }

    flag = diffusion(para, var, Xi1+i, i, den, den0, BINDEX);
    if(flag!=0) {
      sprintf(msg, "den_step(): Could not diffuse species %d", i+1);
      ffd_log(msg, FFD_ERROR);
      return flag;
    }
  }

  /****************************************************************************
  | Solve the trace substances
  ****************************************************************************/
  for(i=0; i<para->bc->nb_C; i++) {
    if(para->outp->version==DEBUG) {
      sprintf(msg, "den_step(): start to solve C%d", i+1);
      ffd_log(msg, FFD_NORMAL);
    }
    den = var[C1+i];
    flag = advect(para, var, Xi1, i, den0, den, BINDEX);
    if(flag!=0) {
      sprintf(msg, "den_step(): Could not advect trace substance %d", i+1);
      ffd_log(msg, FFD_ERROR);
      return flag;
    }

    flag = diffusion(para, var, Xi1, i, den, den0, BINDEX);
    if(flag!=0) {
      sprintf(msg, "den_step(): Could not diffuse trace substance %d", i+1);
      ffd_log(msg, FFD_ERROR);
      return flag;
    }
  }

  return flag;
} // End of den_step( )
Esempio n. 16
0
///////////////////////////////////////////////////////////////////////////////
/// Entrance of interpolation
///
///\param para Pointer to FFD parameters
///\param d0 Pointer to the variable for interpolation
///\param p I-index of the control volume
///\param q J-index of the control volume
///\param r K-index of the control volume
///\param x_1 Reciprocal of X-length
///\param y_1 Reciprocal of Y-length
///\param z_1 Reciprocal of Z-length
///
///\return Interpolated value
///////////////////////////////////////////////////////////////////////////////
REAL interpolation(PARA_DATA *para, REAL *d0, REAL x_1, REAL y_1, REAL z_1,
                   int p, int q, int r) {
  int imax = para->geom->imax, jmax = para->geom->jmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);

  switch(para->solv->interpolation) {
    case BILINEAR:
      return interpolation_bilinear(x_1, y_1, z_1,
        d0[IX(p,q,r)],  d0[IX(p,q+1,r)],  d0[IX(p+1,q,r)],  d0[IX(p+1,q+1,r)],
        d0[IX(p,q,r+1)],d0[IX(p,q+1,r+1)],d0[IX(p+1,q,r+1)],d0[IX(p+1,q+1,r+1)]);
     break;
    default:
      sprintf(msg,
        "interpolation(): the required interpolation method %d is not available.",
        para->solv->interpolation);
      ffd_log(msg, FFD_ERROR);
      return -1;
  }
} // End of interpolation()
Esempio n. 17
0
///////////////////////////////////////////////////////////////////////////////
/// TDMA solver for 3D
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param type Type of variable
///\param psi Pointer to variable
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int TDMA_3D(PARA_DATA *para, REAL **var, int type, REAL *psi) {
  int imax = para->geom->imax;
  int jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int i, j, k;

  //West to East
  for(i=1; i<=imax; i++) {
    if(TDMA_YZ(para, var, psi, i)) {
      ffd_log("TDMA_3D: Could not compute TDMA_YZ.", FFD_ERROR);
      return 1;
    }
  }
  //South to North
  for(j=1; j<=jmax; j++) {
    if(TDMA_ZX(para, var, psi, j)) {
      ffd_log("TDMA_3D: Could not compute TDMA_ZX.", FFD_ERROR);
      return 1;
    }
  }
  //Back to Front
  for(k=1; k<=kmax; k++) {
    if(TDMA_XY(para, var, psi, k)) {
      ffd_log("TDMA_3D: Could not compute TDMA_XY.", FFD_ERROR);
      return 1;
    }
  }
  //East to West
  for(i=imax; i>=1; i--) {
    if(TDMA_YZ(para, var, psi, i)) {
      ffd_log("TDMA_3D: Could not compute TDMA_YZ.", FFD_ERROR);
      return 1;
    }
  }
  //North to South
  for(j=jmax; j>=1; j--) {
    if(TDMA_ZX(para, var, psi, j)) {
      ffd_log("TDMA_3D: Could not compute TDMA_ZX.", FFD_ERROR);
      return 1;
    }
  }
  //Front to Back
  for(k=kmax; k>=1; k--) {
    if(TDMA_XY(para, var, psi, k)) {
      ffd_log("TDMA_3D: Could not compute TDMA_YZ.", FFD_ERROR);
      return 1;
    }
  }
  return 0;
}// end of TDMA_3D()
Esempio n. 18
0
///////////////////////////////////////////////////////////////////////////////
/// Entrance of setting boundary conditions
///
/// Specific boundary conditions will be selected according to the variable 
/// type.
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param var_type The type of variable
///\param index Index of trace substances or species
///\param psi Pointer to the variable needing the boundary conditions
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int set_bnd(PARA_DATA *para, REAL **var, int var_type, int index, REAL *psi, 
            int **BINDEX) {
  int flag;
  switch(var_type) {
    case VX:
      flag = set_bnd_vel(para, var, VX, psi, BINDEX); 
      if(flag!=0)
        ffd_log("set_bnd(): Could not set boundary condition for X-velocity.",
                FFD_ERROR);
      break;
    case VY:
      flag = set_bnd_vel(para, var, VY, psi, BINDEX); 
      if(flag!=0)
        ffd_log("set_bnd(): Could not set boundary condition for Y-velocity.",
                FFD_ERROR);
      break;
    case VZ:
      flag = set_bnd_vel(para, var, VZ, psi, BINDEX); 
      if(flag!=0)
        ffd_log("set_bnd(): Could not set boundary condition for Z-velocity.",
                FFD_ERROR);
      break;
    case TEMP:
      flag = set_bnd_temp(para, var, TEMP, psi, BINDEX); 
      if(flag!=0)
        ffd_log("set_bnd(): Could not set boundary condition for temperature.",
                FFD_ERROR);
      break;
    case Xi1:
    case Xi2:
    case C1:
    case C2:
      flag = set_bnd_trace(para, var, index, psi, BINDEX); 
      if(flag!=0)
        ffd_log("set_bnd(): Could not set boundary condition for trace.",
                FFD_ERROR);
      break;
    default:
      flag = 1;
      sprintf(msg, 
              "set_bnd(): boundary condition for variable type %d is not defined.",
              var_type);
      ffd_log(msg, FFD_ERROR);
  }

  return flag;
} // End of set_bnd() 
Esempio n. 19
0
///////////////////////////////////////////////////////////////////////////////
/// Read other information from sci input file
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param var_type Type of variable
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int read_sci_input(PARA_DATA *para, REAL **var, int **BINDEX) {
  int i, j, k;
  int ii,ij,ik;
  REAL tempx, tempy, tempz;
  REAL Lx = para->geom->Lx;
  REAL Ly = para->geom->Ly;
  REAL Lz = para->geom->Lz;
  REAL *gx = var[GX], *gy = var[GY], *gz = var[GZ];
  REAL *x = var[X], *y = var[Y], *z = var[Z];
  int IWWALL,IEWALL,ISWALL,INWALL,IBWALL,ITWALL;
  int SI,SJ,SK,EI,EJ,EK,FLTMP;
  REAL TMP,MASS,U,V,W;
  char name[1000];
  int imax = para->geom->imax;
  int jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int index=0;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  char string[4000];
  REAL *delx, *dely, *delz;
  REAL *flagp = var[FLAGP];
  int bcnameid = -1;

  // Open the parameter file
  if((file_params=fopen(para->inpu->parameter_file_name,"r")) == NULL ) {
    sprintf(msg,"read_sci_input(): Could not open the file \"%s\".",
            para->inpu->parameter_file_name);
    ffd_log(msg, FFD_ERROR);
    return 1;
  }

  sprintf(msg, "read_sci_input(): Start to read sci input file %s",
          para->inpu->parameter_file_name);
  ffd_log(msg, FFD_NORMAL);

  // Ignore the first and second lines
  fgets(string, 400, file_params);
  fgets(string, 400, file_params);

  /*****************************************************************************
  | Convert the cell dimensions defined by SCI to coordinates in FFD
  *****************************************************************************/
  // Allocate temporary memory for dimension of each cell
  delx = (REAL *) malloc ((imax+2)*sizeof(REAL));
  dely = (REAL *) malloc ((jmax+2)*sizeof(REAL));
  delz = (REAL *) malloc ((kmax+2)*sizeof(REAL));

  if( !delx || !dely ||!delz ) {
    ffd_log("read_sci_input(): Cannot allocate memory for delx, dely or delz.",
            FFD_ERROR);
    return 1;
  }

  delx[0]=0;
  dely[0]=0;
  delz[0]=0;

  // Read cell dimensions in X, Y, Z directions
  for(i=1; i<=imax; i++) fscanf(file_params, "%f", &delx[i]);
  fscanf(file_params,"\n");
  for(j=1; j<=jmax; j++) fscanf(file_params, "%f", &dely[j]);
  fscanf(file_params,"\n");
  for(k=1; k<=kmax; k++) fscanf(file_params, "%f", &delz[k]);
  fscanf(file_params,"\n");

  // Store the locations of grid cell surfaces
  tempx = 0.0; tempy = 0.0; tempz = 0.0;
  for(i=0; i<=imax+1; i++) {
    tempx += delx[i];
    if(i>=imax) tempx = Lx;
    for(j=0; j<=jmax+1; j++)
      for(k=0; k<=kmax+1; k++) var[GX][IX(i,j,k)]=tempx;
  }

  for(j=0; j<=jmax+1; j++) {
    tempy += dely[j];
    if(j>=jmax) tempy = Ly;
    for(i=0; i<=imax+1; i++)
      for(k=0; k<=kmax+1; k++) var[GY][IX(i,j,k)] = tempy;
  }

  for(k=0; k<=kmax+1; k++) {
    tempz += delz[k];
    if(k>=kmax) tempz = Lz;
    for(i=0; i<=imax+1; i++)
      for(j=0; j<=jmax+1; j++) var[GZ][IX(i,j,k)] = tempz;
  }

  /*****************************************************************************
  | Convert the coordinates for cell surfaces to
  | the coordinates for the cell center
  *****************************************************************************/
  FOR_ALL_CELL
    if(i<1)
      x[IX(i,j,k)] = 0;
    else if(i>imax)
      x[IX(i,j,k)] = Lx;
    else
      x[IX(i,j,k)] = (REAL) 0.5 * (gx[IX(i,j,k)]+gx[IX(i-1,j,k)]);

    if(j<1)
      y[IX(i,j,k)] = 0;
    else if(j>jmax)
      y[IX(i,j,k)] = Ly;
    else
      y[IX(i,j,k)] = (REAL) 0.5 * (gy[IX(i,j,k)]+gy[IX(i,j-1,k)]);

    if(k<1)
      z[IX(i,j,k)] = 0;
    else if(k>kmax)
      z[IX(i,j,k)] = Lz;
    else
      z[IX(i,j,k)] = (REAL) 0.5 * (gz[IX(i,j,k)]+gz[IX(i,j,k-1)]);
  END_FOR

  // Get the wall property
  fgets(string, 400, file_params);
  sscanf(string,"%d%d%d%d%d%d", &IWWALL, &IEWALL, &ISWALL,
         &INWALL, &IBWALL, &ITWALL);

  /*****************************************************************************
  | Read total number of boundary conditions
  *****************************************************************************/
  fgets(string, 400, file_params);
  sscanf(string,"%d", &para->bc->nb_bc);
  sprintf(msg, "read_sci_input(): para->bc->nb_bc=%d", para->bc->nb_bc);
  ffd_log(msg, FFD_NORMAL);

  /*****************************************************************************
  | Read the inlet boundary conditions
  *****************************************************************************/
  // Get number of inlet boundaries
  fgets(string, 400, file_params);
  sscanf(string,"%d", &para->bc->nb_inlet);
  sprintf(msg, "read_sci_input(): para->bc->nb_inlet=%d", para->bc->nb_inlet);
  ffd_log(msg, FFD_NORMAL);

  index=0;
  // Set inlet boundary
  if(para->bc->nb_inlet!=0) {
    /*-------------------------------------------------------------------------
    | Allocate the memory for bc name
    -------------------------------------------------------------------------*/
    para->bc->inletName = (char**) malloc(para->bc->nb_inlet*sizeof(char*));
    if(para->bc->inletName==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
              "para->bc->inletName.", FFD_ERROR);
      return 1;
    }

    /*-------------------------------------------------------------------------
    | Loop for each inlet boundary
    --------------------------------------------------------------------------*/
    for(i=0; i<para->bc->nb_inlet; i++) {
      /*.......................................................................
      | Get the names of boundary
      .......................................................................*/
      fgets(string, 400, file_params);
      // Get the length of name (The name may contain white space)
      for(j=0; string[j] != '\n'; j++) {
        continue;
      }

      para->bc->inletName[i] = (char*)malloc((j+1)*sizeof(char));
      if(para->bc->inletName[i]==NULL) {
        sprintf(msg, "read_sci_input(): Could not allocate memory for "
                "para->bc->inletName[%d].", i);
        ffd_log(msg, FFD_ERROR);
        return 1;
      }

      strncpy(para->bc->inletName[i], (const char*)string, j);
      // Add an ending
      para->bc->inletName[i][j] = '\0';
      sprintf(msg, "read_sci_input(): para->bc->inletName[%d]=%s",
              i, para->bc->inletName[i]);
      ffd_log(msg, FFD_NORMAL);
      /*.......................................................................
      | Get the boundary conditions
      .......................................................................*/
      fgets(string, 400, file_params);
      sscanf(string,"%d%d%d%d%d%d%f%f%f%f%f", &SI, &SJ, &SK, &EI,
             &EJ, &EK, &TMP, &MASS, &U, &V, &W);
      sprintf(msg, "read_sci_input(): VX=%f, VY=%f, VZ=%f, T=%f, Xi=%f",
              U, V, W, TMP, MASS);
      ffd_log(msg, FFD_NORMAL);
      if(EI==0) {
        if(SI==1) SI = 0;
        EI = SI + EI;
        EJ = SJ + EJ - 1;
        EK = SK + EK - 1;
      }

      if(EJ==0) {
        if(SJ==1) SJ = 0;
        EI = SI + EI - 1;
        EJ = SJ + EJ;
        EK = SK + EK - 1;
      }

      if(EK==0) {
        if(SK==1) SK = 0;
        EI = SI + EI - 1;
        EJ = SJ + EJ - 1;
        EK = SK + EK;
      }

      // Assign the inlet boundary condition for each cell
      for(ii=SI; ii<=EI; ii++)
        for(ij=SJ; ij<=EJ; ij++)
          for(ik=SK; ik<=EK; ik++) {
            BINDEX[0][index] = ii;
            BINDEX[1][index] = ij;
            BINDEX[2][index] = ik;
            BINDEX[4][index] = i;
            index++;

            var[TEMPBC][IX(ii,ij,ik)] = TMP;
            var[VXBC][IX(ii,ij,ik)] = U;
            var[VYBC][IX(ii,ij,ik)] = V;
            var[VZBC][IX(ii,ij,ik)] = W;
            var[Xi1BC][IX(ii,ij,ik)] = MASS;

            flagp[IX(ii,ij,ik)] = INLET; // Cell flag to be inlet
            if(para->outp->version==DEBUG) {
              sprintf(msg, "read_sci_input(): get inlet cell[%d,%d,%d]=%.1f",
                ii, ij, ik, flagp[IX(ii,ij,ik)]);
              ffd_log(msg, FFD_NORMAL);
            }

          } // End of assigning the inlet B.C. for each cell

    } // End of loop for each inlet boundary
  } // End of setting inlet boundary

  /*****************************************************************************
  | Read the outlet boundary conditions
  *****************************************************************************/
  fgets(string, 400, file_params);
  sscanf(string, "%d", &para->bc->nb_outlet);
  sprintf(msg, "read_sci_input(): para->bc->nb_outlet=%d", para->bc->nb_outlet);
  ffd_log(msg, FFD_NORMAL);

  if(para->bc->nb_outlet!=0) {
    para->bc->outletName = (char**) malloc(para->bc->nb_outlet*sizeof(char*));
    if(para->bc->outletName==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
              "para->bc->outletName.", FFD_ERROR);
      return 1;
    }

    for(i=0; i<para->bc->nb_outlet; i++) {
      /*.......................................................................
      | Get the names of boundary
      .......................................................................*/
      fgets(string, 400, file_params);
      // Get the length of name (The name may contain white space)
      for(j=0; string[j] != '\n'; j++) {
        continue;
      }

      para->bc->outletName[i] = (char*)malloc((j+1)*sizeof(char));
      if(para->bc->outletName[i]==NULL) {
        sprintf(msg, "read_sci_input(): Could not allocate memory "
          "for para->bc->outletName[%d].", i);
        ffd_log(msg, FFD_ERROR);
        return 1;
      }

      strncpy(para->bc->outletName[i], (const char*)string, j);
      // Add an ending
      para->bc->outletName[i][j] = '\0';
      sprintf(msg, "read_sci_input(): para->bc->outletName[%d]=%s",
              i, para->bc->outletName[i]);
      ffd_log(msg, FFD_NORMAL);

      /*.......................................................................
      | Get the boundary conditions
      .......................................................................*/
      fgets(string, 400, file_params);
      sscanf(string,"%d%d%d%d%d%d%f%f%f%f%f",
             &SI, &SJ, &SK, &EI,
             &EJ, &EK, &TMP, &MASS, &U, &V, &W);

      sprintf(msg, "read_sci_input(): VX=%f, VY=%f, VX=%f, T=%f, Xi=%f",
              U, V, W, TMP, MASS);
      ffd_log(msg, FFD_NORMAL);

      if(EI==0) {
        if(SI==1) SI=0;
        EI = SI + EI;
        EJ = SJ + EJ - 1;
        EK = SK + EK - 1;
      }

      if(EJ==0) {
        if(SJ==1) SJ=0;
        EI = SI+EI-1;
        EJ = SJ+EJ;
        EK = SK+EK-1;
      }

      if(EK==0) {
        if(SK==1) SK = 0;
        EI = SI+EI-1;
        EJ = SJ+EJ-1;
        EK = SK+EK;
      }
      // Assign the outlet boundary condition for each cell
      for(ii=SI; ii<=EI ;ii++)
        for(ij=SJ; ij<=EJ ;ij++)
          for(ik=SK; ik<=EK; ik++) {
            BINDEX[0][index] = ii;
            BINDEX[1][index] = ij;
            BINDEX[2][index] = ik;
            BINDEX[4][index] = para->bc->nb_inlet + i;
            index++;

            // Give the initial value, but the value will be overwritten later
            var[TEMPBC][IX(ii,ij,ik)] = TMP;
            var[VXBC][IX(ii,ij,ik)] = U;
            var[VYBC][IX(ii,ij,ik)] = V;
            var[VZBC][IX(ii,ij,ik)] = W;
            var[Xi1BC][IX(ii,ij,ik)] = MASS;
            flagp[IX(ii,ij,ik)] = OUTLET;
            if(para->outp->version==DEBUG) {
              sprintf(msg, "read_sci_input(): get outlet cell[%d,%d,%d]=%.1f",
                ii, ij, ik, flagp[IX(ii,ij,ik)]);
              ffd_log(msg, FFD_NORMAL);
            }
          } // End of assigning the outlet B.C. for each cell
    } // End of loop for each outlet boundary
  } // End of setting outlet boundary

  /*****************************************************************************
  | - Copy the inlet and outlet information to ports
  | - Allocate memory for related port variables
  *****************************************************************************/
  para->bc->nb_port = para->bc->nb_inlet+para->bc->nb_outlet;

  if(para->bc->nb_port>0) {
    // Allocate memory for the array of ports' names
    para->bc->portName = (char**) malloc(para->bc->nb_port*sizeof(char*));
    if(para->bc->portName==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for para->bc->portName.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Copy the inlet names to ports' names
    --------------------------------------------------------------------------*/
    for(i=0; i<para->bc->nb_inlet; i++) {
      // Allocate memory for inlet name
      para->bc->portName[i] =
        (char*) malloc(sizeof(char)*(sizeof(para->bc->inletName[i])+1));

      if(para->bc->portName[i]==NULL) {
        ffd_log("read_sci_input():"
                "Could not allocate memory for para->bc->portName.",
        FFD_ERROR);
        return 1;
      }

      // Copy the inlet name
      strcpy(para->bc->portName[i], para->bc->inletName[i]);
      sprintf(msg, "read_sci_input(): Port[%d]:%s",
              i, para->bc->portName[i]);
      ffd_log(msg, FFD_NORMAL);
    }

    /*--------------------------------------------------------------------------
    | Copy the outlet names to ports' names
    --------------------------------------------------------------------------*/
    j = para->bc->nb_inlet;
    for(i=0; i<para->bc->nb_outlet; i++) {
      // Allocate memory for outlet name
      para->bc->portName[i+j] =
        (char*) malloc(sizeof(char)*(sizeof(para->bc->outletName[i])+1));
      if(para->bc->portName[i+j]==NULL) {
        ffd_log("read_sci_input(): "
                "Could not allocate memory for para->bc->portName.",
        FFD_ERROR);
        return 1;
      }
      else {
        strcpy(para->bc->portName[i+j], para->bc->outletName[i]);
        sprintf(msg, "read_sci_input(): Port[%d]:%s",
                i+j, para->bc->portName[i+j]);
        ffd_log(msg, FFD_NORMAL);
      }
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for the surface area
    --------------------------------------------------------------------------*/
    para->bc->APort = (REAL*) malloc(para->bc->nb_port*sizeof(REAL));
    if(para->bc->APort==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->APort.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for the velocity (used for inlet only)
    --------------------------------------------------------------------------*/
    para->bc->velPort = (REAL*) malloc(para->bc->nb_port*sizeof(REAL));
    if(para->bc->velPort==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->velPort.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for the averaged velocity
    --------------------------------------------------------------------------*/
    para->bc->velPortAve = (REAL*) malloc(para->bc->nb_port*sizeof(REAL));
    if(para->bc->velPortAve==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->velAve.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for mean velocity
    --------------------------------------------------------------------------*/
    para->bc->velPortMean = (REAL*) malloc(para->bc->nb_port*sizeof(REAL));
    if(para->bc->velPortMean==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->velPortMean.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for the temperature (used for inlet only)
    --------------------------------------------------------------------------*/
    para->bc->TPort = (REAL*) malloc(para->bc->nb_port*sizeof(REAL));
    if(para->bc->TPort==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->TPort.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for the averaged temperature
    --------------------------------------------------------------------------*/
    para->bc->TPortAve = (REAL*) malloc(para->bc->nb_port*sizeof(REAL));
    if(para->bc->TPortAve==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->TPortAve.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for the mean velocity
    --------------------------------------------------------------------------*/
    para->bc->TPortMean = (REAL*) malloc(para->bc->nb_port*sizeof(REAL));
    if(para->bc->TPortMean==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->TPortMean.",
      FFD_ERROR);
      return 1;
    }
    /*--------------------------------------------------------------------------
    | Allocate memory for port ID
    --------------------------------------------------------------------------*/
    para->bc->portId = (int*) malloc(para->bc->nb_port*sizeof(int));
    if(para->bc->portId==NULL) {
      ffd_log("read_sci_input(): "
              "Could not allocate memory for para->bc->portId.",
      FFD_ERROR);
      return 1;
    }
  }

  /*****************************************************************************
  | Read the internal solid block boundary conditions
  *****************************************************************************/
  fgets(string, 400, file_params);
  sscanf(string, "%d", &para->bc->nb_block);
  sprintf(msg, "read_sci_input(): para->bc->nb_block=%d", para->bc->nb_block);
  ffd_log(msg, FFD_NORMAL);

  if(para->bc->nb_block!=0) {
    para->bc->blockName = (char**) malloc(para->bc->nb_block*sizeof(char*));
    if(para->bc->blockName==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for para->bc->blockName.",
      FFD_ERROR);
      return 1;
    }

    for(i=0; i<para->bc->nb_block; i++) {
      /*.......................................................................
      | Get the names of boundary
      .......................................................................*/
      fgets(string, 400, file_params);
      // Get the length of name (The name may contain white space)
      for(j=0; string[j] != '\n'; j++) {
        continue;
      }

      para->bc->blockName[i] = (char*)malloc((j+1)*sizeof(char));
      if(para->bc->blockName[i]==NULL) {
        sprintf(msg,"read_sci_input(): Could not allocate memory for "
          "para->bc->blockName[%d].", i);
        ffd_log(msg, FFD_ERROR);
        return 1;
      }

      strncpy(para->bc->blockName[i], (const char*)string, j);
      // Add an ending
      para->bc->blockName[i][j] = '\0';
      sprintf(msg, "read_sci_input(): para->bc->blockName[%d]=%s",
              i, para->bc->blockName[i]);
      ffd_log(msg, FFD_NORMAL);

      /*.......................................................................
      | Get the boundary conditions
      .......................................................................*/
      fgets(string, 400, file_params);
      // X_index_start, Y_index_Start, Z_index_Start,
      // X_index_End, Y_index_End, Z_index_End,
      // Thermal Condition (0: Flux; 1:Temperature), Value of thermal condition
      sscanf(string,"%d%d%d%d%d%d%d%f", &SI, &SJ, &SK, &EI, &EJ, &EK,
                                        &FLTMP, &TMP);
      sprintf(msg, "read_sci_input(): VX=%f, VY=%f, VX=%f, ThermalBC=%d, T/q_dot=%f, Xi=%f",
              U, V, W, FLTMP, TMP, MASS);
      ffd_log(msg, FFD_NORMAL);

      if(SI==1) {
        SI=0;
        if(EI>=imax) EI=EI+SI+1;
        else EI=EI+SI;
      }
      else
        EI=EI+SI-1;

      if(SJ==1) {
        SJ=0;
        if(EJ>=jmax) EJ=EJ+SJ+1;
        else EJ=EJ+SJ;
      }
      else
        EJ=EJ+SJ-1;

      if(SK==1) {
        SK=0;
        if(EK>=kmax) EK=EK+SK+1;
        else EK=EK+SK;
      }
      else
        EK=EK+SK-1;

      for(ii=SI; ii<=EI; ii++)
        for(ij=SJ; ij<=EJ; ij++)
          for(ik=SK; ik<=EK; ik++) {
            BINDEX[0][index] = ii;
            BINDEX[1][index] = ij;
            BINDEX[2][index] = ik;
            BINDEX[3][index] = FLTMP;
            BINDEX[4][index] = i;
            index++;

            switch(FLTMP) {
              case 1:
                var[TEMPBC][IX(ii,ij,ik)] = TMP;
                break;
              case 0:
                var[QFLUXBC][IX(ii,ij,ik)] = TMP;
                break;
              default:
                sprintf(msg, "read_sci_input(): Thermal BC (%d)"
                  "for cell(%d,%d,%d) was not defined",
                  FLTMP, ii, ij, ik);
                ffd_log(msg, FFD_ERROR);
                return 1;
            }

            flagp[IX(ii,ij,ik)] = SOLID; // Flag for solid
          } // End of assigning value for internal solid block
    }
  }

  /*****************************************************************************
  | Read the wall boundary conditions
  *****************************************************************************/
  fgets(string, 400, file_params);
  sscanf(string,"%d", &para->bc->nb_wall);
  sprintf(msg, "read_sci_input(): para->bc->nb_wall=%d", para->bc->nb_wall);
  ffd_log(msg, FFD_NORMAL);

  if(para->bc->nb_wall!=0) {
    /*-------------------------------------------------------------------------
    | Allocate the memory for bc name and id
    -------------------------------------------------------------------------*/
    para->bc->wallName = (char**)malloc(para->bc->nb_wall*sizeof(char*));
    if(para->bc->wallName==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
      "para->bc->wallName.", FFD_ERROR);
      return 1;
    }

    para->bc->wallId = (int *)malloc(sizeof(int)*para->bc->nb_wall);
    if(para->bc->wallId==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
      "para->bc->wallId.", FFD_ERROR);
      return 1;
    }

    for(i=0; i<para->bc->nb_wall; i++)
      para->bc->wallId[i] = -1;

    para->bc->AWall = (REAL*) malloc(para->bc->nb_wall*sizeof(REAL));
    if(para->bc->AWall==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
      "para->bc->AWall.", FFD_ERROR);
      return 1;
    }

    para->bc->temHea = (REAL*) malloc(para->bc->nb_wall*sizeof(REAL));
    if(para->bc->temHea==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
      "para->bc->heaTem.", FFD_ERROR);
      return 1;
    }

    para->bc->temHeaAve = (REAL*) malloc(para->bc->nb_wall*sizeof(REAL));
    if(para->bc->temHeaAve==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
      "para->bc->temHeaAve.", FFD_ERROR);
    return 1;
    }

    para->bc->temHeaMean = (REAL*) malloc(para->bc->nb_wall*sizeof(REAL));
    if(para->bc->temHeaMean==NULL) {
      ffd_log("read_sci_input(): Could not allocate memory for "
      "para->bc->temHeaMean.", FFD_ERROR);
      return 1;
    }

    /*-------------------------------------------------------------------------
    | Read wall conditions for each wall
    -------------------------------------------------------------------------*/
    for(i=0; i<para->bc->nb_wall; i++) {
      /*.......................................................................
      | Get the names of boundary
      .......................................................................*/
      fgets(string, 400, file_params);
      // Get the length of name (The name may contain white space)
      for(j=0; string[j] != '\n'; j++) {
        continue;
      }

      para->bc->wallName[i] = (char*)malloc((j+1)*sizeof(char));
      if(para->bc->wallName[i]==NULL) {
        sprintf(msg, "read_sci_input(): Could not allocate memory for "
                "para->bc->wallName[%d].", i);
        ffd_log(msg, FFD_ERROR);
        return 1;
      }

      strncpy(para->bc->wallName[i], (const char*)string, j);
      // Add an ending
      para->bc->wallName[i][j] = '\0';
      sprintf(msg, "read_sci_input(): para->bc->wallName[%d]=\"%s\"",
             i, para->bc->wallName[i]);
      ffd_log(msg, FFD_NORMAL);
      /*.......................................................................
      | Get the boundary conditions
      .......................................................................*/
      // X_index_start, Y_index_Start, Z_index_Start,
      // X_index_End, Y_index_End, Z_index_End,
      // Thermal Condition (0: Flux; 1:Temperature), Value of thermal condition
      fgets(string, 400, file_params);
      sscanf(string,"%d%d%d%d%d%d%d%f", &SI, &SJ, &SK, &EI,
             &EJ, &EK, &FLTMP, &TMP);
      sprintf(msg, "read_sci_input(): ThermalBC=%d, T/q_dot=%f",
              FLTMP, TMP);
      ffd_log(msg, FFD_NORMAL);

      // Reset X index
      if(SI==1) { // West
        SI = 0;
        if(EI>=imax) EI = EI + 1;
      }
      else if(SI==imax+1) // East
        EI = EI + SI;
      else // Internal
        EI = EI + SI - 1;

      // Reset Y index
      if(SJ==1) { // South
        SJ = 0;
        if(EJ>=jmax) EJ = EJ + 1;
      }
      else if(SJ==jmax+1) // North
        EJ = EJ + SJ;
      else // Internal
        EJ = EJ + SJ - 1;
      // Reset Z index
      if(SK==1) { // Floor
        SK = 0;
        if(EK>=kmax) EK = EK + 1;
      }
      else if (SK==kmax+1) // Ceiling
        EK = EK + SK;
      else // Internal
          EK = EK + SK -1;

      // Assign value for each wall cell
      for(ii=SI; ii<=EI; ii++)
        for(ij=SJ; ij<=EJ; ij++)
          for(ik=SK; ik<=EK; ik++) {
            // If cell hasn't been updated (default value -1)
            if(flagp[IX(ii,ij,ik)]<0) {
              BINDEX[0][index] = ii;
              BINDEX[1][index] = ij;
              BINDEX[2][index] = ik;
              // Define the thermal boundary property
              BINDEX[3][index] = FLTMP;
              BINDEX[4][index] = i;
              index++;

              // Set the cell to solid
              flagp[IX(ii,ij,ik)] = SOLID;
              if(FLTMP==1) var[TEMPBC][IX(ii,ij,ik)] = TMP;
              if(FLTMP==0) var[QFLUXBC][IX(ii,ij,ik)] = TMP;
            }
          } // End of assigning value for each wall cell
    } // End of assigning value for each wall surface
  } // End of assigning value for wall boundary

  /*****************************************************************************
  | Read the boundary conditions for contaminant source
  | Warning: The data is ignored in current version
  *****************************************************************************/
  fgets(string, 400, file_params);
  sscanf(string,"%d", &para->bc->nb_source);
  sprintf(msg, "read_sci_input(): para->bc->nb_source=%d", para->bc->nb_source);
  ffd_log(msg, FFD_NORMAL);

  if(para->bc->nb_source!=0) {
    sscanf(string,"%s%d%d%d%d%d%d%f",
           name, &SI, &SJ, &SK, &EI, &EJ, &EK, &MASS);
    bcnameid++;

    sprintf(msg, "read_sci_input(): Source %s is not used in current version.",
            name);
    ffd_log(msg, FFD_WARNING);
    sprintf(msg, "read_sci_input(): Xi_dot=%f", MASS);
    ffd_log(msg, FFD_NORMAL);
    //Warning: Need to add code to assign the BC value as other part does
  }

  para->geom->index=index;

  /*****************************************************************************
  | Read other simulation data
  *****************************************************************************/
  // Discard the unused data
  fgets(string, 400, file_params); //maximum iteration
  fgets(string, 400, file_params); //convergence rate
  fgets(string, 400, file_params); //Turbulence model
  fgets(string, 400, file_params); //initial value
  fgets(string, 400, file_params); //minimum value
  fgets(string, 400, file_params); //maximum value
  fgets(string, 400, file_params); //fts value
  fgets(string, 400, file_params); //under relaxation
  fgets(string, 400, file_params); //reference point
  fgets(string, 400, file_params); //monitoring point

  // Discard setting for restarting the old FFD simulation
  fgets(string, 400, file_params);
  /*
  sscanf(string,"%d", &para->inpu->read_old_ffd_file);
  sprintf(msg, "read_sci_input(): para->inpu->read_old_ffd_file=%d",
          para->inpu->read_old_ffd_file);
  ffd_log(msg, FFD_NORMAL);
  */
  // Discard the unused data
  fgets(string, 400, file_params); //print frequency
  fgets(string, 400, file_params); //Pressure variable Y/N
  fgets(string, 400, file_params); //Steady state, buoyancy.

  // Discard physical properties
  fgets(string, 400, file_params);
  /*
  sscanf(string,"%f %f %f %f %f %f %f %f %f", &para->prob->rho,
         &para->prob->nu, &para->prob->cond,
         &para->prob->gravx, &para->prob->gravy, &para->prob->gravz,
         &para->prob->beta, &trefmax, &para->prob->Cp);

  sprintf(msg, "read_sci_input(): para->prob->rho=%f", para->prob->rho);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->prob->nu=%f", para->prob->nu);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->prob->cond=%f", para->prob->cond);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->prob->gravx=%f", para->prob->gravx);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->prob->gravy=%f", para->prob->gravy);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->prob->gravz=%f", para->prob->gravz);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->prob->beta=%f", para->prob->beta);
  ffd_log(msg, FFD_NORMAL);

  //para->prob->trefmax=trefmax;
  sprintf(msg, "read_sci_input(): para->prob->Cp=%f", para->prob->Cp);
  ffd_log(msg, FFD_NORMAL);
  */

  // Read simulation time settings
  fgets(string, 400, file_params);
  sscanf(string,"%f %f %d", &para->mytime->t_start, &para->mytime->dt,
    &para->mytime->step_total);

  sprintf(msg, "read_sci_input(): para->mytime->t_start=%f",
          para->mytime->t_start);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->mytime->dt=%f", para->mytime->dt);
  ffd_log(msg, FFD_NORMAL);

  sprintf(msg, "read_sci_input(): para->mytime->step_total=%d",
          para->mytime->step_total);
  ffd_log(msg, FFD_NORMAL);

  fgets(string, 400, file_params); //prandtl

  /*****************************************************************************
  | Conclude the reading process
  *****************************************************************************/
  fclose(file_params);

  free(delx);
  free(dely);
  free(delz);

  sprintf(msg, "read_sci_input(): Read sci input file %s",
          para->inpu->parameter_file_name);
  ffd_log(msg, FFD_NORMAL);
  return 0;
} // End of read_sci_input()
Esempio n. 20
0
///////////////////////////////////////////////////////////////////////////////
/// Calcuate coefficients for difussion equation solver
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param psi Pointer to the variable at current time step
///\param psi0 Pointer to the variable at previous time step
///\param var_type Type of variable
///\param index Index of trace substance or species
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int coef_diff(PARA_DATA *para, REAL **var, REAL *psi, REAL *psi0, 
               int var_type, int index, int **BINDEX) {
  int i, j, k;
  int imax = para->geom->imax, jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  REAL *aw = var[AW], *ae = var[AE], *as = var[AS], *an = var[AN];
  REAL *af = var[AF], *ab = var[AB], *ap = var[AP], *ap0 = var[AP0], *b = var[B];
  REAL *x = var[X], *y = var[Y], *z = var[Z];
  REAL *gx = var[GX], *gy = var[GY], *gz = var[GZ];
  REAL *pp = var[PP];
  REAL *Temp = var[TEMP];
  REAL dxe, dxw, dyn, dys, dzf, dzb, Dx, Dy, Dz;
  REAL dt = para->mytime->dt, beta = para->prob->beta;
  REAL Temp_Buoyancy = para->prob->Temp_Buoyancy;
  REAL gravx = para->prob->gravx, gravy = para->prob->gravy,
       gravz = para->prob->gravz;
  REAL kapa;

  // define kapa
  switch(var_type) {
    /*-------------------------------------------------------------------------
    | X-velocity
    -------------------------------------------------------------------------*/
    case VX:
      if(para->prob->tur_model==LAM)
        kapa = para->prob->nu; 
      else if(para->prob->tur_model==CONSTANT) 
        kapa = 101.0f * para->prob->nu;

      FOR_U_CELL
        dxe = gx[IX(i+1,j  ,k)] - gx[IX(i  ,j,k)];
        dxw = gx[IX(i  ,j  ,k)] - gx[IX(i-1,j,k)];
        dyn =  y[IX(i  ,j+1,k)] -  y[IX(i  ,j,k)];
        dys =  y[IX(i,j,k)] -      y[IX(i,j-1,k)];
        dzf =  z[IX(i,j,k+1)] -    z[IX(i,j,k)];
        dzb =  z[IX(i,j,k)] -      z[IX(i,j,k-1)];
        Dx =   x[IX(i+1,j,k)] -    x[IX(i,j,k)];
        Dy =  gy[IX(i,j,k)] -     gy[IX(i,j-1,k)];
        Dz =  gz[IX(i,j,k)] -     gz[IX(i,j,k-1)];

        if(para->prob->tur_model==CHEN)
          kapa = nu_t_chen_zero_equ(para, var, i, j, k);

        aw[IX(i,j,k)] = kapa*Dy*Dz/dxw;
        ae[IX(i,j,k)] = kapa*Dy*Dz/dxe;
        an[IX(i,j,k)] = kapa*Dx*Dz/dyn;
        as[IX(i,j,k)] = kapa*Dx*Dz/dys;
        af[IX(i,j,k)] = kapa*Dx*Dy/dzf;
        ab[IX(i,j,k)] = kapa*Dx*Dy/dzb;
        ap0[IX(i,j,k)] = Dx*Dy*Dz/dt;
        b[IX(i,j,k)] = psi0[IX(i,j,k)]*ap0[IX(i,j,k)]
                     - beta*gravx*(Temp[IX(i,j,k)]-Temp_Buoyancy)*Dx*Dy*Dz
                     + (pp[IX(i,j,k)]-pp[IX(i+1,j,k)])*Dy*Dz;
      END_FOR

      //set_bnd(para, var, var_type, psi, BINDEX);
      FOR_U_CELL
          ap[IX(i,j,k)] = ap0[IX(i,j,k)] + ae[IX(i,j,k)] + aw[IX(i,j,k)] 
                        + an[IX(i,j,k)]  + as[IX(i,j,k)] + af[IX(i,j,k)] 
                        + ab[IX(i,j,k)];
      END_FOR
      break;
    /*-------------------------------------------------------------------------
    | Y-velocity
    -------------------------------------------------------------------------*/ 
    case VY:
      if(para->prob->tur_model==LAM)
        kapa = para->prob->nu; 
      else if(para->prob->tur_model==CONSTANT) 
        kapa = (REAL) 101.0 * para->prob->nu;

      FOR_V_CELL
        dxe = x[IX(i+1,j,k)] - x[IX(i,j,k)];
        dxw = x[IX(i,j,k)] - x[IX(i-1,j,k)];
        dyn = gy[IX(i,j+1,k)] - gy[IX(i,j,k)];
        dys = gy[IX(i,j,k)] - gy[IX(i,j-1,k)];
        dzf = z[IX(i,j,k+1)] - z[IX(i,j,k)];
        dzb = z[IX(i,j,k)] - z[IX(i,j,k-1)];
        Dx = gx[IX(i,j,k)] - gx[IX(i-1,j,k)];
        Dy = y[IX(i,j+1,k)] - y[IX(i,j,k)];
        Dz = gz[IX(i,j,k)] - gz[IX(i,j,k-1)];

        if(para->prob->tur_model==CHEN)
          kapa = nu_t_chen_zero_equ(para, var, i, j, k);

        aw[IX(i,j,k)] = kapa*Dy*Dz/dxw;
        ae[IX(i,j,k)] = kapa*Dy*Dz/dxe;
        an[IX(i,j,k)] = kapa*Dx*Dz/dyn;
        as[IX(i,j,k)] = kapa*Dx*Dz/dys;
        af[IX(i,j,k)] = kapa*Dx*Dy/dzf;
        ab[IX(i,j,k)] = kapa*Dx*Dy/dzb;
        ap0[IX(i,j,k)] = Dx*Dy*Dz/dt;
        b[IX(i,j,k)] = psi0[IX(i,j,k)]*ap0[IX(i,j,k)]
                     - beta*gravy*(Temp[IX(i,j,k)]-Temp_Buoyancy)*Dx*Dy*Dz
                     + (pp[IX(i,j,k)]-pp[IX(i ,j+1,k)])*Dx*Dz;
      END_FOR

      //set_bnd(para, var, var_type, psi,BINDEX);
      FOR_V_CELL
        ap[IX(i,j,k)] = ap0[IX(i,j,k)] + ae[IX(i,j,k)] + aw[IX(i,j,k)] 
                      + an[IX(i,j,k)] + as[IX(i,j,k)] + af[IX(i,j,k)] 
                      + ab[IX(i,j,k)];
      END_FOR
      break;
    /*-------------------------------------------------------------------------
    | Z-velocity
    -------------------------------------------------------------------------*/
    case VZ:
      if(para->prob->tur_model==LAM)   
        kapa = para->prob->nu; 
      else if(para->prob->tur_model==CONSTANT) 
        kapa = (REAL) 101.0 * para->prob->nu;
        
      FOR_W_CELL
        dxe = x[IX(i+1,j,k)] - x[IX(i,j,k)];
        dxw = x[IX(i,j,k)] - x[IX(i-1,j,k)];
        dyn = y[IX(i,j+1,k)] - y[IX(i,j,k)];
        dys = y[IX(i,j,k)] - y[IX(i,j-1,k)];
        dzf = gz[IX(i,j,k+1)] - gz[IX(i,j,k)];
        dzb = gz[IX(i,j,k)] - gz[IX(i,j,k-1)];
        Dx = gx[IX(i,j,k)] - gx[IX(i-1,j,k)];
        Dy = gy[IX(i,j,k)] - gy[IX(i,j-1,k)];
        Dz = z[IX(i,j,k+1)] - z[IX(i,j,k)];

        if(para->prob->tur_model==CHEN)
          kapa = nu_t_chen_zero_equ(para, var, i, j, k);

        aw[IX(i,j,k)] = kapa*Dy*Dz/dxw;
        ae[IX(i,j,k)] = kapa*Dy*Dz/dxe;
        an[IX(i,j,k)] = kapa*Dx*Dz/dyn;
        as[IX(i,j,k)] = kapa*Dx*Dz/dys;
        af[IX(i,j,k)] = kapa*Dx*Dy/dzf;
        ab[IX(i,j,k)] = kapa*Dx*Dy/dzb;
        ap0[IX(i,j,k)] = Dx*Dy*Dz/dt;
        b[IX(i,j,k)] = psi0[IX(i,j,k)]*ap0[IX(i,j,k)]
                     - beta*gravz*(Temp[IX(i,j,k)]-Temp_Buoyancy)*Dx*Dy*Dz
                     + (pp[IX(i,j,k)]-pp[IX(i ,j,k+1)])*Dy*Dx;
      END_FOR

      //set_bnd(para, var, var_type, psi, BINDEX);

      FOR_W_CELL
        ap[IX(i,j,k)] = ap0[IX(i,j,k)] + ae[IX(i,j,k)] + aw[IX(i,j,k)] 
                      +  an[IX(i,j,k)] + as[IX(i,j,k)] + af[IX(i,j,k)] 
                      + ab[IX(i,j,k)];
      END_FOR
      break;
    /*-------------------------------------------------------------------------
    | Scalar Variable
    -------------------------------------------------------------------------*/
    case TEMP:
    case TRACE:
      if(para->prob->tur_model == LAM)   
        kapa = para->prob->alpha; 
      else if(para->prob->tur_model == CONSTANT) 
        kapa = (REAL) 101.0 * para->prob->alpha;

      FOR_EACH_CELL
        dxe = x[IX(i+1,j,k)] - x[IX(i,j,k)];
        dxw = x[IX(i,j,k)] - x[IX(i-1,j,k)];
        dyn = y[IX(i,j+1,k)] - y[IX(i,j,k)];
        dys = y[IX(i,j,k)] - y[IX(i,j-1,k)];
        dzf = z[IX(i,j,k+1)] - z[IX(i,j,k)];
        dzb = z[IX(i,j,k)] - z[IX(i,j,k-1)];
        Dx = gx[IX(i,j,k)] - gx[IX(i-1,j,k)];
        Dy = gy[IX(i,j,k)] - gy[IX(i,j-1,k)];
        Dz = gz[IX(i,j,k)] - gz[IX(i,j,k-1)];
 
        aw[IX(i,j,k)] = kapa*Dy*Dz/dxw;
        ae[IX(i,j,k)] = kapa*Dy*Dz/dxe;
        an[IX(i,j,k)] = kapa*Dx*Dz/dyn;
        as[IX(i,j,k)] = kapa*Dx*Dz/dys;
        af[IX(i,j,k)] = kapa*Dx*Dy/dzf;
        ab[IX(i,j,k)] = kapa*Dx*Dy/dzb;
        ap0[IX(i,j,k)] = Dx*Dy*Dz/dt;
        b[IX(i,j,k)] = psi0[IX(i,j,k)]*ap0[IX(i,j,k)];
      END_FOR

      set_bnd(para, var, var_type, index, psi, BINDEX);

      FOR_EACH_CELL
        ap[IX(i,j,k)] = ap0[IX(i,j,k)] + ae[IX(i,j,k)] + aw[IX(i,j,k)] 
                      +  an[IX(i,j,k)] + as[IX(i,j,k)] + af[IX(i,j,k)] + ab[IX(i,j,k)];
      END_FOR
      break;
    default:
      sprintf(msg, "coe_diff(): No function for variable type %d", var_type);
      ffd_log(msg, FFD_ERROR);
      return 1;
      break;
  }

  return 0;
}// End of coef_diff( )
Esempio n. 21
0
///////////////////////////////////////////////////////////////////////////////
/// Main routine of FFD
///
///\para coupled simulation Integer to identify the simulation type
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int ffd(int cosimulation) {
#ifndef _MSC_VER //Linux
  //Initialize glut library
  char fakeParam[] = "fake";
  char *fakeargv[] = { fakeParam, NULL };
  int fakeargc = 1;
  glutInit( &fakeargc, fakeargv );
#endif

  // Initialize the parameters
  para.geom = &geom;
  para.inpu = &inpu;
  para.outp = &outp1;
  para.prob = &prob;
  para.mytime = &mytime;
  para.bc     = &bc;
  para.solv   = &solv;
  para.sens   = &sens;
  para.init   = &init;
  // Stand alone simulation: 0; Cosimulaiton: 1
  para.solv->cosimulation = cosimulation; 

  if(initialize(&para)!=0) {
    ffd_log("ffd(): Could not initialize simulation parameters.", FFD_ERROR);
    return 1;
  }

  // Overwrite the mesh and simulation data using SCI generated file
  if(para.inpu->parameter_file_format == SCI) {
    if(read_sci_max(&para, var)!=0) {
      ffd_log("ffd(): Could not read SCI data.", FFD_ERROR);
      return 1;
    }
  }
  
  // Allocate memory for the variables
  if(allocate_memory(&para)!=0) {
    ffd_log("ffd(): Could not allocate memory for the simulation.", FFD_ERROR);
    return 1;
  }

  // Set the initial values for the simulation data
  if(set_initial_data(&para, var, BINDEX)) {
    ffd_log("ffd(): Could not set initial data.", FFD_ERROR);
    return 1;
  }

  // Read previous simulation data as initial values
  if(para.inpu->read_old_ffd_file==1) read_ffd_data(&para, var);

  ffd_log("ffd.c: Start FFD solver.", FFD_NORMAL);
  //write_tecplot_data(&para, var, "initial");

  // Solve the problem
  if(para.outp->version==DEMO) {
    open_glut_window();
    glutMainLoop();
  }
  else
    if(FFD_solver(&para, var, BINDEX)!=0) {
      ffd_log("ffd(): FFD solver failed.", FFD_ERROR);
      return 1;
    }

  /*---------------------------------------------------------------------------
  | Post Process
  ---------------------------------------------------------------------------*/
  // Calculate mean value
  if(para.outp->cal_mean == 1)
    average_time(&para, var);

  if(write_unsteady(&para, var, "unsteady")!=0) {
    ffd_log("FFD_solver(): Could not write the file unsteady.plt.", FFD_ERROR);
    return 1;
  }

  if(write_tecplot_data(&para, var, "result")!=0) {
    ffd_log("FFD_solver(): Could not write the file result.plt.", FFD_ERROR);
    return 1;
  }

  if(para.outp->version == DEBUG)
    write_tecplot_all_data(&para, var, "result_all");

  // Write the data in SCI format
  write_SCI(&para, var, "output");

  // Free the memory
  free_data(var);
  free_index(BINDEX);

  // End the simulation
  if(para.outp->version==DEBUG || para.outp->version==DEMO) {}//getchar();

  // Inform Modelica the stopping command has been received 
  if(para.solv->cosimulation==1) {
    para.cosim->para->flag = 2; 
    ffd_log("ffd(): Sent stopping signal to Modelica", FFD_NORMAL);
  }

  return 0;
} // End of ffd( )
///////////////////////////////////////////////////////////////////////////////
/// Write the FFD data for Modelica
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int write_cosim_data(PARA_DATA *para, REAL **var) {
  int i, j, id;
  
  ffd_log("-------------------------------------------------------------------",
          FFD_NORMAL);
  ffd_log("write_cosim_parameter(): "
          "Start to write the following cosimulation data to Modelica:",
           FFD_NORMAL);

  /****************************************************************************
  | Wait if the previosu data has not been read by Modelica
  ****************************************************************************/
  while(para->cosim->ffd->flag==1) {
    ffd_log("write_cosim_data(): Wait since previosu data is not taken "
            "by Modelica", FFD_NORMAL);
    Sleep(1000);
  }

  /****************************************************************************
  | Start to write new data
  ****************************************************************************/
  para->cosim->ffd->t = para->mytime->t;

  sprintf(msg, "write_cosim_data(): Start to write FFD data to Modelica "
               "at t=%f[s]", 
          para->cosim->ffd->t);
  ffd_log(msg, FFD_NORMAL);
  
  /****************************************************************************
  | Set the time and space averaged temperature of space
  | Convert T from degC to K
  ****************************************************************************/
  para->cosim->ffd->TRoo = average_volume(para, var, var[TEMPM]); 
  sprintf(msg, "\tAveraged room temperature %f[degC]", para->cosim->ffd->TRoo);
  para->cosim->ffd->TRoo += 273.15;
  ffd_log(msg, FFD_NORMAL);

  /****************************************************************************
  | Set temperature of shading devices
  ****************************************************************************/
  if(para->cosim->para->sha==1) {
    ffd_log("\tTemperature of the shade:", FFD_NORMAL);
    for(i=0; i<para->cosim->para->nConExtWin; i++) {
      //Note: The shade feature is to be implemented
      para->cosim->ffd->TSha[i] = 20 + 273.15; 
      sprintf(msg, "\t\tSurface %d: %f[K]\n",
              i, para->cosim->ffd->TSha[i]);
      ffd_log(msg, FFD_NORMAL);
    }
  }

  /****************************************************************************
  | Set data for fluid ports
  ****************************************************************************/
  ffd_log("\tFlow information at the ports:", FFD_NORMAL);
  for(i=0; i<para->bc->nb_port; i++) {
    // Get the corresponding ID in Modelica
    id = para->bc->portId[i];
    /*-------------------------------------------------------------------------
    | Assign the temperature
    -------------------------------------------------------------------------*/
    para->cosim->ffd->TPor[id] = para->bc->TPortMean[i]/para->bc->APort[i] 
                                 + 273.15;
    sprintf(msg, "\t\t%s: TPor[%d]=%f",
            para->cosim->para->portName[id], i, 
            para->cosim->ffd->TPor[id]);
    ffd_log(msg, FFD_NORMAL);
    /*-------------------------------------------------------------------------
    | Assign the Xi
    -------------------------------------------------------------------------*/
    if(para->outp->version==DEBUG) {
      sprintf(msg, "\t\t\tn_Xi=%d, id=%d", para->bc->nb_Xi, id);
      ffd_log(msg, FFD_NORMAL);
    }

    for(j=0; j<para->bc->nb_Xi; j++) {
      para->bc->velPortMean[i] = abs(para->bc->velPortMean[i]) + SMALL;
      para->cosim->ffd->XiPor[id][j] = para->bc->XiPortMean[i][j] 
                                      / para->bc->velPortMean[i];

      sprintf(msg, "\t\t%s: Xi[%d]=%f",
              para->cosim->para->portName[id], j, 
              para->cosim->ffd->XiPor[id][j]);
      ffd_log(msg, FFD_NORMAL);
    }
    /*-------------------------------------------------------------------------
    | Assign the C
    -------------------------------------------------------------------------*/
    for(j=0; j<para->bc->nb_C; j++) {
      para->bc->velPortMean[i] = abs(para->bc->velPortMean[i]) + SMALL;
      para->cosim->ffd->CPor[id][j] = para->bc->CPortMean[i][j]
                                    / para->bc->velPortMean[i]; 
      sprintf(msg, "\t\t%s: C[%d]=%f",
              para->cosim->para->portName[id], j, 
              para->cosim->ffd->CPor[id][j]);
      ffd_log(msg, FFD_NORMAL);
    }
  }

  /****************************************************************************
  | Set data for solid surfaces
  ****************************************************************************/
  ffd_log("\tInformation at solid surfaces:", FFD_NORMAL);
  for(i=0; i<para->bc->nb_wall; i++) {
    id = para->bc->wallId[i];

    // Set the B.C. Temperature
    if(para->cosim->para->bouCon[id]==2) {
      para->cosim->ffd->temHea[id] = para->bc->temHeaMean[i] 
                                  / para->bc->AWall[i] + 273.15;
      sprintf(msg, "\t\t%s: %f[K]",
              para->cosim->para->name[id], para->cosim->ffd->temHea[id]);
    }
    // Set the heat flux
    else {
      para->cosim->ffd->temHea[id] = para->bc->temHeaMean[i];
      sprintf(msg, "\t\t%s: %f[W]",
              para->cosim->para->name[id], para->cosim->ffd->temHea[id]);
    }
    ffd_log(msg, FFD_NORMAL);
  }

  /****************************************************************************
  | Set data for sensors
  ****************************************************************************/
  if (set_sensor_data(para, var)!=0) {
    ffd_log("\tCould not get sensor data", FFD_ERROR);
    return 1;
  }
  else
    ffd_log("\tSensor Information:", FFD_NORMAL); 

  for(i=0; i<para->cosim->para->nSen; i++) {
    para->cosim->ffd->senVal[i] = para->sens->senVal[i];
    sprintf(msg, "\t\t%s: %f", 
            para->cosim->para->sensorName[i], para->cosim->ffd->senVal[i]);
    ffd_log(msg, FFD_NORMAL);
  }

  /****************************************************************************
  | Inform Modelica that the FFD data is updated
  ****************************************************************************/
  para->cosim->ffd->flag = 1;

  return 0;
} // End of write_cosim_data()
Esempio n. 23
0
///////////////////////////////////////////////////////////////////////////////
/// FFD solver
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int FFD_solver(PARA_DATA *para, REAL **var, int **BINDEX) {
  int step_total = para->mytime->step_total;
  REAL t_steady = para->mytime->t_steady;
  double t_cosim;
  int flag, next;

  if(para->solv->cosimulation == 1)
    t_cosim = para->mytime->t + para->cosim->modelica->dt;

  /***************************************************************************
  | Solver Loop
  ***************************************************************************/
  next = 1;
  while(next==1) {
    //-------------------------------------------------------------------------
    // Integration
    //-------------------------------------------------------------------------
    flag = vel_step(para, var, BINDEX);
    if(flag != 0) {
      ffd_log("FFD_solver(): Could not solve velocity.", FFD_ERROR);
      return flag;
    }
    else if(para->outp->version==DEBUG)
      ffd_log("FFD_solver(): solved velocity step.", FFD_NORMAL);

    flag = temp_step(para, var, BINDEX);
    if(flag != 0) {
      ffd_log("FFD_solver(): Could not solve temperature.", FFD_ERROR);
      return flag;
    }
    else if(para->outp->version==DEBUG)
      ffd_log("FFD_solver(): solved temperature step.", FFD_NORMAL);

    flag = den_step(para, var, BINDEX);
    if(flag != 0) {
      ffd_log("FFD_solver(): Could not solve trace substance.", FFD_ERROR);
      return flag;
    }
    else if(para->outp->version==DEBUG)
      ffd_log("FFD_solver(): solved density step.", FFD_NORMAL);

    timing(para);

    //-------------------------------------------------------------------------
    // Process for Cosimulation
    //-------------------------------------------------------------------------
    if(para->solv->cosimulation == 1) {
      /*.......................................................................
      | Conditon 1: If synchronization point is reached, 
      | Action:     Do data exchange
      .......................................................................*/
      if(fabs(para->mytime->t - t_cosim)<SMALL) {
        if(para->outp->version==DEBUG)
          ffd_log("FFD_solver(): Cosimulation, reached synchronization point", 
                  FFD_NORMAL);

        // Average the FFD simulation data
        flag = average_time(para, var);
        if(flag != 0) {
          ffd_log("FFD_solver(): Could not average the data over time.",
            FFD_ERROR);
          return flag;
        }

        // the data for cosimulation
        flag = read_cosim_data(para, var, BINDEX);
        if(flag != 0) {
          ffd_log("FFD_solver(): Could not read cosimulation data.", FFD_ERROR);
          return flag;
        }

        flag =  write_cosim_data(para, var);
        if(flag != 0) {
          ffd_log("FFD_solver(): Could not write cosimulation data.", FFD_ERROR);
          return flag;
        }

        sprintf(msg, "ffd_solver(): Synchronized data at t=%f[s]\n", para->mytime->t);
        ffd_log(msg, FFD_NORMAL);

        // Set the next synchronization time
        t_cosim += para->cosim->modelica->dt;
        // Reset all the averaged data to 0
        flag = reset_time_averaged_data(para, var);
        if(flag != 0) {
          ffd_log("FFD_solver(): Could not reset averaged data.",
            FFD_ERROR);
          return flag;
        }

        /*.......................................................................
        | Check if Modelica asks to stop the simulation 
        .......................................................................*/
        if(para->cosim->para->flag==0) {
          // Stop the solver
          next = 0; 
          sprintf(msg, 
                  "ffd_solver(): Received stop command from Modelica at "
                  "FFD time: %f[s], Modelica Time: %f[s].",
                  para->mytime->t, para->cosim->modelica->t);
          if(para->mytime->t==para->cosim->modelica->t)
            ffd_log(msg, FFD_NORMAL);
          else 
            ffd_log(msg, FFD_WARNING);
        }

        continue;
      } // End of Conditon 1
      /*.......................................................................
      | Conditon 2: synchronization point is not reached , 
      |             but already miss the synchronization point
      | Action:     Stop simulation
      .......................................................................*/
      else if(para->mytime->t-t_cosim>SMALL) {
        sprintf(msg, 
          "ffd_solver(): Mis-matched synchronization step with "
                "t_ffd=%f[s], t_cosim=%f[s], dt_syn=%f[s], dt_ffd=%f[s].",
                para->mytime->t, t_cosim, 
                para->cosim->modelica->dt, para->mytime->dt);
        ffd_log(msg, FFD_ERROR);
        sprintf(msg, "para->mytime->t - t_cosim=%lf", para->mytime->t - t_cosim);
        ffd_log(msg, FFD_ERROR);
        return 1;
      } // end of Conditon 2
      /*.......................................................................
      | Conditon 3: synchronization point is not reached
      |             and not miss the synchronization point
      | Action:     Do FFD internal simulation and add data for future average
      .......................................................................*/
      else {
        if(para->outp->version==DEBUG)
          ffd_log("FFD_solver(): Cosimulation, prepare next step for FFD", 
                  FFD_NORMAL);

        // Integrate the data on the boundary surface
        flag = surface_integrate(para, var, BINDEX);
        if(flag != 0) {
          ffd_log("FFD_solver(): "
            "Could not average the data on boundary.",
            FFD_ERROR);
          return flag;
        }
        else if (para->outp->version==DEBUG)
          ffd_log("FFD_solver(): completed surface integration", 
                  FFD_NORMAL);

        flag = add_time_averaged_data(para, var);
        if(flag != 0) {
          ffd_log("FFD_solver(): "
            "Could not add the averaged data.",
            FFD_ERROR);
          return flag;
        }
        else if (para->outp->version==DEBUG)
          ffd_log("FFD_solver(): completed time average", 
                  FFD_NORMAL);

      } // End of Condition 3
    } // End of cosimulation
    //-------------------------------------------------------------------------
    // Process for single simulation
    //-------------------------------------------------------------------------
    else {
      if(para->outp->version==DEBUG)
        ffd_log("FFD_solver(): Single Simulation, prepare for next time step", 
                FFD_NORMAL);

      // Start to record data for calculating mean velocity if needed
      if(para->mytime->t>t_steady && para->outp->cal_mean==0) {
        para->outp->cal_mean = 1;
        flag = reset_time_averaged_data(para, var);
        if(flag != 0) {
          ffd_log("FFD_solver(): Could not reset averaged data.",
            FFD_ERROR);
          return flag;
        }
        else
          ffd_log("FFD_solver(): Start to calculate mean properties.",
                   FFD_NORMAL);
      }   

      if(para->outp->cal_mean==1) {
        flag = add_time_averaged_data(para, var);
        if(flag != 0) {
          ffd_log("FFD_solver(): Could not add the averaged data.",
            FFD_ERROR);
          return 1;
        }
      }
      next = para->mytime->step_current < step_total ? 1 : 0;
    }    
  } // End of While loop  

  return flag;
} // End of FFD_solver( ) 
///////////////////////////////////////////////////////////////////////////////
/// Compare the names of boundaries and store the relationship 
///
///\param para Pointer to FFD parameters
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int compare_boundary_names(PARA_DATA *para) {
  int i, j, flag;

  char **name1 = para->cosim->para->name;
  char **name2 = para->bc->wallName;
  char **name3 = para->cosim->para->portName;
  char **name4 = para->bc->portName;

  /****************************************************************************
  | Compare the names of solid surfaces
  ****************************************************************************/
  for(i=0; i<para->cosim->para->nSur; i++) {
    /*-------------------------------------------------------------------------
    | Assume we do not find the name
    -------------------------------------------------------------------------*/
    flag = 1;

    /*-------------------------------------------------------------------------
    | Check the wall names in FFD
    -------------------------------------------------------------------------*/
    for(j=0; j<para->bc->nb_wall&&flag!=0; j++) {
      flag = strcmp(name1[i], name2[j]);
      // If found the name
      if(flag==0) {
        // If the same name has been found before
        if(para->bc->wallId[j]>0) {
          sprintf(msg, "compare_boundary_names(): Modelica has "
            "the same name \"%s\" for two BCs.", name1[i]);
          ffd_log(msg, FFD_ERROR);
          return 1;
        }
        // If no same name has been found before, use it
        else {
          sprintf(msg,
          "compare_boundary_names(): Matched boundary name \"%s\".",
          name1[i]);
          ffd_log(msg, FFD_NORMAL);
          para->bc->wallId[j] = i;
        }
      } // End of if(flag==0)
    } // End of for(j=0; j<para->bc->nb_wall&&flag!=0; j++)

    /*-------------------------------------------------------------------------
    | Stop if name is not found 
    -------------------------------------------------------------------------*/
    if(flag!=0) {
      sprintf(msg, "compare_boundary_names(): Could not find the Modelica "
        " wall boundary \"%s\" in FFD.", name1[i]);
      ffd_log(msg, FFD_ERROR);
      return 1;
    }
  } // Next Modelica Wall name

  /****************************************************************************
  | Compare the names of fluid ports
  ****************************************************************************/
  ffd_log("Start to compare port names", FFD_NORMAL);
  for(i=0; i<para->cosim->para->nPorts; i++) {
    /*-------------------------------------------------------------------------
    | Assume we do not find the name
    -------------------------------------------------------------------------*/
    flag = 1;
    sprintf(msg, "\tModelica: port[%d]=%s", i, name3[i]);
    ffd_log(msg, FFD_NORMAL);
    /*-------------------------------------------------------------------------
    | Check the FFD inlet and outlet names
    -------------------------------------------------------------------------*/
    for(j=0; j<para->bc->nb_port&&flag!=0; j++) {
      flag = strcmp(name3[i], name4[j]);
      sprintf(msg, "\tFFD: port[%d]=%s", j, name4[j]);
      ffd_log(msg, FFD_NORMAL);
      // If found the name
      if(flag==0) {
        // If the same name has been found before
        if(para->bc->portId[j]>0) {
          sprintf(msg,
          "compare_boundary_names(): Modelica has the same name \"%s\" for two BCs.",
          name3[i]);
          ffd_log(msg, FFD_ERROR);
          return 1;
        }
        // If no same name has been found before, use it
        else {
          sprintf(msg,
          "compare_boundary_names(): Matched boundary name \"%s\".",
          name3[i]);
          ffd_log(msg, FFD_NORMAL);
          para->bc->portId[j] = i;
        }
      } // End of if(flag==0)
    }

    /*-------------------------------------------------------------------------
    | Stop if name is not found 
    -------------------------------------------------------------------------*/
    if(flag!=0) {
      sprintf(msg, "compare_boundary_names(): Could not find"
        "the Modelica fluid port boundary \"%s\" in FFD.", name3[i]);
      ffd_log(msg, FFD_ERROR);
      return 1;
    }
  } // Next Modelica port name

  return 0;
} // End of compare_boundary_names()
///////////////////////////////////////////////////////////////////////////////
/// Write the data in a format for SCI program
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param name Pointer to the filename
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int write_SCI(PARA_DATA *para, REAL **var, char *name) {
  int i, j, k;
  int IPR, IU, IV, IW, IT, IC1, IC2, IC3, IC4, IC5, IC6, IC7;
  int imax=para->geom->imax, jmax=para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  int n = para->mytime->step_current;
  REAL *x = var[X], *y = var[Y], *z =var[Z];
  REAL *u = var[VX], *v = var[VY], *w = var[VZ], *p = var[IP];
  REAL *um = var[VXM], *vm = var[VYM], *wm = var[VZM], *d = var[TRACE];
  REAL *T = var[TEMP], *Tm = var[TEMPM];
  REAL *tmp1 = var[TMP1], *tmp2 = var[TMP2], *tmp3 = var[TMP3];
  char *filename;
  FILE *dataFile;

  /****************************************************************************
  | Allocate memory for filename
  | Length of filename should be sizeof(ActualName) + 1
  | Using sizeof(ActualName) will cause memory fault in free(filename)
  ****************************************************************************/
  filename = (char *) malloc((strlen(name)+5)*sizeof(char));
  if(filename==NULL) {
    ffd_log("write_SCI(): Failed to allocate memory for file name", 
            FFD_ERROR); 
    return 1;
  }

  strcpy(filename, name);
  strcat(filename, ".cfd");

  // Open output file
  if((dataFile=fopen(filename,"w"))==NULL) {
    sprintf(msg, "write_SCI(): Failed to open file %s.", filename);
    ffd_log(msg, FFD_ERROR);
    return 1;
  }

  /****************************************************************************
  | Identify the output varaible: 1 Yes; 0 No.
  | IPR: Pressure; IU,IV,IW: velocity in x,y,z direction; 
  | IT: Temperature; IC1,IC2,IC3,IC4,IC5,IC6,IC6: other scalars
  ****************************************************************************/
  IPR = 1;
  IU = 1;
  IV = 1;
  IW = 1;
  IT = 1;
  IC1 = 0;
  IC2 = 0;
  IC3 = 0;
  IC4 = 0;
  IC5 = 0;
  IC6 = 0;
  IC7 = 0;

  /****************************************************************************
  | Convert varaible value from cell surface to cell center
  ****************************************************************************/
  for(j=0; j<=jmax+1; j++) {
    for(k=0; k<=kmax+1; k++) {
      u[IX(imax+1,j,k)] = u[IX(imax,j,k)];
      um[IX(imax+1,j,k)] = um[IX(imax,j,k)];
      for(i=imax; i>=1; i--) {
        u[IX(i,j,k)] = (REAL) 0.5 * (u[IX(i,j,k)]+u[IX(i-1,j,k)]);
        um[IX(i,j,k)] = (REAL) 0.5 * (um[IX(i,j,k)]+um[IX(i-1,j,k)]);
      }
    }
  }

  for(i=0; i<=imax+1; i++) {
    for(k=0; k<=kmax+1; k++) {
      v[IX(i,jmax+1,k)] = v[IX(i,jmax,k)];
      vm[IX(i,jmax+1,k)] = vm[IX(i,jmax,k)];  
      for(j=jmax; j>=1; j--) {
          v[IX(i,j,k)] = (REAL) 0.5 * (v[IX(i,j,k)]+v[IX(i,j-1,k)]);
          vm[IX(i,j,k)] = (REAL) 0.5 * (vm[IX(i,j,k)]+vm[IX(i,j-1,k)]);
        }
    }
  }

  for(i=0; i<=imax+1; i++) {
    for(j=0; j<=jmax+1; j++) {
      w[IX(i,j,kmax+1)] = w[IX(i,j,kmax)];
      wm[IX(i,j,kmax+1)] = wm[IX(i,j,kmax)];  
      for(k=kmax; k>=1; k--) {
        w[IX(i,j,k)] = (REAL) 0.5 * (w[IX(i,j,k)]+w[IX(i,j,k-1)]);
        wm[IX(i,j,k)] = (REAL) 0.5 * (wm[IX(i,j,k)]+wm[IX(i,j,k-1)]);
      }
    }
  }

  /****************************************************************************
  | Compute pressure value for the cornor of the domian
  ****************************************************************************/
  //W-S-B
  p[IX(0,0,0)] = (p[IX(0,1,0)]+p[IX(1,0,0)]+p[IX(0,0,1)]) / (REAL) 3.0;
  //W-N-B
  p[IX(0,jmax+1,0)] = ( p[IX(1,jmax+1,0)]+p[IX(0,jmax,0)]
                         +p[IX(0,jmax+1,1)]) / (REAL) 3.0;
  //E-S-B
  p[IX(imax+1,0,0)] = ( p[IX(imax,0,0)]+p[IX(imax+1,1,0)]
                       +p[IX(imax+1,0,1)]) / (REAL) 3.0;
  //E-N-B
  p[IX(imax+1,jmax+1,0)] = ( p[IX(imax,jmax+1,0)]+p[IX(imax+1,jmax,0)]
                            +p[IX(imax+1,jmax+1,1)]) / (REAL) 3.0;
  //W-S-F
  p[IX(0,0,kmax+1)] = ( p[IX(0,1,kmax+1)]+p[IX(1,0,kmax+1)]
                       +p[IX(0,0,kmax)]) / (REAL) 3.0;  
  //W-N-F
  p[IX(0,jmax+1,kmax+1)] = ( p[IX(1,jmax+1,kmax+1)]+p[IX(0,jmax,kmax+1)]
                            +p[IX(0,jmax+1,kmax)]) / (REAL) 3.0;

  //E-S-F
  p[IX(imax+1,0,kmax+1)] = ( p[IX(imax,0,kmax+1)]+p[IX(imax+1,1,kmax+1)]
                            +p[IX(imax+1,0,kmax)]) / (REAL) 3.0;
  //E-N-F
  p[IX(imax+1,jmax+1,kmax+1)] = ( p[IX(imax,jmax+1,0)]+p[IX(imax+1,jmax,0)]
                                 +p[IX(imax+1,jmax+1,kmax)]) / (REAL) 3.0;

  /****************************************************************************
  | Output domain length in x, y, z direction
  ****************************************************************************/
  fprintf(dataFile, "%e\t%e\t%e\n", para->geom->Lx, para->geom->Ly, para->geom->Lz);
  /****************************************************************************
  | Output maximum cell number in x, y, z direction
  ****************************************************************************/
  fprintf(dataFile, "%d\t%d\t%d\n", imax, jmax, kmax);
  /****************************************************************************
  | Output the varaibles needs to be exported
  ****************************************************************************/
  fprintf(dataFile, "%d\t%d\t%d\t%d\t%d\t%d\n", IPR, IU, IV, IW, IT, IC1);
  fprintf(dataFile, "%d\t%d\t%d\t%d\t%d\t%d\n", IC2, IC3, IC4, IC5, IC6, IC7);

   /****************************************************************************
  | Output the cooridates of cell center in x, y, z direction
  ****************************************************************************/ 
  for(i=1; i<=imax; i++)
    fprintf(dataFile, "%e\t", x[IX(i,j,k)]);
  fprintf(dataFile, "\n");
  for(j=1; j<=jmax; j++)
    fprintf(dataFile, "%e\t", y[IX(i,j,k)]);
  fprintf(dataFile, "\n");
  for(k=1; k<=kmax; k++)
    fprintf(dataFile, "%e\t", z[IX(i,j,k)]);
  fprintf(dataFile, "\n");

   /****************************************************************************
  | Output the variables
  | p: Pressure          
  | U: Velocity in X direction
  | V: Velocity in Y direction
  | W: Velocity in Z direction
  | T: Temperature
  ****************************************************************************/ 
  for(j=1; j<=jmax; j++)
    for(i=1; i<=imax; i++) {
      fprintf(dataFile, "%d\t%d\n", i,j);
      if(IPR==1) {
        for(k=1; k<=kmax; k++) 
          fprintf(dataFile, "%e\t", p[IX(i,j,k)]);   
        fprintf(dataFile, "\n");
      }
      if(IU==1) {
        for(k=1; k<=kmax; k++) 
          fprintf(dataFile, "%e\t", u[IX(i,j,k)]);   
        fprintf(dataFile, "\n");
      }
      if(IV==1) {
        for(k=1; k<=kmax; k++)
          fprintf(dataFile, "%e\t", v[IX(i,j,k)]);
        fprintf(dataFile, "\n");
      }
      if(IW==1) {
        for(k=1; k<=kmax; k++)
          fprintf(dataFile, "%e\t", w[IX(i,j,k)]);
          fprintf(dataFile, "\n");
      }

      if(IT==1) {
        for(k=1; k<=kmax; k++)
          fprintf(dataFile, "%e\t", T[IX(i,j,k)]);
        fprintf(dataFile, "\n");
      }

      for(k=1; k<=kmax; k++)
          fprintf(dataFile, "%e\t", T[IX(i,j,k)]);
        fprintf(dataFile, "\n");
       // Extra line because SCI reads turbulence intensity data
    }

  fclose(dataFile);
  sprintf(msg, "wrtie_SCI(): Wrote the SCI data file %s.", filename);
  ffd_log(msg, FFD_NORMAL);
  free(filename);
  return 0;

} // End of write_SCI()
///////////////////////////////////////////////////////////////////////////////
/// Assign the Modelica solid surface thermal boundary condition data to FFD
///
///\param para Pointer to FFD parameters
///\param var Pointer to the FFD simulaiton variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int assign_thermal_bc(PARA_DATA *para, REAL **var, int **BINDEX) {
  int i, j, k, it, id, modelicaId;
  int imax = para->geom->imax, jmax = para->geom->jmax,
      kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  REAL sensibleHeat=para->cosim->modelica->sensibleHeat;
  REAL latentHeat=para->cosim->modelica->latentHeat;
  REAL *temHea, celVol;

  /****************************************************************************
  | Assign the boundary conditon if there is a solid surface
  ****************************************************************************/
  if(para->bc->nb_wall>0) {
    ffd_log("assign_thermal_bc(): Thermal conditions for solid surfaces:",
          FFD_NORMAL);
    temHea = (REAL *) malloc(para->bc->nb_wall*sizeof(REAL));
    if(temHea==NULL) {
      ffd_log("assign_thermal_bc(): Could not allocate memory for temHea.",
              FFD_ERROR);
      return 1;
    }
    //-------------------------------------------------------------------------
    // Convert the data from Modelica order to FFD order
    //-------------------------------------------------------------------------
    for(j=0; j<para->bc->nb_wall; j++) {
      i = para->bc->wallId[j];
      switch(para->cosim->para->bouCon[i]) {
        case 1: // Temperature
          temHea[j] = para->cosim->modelica->temHea[i] - 273.15;
          sprintf(msg, "\t%s: T=%f[degC]", 
            para->bc->wallName[j], temHea[j]);
          ffd_log(msg, FFD_NORMAL);
          break;
        case 2: // Heat flow rate
          temHea[j] = para->cosim->modelica->temHea[i] / para->bc->AWall[j];
          sprintf(msg, "\t%s: Q_dot=%f[W/m2]", 
            para->bc->wallName[j], temHea[j]);
          ffd_log(msg, FFD_NORMAL);
          break;
        default:
          sprintf(msg, 
          "Invalid value (%d) for thermal boundary condition. "
          "Expected value are 1->Fixed T; 2->Fixed heat flux",
          para->cosim->para->bouCon[i]);        
          ffd_log(msg, FFD_ERROR);
          return 1;
      }
    }
    //-------------------------------------------------------------------------
    // Assign the BC
    //-------------------------------------------------------------------------
    for(it=0; it<para->geom->index; it++) {    
      i = BINDEX[0][it];
      j = BINDEX[1][it];
      k = BINDEX[2][it];
      id = BINDEX[4][it];
      modelicaId = para->bc->wallId[id];

      if(var[FLAGP][IX(i,j,k)]==SOLID) 
        switch(para->cosim->para->bouCon[modelicaId]) {
          case 1: 
            var[TEMPBC][IX(i,j,k)] = temHea[id];
            BINDEX[3][it] = 1; // Specified temperature
            break;
          case 2:
            var[QFLUXBC][IX(i,j,k)] = temHea[id];
            BINDEX[3][it] = 0; // Specified heat flux 
            break;
          default:
            sprintf(msg,
              "assign_thermal_bc(): Thermal bc value BINDEX[3][%d]=%d "
              "at [%d,%d,%d] was not valid.",
              it, BINDEX[3][it], i, j, k);
            ffd_log(msg, FFD_ERROR);
            return 1;
      } // End of switch(BINDEX[3][it])
    }

    free(temHea);
  } // End of if(para->bc->nb_wall>0) 
  /****************************************************************************
  | No action since there is not a solid surface
  ****************************************************************************/
  else
    ffd_log("assign_thermal_bc(): No solid surfaces:", FFD_NORMAL);

  /****************************************************************************
  | Calculate heat injected into the space
  ****************************************************************************/
  sprintf(msg, "Convective sensible heat received by FFD is %f", 
                sensibleHeat);
  ffd_log(msg, FFD_NORMAL);

  FOR_EACH_CELL
    if (var[FLAGP][IX(i,j,k)]==FLUID){
       celVol = vol(para, var, i, j, k);
       var[TEMPS][IX(i,j,k)] = sensibleHeat * celVol / para->geom->volFlu;
    }
  END_FOR

  /****************************************************************************
  | Data received, but not used in current version
  ****************************************************************************/
  sprintf(msg, "Latent heat received by FFD is %f",
                 latentHeat);
  ffd_log(msg, FFD_NORMAL);

  return 0;
} // End of assign_thermal_bc()
///////////////////////////////////////////////////////////////////////////////
/// Write standard output data in a format for tecplot 
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param name Pointer to file name
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int write_tecplot_data(PARA_DATA *para, REAL **var, char *name) {
  int i, j, k;
  int imax=para->geom->imax, jmax=para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  REAL *x = var[X], *y = var[Y], *z =var[Z];
  REAL *u = var[VX], *v = var[VY], *w = var[VZ], *p = var[IP];
  REAL *d = var[TRACE];
  REAL *T = var[TEMP];
  REAL *flagp = var[FLAGP];
  char *filename;
  FILE *datafile;

  /****************************************************************************
  | Allocate memory for filename
  | Length of filename should be sizeof(ActualName) + 1
  | Using sizeof(ActualName) will cause memory fault in free(filename)
  ****************************************************************************/
  filename = (char *) malloc((strlen(name)+5)*sizeof(char));
  if(filename==NULL) {
    ffd_log("write_tecplot_data(): Failed to allocate memory for file name", 
            FFD_ERROR); 
    return 1;
  }

  strcpy(filename, name);
  strcat(filename, ".plt");

  // Open output file
  if((datafile=fopen(filename, "w"))==NULL) {
    ffd_log("write_tecplot_data(): Failed to open output file!\n", FFD_ERROR);
    return 1;
  }

  convert_to_tecplot(para, var);

  fprintf(datafile, "TITLE = ");
  fprintf(datafile, "\"dt=%fs, t=%fs, nu=%f, Lx=%f, Ly=%f, Lz=%f, ",
           para->mytime->dt, para->mytime->t, para->prob->nu, 
           para->geom->Lx, para->geom->Ly, para->geom->Lz);
    fprintf(datafile, "Nx=%d, Ny=%d, Nz=%d \"\n",
           imax+2, jmax+2, kmax+2);

  fprintf( datafile, 
           "VARIABLES =X, Y, Z, I, J, K, U, V, W, T, fu, fv \n");
  fprintf( datafile, "ZONE F=POINT, I=%d, J=%d, K=%d\n", imax+2, jmax+2, kmax+2 );
 
  FOR_ALL_CELL
    fprintf(datafile, "%f\t%f\t%f\t%d\t%d\t%d\t",
       x[IX(i,j,k)], y[IX(i,j,k)], z[IX(i,j,k)], i, j, k);    
    fprintf(datafile, "%f\t%f\t%f\t%f\t%f\t%f\n",
            u[IX(i,j,k)], v[IX(i,j,k)], w[IX(i,j,k)], T[IX(i,j,k)],
            flagp[IX(i,j,k)], p[IX(i,j,k)]);    
  END_FOR

  sprintf(msg, "write_tecplot_data(): Wrote file %s.", filename);
  ffd_log(msg, FFD_NORMAL);

  free(filename);
  fclose(datafile);
  return 0;
} //write_tecplot_data()
///////////////////////////////////////////////////////////////////////////////
/// Write all available data in a format for tecplot 
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param name Pointer to file name
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int write_tecplot_all_data(PARA_DATA *para, REAL **var, char *name) {
  int i, j, k;
  int imax=para->geom->imax, jmax=para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  REAL *x = var[X], *y = var[Y], *z =var[Z];
  char *filename;
  FILE *dataFile;

  /****************************************************************************
  | Allocate memory for filename
  | Length of filename should be sizeof(ActualName) + 1
  | Using sizeof(ActualName) will cause memory fault in free(filename)
  ****************************************************************************/
  filename = (char *) malloc((strlen(name)+5)*sizeof(char));
  if(filename==NULL) {
    ffd_log("write_tecplot_all_data(): Failed to allocate memory for file name", 
            FFD_ERROR); 
    return 1;
  }

  strcpy(filename, name);
  strcat(filename, ".plt");

  // Open output file
  if((dataFile=fopen(filename,"w"))==NULL) {
    sprintf(msg, "write_tecplot_data(): Failed to open output file %s.", filename);
    ffd_log(msg, FFD_ERROR);
    return 1;
  }

  convert_to_tecplot(para, var);

  fprintf(dataFile, "TITLE = ");

  // Print simulation, diemension and mesh information
  fprintf(dataFile, "\"dt=%fs, t=%fs, nu=%f, Lx=%d, Ly=%d, Lz%d, ",
          para->mytime->dt, para->mytime->t, para->prob->nu, 
          para->geom->Lx, para->geom->Ly, para->geom->Lz);
  fprintf(dataFile, "Nx=%d, Ny=%d, Nz=%d \"\n", imax+2, jmax+2, kmax+2);

  // Print variables 
  fprintf(dataFile, "VARIABLES = X, Y, Z, I, J, K, ");
  fprintf(dataFile, "U, V, W, UM, VM, WM, US, VS, WS, ");
  fprintf(dataFile, "P, ");
  fprintf(dataFile, "T, TM, TS, ");
  fprintf(dataFile, "GX, GY, GZ, ");
  fprintf(dataFile, "FLAGU, FLAGV, FLAGW, FLAGP, ");
  fprintf(dataFile, "VXBC, VYBC, VZBV, TEMPBC, ");
  fprintf(dataFile, "QFLUX, QFLUXBC, ");
  fprintf(dataFile, "AP, AN, AS, AW, AE, AF, AB, B, AP0, PP");
  fprintf(dataFile, "\n");
  fprintf(dataFile, "ZONE F=POINT, I=%d, J=%d, K=%d\n", imax+2, jmax+2, kmax+2 );
 
  FOR_ALL_CELL
    // Coordinates
    fprintf(dataFile, "%f\t%f\t%f\t%d\t%d\t%d\t",
            x[IX(i,j,k)], y[IX(i,j,k)], z[IX(i,j,k)], i, j, k);
    // Velocities
    fprintf(dataFile, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t", 
            var[VX][IX(i,j,k)], var[VY][IX(i,j,k)], var[VZ][IX(i,j,k)], 
            var[VXM][IX(i,j,k)], var[VYM][IX(i,j,k)], var[VZM][IX(i,j,k)],
            var[VXS][IX(i,j,k)], var[VYS][IX(i,j,k)], var[VZS][IX(i,j,k)]);
    // Pressure
    fprintf(dataFile, "%f\t", var[IP][IX(i,j,k)]);
    // Temperature
    fprintf(dataFile, "%f\t%f\t%f\t",
            var[TEMP][IX(i,j,k)], var[TEMPM][IX(i,j,k)], 
            var[TEMPS][IX(i,j,k)]);
    // Gravity
    fprintf(dataFile, "%f\t%f\t%f\t",
            var[GX][IX(i,j,k)], var[GY][IX(i,j,k)], var[GZ][IX(i,j,k)]);
    // Flags for simulaiton
    fprintf(dataFile, "%f\t%f\t%f\t%f\t",
            var[FLAGU][IX(i,j,k)], var[FLAGV][IX(i,j,k)], 
            var[FLAGW][IX(i,j,k)], var[FLAGP][IX(i,j,k)]);
    // Boundary conditions
    fprintf(dataFile, "%f\t%f\t%f\t%f\t",
            var[VXBC][IX(i,j,k)], var[VYBC][IX(i,j,k)], 
            var[VZBC][IX(i,j,k)], var[TEMPBC][IX(i,j,k)]);
    // Heat flux
    fprintf(dataFile, "%f\t%f\t",
            var[QFLUX][IX(i,j,k)], var[QFLUXBC][IX(i,j,k)]);

    // Coefficients
    fprintf(dataFile, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
            var[AP][IX(i,j,k)], var[AN][IX(i,j,k)], var[AS][IX(i,j,k)], 
            var[AW][IX(i,j,k)], var[AE][IX(i,j,k)], var[AF][IX(i,j,k)], 
            var[AB][IX(i,j,k)], var[B][IX(i,j,k)], var[AP0][IX(i,j,k)], 
            var[PP][IX(i,j,k)]);

  END_FOR

  fclose(dataFile);
  sprintf(msg, "write_tecplot_all_data(): Wrote file %s.", filename);
  ffd_log(msg, FFD_NORMAL);
  free(filename);

  return 0;
} //write_tecplot_all_data()
///////////////////////////////////////////////////////////////////////////////
/// Assign the Modelica inlet and outlet boundary condition data to FFD
///
/// The inlet and outlet boundaries are not fixed and they can change during 
/// the simulation. The reason is that the Modelica uses acausal modeling
/// and the flow direction can change during the simulation depending on the 
/// pressure difference. As a result, the FFD has to change its inlet and outlet
/// boundry condition accordingly. The inlet or outlet boundary is decided 
/// according to the flow rate para->cosim->modelica->mFloRarPor. The port is
/// inlet if mFloRarPor>0 and outlet if mFloRarPor<0. We will need to reset the 
/// var[FLAGP][IX(i,j,k)] to apply the change of boundary conditions.
///
///\param para Pointer to FFD parameters
///\param var Pointer to the FFD simulaiton variables
///\param BINDEX Pointer to boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int assign_port_bc(PARA_DATA *para, REAL **var, int **BINDEX) {
  int i, j, k, id, it, Xid, Cid;
  int imax = para->geom->imax, jmax = para->geom->jmax;
  int kmax = para->geom->kmax;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);

  ffd_log("assign_port_bc():", FFD_NORMAL);

  /****************************************************************************
  | Convert the data from Modelica to FFD for the Inlet
  ****************************************************************************/
  for(j=0; j<para->bc->nb_port; j++) {
    i = para->bc->portId[j];

    /*-------------------------------------------------------------------------
    | Convert for mass flow rate and temperature
    -------------------------------------------------------------------------*/
    para->bc->velPort[j] = para->cosim->modelica->mFloRatPor[i] 
                              / (para->prob->rho*para->bc->APort[j]);
    para->bc->TPort[j] = para->cosim->modelica->TPor[i] - 273.15;
    sprintf(msg, "\t%s: vel=%f[m/s], T=%f[degC]", 
          para->bc->portName[j], para->bc->velPort[j], 
          para->bc->TPort[j]);
    ffd_log(msg, FFD_NORMAL);
    /*-------------------------------------------------------------------------
    | Convert nXi types of species
    -------------------------------------------------------------------------*/
    for(Xid=0; Xid<para->cosim->para->nXi; Xid++) {
      para->bc->XiPort[j][Xid] = para->cosim->modelica->XiPor[i][Xid];
      sprintf(msg, "\tXi[%d]=%f", Xid, para->bc->XiPort[j][Xid]);
      ffd_log(msg, FFD_NORMAL);
    }
    /*-------------------------------------------------------------------------
    | Convert nC types of trace substances
    -------------------------------------------------------------------------*/
    for(Cid=0; Cid<para->cosim->para->nC; Cid++) {
      para->bc->CPort[j][Cid] = para->cosim->modelica->CPor[i][Cid];
      sprintf(msg, "\tC[%d]=%f", Cid, para->bc->CPort[j][Cid]);
      ffd_log(msg, FFD_NORMAL);
    }
  }

  /****************************************************************************
  | Assign the BC
  ****************************************************************************/
  for(it=0; it<para->geom->index; it++) {    
    i = BINDEX[0][it];
    j = BINDEX[1][it];
    k = BINDEX[2][it];
    id = BINDEX[4][it];

    /*-------------------------------------------------------------------------
    | Only treat those inlet and outlet boundaries
    -------------------------------------------------------------------------*/
    if(var[FLAGP][IX(i,j,k)]==INLET || var[FLAGP][IX(i,j,k)]==OUTLET) {
      // Set it to inlet if the flow velocity is positive or equal to 0
      if(para->bc->velPort[id]>=0) {
        var[FLAGP][IX(i,j,k)] = INLET; 
        var[TEMPBC][IX(i,j,k)] = para->bc->TPort[id];
        for(Xid=0; Xid<para->cosim->para->nXi; Xid++)
          var[Xi1BC+Xid][IX(i,j,k)] = para->bc->XiPort[id][Xid];
        for(Cid=0; Cid<para->cosim->para->nC; Cid++)
          var[C1BC+Cid][IX(i,j,k)] = para->bc->CPort[id][Cid];


        if(i==0)
          var[VXBC][IX(i,j,k)] = para->bc->velPort[id];
        else if(i==imax+1)
          var[VXBC][IX(i,j,k)] = -para->bc->velPort[id];

        if(j==0)
          var[VYBC][IX(i,j,k)] = para->bc->velPort[id];
        else if(j==jmax+1)
          var[VYBC][IX(i,j,k)] = -para->bc->velPort[id];

        if(k==0)
          var[VZBC][IX(i,j,k)] = para->bc->velPort[id];
        else if(k==kmax+1)
          var[VZBC][IX(i,j,k)] = -para->bc->velPort[id];
      }
      // Set it to outlet if the flow velocity is negative
      else
        var[FLAGP][IX(i,j,k)] = OUTLET;
    }
  }
  return 0;
} // End of assign_inlet_outlet_bc()
///////////////////////////////////////////////////////////////////////////////
/// Integrate the cosimulation exchange data over the surfaces 
///
/// Fluid port: 
///   - T/Xi/C: sum(u*T*dA)
///   - m_dot:  sum(u*dA)
///
/// Solid Surface Boundary:
///   - T:      sum(T*dA)
///   - Q_dot:  sum(q_dot*dA)
///
///\param para Pointer to FFD parameters
///\param var Pointer to FFD simulation variables
///\param BINDEX Pointer to the boundary index
///
///\return 0 if no error occurred
///////////////////////////////////////////////////////////////////////////////
int surface_integrate(PARA_DATA *para, REAL **var, int **BINDEX) {
  int imax = para->geom->imax, jmax = para->geom->jmax; 
  int kmax = para->geom->kmax;
  int i, j, k, it, bcid;
  int IMAX = imax+2, IJMAX = (imax+2)*(jmax+2);
  REAL vel_tmp, A_tmp; 

  /****************************************************************************
  | Set the variable to 0
  ****************************************************************************/
  if(para->outp->version==DEBUG)
    ffd_log("surface_integrate(): Start to set the variable to 0", 
            FFD_NORMAL);

  for(i=0; i<para->bc->nb_wall; i++)
    para->bc->temHeaAve[i] = 0;

  for(i=0; i<para->bc->nb_port; i++) {
    para->bc->TPortAve[i] = 0;
    para->bc->velPortAve[i] = 0;
    for(j=0; j<para->bc->nb_Xi; j++)
      para->bc->XiPortAve[i][j] = 0;
    for(j=0; j<para->bc->nb_C; j++)
      para->bc->CPortAve[i][j] = 0;
  }

  /****************************************************************************
  | Go through all the boundary cells
  ****************************************************************************/
  if(para->outp->version==DEBUG)
    ffd_log("surface_integrate(): Start to sum all the cells", FFD_NORMAL);

  for(it=0; it<para->geom->index; it++) {
    i = BINDEX[0][it];
    j = BINDEX[1][it];
    k = BINDEX[2][it];
    bcid = BINDEX[4][it];

    if(i==0 || i==imax+1) {
      vel_tmp = var[VX][IX(i,j,k)];
      A_tmp = area_yz(para, var, i, j, k);
    }
    else if(j==0 || j==jmax+1) {
      vel_tmp = var[VY][IX(i,j,k)];
      A_tmp = area_zx(para, var, i, j, k);
    }
    else if(k==0 || k==kmax+1) {
      vel_tmp = var[VZ][IX(i,j,k)];
      A_tmp = area_xy(para, var, i, j, k);
    }

    /*-------------------------------------------------------------------------
    | Set the thermal conditions data for Modelica.
    | In FFD simulation, the BINDEX[3][it] indicates: 1->T, 0->Heat Flux.
    | Those BINDEX[3][it] will be reset according to the Modelica data 
    | para->comsim->para->bouCon (1->Heat Flux, 2->T). 
    | Here is to give the Modelica the missing data (For instance, if Modelica 
    | send FFD Temperature, FFD should then send Modelica Heat Flux).
    -------------------------------------------------------------------------*/
    /*-------------------------------------------------------------------------
    | Solid Wall
    --------------------------------------------------------------------------*/
    if(var[FLAGP][IX(i,j,k)]==SOLID) {
      switch(BINDEX[3][it]) {
        // FFD uses heat flux as BC to compute temperature
        // Then send Modelica the tempearture
        case 0: 
          para->bc->temHeaAve[bcid] += var[TEMP][IX(i,j,k)] * A_tmp;
          break;
        // FFD uses temperature as BC to compute heat flux
        // Then send Modelica the heat flux
        case 1: 
          para->bc->temHeaAve[bcid] += var[QFLUX][IX(i,j,k)] * A_tmp;
          //sprintf(msg, "Cell(%d,%d,%d):\tQFLUX=%f,\tA=%f", i,j,k,var[QFLUX][IX(i,j,k)], A_tmp);
          //ffd_log(msg, FFD_NORMAL);
          break;
        default:
          sprintf(msg, "average_bc_area(): Thermal boundary (%d)"
                 "for cell (%d,%d,%d) was not defined",
                 BINDEX[3][it], i, j, k);
          ffd_log(msg, FFD_ERROR);
          return 1;
      }
    }
    /*-------------------------------------------------------------------------
    | Outlet
    -------------------------------------------------------------------------*/
    else if(var[FLAGP][IX(i,j,k)]==OUTLET) {
      if(para->outp->version==DEBUG) {
        sprintf(msg, "surface_integrate(): Set the outlet[%d, %d, %d]", 
                i, j, k);
        ffd_log(msg, FFD_NORMAL);
      }

      para->bc->TPortAve[bcid] += var[TEMP][IX(i,j,k)] * A_tmp;
      para->bc->velPortAve[bcid] += vel_tmp * A_tmp;
      for(j=0; j<para->bc->nb_Xi; j++)
        para->bc->XiPortAve[bcid][j] += var[Xi1+j][IX(i,j,k)] * A_tmp;

      for(j=0; j<para->bc->nb_C; j++)
        para->bc->CPortAve[bcid][j] += var[C1+j][IX(i,j,k)] * A_tmp;
        
    } 
    /*-------------------------------------------------------------------------
    | Inlet
    -------------------------------------------------------------------------*/
    else if(var[FLAGP][IX(i,j,k)]==INLET) {  
      if(para->outp->version==DEBUG) {
        sprintf(msg, "surface_integrate(): Set 0 for inlet [%d,%d,%d].", 
                i, j, k);
        ffd_log(msg, FFD_NORMAL);
      }
      
      para->bc->TPortAve[bcid] = 0; 
      para->bc->velPortAve[bcid] = 0;
      for(j=0; j<para->bc->nb_Xi; j++)
        para->bc->XiPortAve[bcid][j] = 0;

      for(j=0; j<para->bc->nb_C; j++)
        para->bc->CPortAve[bcid][j] = 0;
    } 
    
  } // End of for(it=0; it<para->geom->index; it++)
  
  return 0;
} // End of surface_integrate()