OGS
BcAndStLocalAssemblerImpl.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
8#include "NsAndWeight.h"
13
15{
16
25template <typename BcOrStData, typename ShapeFunction,
26 typename LowerOrderShapeFunction, int GlobalDim>
28{
29public:
30 using Traits =
32
33private:
35
36public:
38 MeshLib::Element const& e,
39 NumLib::GenericIntegrationMethod const& integration_method_,
40 bool is_axially_symmetric,
41 BcOrStData const& data)
42 : bc_or_st_data(data),
43 element(e),
44 integration_method(integration_method_),
46 computeNsAndWeights<ShapeFunction, LowerOrderShapeFunction,
47 GlobalDim>(e, is_axially_symmetric,
49 {
50 }
51
54 void assemble(std::size_t const boundary_element_id,
55 NumLib::LocalToGlobalIndexMap const& dof_table_boundary,
56 double const t, GlobalVector const& x, GlobalVector& b,
57 GlobalMatrix* const Jac) const
58 {
59 // Variables for input data
60 Eigen::MatrixXd const primary_variables_mat = ProcessLib::
62 element, bc_or_st_data.bc_or_st_mesh.getID(),
63 dof_table_boundary, x);
64
65 // Variables for output data
66 auto const& indices_this_component =
67 dof_table_boundary(boundary_element_id,
68 bc_or_st_data.global_component_id)
69 .rows;
70 std::vector<GlobalIndexType> indices_all_components_for_Jac;
71
72 auto const num_dof_this_component = indices_this_component.size();
73
74 Eigen::VectorXd local_rhs =
75 Eigen::VectorXd::Zero(num_dof_this_component);
76 Eigen::MatrixXd local_Jac;
77
78 if (Jac)
79 {
80 indices_all_components_for_Jac =
81 NumLib::getIndices(boundary_element_id, dof_table_boundary);
82
83 auto const num_dof_all_components =
84 indices_all_components_for_Jac.size();
85
86 local_Jac = Eigen::MatrixXd::Zero(num_dof_this_component,
87 num_dof_all_components);
88 }
89
90 // Variables for temporary data
91 auto const num_comp_total =
92 dof_table_boundary.getNumberOfGlobalComponents();
93 std::vector<double> prim_vars_data(num_comp_total);
94 auto prim_vars = MathLib::toVector(prim_vars_data);
95
96 // Variables for the integration loop
97 unsigned const num_integration_points =
98 integration_method.getNumberOfPoints();
101
102 for (unsigned ip = 0; ip < num_integration_points; ip++)
103 {
104 auto const& ns_and_weight = nss_and_weights[ip];
105 auto const coords = interpolateCoords(ns_and_weight, fe);
106
108 primary_variables_mat,
109 bc_or_st_data.all_process_variables_for_this_process,
110 nss_and_weights[ip], prim_vars);
111
112 auto const [flag, flux, dFlux] =
113 bc_or_st_data.getFlagAndFluxAndDFlux(t, coords, prim_vars_data);
114
115 if (!flag)
116 {
117 // No flux value for this integration point. Skip assembly of
118 // the entire element.
119 return;
120 }
121
122 assembleLocalRhs(flux, ns_and_weight, local_rhs);
123
124 if (static_cast<int>(dFlux.size()) != num_comp_total)
125 {
126 // This strict check is technically mandatory only if a Jacobian
127 // is assembled. However, it is done as a consistency check also
128 // for cases without Jacobian assembly.
129 OGS_FATAL(
130 "The Python BC or ST must return the derivative of the "
131 "flux w.r.t. each component of each primary variable. "
132 "{:d} components expected. {:d} components returned from "
133 "Python."
134 "The expected number of components depends on multiple "
135 "factors. In the case of vectorial primary variables (such "
136 "as displacement), it will depend on the space dimension. "
137 "In the case of staggered coupling, the number of "
138 "components can be different for each staggered process "
139 "and different from monolithic coupling.",
140 num_comp_total, dFlux.size());
141 }
142
143 if (Jac)
144 {
145 assembleLocalJacobian(dFlux, ns_and_weight, local_Jac);
146 }
147 }
148
149 b.add(indices_this_component, local_rhs);
150
151 if (Jac)
152 {
154 indices_this_component, indices_all_components_for_Jac};
155 Jac->add(rci, local_Jac);
156 }
157 }
158
159private:
165 std::array<double, 3> interpolateCoords(
166 typename Traits::NsAndWeight const& ns_and_weight,
168 fe) const
169 {
170 auto const& N_higher = ns_and_weight.NHigherOrder();
171 return fe.interpolateCoordinates(N_higher);
172 }
173
176 void assembleLocalRhs(double const flux,
177 typename Traits::NsAndWeight const& ns_and_weight,
178 Eigen::VectorXd& local_rhs) const
179 {
180 auto const w = ns_and_weight.weight();
181 auto const N = ns_and_weight.N(bc_or_st_data.shape_function_order);
182
183 local_rhs.noalias() += N.transpose() * (flux * w);
184 }
185
199 std::vector<double> const& dFlux,
200 typename Traits::NsAndWeight const& ns_and_weight,
201 Eigen::MatrixXd& local_Jac) const
202 {
203 auto const& pv_refs =
204 bc_or_st_data.all_process_variables_for_this_process;
205 auto const weight = ns_and_weight.weight();
206
207 auto const this_shp_fct_order = bc_or_st_data.shape_function_order;
208 auto const N_this = ns_and_weight.N(this_shp_fct_order);
209
210 Eigen::Index left = 0;
211
212 for (auto pv_ref : pv_refs)
213 {
214 auto const& pv = pv_ref.get();
215 auto const other_num_comp = pv.getNumberOfGlobalComponents();
216 auto const other_shp_fct_order = pv.getShapeFunctionOrder();
217 auto const N_other = ns_and_weight.N(other_shp_fct_order);
218 auto const width = N_other.size();
219
220 for (decltype(+other_num_comp) other_comp = 0;
221 other_comp < other_num_comp;
222 ++other_comp)
223 {
224 // The assignment -= takes into account the sign convention
225 // of 1st-order in time in ODE systems in OpenGeoSys.
226 local_Jac.middleCols(left, width).noalias() -=
227 N_this.transpose() * (dFlux[other_comp] * weight) * N_other;
228
229 left += width;
230 }
231 }
232
233 assert(left == local_Jac.cols());
234 }
235
236public:
239
241 std::vector<typename Traits::NsAndWeight> const nss_and_weights;
242};
243
244} // namespace ProcessLib::BoundaryConditionAndSourceTerm::Python
#define OGS_FATAL(...)
Definition Error.h:19
MathLib::EigenMatrix GlobalMatrix
MathLib::EigenVector GlobalVector
int add(IndexType row, IndexType col, double val)
Definition EigenMatrix.h:80
void add(IndexType rowId, double v)
add entry
Definition EigenVector.h:70
Template class for isoparametric elements.
std::array< double, 3 > interpolateCoordinates(typename ShapeMatrices::ShapeType const &N) const
Interpolates the coordinates of the element with the given shape matrix.
Eigen::Map< const Vector > toVector(std::vector< double > const &data, Eigen::VectorXd::Index size)
Creates an Eigen mapped vector from the given data vector.
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
NumLib::TemplateIsoparametric< ShapeFunction, ShapeMatricesType > createIsoparametricFiniteElement(MeshLib::Element const &e)
auto computeNsAndWeights(MeshLib::Element const &element, bool const is_axially_symmetric, IntegrationMethod const &integration_method)
Eigen::MatrixXd collectDofsToMatrix(MeshLib::Element const &element, std::size_t const mesh_id, NumLib::LocalToGlobalIndexMap const &dof_table, GlobalVector const &x)
void interpolate(Eigen::MatrixXd const &primary_variables_mat, std::vector< std::reference_wrapper< ProcessVariable > > const &pv_refs, NsAndWeight const &ns_and_weight, Eigen::Ref< Eigen::VectorXd > interpolated_primary_variables)
void assembleLocalRhs(double const flux, typename Traits::NsAndWeight const &ns_and_weight, Eigen::VectorXd &local_rhs) const
void assemble(std::size_t const boundary_element_id, NumLib::LocalToGlobalIndexMap const &dof_table_boundary, double const t, GlobalVector const &x, GlobalVector &b, GlobalMatrix *const Jac) const
BcAndStLocalAssemblerImpl(MeshLib::Element const &e, NumLib::GenericIntegrationMethod const &integration_method_, bool is_axially_symmetric, BcOrStData const &data)
std::array< double, 3 > interpolateCoords(typename Traits::NsAndWeight const &ns_and_weight, NumLib::TemplateIsoparametric< ShapeFunction, ShapeMatrixPolicy > const &fe) const
void assembleLocalJacobian(std::vector< double > const &dFlux, typename Traits::NsAndWeight const &ns_and_weight, Eigen::MatrixXd &local_Jac) const
NsAndWeightsTraits< ShapeFunction, LowerOrderShapeFunction, GlobalDim > Traits
Eigen::Ref< const Eigen::RowVectorXd > N(unsigned order) const
Definition NsAndWeight.h:44
Collects common type aliases needed when working with NsAndWeight.
ProcessLib::BoundaryConditionAndSourceTerm::Python::NsAndWeight< ShapeFunction, LowerOrderShapeFunction, ShapeMatrix, LowerOrderShapeMatrix > NsAndWeight
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatrixPolicy