/*! Returns maximum norm if p == 0. */ template<class Grid_T> double get_diff_lp_norm( const std::vector<uint64_t>& cells, const Grid_T& grid, const double p, const double cell_volume, const size_t dimension ) { double local_norm = 0, global_norm = 0; for (const auto& cell: cells) { const auto* const cell_data = grid[cell]; if (cell_data == NULL) { std::cerr << __FILE__ << ":" << __LINE__ << ": No data for cell " << cell << std::endl; abort(); } const auto curl_of = curl_of_function(grid.geometry.get_center(cell)); if (p == 0) { local_norm = std::max( local_norm, std::fabs((*cell_data)[Curl()][dimension] - curl_of[dimension]) ); } else { local_norm += std::pow( std::fabs((*cell_data)[Curl()][dimension] - curl_of[dimension]), p ); } } local_norm *= cell_volume; if (p == 0) { MPI_Comm comm = grid.get_communicator(); MPI_Allreduce(&local_norm, &global_norm, 1, MPI_DOUBLE, MPI_MAX, comm); MPI_Comm_free(&comm); return global_norm; } else { MPI_Comm comm = grid.get_communicator(); MPI_Allreduce(&local_norm, &global_norm, 1, MPI_DOUBLE, MPI_SUM, comm); MPI_Comm_free(&comm); return std::pow(global_norm, 1.0 / p); } }
int physics_run(real t) { // Run communications comms.run(); msg_stack.push("F_rho"); F_rho = -V_dot_Grad(v, rho) - rho*Div(v); msg_stack.pop(); msg_stack.push("F_p"); F_p = -V_dot_Grad(v, p) - gamma*p*Div(v); msg_stack.pop(); msg_stack.push("F_v"); F_v = -V_dot_Grad(v, v) + ((Curl(B)^B) - Grad(p))/rho; if(include_viscos) { F_v.x += viscos * Laplacian(F_v.x); F_v.y += viscos * Laplacian(F_v.y); F_v.z += viscos * Laplacian(F_v.z); } msg_stack.pop(); msg_stack.push("F_B"); F_B = Curl(v^B); // boundary conditions apply_boundary(F_rho, "density"); apply_boundary(F_p, "pressure"); F_v.to_covariant(); apply_boundary(F_v, "v"); F_B.to_contravariant(); apply_boundary(F_B, "B"); msg_stack.pop(); msg_stack.push("DivB"); divB = Div(B); // Just for diagnostic bndry_inner_zero(divB); bndry_sol_zero(divB); return 0; }
tmp<GeometricField<Type, fvPatchField, volMesh> > curl ( const tmp<GeometricField<Type, fvPatchField, volMesh> >& tvf ) { tmp<GeometricField<Type, fvPatchField, volMesh> > Curl(fvc::curl(tvf())); tvf.clear(); return Curl; }
int main(int argc, char* argv[]) { if (MPI_Init(&argc, &argv) != MPI_SUCCESS) { std::cerr << "Couldn't initialize MPI." << std::endl; abort(); } MPI_Comm comm = MPI_COMM_WORLD; int rank = 0, comm_size = 0; if (MPI_Comm_rank(comm, &rank) != MPI_SUCCESS) { std::cerr << "Couldn't obtain MPI rank." << std::endl; abort(); } if (MPI_Comm_size(comm, &comm_size) != MPI_SUCCESS) { std::cerr << "Couldn't obtain size of MPI communicator." << std::endl; abort(); } // intialize Zoltan float zoltan_version; if (Zoltan_Initialize(argc, argv, &zoltan_version) != ZOLTAN_OK) { std::cerr << "Zoltan_Initialize failed." << std::endl; abort(); } const unsigned int neighborhood_size = 0; const int max_refinement_level = 0; double old_norm_x = std::numeric_limits<double>::max(), old_norm_y = std::numeric_limits<double>::max(), old_norm_z = std::numeric_limits<double>::max(); size_t old_nr_of_cells = 0; for (size_t nr_of_cells = 8; nr_of_cells <= 64; nr_of_cells *= 2) { dccrg::Dccrg<Cell, dccrg::Cartesian_Geometry> grid; const std::array<uint64_t, 3> grid_size{{nr_of_cells + 2, nr_of_cells + 2, nr_of_cells + 2}}; if ( not grid.initialize( grid_size, comm, "RANDOM", neighborhood_size, max_refinement_level, false, false, false ) ) { std::cerr << __FILE__ << ":" << __LINE__ << ": Couldn't initialize grid." << std::endl; abort(); } const std::array<double, 3> cell_length{{ double(3) / (grid_size[0] - 2), 1.5 / (grid_size[1] - 2), double(4) / (grid_size[2] - 2) }}, grid_start{{ -1 - cell_length[0], -M_PI / 4 - cell_length[1], -2 - cell_length[2] }}; const double cell_volume = cell_length[0] * cell_length[1] * cell_length[2]; dccrg::Cartesian_Geometry::Parameters geom_params; geom_params.start = grid_start; geom_params.level_0_cell_length = cell_length; if (not grid.set_geometry(geom_params)) { std::cerr << __FILE__ << ":" << __LINE__ << ": Couldn't set grid geometry." << std::endl; abort(); } grid.balance_load(); const auto all_cells = grid.get_cells(); for (const auto& cell: all_cells) { auto* const cell_data = grid[cell]; if (cell_data == NULL) { std::cerr << __FILE__ << ":" << __LINE__ << ": No data for cell " << cell << std::endl; abort(); } (*cell_data)[Vector()] = function(grid.geometry.get_center(cell)); } grid.update_copies_of_remote_neighbors(); std::vector<uint64_t> solve_cells; for (const auto& cell: all_cells) { const auto index = grid.mapping.get_indices(cell); if ( index[0] > 0 and index[0] < grid_size[0] - 1 and index[1] > 0 and index[1] < grid_size[1] - 1 and index[2] > 0 and index[2] < grid_size[2] - 1 ) { solve_cells.push_back(cell); } } pamhd::divergence::get_curl( solve_cells, grid, [](Cell& cell_data) -> Vector::data_type& { return cell_data[Vector()]; }, [](Cell& cell_data) -> Curl::data_type& { return cell_data[Curl()]; } ); const double p_of_norm = 2, norm_x = get_diff_lp_norm(solve_cells, grid, p_of_norm, cell_volume, 0), norm_y = get_diff_lp_norm(solve_cells, grid, p_of_norm, cell_volume, 1), norm_z = get_diff_lp_norm(solve_cells, grid, p_of_norm, cell_volume, 2); if (norm_x > old_norm_x) { if (grid.get_rank() == 0) { std::cerr << __FILE__ << ":" << __LINE__ << ": X norm with " << nr_of_cells << " cells " << norm_x << " is larger than with " << nr_of_cells / 2 << " cells " << old_norm_x << std::endl; } abort(); } if (norm_y > old_norm_y) { if (grid.get_rank() == 0) { std::cerr << __FILE__ << ":" << __LINE__ << ": Y norm with " << nr_of_cells << " cells " << norm_y << " is larger than with " << nr_of_cells / 2 << " cells " << old_norm_y << std::endl; } abort(); } if (norm_z > old_norm_z) { if (grid.get_rank() == 0) { std::cerr << __FILE__ << ":" << __LINE__ << ": Z norm with " << nr_of_cells << " cells " << norm_z << " is larger than with " << nr_of_cells / 2 << " cells " << old_norm_z << std::endl; } abort(); } if (old_nr_of_cells > 0) { const double order_of_accuracy_x = -log(norm_x / old_norm_x) / log(double(nr_of_cells) / old_nr_of_cells), order_of_accuracy_y = -log(norm_y / old_norm_y) / log(double(nr_of_cells) / old_nr_of_cells), order_of_accuracy_z = -log(norm_z / old_norm_z) / log(double(nr_of_cells) / old_nr_of_cells); if (order_of_accuracy_x < 1.95) { if (grid.get_rank() == 0) { std::cerr << __FILE__ << ":" << __LINE__ << ": Order of accuracy from " << old_nr_of_cells << " to " << nr_of_cells << " is too low for x: " << order_of_accuracy_x << std::endl; } abort(); } if (order_of_accuracy_y < 1.95) { if (grid.get_rank() == 0) { std::cerr << __FILE__ << ":" << __LINE__ << ": Order of accuracy from " << old_nr_of_cells << " to " << nr_of_cells << " is too low for y: " << order_of_accuracy_y << std::endl; } abort(); } if (order_of_accuracy_z < 1.95) { if (grid.get_rank() == 0) { std::cerr << __FILE__ << ":" << __LINE__ << ": Order of accuracy from " << old_nr_of_cells << " to " << nr_of_cells << " is too low for z: " << order_of_accuracy_z << std::endl; } abort(); } } old_nr_of_cells = nr_of_cells; old_norm_x = norm_x; old_norm_y = norm_y; old_norm_z = norm_z; } MPI_Finalize(); return EXIT_SUCCESS; }