222 lines
7.4 KiB
C++
222 lines
7.4 KiB
C++
// Copyright (c) 2010-2025, 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.
|
|
|
|
#ifndef MFEM_COMPLEX_BLOCK_STATIC_CONDENSATION
|
|
#define MFEM_COMPLEX_BLOCK_STATIC_CONDENSATION
|
|
|
|
#include "mfem.hpp"
|
|
|
|
namespace mfem
|
|
{
|
|
|
|
|
|
/** @brief Class that performs static condensation of interior dofs for
|
|
multiple FE spaces for complex systems (see BlockStaticCondensation). It's used
|
|
by the class ComplexDPGWeakForm. */
|
|
class ComplexBlockStaticCondensation
|
|
{
|
|
int height, width;
|
|
int nblocks; // original number of blocks
|
|
int rblocks; // reduces number of blocks
|
|
Mesh * mesh = nullptr;
|
|
bool parallel = false;
|
|
// original set of Finite Element Spaces
|
|
Array<FiniteElementSpace *> fes;
|
|
// indicates if the original space is already a trace space
|
|
Array<bool> IsTraceSpace;
|
|
|
|
// New set of "reduced" Finite Element Spaces
|
|
// (after static condensation)
|
|
Array<FiniteElementSpace *> tr_fes;
|
|
|
|
Array<int> dof_offsets;
|
|
Array<int> tdof_offsets;
|
|
|
|
Array<int> rdof_offsets;
|
|
Array<int> rtdof_offsets;
|
|
|
|
// Schur complement matrix
|
|
// S = A_ii - A_ib (A_bb)^{-1} A_bi.
|
|
BlockMatrix * S_r = nullptr;
|
|
BlockMatrix * S_i = nullptr;
|
|
BlockMatrix * S_e_r = nullptr;
|
|
BlockMatrix * S_e_i = nullptr;
|
|
ComplexOperator * S = nullptr;
|
|
|
|
BlockVector * y_r = nullptr;
|
|
BlockVector * y_i = nullptr;
|
|
Vector * y = nullptr;
|
|
|
|
Array<ComplexDenseMatrix * > lmat;
|
|
Array<Vector * > lvec;
|
|
|
|
Array<int> rdof_edof; // Map from reduced dofs to exposed dofs
|
|
Array<int> ess_rtdof_list;
|
|
|
|
BlockMatrix * P = nullptr; // Block Prolongation
|
|
BlockMatrix * R = nullptr; // Block Restriction
|
|
|
|
#ifdef MFEM_USE_MPI
|
|
BlockOperator * pS_r = nullptr;
|
|
BlockOperator * pS_e_r = nullptr;
|
|
BlockOperator * pS_i = nullptr;
|
|
BlockOperator * pS_e_i = nullptr;
|
|
// Block HypreParMatrix for Prolongation
|
|
BlockOperator * pP = nullptr;
|
|
#endif
|
|
|
|
bool Parallel() const { return parallel; }
|
|
|
|
|
|
// tr_idx (trace dofs indices)
|
|
// int_idx (interior dof indices)
|
|
void GetReduceElementIndicesAndOffsets(int el, Array<int> & tr_idx,
|
|
Array<int> & int_idx,
|
|
Array<int> & offsets) const;
|
|
|
|
void GetReduceElementVDofs(int el, Array<int> & rdofs) const;
|
|
void GetElementVDofs(int el, Array<int> & vdofs) const;
|
|
|
|
|
|
// S = A_ii - A_ib (A_bb)^{-1} A_bi.
|
|
// y = y_i - A_ib (A_bb)^{-1} y_b
|
|
ComplexDenseMatrix * GetLocalShurComplement(int el, const Array<int> & tr_idx,
|
|
const Array<int> & int_idx,
|
|
const ComplexDenseMatrix & elmat,
|
|
const Vector & elvect_r,
|
|
const Vector & elvect_i,
|
|
Vector & rvect_r,
|
|
Vector & rvect_i);
|
|
|
|
void ComputeOffsets();
|
|
|
|
void BuildProlongation();
|
|
#ifdef MFEM_USE_MPI
|
|
void BuildParallelProlongation();
|
|
#endif
|
|
|
|
// ess_tdof list for each space
|
|
Array<Array<int> *> ess_tdofs;
|
|
void FillEssTdofLists(const Array<int> & ess_tdof_list);
|
|
|
|
void ConformingAssemble(int skip_zeros);
|
|
|
|
/** Restrict a marker Array on the true FE spaces dofs to a marker Array on
|
|
the reduced/trace true FE spaces dofs. */
|
|
void ConvertMarkerToReducedTrueDofs(Array<int> & tdof_marker,
|
|
Array<int> & rtdof_marker);
|
|
|
|
void SetSpaces(Array<FiniteElementSpace*> & fes_);
|
|
|
|
void Init();
|
|
|
|
public:
|
|
|
|
ComplexBlockStaticCondensation(Array<FiniteElementSpace *> & fes_);
|
|
|
|
~ComplexBlockStaticCondensation();
|
|
|
|
/** Assemble the contribution to the Schur complement from the given
|
|
element matrix @a elmat. Save the other blocks internally: A_bb_inv, A_bi,
|
|
and A_bi. */
|
|
void AssembleReducedSystem(int el, ComplexDenseMatrix &elmat,
|
|
Vector & elvect_r, Vector & elvect_i);
|
|
|
|
/// Finalize the construction of the Schur complement matrix.
|
|
void Finalize(int skip_zeros = 0);
|
|
|
|
/// Determine and save internally essential reduced true dofs.
|
|
void SetEssentialTrueDofs(const Array<int> &ess_tdof_list);
|
|
|
|
/// Eliminate the given reduced true dofs from the Schur complement matrix S.
|
|
void EliminateReducedTrueDofs(const Array<int> &ess_rtdof_list,
|
|
Matrix::DiagonalPolicy dpolicy);
|
|
|
|
bool HasEliminatedBC() const
|
|
{
|
|
#ifndef MFEM_USE_MPI
|
|
return S_e_r;
|
|
#else
|
|
return S_e_r || pS_e_r;
|
|
#endif
|
|
|
|
}
|
|
|
|
/// Return the serial Schur complement matrix.
|
|
BlockMatrix &GetSchurMatrix_r() { return *S_r; }
|
|
BlockMatrix &GetSchurMatrix_i() { return *S_i; }
|
|
ComplexOperator &GetSchurComplexOperator()
|
|
{
|
|
if (!S)
|
|
{
|
|
#ifndef MFEM_USE_MPI
|
|
S = new ComplexOperator(S_r,S_i,false,false);
|
|
#else
|
|
if (parallel)
|
|
{
|
|
S = new ComplexOperator(pS_r,pS_i,false,false);
|
|
}
|
|
else
|
|
{
|
|
S = new ComplexOperator(S_r,S_i,false,false);
|
|
}
|
|
#endif
|
|
}
|
|
return *S;
|
|
}
|
|
|
|
/// Return the eliminated part of the serial Schur complement matrix.
|
|
BlockMatrix &GetSchurMatrixElim_r() { return *S_e_r; }
|
|
BlockMatrix &GetSchurMatrixElim_i() { return *S_e_i; }
|
|
|
|
#ifdef MFEM_USE_MPI
|
|
/// Return the parallel Schur complement matrix.
|
|
BlockOperator &GetParallelSchurMatrix_r() { return *pS_r; }
|
|
BlockOperator &GetParallelSchurMatrix_i() { return *pS_i; }
|
|
|
|
/// Return the eliminated part of the parallel Schur complement matrix.
|
|
BlockOperator &GetParallelSchurMatrixElim_r() { return *pS_e_r; }
|
|
BlockOperator &GetParallelSchurMatrixElim_i() { return *pS_e_i; }
|
|
|
|
void ParallelAssemble(BlockMatrix *m_r, BlockMatrix*m_i);
|
|
#endif
|
|
|
|
/** Form the global reduced system matrix using the given @a diag_policy.
|
|
This method can be called after Assemble() is called. */
|
|
void FormSystemMatrix(Operator::DiagonalPolicy diag_policy);
|
|
|
|
/** Restrict a solution vector on the full FE space dofs to a vector on the
|
|
reduced/trace true FE space dofs. */
|
|
void ReduceSolution(const Vector &sol, Vector &sc_sol) const;
|
|
|
|
/** @brief Set the reduced solution `X` and r.h.s `B` vectors from the full
|
|
linear system solution `x` and r.h.s. `b` vectors.
|
|
This method should be called after the internal reduced essential dofs
|
|
have been set using SetEssentialTrueDofs() and both the Schur complement
|
|
and its eliminated part have been finalized. */
|
|
void ReduceSystem(Vector &x, Vector &X, Vector &B,
|
|
int copy_interior = 0) const;
|
|
|
|
/** Restrict a list of true FE space dofs to a list of reduced/trace true FE
|
|
space dofs. */
|
|
void ConvertListToReducedTrueDofs(const Array<int> &ess_tdof_list,
|
|
Array<int> &ess_rtdof_list) const;
|
|
|
|
/** Given a solution of the reduced system 'sc_sol' and the RHS 'b' for the
|
|
full linear system, compute the solution of the full system 'sol'. */
|
|
void ComputeSolution(const Vector &sc_sol, Vector &sol) const;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|