void advance (MultiFab& old_phi, MultiFab& new_phi, PArray<MultiFab>& flux, Real time, Real dt, const Geometry& geom, PhysBCFunct& physbcf, BCRec& bcr) { // Fill the ghost cells of each grid from the other grids // includes periodic domain boundaries old_phi.FillBoundary(geom.periodicity()); // Fill physical boundaries physbcf.FillBoundary(old_phi, time); int Ncomp = old_phi.nComp(); int ng_p = old_phi.nGrow(); int ng_f = flux[0].nGrow(); const Real* dx = geom.CellSize(); // // Note that this simple example is not optimized. // The following two MFIter loops could be merged // and we do not have to use flux MultiFab. // // Compute fluxes one grid at a time for ( MFIter mfi(old_phi); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); compute_flux(old_phi[mfi].dataPtr(), &ng_p, flux[0][mfi].dataPtr(), flux[1][mfi].dataPtr(), #if (BL_SPACEDIM == 3) flux[2][mfi].dataPtr(), #endif &ng_f, bx.loVect(), bx.hiVect(), (geom.Domain()).loVect(), (geom.Domain()).hiVect(), bcr.vect(), &dx[0]); } // Advance the solution one grid at a time for ( MFIter mfi(old_phi); mfi.isValid(); ++mfi ) { const Box& bx = mfi.validbox(); update_phi(old_phi[mfi].dataPtr(), new_phi[mfi].dataPtr(), &ng_p, flux[0][mfi].dataPtr(), flux[1][mfi].dataPtr(), #if (BL_SPACEDIM == 3) flux[2][mfi].dataPtr(), #endif &ng_f, bx.loVect(), bx.hiVect(), &dx[0] , &dt); } }
/* * Main function */ int main(int argc, char** argv) { if (argc < 2) { std::cout << "specify data file name" << std::endl; return 0; } const char* data_file_name = argv[1]; const unsigned long long full_program_start = current_time_ns(); { // set far field conditions { const double angle_of_attack = double(3.1415926535897931 / 180.0) * double(deg_angle_of_attack); ff_variable[VAR_DENSITY] = double(1.4); double ff_pressure = double(1.0); double ff_speed_of_sound = sqrt(GAMMA*ff_pressure / ff_variable[VAR_DENSITY]); double ff_speed = double(ff_mach)*ff_speed_of_sound; cfd_double3 ff_velocity; ff_velocity.x = ff_speed*double(cos((double)angle_of_attack)); ff_velocity.y = ff_speed*double(sin((double)angle_of_attack)); ff_velocity.z = 0.0; ff_variable[VAR_MOMENTUM+0] = ff_variable[VAR_DENSITY] * ff_velocity.x; ff_variable[VAR_MOMENTUM+1] = ff_variable[VAR_DENSITY] * ff_velocity.y; ff_variable[VAR_MOMENTUM+2] = ff_variable[VAR_DENSITY] * ff_velocity.z; ff_variable[VAR_DENSITY_ENERGY] = ff_variable[VAR_DENSITY]*(double(0.5)*(ff_speed*ff_speed)) + (ff_pressure / double(GAMMA-1.0)); cfd_double3 ff_momentum; ff_momentum.x = *(ff_variable+VAR_MOMENTUM+0); ff_momentum.y = *(ff_variable+VAR_MOMENTUM+1); ff_momentum.z = *(ff_variable+VAR_MOMENTUM+2); compute_flux_contribution(ff_variable[VAR_DENSITY], ff_momentum, ff_variable[VAR_DENSITY_ENERGY], ff_pressure, ff_velocity, ff_flux_contribution_momentum_x, ff_flux_contribution_momentum_y, ff_flux_contribution_momentum_z, ff_flux_contribution_density_energy); } int nel; int nelr; // read in domain geometry double* areas; int* elements_surrounding_elements; double* normals; { std::ifstream file(data_file_name); file >> nel; nelr = block_length*((nel / block_length )+ std::min(1, nel % block_length)); areas = new double[nelr]; elements_surrounding_elements = new int[nelr*NNB]; normals = new double[NDIM*NNB*nelr]; // read in data for(int i = 0; i < nel; i++) { file >> areas[i]; for(int j = 0; j < NNB; j++) { file >> elements_surrounding_elements[i*NNB + j]; if(elements_surrounding_elements[i*NNB+j] < 0) elements_surrounding_elements[i*NNB+j] = -1; elements_surrounding_elements[i*NNB + j]--; //it's coming in with Fortran numbering for(int k = 0; k < NDIM; k++) { file >> normals[(i*NNB + j)*NDIM + k]; normals[(i*NNB + j)*NDIM + k] = -normals[(i*NNB + j)*NDIM + k]; } } } // fill in remaining data int last = nel-1; for(int i = nel; i < nelr; i++) { areas[i] = areas[last]; for(int j = 0; j < NNB; j++) { // duplicate the last element elements_surrounding_elements[i*NNB + j] = elements_surrounding_elements[last*NNB + j]; for(int k = 0; k < NDIM; k++) normals[(i*NNB + j)*NDIM + k] = normals[(last*NNB + j)*NDIM + k]; } } } // Create arrays and set initial conditions double* variables = alloc<double>(nelr*NVAR); initialize_variables(nelr, variables); double* old_variables = alloc<double>(nelr*NVAR); double* fluxes = alloc<double>(nelr*NVAR); double* step_factors = alloc<double>(nelr); // these need to be computed the first time in order to compute time step std::cout << "Starting..." << std::endl; // Begin iterations for(int i = 0; i < iterations; i++) { copy(old_variables, variables, nelr*NVAR); // for the first iteration we compute the time step compute_step_factor(nelr, variables, areas, step_factors); for(int j = 0; j < RK; j++) { compute_flux(nelr, elements_surrounding_elements, normals, variables, fluxes); time_step(j, nelr, old_variables, variables, step_factors, fluxes); } } std::cout << "Saving solution..." << std::endl; dump(variables, nel, nelr); std::cout << "Saved solution..." << std::endl; std::cout << "Cleaning up..." << std::endl; dealloc<double>(areas); dealloc<int>(elements_surrounding_elements); dealloc<double>(normals); dealloc<double>(variables); dealloc<double>(old_variables); dealloc<double>(fluxes); dealloc<double>(step_factors); } ; const unsigned long long full_program_end = current_time_ns(); printf("full_program %llu ns\n", full_program_end - full_program_start); std::cout << "Done..." << std::endl; return 0; }