/* SPDX-FileCopyrightText: Copyright (c) 2021 - 2024, the adamantine authors. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #include #include #include #include #include #include #include #include #include #include namespace adamantine { template std::pair, std::vector>> get_dof_to_support_mapping(dealii::DoFHandler const &dof_handler) { std::vector dof_indices; std::vector> support_points; std::unordered_set visited_dof_indices; // Manually do what dealii::DoFTools::map_dofs_to_support_points does, since // that doesn't currently work with FE_Nothing. The issue has been fixed in // deal.II 9.7 const dealii::FiniteElement &fe = dof_handler.get_fe(0); dealii::FEValues fe_values(fe, fe.get_unit_support_points(), dealii::update_quadrature_points); std::vector local_dof_indices( fe.n_dofs_per_cell()); auto locally_owned_dofs = dof_handler.locally_owned_dofs(); for (auto const &cell : dealii::filter_iterators(dof_handler.active_cell_iterators(), dealii::IteratorFilters::ActiveFEIndexEqualTo( 0, /* locally owned */ true))) { fe_values.reinit(cell); cell->get_dof_indices(local_dof_indices); const std::vector> &points = fe_values.get_quadrature_points(); for (unsigned int i = 0; i < fe.n_dofs_per_cell(); ++i) { // Skip duplicate points like vertices and indices that correspond to // ghosted elements if ((visited_dof_indices.count(local_dof_indices[i]) == 0) && (locally_owned_dofs.is_element(local_dof_indices[i]))) { dof_indices.push_back(local_dof_indices[i]); support_points.push_back(points[i]); visited_dof_indices.insert(local_dof_indices[i]); } } } return {dof_indices, support_points}; } template std::pair, std::vector> get_expt_to_dof_mapping(PointsValues const &points_values, dealii::DoFHandler const &dof_handler) { auto [dof_indices, support_points] = get_dof_to_support_mapping(dof_handler); #if DEAL_II_VERSION_GTE(9, 7, 0) auto communicator = dof_handler.get_mpi_communicator(); #else auto communicator = dof_handler.get_communicator(); #endif int my_rank = dealii::Utilities::MPI::this_mpi_process(communicator); // Perform the search dealii::ArborXWrappers::DistributedTree distributed_tree(communicator, support_points); dealii::ArborXWrappers::PointNearestPredicate pt_nearest(points_values.points, 1); auto [indices_ranks, offset] = distributed_tree.query(pt_nearest); // Convert the indices and offsets to a pair that maps experimental indices to // dof indices std::vector obs_indices; std::vector global_indices; obs_indices.resize(indices_ranks.size()); global_indices.resize(indices_ranks.size()); unsigned int const n_queries = points_values.points.size(); for (unsigned int i = 0; i < n_queries; ++i) { for (int j = offset[i]; j < offset[i + 1]; ++j) { obs_indices[j] = i; global_indices[j] = indices_ranks[j].second == my_rank ? dof_indices[indices_ranks[j].first] : -1; } } dealii::Utilities::MPI::max(global_indices, communicator, global_indices); return std::make_pair(obs_indices, global_indices); } template void set_with_experimental_data( MPI_Comm const &communicator, PointsValues const &points_values, std::pair, std::vector> &expt_to_dof_mapping, dealii::LinearAlgebra::distributed::Vector &temperature, bool verbose_output) { unsigned int rank = dealii::Utilities::MPI::this_mpi_process(communicator); if ((rank == 0) && verbose_output) { std::cout << "Number of unique experimental points is " << std::set(expt_to_dof_mapping.second.begin(), expt_to_dof_mapping.second.end()) .size() << std::endl; } auto locally_owned_dofs = temperature.locally_owned_elements(); for (unsigned int i = 0; i < points_values.values.size(); ++i) { // Only add locally owned elements if (locally_owned_dofs.is_element(expt_to_dof_mapping.second[i])) temperature[expt_to_dof_mapping.second[i]] = points_values.values[i]; } temperature.compress(dealii::VectorOperation::insert); } std::vector> read_frame_timestamps(boost::property_tree::ptree const &experiment_database) { // PropertyTreeInput experiment.log_filename std::string log_filename = experiment_database.get("log_filename"); wait_for_file(log_filename, "Waiting for frame time stamps: " + log_filename); // PropertyTreeInput experiment.first_frame_temporal_offset double first_frame_offset = experiment_database.get("first_frame_temporal_offset", 0.0); // PropertyTreeInput experiment.first_frame unsigned int first_frame = experiment_database.get("first_frame", 0); // PropertyTreeInput experiment.last_frame unsigned int last_frame = experiment_database.get("last_frame"); // PropertyTreeInput experiment.first_camera_id unsigned int first_camera_id = experiment_database.get("first_camera_id"); // PropertyTreeInput experiment.last_camera_id unsigned int last_camera_id = experiment_database.get("last_camera_id"); unsigned int num_cameras = last_camera_id - first_camera_id + 1; std::vector> time_stamps(num_cameras); // Read and parse the file std::ifstream file; file.open(log_filename); std::string line; while (std::getline(file, line)) { unsigned int entry_index = 0; std::stringstream s_stream(line); bool frame_of_interest = false; unsigned int frame = std::numeric_limits::max(); while (s_stream.good()) { std::string substring; std::getline(s_stream, substring, ','); boost::trim(substring); if (entry_index == 0) { std::string error_message = "The file " + log_filename + " does not have consecutive frame indices."; ASSERT_THROW(std::stoi(substring) - frame == 1 || frame == std::numeric_limits::max(), error_message.c_str()); frame = std::stoi(substring); if (frame >= first_frame && frame <= last_frame) frame_of_interest = true; } else { if (frame_of_interest && substring.size() > 0) time_stamps[entry_index - 1].push_back(std::stod(substring) + first_frame_offset); } entry_index++; } } return time_stamps; } } // namespace adamantine //-------------------- Explicit Instantiations --------------------// namespace adamantine { template void set_with_experimental_data( MPI_Comm const &communicator, PointsValues<2> const &points_values, std::pair, std::vector> &expt_to_dof_mapping, dealii::LinearAlgebra::distributed::Vector &temperature, bool verbose_output); template void set_with_experimental_data( MPI_Comm const &communicator, PointsValues<3> const &points_values, std::pair, std::vector> &expt_to_dof_mapping, dealii::LinearAlgebra::distributed::Vector &temperature, bool verbose_output); template std::pair, std::vector> get_expt_to_dof_mapping(PointsValues<2> const &points_values, dealii::DoFHandler<2> const &dof_handler); template std::pair, std::vector> get_expt_to_dof_mapping(PointsValues<3> const &points_values, dealii::DoFHandler<3> const &dof_handler); template std::pair, std::vector>> get_dof_to_support_mapping(dealii::DoFHandler<2> const &dof_handler); template std::pair, std::vector>> get_dof_to_support_mapping(dealii::DoFHandler<3> const &dof_handler); } // namespace adamantine