/*! 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 center = grid.geometry.get_center(cell); if (p == 0) { local_norm = std::max( local_norm, std::fabs( (*cell_data)[Gradient()][dimension] - grad_of_function(center[dimension]) ) ); } else { local_norm += std::pow( std::fabs( (*cell_data)[Gradient()][dimension] - grad_of_function(center[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); } }
/*! Returns maximum norm */ template<class Grid_T> std::array<double, 3> get_max_norm( const std::vector<uint64_t>& cells, const Grid_T& grid ) { std::array<double, 3> local_norm{{0, 0, 0}}, global_norm{{0, 0, 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 center = grid.geometry.get_center(cell); const auto grad_of = grad_of_function(center); for (size_t i = 0; i < 3; i++) { local_norm[i] = std::max( local_norm[i], std::fabs((*cell_data)[Gradient()][i] - grad_of[i]) ); } } MPI_Comm comm = grid.get_communicator(); MPI_Allreduce( local_norm.data(), global_norm.data(), 3, MPI_DOUBLE, MPI_MAX, comm ); MPI_Comm_free(&comm); return global_norm; }