/* * 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()
/////////////////////////////////////////////////////////////////////////////// /// 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() */
/////////////////////////////////////////////////////////////////////////////// /// 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()
/////////////////////////////////////////////////////////////////////////////// /// 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()
/////////////////////////////////////////////////////////////////////////////// /// 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()
/////////////////////////////////////////////////////////////////////////////// /// 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
/****************************************************************************** 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()
/****************************************************************************** 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( )
/////////////////////////////////////////////////////////////////////////////// /// 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()
/////////////////////////////////////////////////////////////////////////////// /// 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( )
/////////////////////////////////////////////////////////////////////////////// /// 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( )
/////////////////////////////////////////////////////////////////////////////// /// 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( )
/////////////////////////////////////////////////////////////////////////////// /// 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()
/////////////////////////////////////////////////////////////////////////////// /// 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()
/////////////////////////////////////////////////////////////////////////////// /// 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()
/////////////////////////////////////////////////////////////////////////////// /// 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", ¶->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", ¶->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", ¶->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", ¶->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", ¶->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", ¶->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", ¶->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", ¶->prob->rho, ¶->prob->nu, ¶->prob->cond, ¶->prob->gravx, ¶->prob->gravy, ¶->prob->gravz, ¶->prob->beta, &trefmax, ¶->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", ¶->mytime->t_start, ¶->mytime->dt, ¶->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()
/////////////////////////////////////////////////////////////////////////////// /// 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( )
/////////////////////////////////////////////////////////////////////////////// /// 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(¶)!=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(¶, var)!=0) { ffd_log("ffd(): Could not read SCI data.", FFD_ERROR); return 1; } } // Allocate memory for the variables if(allocate_memory(¶)!=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(¶, 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(¶, var); ffd_log("ffd.c: Start FFD solver.", FFD_NORMAL); //write_tecplot_data(¶, var, "initial"); // Solve the problem if(para.outp->version==DEMO) { open_glut_window(); glutMainLoop(); } else if(FFD_solver(¶, 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(¶, var); if(write_unsteady(¶, var, "unsteady")!=0) { ffd_log("FFD_solver(): Could not write the file unsteady.plt.", FFD_ERROR); return 1; } if(write_tecplot_data(¶, 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(¶, var, "result_all"); // Write the data in SCI format write_SCI(¶, 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()
/////////////////////////////////////////////////////////////////////////////// /// 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()