// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. // Implementation of data types for sparse matrix smoothers #include "vector.hpp" #include "matrix.hpp" #include "sparsemat.hpp" #include "sparsesmoothers.hpp" #include namespace mfem { void SparseSmoother::SetOperator(const Operator &a) { oper = dynamic_cast(&a); if (oper == NULL) { mfem_error("SparseSmoother::SetOperator : not a SparseMatrix!"); } height = oper->Height(); width = oper->Width(); } /// Matrix vector multiplication with GS Smoother. void GSSmoother::Mult(const Vector &x, Vector &y) const { if (!iterative_mode) { y = 0.0; } for (int i = 0; i < iterations; i++) { if (type != 2) { oper->Gauss_Seidel_forw(x, y); } if (type != 1) { oper->Gauss_Seidel_back(x, y); } } } /// Create the Jacobi smoother. DSmoother::DSmoother(const SparseMatrix &a, int t, double s, int it) : SparseSmoother(a) { type = t; scale = s; iterations = it; } /// Matrix vector multiplication with Jacobi smoother. void DSmoother::Mult(const Vector &x, Vector &y) const { if (!iterative_mode && type == 0 && iterations == 1) { oper->DiagScale(x, y, scale, use_abs_diag); return; } z.SetSize(width); Vector *r = &y, *p = &z; if (iterations % 2 == 0) { Swap(r, p); } if (!iterative_mode) { *p = 0.0; } else if (iterations % 2) { *p = y; } for (int i = 0; i < iterations; i++) { if (type == 0) { oper->Jacobi(x, *p, *r, scale, use_abs_diag); } else if (type == 1) { oper->Jacobi2(x, *p, *r, scale); } else if (type == 2) { oper->Jacobi3(x, *p, *r, scale); } else { mfem_error("DSmoother::Mult wrong type"); } Swap(r, p); } } }