13#ifndef dealii_solver_idr_h
14#define dealii_solver_idr_h
30#include <Kokkos_Random.hpp>
48 namespace SolverIDRImplementation
54 template <
typename VectorType>
82 operator()(
const unsigned int i,
const VectorType &temp);
93 std::vector<typename VectorMemory<VectorType>::Pointer>
data;
120template <
typename VectorType = Vector<
double>>
137 const unsigned int s;
162 template <
typename MatrixType,
typename PreconditionerType>
166 void solve(const MatrixType &A,
169 const PreconditionerType &preconditioner);
178 print_vectors(const
unsigned int step,
181 const VectorType &d) const;
198 namespace SolverIDRImplementation
200 template <
typename VectorType>
209 template <
typename VectorType>
221 template <
typename VectorType>
224 const VectorType &temp)
227 if (
data[i] ==
nullptr)
230 data[i]->reinit(temp,
true);
237 template <
typename VectorType,
238 std::enable_if_t<!IsBlockVector<VectorType>::value, VectorType>
241 n_blocks(
const VectorType &)
248 template <
typename VectorType,
249 std::enable_if_t<IsBlockVector<VectorType>::value, VectorType> * =
252 n_blocks(
const VectorType &vector)
254 return vector.n_blocks();
259 template <
typename VectorType,
260 std::enable_if_t<!IsBlockVector<VectorType>::value, VectorType>
263 block(VectorType &vector,
const unsigned int b)
271 template <
typename VectorType,
272 std::enable_if_t<IsBlockVector<VectorType>::value, VectorType> * =
274 typename VectorType::BlockType &
275 block(VectorType &vector,
const unsigned int b)
277 return vector.block(b);
282 template <
typename Number>
284 initialize_random_vector(
287 std::normal_distribution<> &)
289 using ExecutionSpace = Kokkos::DefaultExecutionSpace;
290 std::uniform_int_distribution<std::uint64_t> distribution;
291 const std::uint64_t seed = distribution(rng);
292 Kokkos::Random_XorShift64_Pool<ExecutionSpace> random_pool(seed);
294 Number *values = vector.get_values();
295 Kokkos::parallel_for(
296 "SolverIDR initialize random vector",
297 Kokkos::RangePolicy<ExecutionSpace>(0, vector.locally_owned_size()),
299 auto random_state = random_pool.get_state();
300 values[i] = random_state.normal();
301 random_pool.free_state(random_state);
303 ExecutionSpace().fence();
308 template <
typename VectorType>
310 initialize_random_vector(VectorType &vector,
312 std::normal_distribution<> &normal_distribution)
314 for (
const auto index : vector.locally_owned_elements())
315 vector(
index) = normal_distribution(rng);
323template <
typename VectorType>
327 const AdditionalData &
data)
329 , additional_data(
data)
334template <
typename VectorType>
338 , additional_data(
data)
343template <
typename VectorType>
348 const VectorType &)
const
353template <
typename VectorType>
355template <
typename MatrixType,
typename PreconditionerType>
362 const PreconditionerType &preconditioner)
367 unsigned int step = 0;
369 const unsigned int s = additional_data.
s;
382 uhat.reinit(x,
true);
386 r.sadd(-1.0, 1.0, b);
388 using value_type =
typename VectorType::value_type;
392 real_type res = r.l2_norm();
393 iteration_state = this->iteration_status(step, res, x);
406 std::normal_distribution<> normal_distribution(0.0, 1.0);
407 for (
unsigned int i = 0; i < s; ++i)
421 for (
unsigned int b = 0;
422 b < internal::SolverIDRImplementation::n_blocks(tmp_q);
424 internal::SolverIDRImplementation::initialize_random_vector(
425 internal::SolverIDRImplementation::block(tmp_q, b),
427 normal_distribution);
433 for (
unsigned int j = 0; j < i; ++j)
436 v *= (v * tmp_q) / (tmp_q * tmp_q);
441 tmp_q *= 1.0 / tmp_q.l2_norm();
448 bool early_exit =
false;
457 for (
unsigned int i = 0; i < s; ++i)
461 for (
unsigned int k = 0; k < s; ++k)
468 std::vector<unsigned int> indices;
470 for (
unsigned int i = k; i < s; ++i, ++j)
472 indices.push_back(i);
475 Mk.extract_submatrix_from(M, indices, indices);
479 Mk_inv.vmult(gamma, phik);
486 for (
unsigned int i = k, j = 0; i < s; ++i, ++j)
487 v.add(-
gamma(j), G[i]);
490 preconditioner.vmult(uhat, v);
494 uhat.sadd(omega,
gamma(0), U[k]);
495 for (
unsigned int i = k + 1, j = 1; i < s; ++i, ++j)
496 uhat.add(
gamma(j), U[i]);
508 for (
unsigned int i = 1; i < k; ++i)
511 alpha = G[k].add_and_dot(-alpha, G[i - 1], Q[i]) / M(i, i);
515 uhat.add(-alpha_old, U[i - 1], -alpha, U[i]);
517 M(k, k) = G[k].add_and_dot(-alpha, G[k - 1], Q[k]);
519 uhat.add(-alpha, U[k - 1]);
522 M(k, k) = G[k] * Q[k];
527 for (
unsigned int i = k + 1; i < s; ++i)
528 M(i, k) = Q[i] * G[k];
536 print_vectors(step, x, r, U[k]);
542 iteration_state = this->iteration_status(step, res, x);
552 for (
unsigned int i = 0; i < k + 1; ++i)
554 for (
unsigned int i = k + 1; i < s; ++i)
555 phi(i) -= beta * M(i, k);
559 if (early_exit ==
true)
563 preconditioner.vmult(uhat, r);
566 omega = (v * r) / (v * v);
568 res =
std::sqrt(r.add_and_dot(-1.0 * omega, v, r));
571 print_vectors(step, x, r, uhat);
574 iteration_state = this->iteration_status(step, res, x);
@ iterate
Continue iteration.
@ success
Stop iteration, goal reached.
virtual void print_vectors(const unsigned int step, const VectorType &x, const VectorType &r, const VectorType &d) const
SolverIDR(SolverControl &cn, const AdditionalData &data=AdditionalData())
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
SolverIDR(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
virtual ~SolverIDR() override=default
TmpVectors(const unsigned int s_param, VectorMemory< VectorType > &vmem)
VectorType & operator()(const unsigned int i, const VectorType &temp)
VectorType & operator[](const unsigned int i) const
VectorMemory< VectorType > & mem
std::vector< typename VectorMemory< VectorType >::Pointer > data
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_CXX20_REQUIRES(condition)
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcNotInitialized()
#define AssertThrow(cond, exc)
std::vector< index_type > data
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
long double gamma(const unsigned int n)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
AdditionalData(const unsigned int s=2)