From 19a7a20ef73afba1641f087acaab3e9760634790 Mon Sep 17 00:00:00 2001 From: Thomas Fischer <thomas.fischer@ufz.de> Date: Wed, 21 Sep 2016 12:59:10 +0200 Subject: [PATCH] [PL] Impl. of CalculateSurfaceFluxLocalAssembler. --- .../CalculateSurfaceFluxLocalAssembler.h | 153 ++++++++++++++++++ .../MapBulkElementPoint.h | 4 +- 2 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 ProcessLib/CalculateSurfaceFlux/CalculateSurfaceFluxLocalAssembler.h diff --git a/ProcessLib/CalculateSurfaceFlux/CalculateSurfaceFluxLocalAssembler.h b/ProcessLib/CalculateSurfaceFlux/CalculateSurfaceFluxLocalAssembler.h new file mode 100644 index 00000000000..da0774e095f --- /dev/null +++ b/ProcessLib/CalculateSurfaceFlux/CalculateSurfaceFluxLocalAssembler.h @@ -0,0 +1,153 @@ +/** + * \copyright + * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#ifndef PROCESSLIB_BALANCEPROCESSLOCALASSEMBLER_H +#define PROCESSLIB_BALANCEPROCESSLOCALASSEMBLER_H + +#include "NumLib/Fem/ShapeMatrixPolicy.h" + +#include "NumLib/DOF/DOFTableUtil.h" +#include "ProcessLib/Parameter/Parameter.h" + +#include "ProcessLib/Utils/InitShapeMatrices.h" + +#include "MapBulkElementPoint.h" + +#include "MeshLib/Elements/FaceRule.h" +#include "MeshLib/Elements/Elements.h" + +namespace ProcessLib +{ +class CalculateSurfaceFluxLocalAssemblerInterface +{ +public: + virtual ~CalculateSurfaceFluxLocalAssemblerInterface() = default; + + virtual void integrate(std::size_t element_id, + GlobalVector const& x, + MeshLib::PropertyVector<double>& balance, + Process const& bulk_process) = 0; +}; + +template <typename ShapeFunction, typename IntegrationMethod, + unsigned GlobalDim> +class CalculateSurfaceFluxLocalAssembler final + : public CalculateSurfaceFluxLocalAssemblerInterface +{ +protected: + using ShapeMatricesType = ShapeMatrixPolicyType<ShapeFunction, GlobalDim>; + using NodalMatrixType = typename ShapeMatricesType::NodalMatrixType; + using NodalVectorType = typename ShapeMatricesType::NodalVectorType; + +public: + /// Precomputes the shape matrices for a given surface element. + /// @param surface_element The surface element used for precomputing the + /// shape matrices used later on for the integration. + /// @param integration_order the order of the integration + /// @param mesh Needed for fetching the id of the bulk element and the id of + /// the face + CalculateSurfaceFluxLocalAssembler( + MeshLib::Element const& surface_element, + std::size_t const /*local_matrix_size*/, + unsigned const integration_order, + MeshLib::PropertyVector<std::size_t> const& bulk_element_ids, + MeshLib::PropertyVector<std::size_t> const& bulk_face_ids) + : _surface_element(surface_element), + _integration_method(integration_order), + _bulk_element_id(bulk_element_ids[surface_element.getID()]), + _bulk_face_id(bulk_face_ids[surface_element.getID()]) + { + using FemType = + NumLib::TemplateIsoparametric<ShapeFunction, ShapeMatricesType>; + + FemType fe(*static_cast<const typename ShapeFunction::MeshElement*>( + &surface_element)); + + std::size_t const n_integration_points = + _integration_method.getNumberOfPoints(); + + std::vector<typename ShapeMatricesType::ShapeMatrices> shape_matrices; + shape_matrices.reserve(n_integration_points); + _detJ.reserve(n_integration_points); + for (std::size_t ip = 0; ip < n_integration_points; ++ip) + { + shape_matrices.emplace_back(ShapeFunction::DIM, GlobalDim, + ShapeFunction::NPOINTS); + fe.template computeShapeFunctions<NumLib::ShapeMatrixType::N_J>( + _integration_method.getWeightedPoint(ip).getCoords(), + shape_matrices[ip], GlobalDim); + _detJ.push_back(shape_matrices[ip].detJ); + } + } + + /// Integration for the element with the id \c element_id. + /// @param element_id id of the element + /// @param x The global vector containing the values for numerical + /// integration. + /// @param balance PropertyVector the integration result will be stored + /// into, where balance has the same number of entries like mesh elements + /// exists. + /// @param bulk_process Reference to the bulk process is used to compute the + /// flux. + void integrate(std::size_t element_id, + GlobalVector const& x, + MeshLib::PropertyVector<double>& balance, + Process const& bulk_process) override + { + auto surface_element_normal = + MeshLib::FaceRule::getSurfaceNormal(&_surface_element); + surface_element_normal.normalize(); + // At the moment (2016-09-28) the surface normal is not oriented + // according to the right hand rule + // for correct results it is necessary to multiply the normal with -1 + surface_element_normal *= -1; + + std::size_t const n_integration_points = + _integration_method.getNumberOfPoints(); + // balance[id_of_element] = + // int_{\Gamma_e} \alpha \cdot flux \cdot normal \d \Gamma + for (std::size_t ip(0); ip < n_integration_points; ip++) + { + auto const& wp = _integration_method.getWeightedPoint(ip); + + auto const bulk_element_point = getBulkElementPoint( + bulk_process.getMesh(), _bulk_element_id, _bulk_face_id, wp); + auto const bulk_flux = + bulk_process.getFlux(_bulk_element_id, bulk_element_point, x); + + for (std::size_t component_id(0); + component_id < balance.getNumberOfComponents(); + ++component_id) + { + // TODO find solution for 2d case + double const bulk_grad_times_normal( + Eigen::Map<Eigen::RowVectorXd const>(bulk_flux.data(), + bulk_flux.size()) + .dot(Eigen::Map<Eigen::RowVectorXd const>( + surface_element_normal.getCoords(), 3))); + + balance.getComponent(element_id, component_id) += + bulk_grad_times_normal * _detJ[ip] * wp.getWeight(); + } + } + } + +private: + MeshLib::Element const& _surface_element; + + std::vector<double> _detJ; + + IntegrationMethod const _integration_method; + std::size_t _bulk_element_id; + std::size_t _bulk_face_id; +}; + +} // ProcessLib + +#endif // PROCESSLIB_BALANCEPROCESSLOCALASSEMBLER_H diff --git a/ProcessLib/CalculateSurfaceFlux/MapBulkElementPoint.h b/ProcessLib/CalculateSurfaceFlux/MapBulkElementPoint.h index 74406d61321..07ed74214f7 100644 --- a/ProcessLib/CalculateSurfaceFlux/MapBulkElementPoint.h +++ b/ProcessLib/CalculateSurfaceFlux/MapBulkElementPoint.h @@ -7,8 +7,8 @@ * */ -#ifndef PROCESSLIB_BALANCEPROCESS_MAPBULKELEMENT_H -#define PROCESSLIB_BALANCEPROCESS_MAPBULKELEMENT_H +#ifndef PROCESSLIB_CALCULATESURFACEFLUX_MAPBULKELEMENT_H +#define PROCESSLIB_CALCULATESURFACEFLUX_MAPBULKELEMENT_H #include <array> -- GitLab