Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 : 4 : // This library is free software; you can redistribute it and/or 5 : // modify it under the terms of the GNU Lesser General Public 6 : // License as published by the Free Software Foundation; either 7 : // version 2.1 of the License, or (at your option) any later version. 8 : 9 : // This library is distributed in the hope that it will be useful, 10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : // Lesser General Public License for more details. 13 : 14 : // You should have received a copy of the GNU Lesser General Public 15 : // License along with this library; if not, write to the Free Software 16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 : 18 : 19 : 20 : #ifndef LIBMESH_DG_FEM_CONTEXT_H 21 : #define LIBMESH_DG_FEM_CONTEXT_H 22 : 23 : // Local Includes 24 : #include "libmesh/fem_context.h" 25 : 26 : 27 : namespace libMesh 28 : { 29 : 30 : /** 31 : * This class extends FEMContext in order to provide extra data 32 : * required to perform local element residual and Jacobian assembly 33 : * in the case of a discontinuous Galerkin (DG) discretization. 34 : * 35 : * \author David Knezevic 36 : * \date 2015 37 : * \brief Extends FEMContext to work for DG problems. 38 : */ 39 580 : class DGFEMContext : public FEMContext 40 : { 41 : public: 42 : 43 : /** 44 : * Constructor. Allocates some but fills no data structures. 45 : */ 46 : explicit 47 : DGFEMContext (const System & sys); 48 : 49 : /** 50 : * Destructor. 51 : */ 52 : virtual ~DGFEMContext (); 53 : 54 : /** 55 : * Override side_fe_reinit to set a boolean flag so that by 56 : * default DG terms are assumed to be inactive. DG terms are 57 : * only active if neighbor_side_fe_reinit is called. 58 : */ 59 : virtual void side_fe_reinit () override; 60 : 61 : /** 62 : * Initialize neighbor side data needed to assemble DG terms. 63 : * The neighbor element is determined by the current value of 64 : * get_neighbor(). 65 : */ 66 : void neighbor_side_fe_reinit (); 67 : 68 : /** 69 : * Accessor for neighbor dof indices 70 : */ 71 0 : const std::vector<dof_id_type> & get_neighbor_dof_indices() const 72 0 : { return _neighbor_dof_indices; } 73 : 74 : /** 75 : * Accessor for element dof indices of a particular variable corresponding 76 : * to the index argument. 77 : */ 78 : const std::vector<dof_id_type> & get_neighbor_dof_indices( unsigned int var ) const 79 : { return _neighbor_dof_indices_var[var]; } 80 : 81 : /** 82 : * Const accessor for neighbor residual. 83 : */ 84 : const DenseVector<Number> & get_neighbor_residual() const 85 : { return _neighbor_residual; } 86 : 87 : /** 88 : * Non-const accessor for neighbor residual. 89 : */ 90 : DenseVector<Number> & get_neighbor_residual() 91 : { return _neighbor_residual; } 92 : 93 : /** 94 : * Const accessor for neighbor residual of a particular variable corresponding 95 : * to the variable index argument. 96 : */ 97 : const DenseSubVector<Number> & get_neighbor_residual( unsigned int var ) const 98 : { return *(_neighbor_subresiduals[var]); } 99 : 100 : /** 101 : * Non-const accessor for neighbor residual of a particular variable corresponding 102 : * to the variable index argument. 103 : */ 104 : DenseSubVector<Number> & get_neighbor_residual( unsigned int var ) 105 : { return *(_neighbor_subresiduals[var]); } 106 : 107 : /** 108 : * Const accessor for element-element Jacobian. 109 : */ 110 : const DenseMatrix<Number> & get_elem_elem_jacobian() const 111 : { return _elem_elem_jacobian; } 112 : 113 : /** 114 : * Non-const accessor for element-element Jacobian. 115 : */ 116 0 : DenseMatrix<Number> & get_elem_elem_jacobian() 117 0 : { return _elem_elem_jacobian; } 118 : 119 : /** 120 : * Const accessor for element-element Jacobian of particular variables corresponding 121 : * to the variable index arguments. 122 : */ 123 : const DenseSubMatrix<Number> & get_elem_elem_jacobian( unsigned int var1, unsigned int var2 ) const 124 : { return *(_elem_elem_subjacobians[var1][var2]); } 125 : 126 : /** 127 : * Non-const accessor for element-element Jacobian of particular variables corresponding 128 : * to the variable index arguments. 129 : */ 130 : DenseSubMatrix<Number> & get_elem_elem_jacobian( unsigned int var1, unsigned int var2 ) 131 : { return *(_elem_elem_subjacobians[var1][var2]); } 132 : 133 : /** 134 : * Const accessor for element-neighbor Jacobian. 135 : */ 136 : const DenseMatrix<Number> & get_elem_neighbor_jacobian() const 137 : { return _elem_neighbor_jacobian; } 138 : 139 : /** 140 : * Non-const accessor for element -neighborJacobian. 141 : */ 142 0 : DenseMatrix<Number> & get_elem_neighbor_jacobian() 143 0 : { return _elem_neighbor_jacobian; } 144 : 145 : /** 146 : * Const accessor for element-neighbor Jacobian of particular variables corresponding 147 : * to the variable index arguments. 148 : */ 149 : const DenseSubMatrix<Number> & get_elem_neighbor_jacobian( unsigned int var1, unsigned int var2 ) const 150 : { return *(_elem_neighbor_subjacobians[var1][var2]); } 151 : 152 : /** 153 : * Non-const accessor for element-neighbor Jacobian of particular variables corresponding 154 : * to the variable index arguments. 155 : */ 156 : DenseSubMatrix<Number> & get_elem_neighbor_jacobian( unsigned int var1, unsigned int var2 ) 157 : { return *(_elem_neighbor_subjacobians[var1][var2]); } 158 : 159 : /** 160 : * Const accessor for element-neighbor Jacobian. 161 : */ 162 : const DenseMatrix<Number> & get_neighbor_elem_jacobian() const 163 : { return _neighbor_elem_jacobian; } 164 : 165 : /** 166 : * Non-const accessor for element Jacobian. 167 : */ 168 0 : DenseMatrix<Number> & get_neighbor_elem_jacobian() 169 0 : { return _neighbor_elem_jacobian; } 170 : 171 : /** 172 : * Const accessor for neighbor-element Jacobian of particular variables corresponding 173 : * to the variable index arguments. 174 : */ 175 : const DenseSubMatrix<Number> & get_neighbor_elem_jacobian( unsigned int var1, unsigned int var2 ) const 176 : { return *(_neighbor_elem_subjacobians[var1][var2]); } 177 : 178 : /** 179 : * Non-const accessor for neighbor-element Jacobian of particular variables corresponding 180 : * to the variable index arguments. 181 : */ 182 : DenseSubMatrix<Number> & get_neighbor_elem_jacobian( unsigned int var1, unsigned int var2 ) 183 : { return *(_neighbor_elem_subjacobians[var1][var2]); } 184 : 185 : /** 186 : * Const accessor for element-neighbor Jacobian. 187 : */ 188 : const DenseMatrix<Number> & get_neighbor_neighbor_jacobian() const 189 : { return _neighbor_neighbor_jacobian; } 190 : 191 : /** 192 : * Non-const accessor for element Jacobian. 193 : */ 194 0 : DenseMatrix<Number> & get_neighbor_neighbor_jacobian() 195 0 : { return _neighbor_neighbor_jacobian; } 196 : 197 : /** 198 : * Const accessor for neighbor-neighbor Jacobian of particular variables corresponding 199 : * to the variable index arguments. 200 : */ 201 : const DenseSubMatrix<Number> & get_neighbor_neighbor_jacobian( unsigned int var1, unsigned int var2 ) const 202 : { return *(_neighbor_neighbor_subjacobians[var1][var2]); } 203 : 204 : /** 205 : * Non-const accessor for neighbor-neighbor Jacobian of particular variables corresponding 206 : * to the variable index arguments. 207 : */ 208 : DenseSubMatrix<Number> & get_neighbor_neighbor_jacobian( unsigned int var1, unsigned int var2 ) 209 : { return *(_neighbor_neighbor_subjacobians[var1][var2]); } 210 : 211 : /** 212 : * Set the neighbor element which we will use to assemble DG terms. 213 : * 214 : * \note We do not assume that this element is get_elem().neighbor(side) 215 : * because we also need to be able to handle the special case of DG terms on 216 : * "cracks" in a mesh to model certain types of interface conditions. In this 217 : * case, we need to be able to specify the neighbor element manually. 218 : * Also, this should give us more flexibility to handle non-conforming meshes. 219 : */ 220 : void set_neighbor(const Elem & neighbor) 221 : { _neighbor = &neighbor; } 222 : 223 : /** 224 : * Accessor for current neighbor Elem object for assembling DG terms. 225 : */ 226 4800 : const Elem & get_neighbor() const 227 40800 : { return *_neighbor; } 228 : 229 : /** 230 : * Are the DG terms active, i.e. have they been assembled? 231 : */ 232 9780 : bool dg_terms_are_active() const 233 111880 : { return _dg_terms_active; } 234 : 235 : /** 236 : * Accessor for neighbor edge/face (2D/3D) finite element object for variable var. 237 : */ 238 : template<typename OutputShape> 239 : void get_neighbor_side_fe( unsigned int var, FEGenericBase<OutputShape> *& fe ) const; 240 : 241 : private: 242 : 243 : /** 244 : * Current neighbor element for assembling DG terms. 245 : */ 246 : const Elem * _neighbor; 247 : 248 : /** 249 : * Residual vector of the neighbor component. 250 : */ 251 : DenseVector<Number> _neighbor_residual; 252 : 253 : /** 254 : * The DG Jacobian terms. 255 : * Trial and test functions come from either element or neighbor. 256 : */ 257 : DenseMatrix<Number> _elem_elem_jacobian; 258 : DenseMatrix<Number> _elem_neighbor_jacobian; 259 : DenseMatrix<Number> _neighbor_elem_jacobian; 260 : DenseMatrix<Number> _neighbor_neighbor_jacobian; 261 : 262 : /** 263 : * Element residual subvectors and Jacobian submatrices 264 : */ 265 : std::vector<std::unique_ptr<DenseSubVector<Number>>> _neighbor_subresiduals; 266 : std::vector<std::vector<std::unique_ptr<DenseSubMatrix<Number>>>> _elem_elem_subjacobians; 267 : std::vector<std::vector<std::unique_ptr<DenseSubMatrix<Number>>>> _elem_neighbor_subjacobians; 268 : std::vector<std::vector<std::unique_ptr<DenseSubMatrix<Number>>>> _neighbor_elem_subjacobians; 269 : std::vector<std::vector<std::unique_ptr<DenseSubMatrix<Number>>>> _neighbor_neighbor_subjacobians; 270 : 271 : /** 272 : * Global Degree of freedom index lists for the neighbor element 273 : */ 274 : std::vector<dof_id_type> _neighbor_dof_indices; 275 : std::vector<std::vector<dof_id_type>> _neighbor_dof_indices_var; 276 : 277 : /** 278 : * Finite element objects for each variable's 279 : * sides on the neighbor element. 280 : * We do not need FE objects for neighbor element 281 : * interior since we just need to handle DG interface 282 : * terms here. 283 : */ 284 : std::map<FEType, std::unique_ptr<FEAbstract>> _neighbor_side_fe; 285 : 286 : /** 287 : * Pointers to the same finite element objects on the neighbor element, 288 : * but indexed by variable number 289 : */ 290 : std::vector<FEAbstract *> _neighbor_side_fe_var; 291 : 292 : /** 293 : * Boolean flag to indicate whether or not the DG terms have been 294 : * assembled and should be used in the global matrix assembly. 295 : */ 296 : bool _dg_terms_active; 297 : }; 298 : 299 : template<typename OutputShape> 300 : inline 301 : void DGFEMContext::get_neighbor_side_fe( unsigned int var, FEGenericBase<OutputShape> *& fe ) const 302 : { 303 : libmesh_assert_less ( var, _neighbor_side_fe_var.size() ); 304 : fe = cast_ptr<FEGenericBase<OutputShape> *>( _neighbor_side_fe_var[var] ); 305 : } 306 : 307 : } // namespace libMesh 308 : 309 : #endif // LIBMESH_FEM_CONTEXT_H