OGS
HeatTransportBHELocalAssemblerBHE-impl.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
6#include <algorithm>
7
8#include "BaseLib/Error.h"
12
13namespace ProcessLib
14{
15namespace HeatTransportBHE
16{
17template <typename ShapeFunction, typename BHEType>
20 MeshLib::Element const& e,
21 NumLib::GenericIntegrationMethod const& integration_method,
22 BHEType const& bhe,
23 bool const is_axially_symmetric,
24 HeatTransportBHEProcessData& process_data,
25 BHEMeshData const& bhe_mesh_data)
26 : _process_data(process_data),
27 _integration_method(integration_method),
28 _bhe(bhe),
29 _element_id(e.getID()),
30 _bhe_mesh_data(bhe_mesh_data)
31{
32 // need to make sure that the BHE elements are one-dimensional
33 assert(e.getDimension() == 1);
34
35 unsigned const n_integration_points =
36 _integration_method.getNumberOfPoints();
37
38 _ip_data.reserve(n_integration_points);
39 _secondary_data.N.resize(n_integration_points);
40
41 auto const shape_matrices =
43 3 /* GlobalDim */>(e, is_axially_symmetric,
45
46 // ip data initialization
47 for (unsigned ip = 0; ip < n_integration_points; ip++)
48 {
49 auto const& sm = shape_matrices[ip];
50 // create the class IntegrationPointDataBHE in place
51 _ip_data.push_back(
52 {sm.N, sm.dNdx,
53 _integration_method.getWeightedPoint(ip).getWeight() *
54 sm.integralMeasure * sm.detJ});
55
56 _secondary_data.N[ip] = sm.N;
57 }
58
59 // calculate the element direction vector
60 auto const& p0 = e.getNode(0)->asEigenVector3d();
61 auto const& p1 = e.getNode(1)->asEigenVector3d();
62
63 _element_direction = (p1 - p0).normalized();
64
65 auto const section_it =
66 _bhe_mesh_data.BHE_element_section_indices.find(_element_id);
67 if (section_it == _bhe_mesh_data.BHE_element_section_indices.end())
68 {
70 "Could not read BHE element section index for element id "
71 "{:d}.",
73 }
74
75 _section_index = section_it->second;
76 if (_section_index < 0)
77 {
79 "Invalid BHE section index for element id {:d}. Check BHE mesh "
80 "data initialisation.",
82 }
83
87 static constexpr int max_num_thermal_exchange_terms = 5;
88 // Formulate the local BHE R matrix.
89 // Only unknowns with thermal exchange terms need resistance assembly.
90 // In CXA/CXC there are 3 exchange terms (= number of unknowns),
91 // in 1U there are 4 (= number of unknowns),
92 // in 2U there are 5 but 8 unknowns — unknowns 5-7 (extra grout zones)
93 // have no exchange terms. See Diersch (2013) FEFLOW, M.127-M.128.
94 for (int idx_bhe_unknowns = 0;
95 idx_bhe_unknowns <
96 std::min(bhe_unknowns, max_num_thermal_exchange_terms);
97 idx_bhe_unknowns++)
98 {
99 typename ShapeMatricesType::template MatrixType<
101 matBHE_loc_R = ShapeMatricesType::template MatrixType<
105 // Loop over Gauss points
106 for (unsigned ip = 0; ip < n_integration_points; ip++)
107 {
108 auto const& N = _ip_data[ip].N;
109 auto const& w = _ip_data[ip].integration_weight;
110
111 // Get thermal resistance for this element's section
112 auto const& R = _bhe.thermalResistanceAtSection(idx_bhe_unknowns,
114 // calculate mass matrix for current unknown
115 matBHE_loc_R += N.transpose() * N * (1 / R) * w;
116 } // end of loop over integration point
117
118 _bhe.template assembleRMatrices<ShapeFunction::NPOINTS>(
119 idx_bhe_unknowns, matBHE_loc_R, _R_matrix, _R_pi_s_matrix,
121 } // end of loop over BHE unknowns
122}
123
124template <typename ShapeFunction, typename BHEType>
126 double const /*t*/, double const /*dt*/,
127 std::vector<double> const& /*local_x*/,
128 std::vector<double> const& /*local_x_prev*/,
129 std::vector<double>& local_M_data, std::vector<double>& local_K_data,
130 std::vector<double>& /*local_b_data*/) // local b vector is not touched
131{
133 local_M_data, local_matrix_size, local_matrix_size);
135 local_K_data, local_matrix_size, local_matrix_size);
136
137 unsigned const n_integration_points =
138 _integration_method.getNumberOfPoints();
139
140 auto const& pipe_heat_capacities = _bhe.pipeHeatCapacities();
141 auto const& pipe_heat_conductions =
142 _bhe.pipeHeatConductions(_section_index);
143 auto const& pipe_advection_vectors =
144 _bhe.pipeAdvectionVectors(_element_direction, _section_index);
145 auto const& cross_section_areas = _bhe.crossSectionAreas(_section_index);
146
147 // the mass and conductance matrix terms
148 for (unsigned ip = 0; ip < n_integration_points; ip++)
149 {
150 auto const& ip_data = _ip_data[ip];
151
152 auto const& w = ip_data.integration_weight;
153 auto const& N = ip_data.N;
154 auto const& dNdx = ip_data.dNdx;
155
156 // looping over all unknowns.
157 for (int idx_bhe_unknowns = 0; idx_bhe_unknowns < bhe_unknowns;
158 idx_bhe_unknowns++)
159 {
160 // get coefficient of mass from corresponding BHE.
161 auto const& mass_coeff = pipe_heat_capacities[idx_bhe_unknowns];
162 auto const& lambda = pipe_heat_conductions[idx_bhe_unknowns];
163 auto const& advection_vector =
164 pipe_advection_vectors[idx_bhe_unknowns];
165 auto const& A = cross_section_areas[idx_bhe_unknowns];
166
167 int const single_bhe_unknowns_index =
169 single_bhe_unknowns_size * idx_bhe_unknowns;
170 // local M
171 local_M
172 .template block<single_bhe_unknowns_size,
174 single_bhe_unknowns_index, single_bhe_unknowns_index)
175 .noalias() += N.transpose() * N * mass_coeff * A * w;
176
177 // local K
178 // laplace part
179 local_K
180 .template block<single_bhe_unknowns_size,
182 single_bhe_unknowns_index, single_bhe_unknowns_index)
183 .noalias() += dNdx.transpose() * dNdx * lambda * A * w;
184 // advection part
185 local_K
186 .template block<single_bhe_unknowns_size,
188 single_bhe_unknowns_index, single_bhe_unknowns_index)
189 .noalias() +=
190 N.transpose() * advection_vector.transpose() * dNdx * A * w;
191 }
192 }
193
194 // add the R matrix to local_K
195 local_K.template block<bhe_unknowns_size, bhe_unknowns_size>(
197
198 // add the R_pi_s matrix to local_K
199 local_K
200 .template block<bhe_unknowns_size, soil_temperature_size>(
202 .noalias() += _R_pi_s_matrix;
203 local_K
204 .template block<soil_temperature_size, bhe_unknowns_size>(
206 .noalias() += _R_pi_s_matrix.transpose();
207
208 // add the R_s matrix to local_K
209 local_K
210 .template block<soil_temperature_size, soil_temperature_size>(
212 .noalias() += _bhe.number_of_grout_zones * _R_s_matrix;
213}
214
215template <typename ShapeFunction, typename BHEType>
217 assembleWithJacobian(double const t, double const dt,
218 std::vector<double> const& local_x,
219 std::vector<double> const& local_x_prev,
220 std::vector<double>& local_rhs_data,
221 std::vector<double>& local_Jac_data)
222{
223 auto const local_matrix_size = local_x.size();
224 // initialize x and x_prev
225 auto x =
226 Eigen::Map<BheLocalVectorType const>(local_x.data(), local_matrix_size);
227 auto x_prev = Eigen::Map<BheLocalVectorType const>(local_x_prev.data(),
229 // initialize local_Jac and local_rhs
231 local_Jac_data, local_matrix_size, local_matrix_size);
233 local_rhs_data, local_matrix_size);
234
235 std::vector<double> local_M_data;
236 std::vector<double> local_K_data;
237 assemble(t, dt, local_x, local_x_prev, local_M_data, local_K_data,
238 local_rhs_data /*not going to be used*/);
239
240 // convert to matrix
242 local_M_data, local_matrix_size, local_matrix_size);
244 local_K_data, local_matrix_size, local_matrix_size);
245
246 // Jac matrix and rhs vector operation
247 local_Jac.noalias() += local_K + local_M / dt;
248 local_rhs.noalias() -= local_K * x + local_M * (x - x_prev) / dt;
249
250 local_M.setZero();
251 local_K.setZero();
252}
253
254} // namespace HeatTransportBHE
255} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
Eigen::Vector3d const & asEigenVector3d() const
Definition Point3d.h:55
virtual const Node * getNode(unsigned idx) const =0
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
ShapeMatricesType::template MatrixType< bhe_unknowns_size, bhe_unknowns_size > _R_matrix
ShapeMatricesType::template MatrixType< soil_temperature_size, soil_temperature_size > _R_s_matrix
std::vector< IntegrationPointDataBHE< ShapeMatricesType >, Eigen::aligned_allocator< IntegrationPointDataBHE< ShapeMatricesType > > > _ip_data
ShapeMatricesType::template MatrixType< bhe_unknowns_size, soil_temperature_size > _R_pi_s_matrix
void assemble(double const, double const, std::vector< double > const &, std::vector< double > const &, std::vector< double > &, std::vector< double > &, std::vector< double > &) override
void assembleWithJacobian(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &local_x_prev, std::vector< double > &local_rhs_data, std::vector< double > &local_Jac_data) override
HeatTransportBHELocalAssemblerBHE(HeatTransportBHELocalAssemblerBHE const &)=delete
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Eigen::Map< const Matrix > toMatrix(std::vector< double > const &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > initShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, IntegrationMethod const &integration_method)