// 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. #ifndef MFEM_L2P_PAR_MORTAR_ASSEMBLER_HPP #define MFEM_L2P_PAR_MORTAR_ASSEMBLER_HPP #include "../../config/config.hpp" #ifdef MFEM_USE_MPI #include #include #include "../fem.hpp" #include "mortarintegrator.hpp" namespace mfem { /*! * @brief This class implements the parallel variational transfer between finite * element spaces. Variational transfer has been shown to have better * approximation properties than standard interpolation. This facilities can be * used for supporting applications which require the handling of non matching * meshes. For instance: General multi-physics problems, fluid structure * interaction, or even visualization of average quantities within subvolumes. This * particular code is also used with LLNL for large scale multilevel Monte Carlo * simulations. * This algorithm allows to perform quadrature in the intersection of elements * of two separate, unrelated, and arbitrarily distributed meshes. * It generates quadrature rules in the intersection which allows us to * integrate with to machine precision using the mfem::MortarIntegrator * interface. See https://doi.org/10.1137/15M1008361 for and in-depth * explanation. At this time curved elements are not supported. * Convex non-affine elements are partially supported, however, high order (>3) * finite element discretizations or nonlinear geometric transformations might * generate undesired oscillations. Discontinuous fields in general can only * be mapped to order 0 destination fields. * For such cases localized versions of the projection will have to be developed. */ class ParMortarAssembler { public: /*! * @brief constructs the object with source and destination spaces * @param source the source space from where we want to transfer the discrete * field * @param destination the source space to where we want to transfer the * discrete field */ ParMortarAssembler(const std::shared_ptr &source, const std::shared_ptr &destination); ~ParMortarAssembler(); /*! * @brief assembles the coupling matrix B. B : source -> destination If u is a * coefficient associated with source and v with destination Then v = M^(-1) * * B * u; where M is the mass matrix in destination. Works with * L2_FECollection, H1_FECollection and DG_FECollection (experimental with * RT_FECollection and ND_FECollection). * @param B the assembled coupling operator. B can be passed uninitialized. * @return true if there was an intersection and the operator has been * assembled. False otherwise. */ bool Assemble(std::shared_ptr &B); /*! * @brief transfer a function from source to destination. if the transfer is * to be performed multiple times use Assemble or Update/Apply instead * @param src_fun the function associated with the source finite element space * @param[out] dest_fun the function associated with the destination finite * element space * @return true if there was an intersection and the output can be used. */ bool Transfer(const ParGridFunction &src_fun, ParGridFunction &dest_fun); /*! * @brief transfer a function from source to destination. It requires that * the Update function is called before * @param src_fun the function associated with the source finite element space * @param[out] dest_fun the function associated with the destination finite element space * @return true if the transfer was successful, fail otherwise. */ bool Apply(const ParGridFunction &src_fun, ParGridFunction &dest_fun); /*! * @brief assembles the various components necessary for the transfer. * To be called before calling the Apply function if the mesh geometry * changed, after previous call. Works with L2_FECollection, H1_FECollection * and DG_FECollection (experimental with RT_FECollection and * ND_FECollection). * @return true if there was an intersection and the operator has been * assembled. False otherwise. */ bool Update(); /*! * @brief This method must be called before Assemble or Transfer. * It will assemble the operator in all intersections found. * @param integrator the integrator object */ void AddMortarIntegrator(const std::shared_ptr &integrator); /*! * @brief Expose process details with verbose output * @param verbose set to true for verbose output */ void SetVerbose(const bool verbose); /*! * @brief Control if the Mass matrix is computed together with the coupling * operator every time. * @param value is set to true for computing the mass matrix operator with * the coupling operator, false otherwise. The option is true by default, * set to false if only the coupling operator is needed. */ void SetAssembleMassAndCouplingTogether(const bool value); /*! * @brief Control the maximum numbers of conjugate gradients steps for mass * matrix inversion * @param max_solver_iterations the maximum number of iterations */ void SetMaxSolverIterations(const int max_solver_iterations); /*! * @brief Changes the solver to be used for solving the mass-matrix linear * system * @param solver new strategy */ void SetSolver(const std::shared_ptr &solver); struct Impl; private: std::unique_ptr impl_; }; } // namespace mfem #endif // MFEM_USE_MPI #endif // MFEM_L2P_PAR_MORTAR_ASSEMBLER_HPP