#ifndef GRIDS_H #define GRIDS_H #include "nufi/cells.h" #include "nufi/parameters.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace dealii; template class PoissonProblem; template struct GridStructure { std::unique_ptr> triangulation; std::unique_ptr> dof_handler; std::unique_ptr> mapping; std::unique_ptr> fe; std::unique_ptr> locator; unsigned int grid_version = 0; std::vector eval_vector_grad(const Vector &solution, const std::vector> &points) const { const unsigned int n_points = points.size(); std::vector values(n_points); std::vector> locations(n_points); for (unsigned int p = 0; p < n_points; ++p) locations[p] = locator->locate(points[p]); std::unordered_map> cell_to_indices; for (unsigned int p = 0; p < n_points; ++p) cell_to_indices[locations[p].cell->active_cell_index()].push_back(p); std::vector::active_cell_iterator> cells; std::vector> groups; cells.reserve(cell_to_indices.size()); groups.reserve(cell_to_indices.size()); for (auto &kv : cell_to_indices) { groups.push_back(std::move(kv.second)); cells.push_back(locations[groups.back().front()].cell); } #pragma omp parallel { std::vector local_solution_buffer(fe->n_dofs_per_cell()); FEPointEvaluation evaluator(*mapping, *fe, update_gradients); #pragma omp for for (long c = 0; c < static_cast(cells.size()); ++c) { const auto &cell = cells[c]; const auto &idxs = groups[c]; std::vector> unit_points(idxs.size()); for (size_t k = 0; k < idxs.size(); ++k) unit_points[k] = locations[idxs[k]].reference_point; cell->get_dof_values(solution, local_solution_buffer.begin(), local_solution_buffer.end()); evaluator.reinit(cell, ArrayView>(unit_points)); evaluator.evaluate(local_solution_buffer, EvaluationFlags::gradients); for (size_t k = 0; k < idxs.size(); ++k) values[idxs[k]] = evaluator.get_gradient(k)[0]; } } return values; } }; template GridStructure make_grid_snapshot(PoissonProblem &poisson) { GridStructure grid; grid.grid_version = 0; grid.triangulation = std::make_unique>(); grid.triangulation->copy_triangulation(poisson.get_triangulation()); grid.fe = std::make_unique>(poisson.get_fe()); grid.dof_handler = std::make_unique>(*grid.triangulation); grid.dof_handler->distribute_dofs(*grid.fe); grid.mapping = std::make_unique>(poisson.get_mapping()); grid.locator = std::make_unique>(); grid.locator->rebuild(*grid.dof_handler, *grid.triangulation); return grid; } template struct SolutionSnapshot { unsigned int grid_version; Vector solution; }; template inline void update_grid_versions(std::vector> &grid_versions, PoissonProblem &poisson) { auto grid = make_grid_snapshot(poisson); if (!grid_versions.empty()) grid.grid_version = grid_versions.back().grid_version + 1; grid_versions.push_back(std::move(grid)); std::cout << "@ update_grid_history: " << "grid version " << grid.grid_version << " size " << poisson.get_solution().size() << "\n"; } template inline void update_solution_history(std::vector> &solution_history, PoissonProblem &poisson, unsigned int current_grid_version) { SolutionSnapshot snapshot; snapshot.grid_version = current_grid_version; // where I might need to change something to pass the correct solution or in // the correct form Vector solution = poisson.get_solution(); snapshot.solution = solution; std::cout << "@ update_solution_history: " << "grid version " << current_grid_version << " size " << poisson.get_solution().size() << "\n"; solution_history.push_back(std::move(snapshot)); } #endif // !GRIDS_H