OGS
TimeDiscretizedODESystem.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <range/v3/numeric/accumulate.hpp>
7#include <range/v3/view/transform.hpp>
8
11#include "NumLib/Exceptions.h"
13
14namespace detail
15{
17template <typename Solutions, typename Vector>
18void applyKnownSolutions(std::vector<Solutions> const* const known_solutions,
19 Vector& x)
20{
21 if (!known_solutions)
22 {
23 return;
24 }
25
26 for (auto const& bc : *known_solutions)
27 {
28 for (std::size_t i = 0; i < bc.ids.size(); ++i)
29 {
30 // TODO that might have bad performance for some Vector types, e.g.,
31 // PETSc.
32 MathLib::setVector(x, bc.ids[i], bc.values[i]);
33 }
34 }
36}
37} // namespace detail
38
39namespace NumLib
40{
43 TimeDiscretizedODESystem(const int process_id, ODE& ode,
44 TimeDisc& time_discretization)
45 : _ode(ode),
46 _time_disc(time_discretization),
47 _mat_trans(createMatrixTranslator<ODETag>(time_discretization))
48{
50 _ode.getMatrixSpecifications(process_id), _Jac_id);
52 _ode.getMatrixSpecifications(process_id), _b_id);
53}
54
62
65 assemble(std::vector<GlobalVector*> const& x_new_timestep,
66 std::vector<GlobalVector*> const& x_prev,
67 int const process_id)
68{
69 auto const t = _time_disc.getCurrentTime();
70 auto const dt = _time_disc.getCurrentTimeIncrement();
71 auto const& x_curr = *x_new_timestep[process_id];
72
73 _b->setZero();
74 _Jac->setZero();
75 try
76 {
77 _ode.preAssemble(t, dt, x_curr);
78 _ode.assembleWithJacobian(t, dt, x_new_timestep, x_prev, process_id,
79 *_b, *_Jac);
80 }
81 catch (AssemblyException const&)
82 {
85 throw;
86 }
89}
90
93 getResidual(GlobalVector const& /*x_new_timestep*/,
94 GlobalVector const& /*x_prev*/,
95 GlobalVector& res) const
96{
97 MathLib::LinAlg::copy(*_b, res); // res = b
98 MathLib::LinAlg::scale(res, -1.); // res = -b
99}
100
104{
105 _mat_trans->computeJacobian(*_Jac, Jac);
106}
107
111 int const process_id)
112{
114 _ode.getKnownSolutions(_time_disc.getCurrentTime(), x, process_id);
115}
116
123
126 applyKnownSolutionsNewton(GlobalMatrix& Jac, GlobalVector& res,
127 GlobalVector const& x,
128 GlobalVector& minus_delta_x) const
129{
130 if (!_known_solutions)
131 {
132 return;
133 }
134
136 std::size_t const size = ranges::accumulate(
137 *_known_solutions | ranges::views::transform([](auto const& bc)
138 { return bc.ids.size(); }),
139 0);
140 std::vector<IndexType> ids;
141 ids.reserve(size);
142 std::vector<double> values;
143 values.reserve(size);
144
145 for (auto const& bc : *_known_solutions)
146 {
147 for (std::size_t i = 0; i < bc.ids.size(); ++i)
148 {
149 auto const id = bc.ids[i];
150 ids.push_back(id);
151 // minus_delta_x will be set to the difference between the current
152 // value and the Dirichlet BC value.
153 values.push_back(x[id] - bc.values[i]);
154 }
155 }
156
158 Jac, res, minus_delta_x, ids, values,
160}
161
164 applyKnownSolutionsPETScSNES(GlobalMatrix& Jac, GlobalVector& res,
165 GlobalVector& x) const
166{
167 if (!_known_solutions)
168 {
169 return;
170 }
171
173 std::vector<IndexType> ids;
174 for (auto const& bc : *_known_solutions)
175 {
176 ids.insert(end(ids), begin(bc.ids), end(bc.ids));
177 }
178
179 // For the Newton method the values must be zero
180 std::vector<double> values(ids.size(), 0);
182 Jac, res, x, ids, values,
184}
185
188 TimeDiscretizedODESystem(const int process_id, ODE& ode,
189 TimeDisc& time_discretization)
190 : _ode(ode),
191 _time_disc(time_discretization),
192 _mat_trans(createMatrixTranslator<ODETag>(time_discretization))
193{
195 ode.getMatrixSpecifications(process_id), _M_id);
197 ode.getMatrixSpecifications(process_id), _K_id);
199 ode.getMatrixSpecifications(process_id), _b_id);
200}
201
210
213 assemble(std::vector<GlobalVector*> const& x_new_timestep,
214 std::vector<GlobalVector*> const& x_prev,
215 int const process_id)
216{
217 namespace LinAlg = MathLib::LinAlg;
218
219 auto const t = _time_disc.getCurrentTime();
220 auto const dt = _time_disc.getCurrentTimeIncrement();
221 auto const& x_curr = *x_new_timestep[process_id];
222
223 _M->setZero();
224 _K->setZero();
225 _b->setZero();
226
227 _ode.preAssemble(t, dt, x_curr);
228 _ode.assemble(t, dt, x_new_timestep, x_prev, process_id, *_M, *_K, *_b);
229
233}
234
238 int const process_id)
239{
241 _ode.getKnownSolutions(_time_disc.getCurrentTime(), x, process_id);
242}
243
250
253 applyKnownSolutionsPicard(
256{
257 if (!_known_solutions)
258 {
259 return;
260 }
261
263 std::vector<IndexType> ids;
264 std::vector<double> values;
265 for (auto const& bc : *_known_solutions)
266 {
267 ids.insert(end(ids), begin(bc.ids), end(bc.ids));
268 values.insert(end(values), begin(bc.values), end(bc.values));
269 }
270 MathLib::applyKnownSolution(A, rhs, x, ids, values, mode);
271}
272
273} // namespace NumLib
MathLib::EigenMatrix GlobalMatrix
MathLib::EigenVector GlobalVector
std::unique_ptr< MatTrans > _mat_trans
the object used to compute the matrix/vector for the nonlinear solver
std::vector< NumLib::IndexValueVector< Index > > const * _known_solutions
stores precomputed values for known solutions
std::vector< NumLib::IndexValueVector< Index > > const * _known_solutions
stores precomputed values for known solutions
std::unique_ptr< MatTrans > _mat_trans
the object used to compute the matrix/vector for the nonlinear solver
std::unique_ptr< MatrixTranslator< ODETag > > createMatrixTranslator(TimeDiscretization const &timeDisc)
@ FirstOrderImplicitQuasilinear
Definition Types.h:27
void finalizeAssembly(PETScMatrix &A)
Definition LinAlg.cpp:191
void copy(PETScVector const &x, PETScVector &y)
Definition LinAlg.cpp:30
void scale(PETScVector &x, PetscScalar const a)
Definition LinAlg.cpp:37
DirichletBCApplicationMode
Definition LinAlgEnums.h:33
@ COMPLETE_MATRIX_UPDATE
Both A and b fully updated.
Definition LinAlgEnums.h:34
void setVector(PETScVector &v, std::initializer_list< double > values)
void applyKnownSolution(EigenMatrix &A, EigenVector &b, EigenVector &, const std::vector< EigenMatrix::IndexType > &vec_knownX_id, const std::vector< double > &vec_knownX_x, DirichletBCApplicationMode const mode)
void applyKnownSolutions(std::vector< Solutions > const *const known_solutions, Vector &x)
Applies known solutions to the solution vector x.
static NUMLIB_EXPORT MatrixProvider & provider
static NUMLIB_EXPORT VectorProvider & provider