void InitSim(char const *fileName) { std::cout << "Loading file \"" << fileName << "\"..." << std::endl; std::ifstream file(fileName, std::ios::binary); if(!file) { std::cerr << "Error opening file. Aborting." << std::endl; exit(1); } //Always use single precision float variables b/c file format uses single precision float restParticlesPerMeter_le; int numParticles_le; file.read((char *)&restParticlesPerMeter_le, FILE_SIZE_FLOAT); file.read((char *)&numParticles_le, FILE_SIZE_INT); if(!isLittleEndian()) { restParticlesPerMeter = bswap_float(restParticlesPerMeter_le); numParticles = bswap_int32(numParticles_le); } else { restParticlesPerMeter = restParticlesPerMeter_le; numParticles = numParticles_le; } cellpool_init(&pool, numParticles); h = kernelRadiusMultiplier / restParticlesPerMeter; hSq = h*h; #ifndef ENABLE_DOUBLE_PRECISION fptype coeff1 = 315.0 / (64.0*pi*powf(h,9.0)); fptype coeff2 = 15.0 / (pi*powf(h,6.0)); fptype coeff3 = 45.0 / (pi*powf(h,6.0)); #else fptype coeff1 = 315.0 / (64.0*pi*pow(h,9.0)); fptype coeff2 = 15.0 / (pi*pow(h,6.0)); fptype coeff3 = 45.0 / (pi*pow(h,6.0)); #endif //ENABLE_DOUBLE_PRECISION fptype particleMass = 0.5*doubleRestDensity / (restParticlesPerMeter*restParticlesPerMeter*restParticlesPerMeter); densityCoeff = particleMass * coeff1; pressureCoeff = 3.0*coeff2 * 0.50*stiffnessPressure * particleMass; viscosityCoeff = viscosity * coeff3 * particleMass; Vec3 range = domainMax - domainMin; nx = (int)(range.x / h); ny = (int)(range.y / h); nz = (int)(range.z / h); assert(nx >= 1 && ny >= 1 && nz >= 1); numCells = nx*ny*nz; std::cout << "Number of cells: " << numCells << std::endl; delta.x = range.x / nx; delta.y = range.y / ny; delta.z = range.z / nz; assert(delta.x >= h && delta.y >= h && delta.z >= h); //make sure Cell structure is multiple of estiamted cache line size assert(sizeof(Cell) % CACHELINE_SIZE == 0); //make sure helper Cell structure is in sync with real Cell structure #pragma warning( disable : 1684) // warning #1684: conversion from pointer to same-sized integral type (potential portability problem) assert(offsetof(struct Cell_aux, padding) == offsetof(struct Cell, padding)); #if defined(WIN32) cells = (struct Cell*)_aligned_malloc(sizeof(struct Cell) * numCells, CACHELINE_SIZE); cells2 = (struct Cell*)_aligned_malloc(sizeof(struct Cell) * numCells, CACHELINE_SIZE); cnumPars = (int*)_aligned_malloc(sizeof(int) * numCells, CACHELINE_SIZE); cnumPars2 = (int*)_aligned_malloc(sizeof(int) * numCells, CACHELINE_SIZE); last_cells = (struct Cell **)_aligned_malloc(sizeof(struct Cell *) * numCells, CACHELINE_SIZE); assert((cells!=NULL) && (cells2!=NULL) && (cnumPars!=NULL) && (cnumPars2!=NULL) && (last_cells!=NULL)); #else int rv0 = posix_memalign((void **)(&cells), CACHELINE_SIZE, sizeof(struct Cell) * numCells); int rv1 = posix_memalign((void **)(&cells2), CACHELINE_SIZE, sizeof(struct Cell) * numCells); int rv2 = posix_memalign((void **)(&cnumPars), CACHELINE_SIZE, sizeof(int) * numCells); int rv3 = posix_memalign((void **)(&cnumPars2), CACHELINE_SIZE, sizeof(int) * numCells); int rv4 = posix_memalign((void **)(&last_cells), CACHELINE_SIZE, sizeof(struct Cell *) * numCells); assert((rv0==0) && (rv1==0) && (rv2==0) && (rv3==0) && (rv4==0)); #endif // because cells and cells2 are not allocated via new // we construct them here for(int i=0; i<numCells; ++i) { new (&cells[i]) Cell; new (&cells2[i]) Cell; } memset(cnumPars, 0, numCells*sizeof(int)); //Always use single precision float variables b/c file format uses single precision float px, py, pz, hvx, hvy, hvz, vx, vy, vz; for(int i = 0; i < numParticles; ++i) { file.read((char *)&px, FILE_SIZE_FLOAT); file.read((char *)&py, FILE_SIZE_FLOAT); file.read((char *)&pz, FILE_SIZE_FLOAT); file.read((char *)&hvx, FILE_SIZE_FLOAT); file.read((char *)&hvy, FILE_SIZE_FLOAT); file.read((char *)&hvz, FILE_SIZE_FLOAT); file.read((char *)&vx, FILE_SIZE_FLOAT); file.read((char *)&vy, FILE_SIZE_FLOAT); file.read((char *)&vz, FILE_SIZE_FLOAT); if(!isLittleEndian()) { px = bswap_float(px); py = bswap_float(py); pz = bswap_float(pz); hvx = bswap_float(hvx); hvy = bswap_float(hvy); hvz = bswap_float(hvz); vx = bswap_float(vx); vy = bswap_float(vy); vz = bswap_float(vz); } int ci = (int)(((fptype)px - domainMin.x) / delta.x); int cj = (int)(((fptype)py - domainMin.y) / delta.y); int ck = (int)(((fptype)pz - domainMin.z) / delta.z); if(ci < 0) ci = 0; else if(ci >= nx) ci = nx-1; if(cj < 0) cj = 0; else if(cj >= ny) cj = ny-1; if(ck < 0) ck = 0; else if(ck >= nz) ck = nz-1; int index = (ck*ny + cj)*nx + ci; Cell *cell = &cells[index]; //go to last cell structure in list int np = cnumPars[index]; while(np > PARTICLES_PER_CELL) { cell = cell->next; np = np - PARTICLES_PER_CELL; } //add another cell structure if everything full if( (np % PARTICLES_PER_CELL == 0) && (cnumPars[index] != 0) ) { cell->next = cellpool_getcell(&pool); cell = cell->next; np = np - PARTICLES_PER_CELL; // np = 0; } //add particle to cell cell->p[np].x = px; cell->p[np].y = py; cell->p[np].z = pz; cell->hv[np].x = hvx; cell->hv[np].y = hvy; cell->hv[np].z = hvz; cell->v[np].x = vx; cell->v[np].y = vy; cell->v[np].z = vz; #ifdef ENABLE_VISUALIZATION vMin.x = std::min(vMin.x, cell->v[np].x); vMax.x = std::max(vMax.x, cell->v[np].x); vMin.y = std::min(vMin.y, cell->v[np].y); vMax.y = std::max(vMax.y, cell->v[np].y); vMin.z = std::min(vMin.z, cell->v[np].z); vMax.z = std::max(vMax.z, cell->v[np].z); #endif ++cnumPars[index]; } std::cout << "Number of particles: " << numParticles << std::endl; }
extern void import_cnfg_ildg(char *in) { int my_rank,np[4],n,ie,tag,status,prec=0; int i,l,ix,iy,iz,it,ixx; n_uint64_t read_bytes,nbytes=0; double plaq1,eps; MPI_Status stat; LimeReader *reader=NULL; FILE *fin; char lime_type_target[100]="ildg-binary-data"; char *lime_type; MPI_Comm_rank(MPI_COMM_WORLD,&my_rank); /* allocate IO-buffers */ if (ubuf==NULL) alloc_ubuf_ildg(my_rank); error(pud[VOLUME/2][0]==NULL,1,"import_cnfg [archive_ildg.c]", "Double-precision gauge field is not allocated"); ie=check_machine(); if (my_rank==0) { fin=fopen(in,"rb"); error_root(fin==NULL,1,"import_cnfg [archive_ildg.c]", "Unable to open input file"); reader=limeCreateReader(fin); error( reader == (LimeReader *)NULL ,1,"import_cnfg [archive_ildg.c]", "Unable to open LimeReader"); nbytes = (n_uint64_t)0; /* set the file-pointer to the beginning of the "ildg-binary-data" tag * in the LIME file */ while( (status = limeReaderNextRecord(reader)) != LIME_EOF ){ nbytes = limeReaderBytes(reader); lime_type = limeReaderType(reader); error((status!=LIME_SUCCESS),1,"import_cnfg [archive_ildg.c]", "limeReaderNextRecord returned status %d and LIME_SUCCESS %d\n", status,LIME_SUCCESS); if (strcmp(lime_type,lime_type_target) != 0) continue; break; } /* Decide whether the gauge file is stored in single or * double precision format */ if ((int)nbytes==8*VOLUME*NPROC*3*3*4*2){ prec=8; message("ILDG-file contains double precision gauge field\n"); } else if ((int)nbytes==4*VOLUME*NPROC*3*3*4*2){ prec=4; message("ILDG-file contains single precision gauge field\n"); } else error(1!=0,1,"import_cnfg [archive_ildg]", "Lattice geometry doesn't match size of gauge field %d %d\n"); } /* Now read the gauge file in steps of 4 SU(3) matrices */ for (it=0;it<N0;it++){ for (iz=0;iz<N3;iz++){ for (iy=0;iy<N2;iy++){ for (ix=0;ix<N1;ix++){ if(my_rank==0){ if(prec==8){ read_bytes = (n_uint64_t)(4*18*sizeof(double)); status = limeReaderReadData((double *)vbuf,&read_bytes, reader); bswap_double(4*18,(double *)(vbuf));/* ILDG always big endian */ } else if(prec==4){ read_bytes = (n_uint64_t)(4*18*sizeof(float)); status = limeReaderReadData((void *)vbuf_s,&read_bytes, reader); bswap_float(4*18,(float *)(vbuf_s)); /* ILDG always big endian */ for (i=0;i<4;i++) su3_copy_singletodouble((vbuf_s+i),(vbuf+i)); } } np[0]=it; np[1]=ix; np[2]=iy; np[3]=iz; n=ipr_global(np); MPI_Barrier(MPI_COMM_WORLD); if (n>0) { tag=mpi_tag(); if (my_rank==0) MPI_Send((double*)(vbuf),4*18,MPI_DOUBLE,n,tag, MPI_COMM_WORLD); if (my_rank==n) MPI_Recv((double*)(ubuf),4*18,MPI_DOUBLE,0,tag, MPI_COMM_WORLD,&stat); } else if (my_rank==0) for (l=0;l<(4);l++) ubuf[l]=vbuf[l]; ixx = ((iy%L2)*L3 + (ix%L1)*L3*L2 + (it%L0)*L1*L2*L3); if (my_rank==n) set_links_ildg(ixx,iz); } } } } plaq1=plaq_sum_dble()/(double)(6*NPROC*VOLUME); message("Plaquette %f\n",plaq1); message("Plaquette/3 %f\n",plaq1/3); message("Please check consistency of average plaquette by hand\n"); eps=sqrt((double)(6*NPROC*VOLUME))*DBL_EPSILON; }
void SaveFile(char const *fileName) { std::cout << "Saving file \"" << fileName << "\"..." << std::endl; std::ofstream file(fileName, std::ios::binary); assert(file); //Always use single precision float variables b/c file format uses single precision if(!isLittleEndian()) { float restParticlesPerMeter_le; int numParticles_le; restParticlesPerMeter_le = bswap_float((float)restParticlesPerMeter); numParticles_le = bswap_int32(numParticles); file.write((char *)&restParticlesPerMeter_le, FILE_SIZE_FLOAT); file.write((char *)&numParticles_le, FILE_SIZE_INT); } else { file.write((char *)&restParticlesPerMeter, FILE_SIZE_FLOAT); file.write((char *)&numParticles, FILE_SIZE_INT); } int count = 0; for(int i = 0; i < numCells; ++i) { Cell *cell = &cells[i]; int np = cnumPars[i]; for(int j = 0; j < np; ++j) { //Always use single precision float variables b/c file format uses single precision float px, py, pz, hvx, hvy, hvz, vx,vy, vz; if(!isLittleEndian()) { px = bswap_float((float)(cell->p[j % PARTICLES_PER_CELL].x)); py = bswap_float((float)(cell->p[j % PARTICLES_PER_CELL].y)); pz = bswap_float((float)(cell->p[j % PARTICLES_PER_CELL].z)); hvx = bswap_float((float)(cell->hv[j % PARTICLES_PER_CELL].x)); hvy = bswap_float((float)(cell->hv[j % PARTICLES_PER_CELL].y)); hvz = bswap_float((float)(cell->hv[j % PARTICLES_PER_CELL].z)); vx = bswap_float((float)(cell->v[j % PARTICLES_PER_CELL].x)); vy = bswap_float((float)(cell->v[j % PARTICLES_PER_CELL].y)); vz = bswap_float((float)(cell->v[j % PARTICLES_PER_CELL].z)); } else { px = (float)(cell->p[j % PARTICLES_PER_CELL].x); py = (float)(cell->p[j % PARTICLES_PER_CELL].y); pz = (float)(cell->p[j % PARTICLES_PER_CELL].z); hvx = (float)(cell->hv[j % PARTICLES_PER_CELL].x); hvy = (float)(cell->hv[j % PARTICLES_PER_CELL].y); hvz = (float)(cell->hv[j % PARTICLES_PER_CELL].z); vx = (float)(cell->v[j % PARTICLES_PER_CELL].x); vy = (float)(cell->v[j % PARTICLES_PER_CELL].y); vz = (float)(cell->v[j % PARTICLES_PER_CELL].z); } file.write((char *)&px, FILE_SIZE_FLOAT); file.write((char *)&py, FILE_SIZE_FLOAT); file.write((char *)&pz, FILE_SIZE_FLOAT); file.write((char *)&hvx, FILE_SIZE_FLOAT); file.write((char *)&hvy, FILE_SIZE_FLOAT); file.write((char *)&hvz, FILE_SIZE_FLOAT); file.write((char *)&vx, FILE_SIZE_FLOAT); file.write((char *)&vy, FILE_SIZE_FLOAT); file.write((char *)&vz, FILE_SIZE_FLOAT); ++count; //move pointer to next cell in list if end of array is reached if(j % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) { cell = cell->next; } } } assert(count == numParticles); }
void ReadFile(char const *fileName, fluid_t *f) { assert(fileName); assert(f); std::ifstream file(fileName, std::ios::binary); if(!file) { std::cerr << "Error opening file. Aborting." << std::endl; exit(1); } //Always use single precision float variables b/c file format uses single precision float restParticlesPerMeter_le; int numParticles_le; file.read((char *)&restParticlesPerMeter_le, FILE_SIZE_FLOAT); file.read((char *)&numParticles_le, FILE_SIZE_INT); if(!isLittleEndian()) { f->restParticlesPerMeter = bswap_float(restParticlesPerMeter_le); f->numParticles = bswap_int32(numParticles_le); } else { f->restParticlesPerMeter = restParticlesPerMeter_le; f->numParticles = numParticles_le; } #if defined(SPARC_SOLARIS) f->bbox.min.x = MAXFLOAT; f->bbox.min.y = MAXFLOAT; f->bbox.min.z = MAXFLOAT; f->bbox.max.x = -MAXFLOAT; f->bbox.max.y = -MAXFLOAT; f->bbox.max.z = -MAXFLOAT; #else f->bbox.min.x = INFINITY; f->bbox.min.y = INFINITY; f->bbox.min.z = INFINITY; f->bbox.max.x = -INFINITY; f->bbox.max.y = -INFINITY; f->bbox.max.z = -INFINITY; #endif malloc_fluid(f, f->numParticles); //Always use single precision float variables b/c file format uses single precision float px, py, pz, hvx, hvy, hvz, vx, vy, vz; for(int i = 0; i < f->numParticles; ++i) { file.read((char *)&px, FILE_SIZE_FLOAT); file.read((char *)&py, FILE_SIZE_FLOAT); file.read((char *)&pz, FILE_SIZE_FLOAT); file.read((char *)&hvx, FILE_SIZE_FLOAT); file.read((char *)&hvy, FILE_SIZE_FLOAT); file.read((char *)&hvz, FILE_SIZE_FLOAT); file.read((char *)&vx, FILE_SIZE_FLOAT); file.read((char *)&vy, FILE_SIZE_FLOAT); file.read((char *)&vz, FILE_SIZE_FLOAT); if(!isLittleEndian()) { px = bswap_float(px); py = bswap_float(py); pz = bswap_float(pz); hvx = bswap_float(hvx); hvy = bswap_float(hvy); hvz = bswap_float(hvz); vx = bswap_float(vx); vy = bswap_float(vy); vz = bswap_float(vz); } //add particle to fluid structure f->p[i].x = px; f->p[i].y = py; f->p[i].z = pz; f->hv[i].x = hvx; f->hv[i].y = hvy; f->hv[i].z = hvz; f->v[i].x = vx; f->v[i].y = vy; f->v[i].z = vz; //update bounding box if(px < f->bbox.min.x) f->bbox.min.x = px; if(py < f->bbox.min.y) f->bbox.min.y = py; if(pz < f->bbox.min.z) f->bbox.min.z = pz; if(px > f->bbox.max.x) f->bbox.max.x = px; if(py > f->bbox.max.y) f->bbox.max.y = py; if(pz > f->bbox.max.z) f->bbox.max.z = pz; } }