/** * \file * \copyright * Copyright (c) 2012-2020, 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 "MaterialLib/Adsorption/Adsorption.h" #include "MathLib/LinAlg/Eigen/EigenMapTools.h" #include "NumLib/DOF/DOFTableUtil.h" #include "NumLib/Fem/FiniteElement/TemplateIsoparametric.h" #include "NumLib/Fem/InitShapeMatrices.h" #include "NumLib/Fem/ShapeMatrixPolicy.h" #include "NumLib/Function/Interpolation.h" #include "TESLocalAssembler.h" #include "TESReactionAdaptor.h" namespace { enum class MatOutType { OGS5, PYTHON }; const MatOutType MATRIX_OUTPUT_FORMAT = MatOutType::PYTHON; // TODO move to some location in the OGS core. template void ogs5OutMat(const Mat& mat) { for (unsigned r = 0; r < mat.rows(); ++r) { switch (MATRIX_OUTPUT_FORMAT) { case MatOutType::OGS5: if (r != 0) { std::printf("\n"); } std::printf("|"); break; case MatOutType::PYTHON: if (r != 0) { std::printf(",\n"); } std::printf("["); break; } for (unsigned c = 0; c < mat.cols(); ++c) { switch (MATRIX_OUTPUT_FORMAT) { case MatOutType::OGS5: std::printf(" %.16e", mat(r, c)); break; case MatOutType::PYTHON: if (c != 0) { std::printf(","); } std::printf(" %23.16g", mat(r, c)); break; } } switch (MATRIX_OUTPUT_FORMAT) { case MatOutType::OGS5: std::printf(" | "); break; case MatOutType::PYTHON: std::printf(" ]"); break; } } std::printf("\n"); } template void ogs5OutVec(const Vec& vec) { for (unsigned r = 0; r < vec.size(); ++r) { switch (MATRIX_OUTPUT_FORMAT) { case MatOutType::OGS5: if (r != 0) { std::printf("\n"); } std::printf("| %.16e | ", vec[r]); break; case MatOutType::PYTHON: if (r != 0) { std::printf(",\n"); } std::printf("[ %23.16g ]", vec[r]); break; } } std::printf("\n"); } } // anonymous namespace namespace ProcessLib { namespace TES { template TESLocalAssembler:: TESLocalAssembler(MeshLib::Element const& e, std::size_t const /*local_matrix_size*/, bool is_axially_symmetric, unsigned const integration_order, AssemblyParams const& asm_params) : _element(e), _integration_method(integration_order), _shape_matrices(NumLib::initShapeMatrices( e, is_axially_symmetric, _integration_method)), _d(asm_params, _integration_method.getNumberOfPoints(), GlobalDim) { } template void TESLocalAssembler::assemble( double const /*t*/, double const /*dt*/, std::vector const& local_x, std::vector const& /*local_xdot*/, std::vector& local_M_data, std::vector& local_K_data, std::vector& local_b_data) { auto const local_matrix_size = local_x.size(); // This assertion is valid only if all nodal d.o.f. use the same shape matrices. assert(local_matrix_size == ShapeFunction::NPOINTS * NODAL_DOF); auto local_M = MathLib::createZeroedMatrix( local_M_data, local_matrix_size, local_matrix_size); auto local_K = MathLib::createZeroedMatrix( local_K_data, local_matrix_size, local_matrix_size); auto local_b = MathLib::createZeroedVector(local_b_data, local_matrix_size); unsigned const n_integration_points = _integration_method.getNumberOfPoints(); _d.preEachAssemble(); for (unsigned ip = 0; ip < n_integration_points; ip++) { auto const& sm = _shape_matrices[ip]; auto const& wp = _integration_method.getWeightedPoint(ip); auto const weight = wp.getWeight(); _d.assembleIntegrationPoint(ip, local_x, sm, weight, local_M, local_K, local_b); } if (_d.getAssemblyParameters().output_element_matrices) { std::puts("### Element: ?"); std::puts("---Velocity of water"); for (auto const& vs : _d.getData().velocity) { std::printf("| "); for (auto v : vs) { std::printf("%23.16e ", v); } std::printf("|\n"); } std::printf("\n---Mass matrix: \n"); ogs5OutMat(local_M); std::printf("\n"); std::printf("---Laplacian + Advective + Content matrix: \n"); ogs5OutMat(local_K); std::printf("\n"); std::printf("---RHS: \n"); ogs5OutVec(local_b); std::printf("\n"); } } template std::vector const& TESLocalAssembler:: getIntPtSolidDensity( const double /*t*/, std::vector const& /*x*/, std::vector const& /*dof_table*/, std::vector& /*cache*/) const { return _d.getData().solid_density; } template std::vector const& TESLocalAssembler:: getIntPtLoading( const double /*t*/, std::vector const& /*x*/, std::vector const& /*dof_table*/, std::vector& cache) const { auto const rho_SR = _d.getData().solid_density; auto const rho_SR_dry = _d.getAssemblyParameters().rho_SR_dry; cache.clear(); cache.reserve(rho_SR.size()); transform(cbegin(rho_SR), cend(rho_SR), back_inserter(cache), [&](auto const rho) { return rho / rho_SR_dry - 1.0; }); return cache; } template std::vector const& TESLocalAssembler:: getIntPtReactionDampingFactor( const double /*t*/, std::vector const& /*x*/, std::vector const& /*dof_table*/, std::vector& cache) const { auto const fac = _d.getData().reaction_adaptor->getReactionDampingFactor(); auto const num_integration_points = _d.getData().solid_density.size(); cache.clear(); cache.resize(num_integration_points, fac); return cache; } template std::vector const& TESLocalAssembler:: getIntPtReactionRate( const double /*t*/, std::vector const& /*x*/, std::vector const& /*dof_table*/, std::vector& /*cache*/) const { return _d.getData().reaction_rate; } template std::vector const& TESLocalAssembler:: getIntPtDarcyVelocity( const double /*t*/, std::vector const& x, std::vector const& dof_table, std::vector& cache) const { auto const n_integration_points = _integration_method.getNumberOfPoints(); constexpr int process_id = 0; // monolithic scheme auto const indices = NumLib::getIndices(_element.getID(), *dof_table[process_id]); assert(!indices.empty()); auto const local_x = x[process_id]->get(indices); // local_x is ordered by component, local_x_mat is row major auto const local_x_mat = MathLib::toMatrix< Eigen::Matrix>( local_x, NODAL_DOF, ShapeFunction_::NPOINTS); cache.clear(); auto cache_mat = MathLib::createZeroedMatrix< Eigen::Matrix>( cache, GlobalDim, n_integration_points); for (unsigned i = 0; i < n_integration_points; ++i) { double p, T, x; NumLib::shapeFunctionInterpolate(local_x, _shape_matrices[i].N, p, T, x); const double eta_GR = fluid_viscosity(p, T, x); auto const& k = _d.getAssemblyParameters().solid_perm_tensor; cache_mat.col(i).noalias() = k * (_shape_matrices[i].dNdx * local_x_mat.row(COMPONENT_ID_PRESSURE).transpose()) / -eta_GR; } return cache; } template bool TESLocalAssembler< ShapeFunction_, IntegrationMethod_, GlobalDim>::checkBounds(std::vector const& local_x, std::vector const& local_x_prev_ts) { return _d.getReactionAdaptor().checkBounds(local_x, local_x_prev_ts); } } // namespace TES } // namespace ProcessLib