From 0e5c9184df34048c94e2d329ceb2aba27c7ac155 Mon Sep 17 00:00:00 2001 From: Christoph Lehmann <christoph.lehmann@ufz.de> Date: Tue, 23 Apr 2024 12:20:08 +0200 Subject: [PATCH] [PL] Added generic cell average output functionalty --- ProcessLib/Output/CellAverageData.cpp | 59 ++++++++++++++++++ ProcessLib/Output/CellAverageData.h | 87 +++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 ProcessLib/Output/CellAverageData.cpp create mode 100644 ProcessLib/Output/CellAverageData.h diff --git a/ProcessLib/Output/CellAverageData.cpp b/ProcessLib/Output/CellAverageData.cpp new file mode 100644 index 00000000000..1e46fa1a4cf --- /dev/null +++ b/ProcessLib/Output/CellAverageData.cpp @@ -0,0 +1,59 @@ +/** + * \file + * \copyright + * Copyright (c) 2012-2024, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#include "CellAverageData.h" + +#include "MeshLib/Utils/getOrCreateMeshProperty.h" + +namespace ProcessLib +{ +MeshLib::PropertyVector<double>& CellAverageData::getOrCreatePropertyVector( + std::string const& name, unsigned const num_comp) +{ + if (auto const it = cell_averages_.find(name); it != cell_averages_.end()) + { + auto& prop_vec = *it->second; + auto const num_comp_mesh = prop_vec.getNumberOfGlobalComponents(); + if (num_comp_mesh == static_cast<int>(num_comp)) + { + return prop_vec; + } + + OGS_FATAL( + "The requested property '{}' has {} components, but the one " + "present in the mesh has {} components.", + name, num_comp, num_comp_mesh); + } + + auto const name_in_mesh = name + "_avg"; + auto [it, emplaced] = cell_averages_.emplace( + name, MeshLib::getOrCreateMeshProperty<double>( + const_cast<MeshLib::Mesh&>(mesh_), name_in_mesh, + MeshLib::MeshItemType::Cell, num_comp)); + + if (!it->second) + { + OGS_FATAL("The cell property '{}' could not be added to the mesh.", + name_in_mesh); + } + + if (!emplaced) + { + OGS_FATAL( + "Internal logic error. Something very bad happened. The cell " + "property '{}' was not added to the list of cell averages to " + "compute. There is some very strange inconsistency in the " + "code. Trouble ahead!", + name_in_mesh); + } + + return *it->second; +} +} // namespace ProcessLib diff --git a/ProcessLib/Output/CellAverageData.h b/ProcessLib/Output/CellAverageData.h new file mode 100644 index 00000000000..3f8be132048 --- /dev/null +++ b/ProcessLib/Output/CellAverageData.h @@ -0,0 +1,87 @@ +/** + * \file + * \copyright + * Copyright (c) 2012-2024, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include "MeshLib/Mesh.h" +#include "MeshLib/PropertyVector.h" +#include "ProcessLib/Reflection/ReflectionIPData.h" + +namespace ProcessLib +{ +struct CellAverageData +{ + explicit CellAverageData(MeshLib::Mesh& mesh) : mesh_{mesh} {} + + template <typename LAIntf> + void computeSecondaryVariable( + int const dim, + std::vector<std::unique_ptr<LAIntf>> const& local_assemblers) + { + auto const callback = + [this, &local_assemblers](std::string const& name, + unsigned const num_comp, + auto&& flattened_ip_data_accessor) + { + computeCellAverages(name, num_comp, flattened_ip_data_accessor, + local_assemblers); + }; + + if (dim == 2) + { + ProcessLib::Reflection:: + forEachReflectedFlattenedIPDataAccessor<2, LAIntf>( + LAIntf::getReflectionDataForOutput(), callback); + } + else if (dim == 3) + { + ProcessLib::Reflection:: + forEachReflectedFlattenedIPDataAccessor<3, LAIntf>( + LAIntf::getReflectionDataForOutput(), callback); + } + else + { + OGS_FATAL( + "Generic averaged output is only implemented for dimensions 2 " + "and 3 ATM. You requested dim = {}.", + dim); + } + } + +private: + MeshLib::PropertyVector<double>& getOrCreatePropertyVector( + std::string const& name, unsigned const num_comp); + + void computeCellAverages(std::string const& name, + unsigned const num_comp, + auto&& flattened_ip_data_accessor, + auto const& local_assemblers) + { + auto& prop_vec = getOrCreatePropertyVector(name, num_comp); + + for (std::size_t i = 0; i < local_assemblers.size(); ++i) + { + auto const& loc_asm = *local_assemblers[i]; + auto const& ip_data = flattened_ip_data_accessor(loc_asm); + assert(ip_data.size() % num_comp == 0); + auto const num_ips = + static_cast<Eigen::Index>(ip_data.size() / num_comp); + Eigen::Map<const Eigen::MatrixXd> ip_data_mapped{ip_data.data(), + num_comp, num_ips}; + + Eigen::Map<Eigen::VectorXd>{&prop_vec[i * num_comp], num_comp} = + ip_data_mapped.rowwise().mean(); + } + } + + MeshLib::Mesh const& mesh_; + std::map<std::string, MeshLib::PropertyVector<double>*> cell_averages_; +}; +} // namespace ProcessLib -- GitLab