MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg_trace_jump_ea.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
14#include "../bilininteg.hpp"
16
17namespace mfem
18{
19
21 const FiniteElementSpace &trial_fes,
22 const FiniteElementSpace &test_fes,
23 Vector &emat,
24 const bool add)
25{
26 Mesh &mesh = *trial_fes.GetMesh();
27 const int dim = mesh.Dimension();
28 const FaceType ftype = FaceType::Interior;
29 const int nf = mesh.GetNFbyType(ftype);
30
31 const Geometry::Type geom = mesh.GetTypicalFaceGeometry();
32 const int trial_order = trial_fes.GetMaxElementOrder();
33 const int test_order = test_fes.GetMaxElementOrder();
34 const int qorder = test_order + trial_order - 1;
35 const IntegrationRule &ir = IntRule ? *IntRule : IntRules.Get(geom, qorder);
36 const int nquad = ir.Size();
37
38 Vector pa_data(nquad * nf);
39 {
40 const auto d_w = ir.GetWeights().Read();
41 auto d_pa_data = Reshape(pa_data.Write(), nquad, nf);
42 mfem::forall(nquad * nf, [=] MFEM_HOST_DEVICE (int idx)
43 {
44 const int q = idx % nquad;
45 const int f = idx / nquad;
46 d_pa_data(q, f) = d_w[q];
47 });
48 }
49
50 const FiniteElement &trial_face_el = *trial_fes.GetTypicalTraceElement();
51 const auto maps = &trial_face_el.GetDofToQuad(ir, DofToQuad::TENSOR);
52 const int ndof_face = trial_face_el.GetDof();
53
54 const Array<real_t> &B = maps->B;
55 const int d1d = maps->ndof;
56 const int q1d = maps->nqpt;
57
58 Vector mass_emat(ndof_face*ndof_face*nf);
59
60 // Note: dim is the element dimension, and we integrate over the faces (one
61 // dimension less)
62 if (dim == 2)
63 {
64 internal::EAMassAssemble1D(nf, B, pa_data, mass_emat, false, d1d, q1d);
65 }
66 else if (dim == 3)
67 {
68 internal::EAMassAssemble2D(nf, B, pa_data, mass_emat, false, d1d, q1d);
69 }
70 else
71 {
72 MFEM_ABORT("Unknown kernel.");
73 }
74
75 const FiniteElement &test_el = *test_fes.GetTypicalFE();
76 const int n_faces_per_el = 2*dim; // assuming tensor product
77 // Get all the local face maps (mapping from lexicographic face index to
78 // lexicographic volume index, depending on the local face index).
79 Array<int> face_maps(ndof_face * n_faces_per_el);
80 for (int lf_i = 0; lf_i < n_faces_per_el; ++lf_i)
81 {
82 Array<int> face_map(ndof_face);
83 test_el.GetFaceMap(lf_i, face_map);
84 for (int i = 0; i < ndof_face; ++i)
85 {
86 face_maps[i + lf_i*ndof_face] = face_map[i];
87 }
88 }
89
90 Array<int> face_info(nf * 4);
91 {
92 int fidx = 0;
93 for (int f = 0; f < mesh.GetNumFacesWithGhost(); ++f)
94 {
96 if (!finfo.IsInterior() || finfo.IsNonconformingCoarse()) { continue; }
97 face_info[0 + fidx*4] = finfo.element[0].local_face_id;
98 face_info[1 + fidx*4] = finfo.element[0].orientation;
99 face_info[2 + fidx*4] = finfo.element[1].local_face_id;
100 face_info[3 + fidx*4] = finfo.element[1].orientation;
101 fidx++;
102 }
103 }
104
105 const int ndof_vol = test_el.GetDof();
106 const auto d_face_maps = Reshape(face_maps.Read(), ndof_face, n_faces_per_el);
107 const auto d_face_info = Reshape(face_info.Read(), 2, 2, nf);
108
109 real_t *d_emat;
110 if (add)
111 {
112 d_emat = emat.ReadWrite();
113 }
114 else
115 {
116 d_emat = emat.Write();
117 emat = 0.0; // Will execute on device, since Write() sets the device flag
118 }
119
120 const auto face_mats = Reshape(mass_emat.Read(), ndof_face, ndof_face, nf);
121 auto el_mats = Reshape(d_emat, ndof_vol, ndof_face, 2, nf);
122
123 auto permute_face = [=] MFEM_HOST_DEVICE(int local_face_id, int orient,
124 int size1d, int index)
125 {
126 if (dim == 2)
127 {
128 return internal::PermuteFace2D(local_face_id, orient, size1d, index);
129 }
130 else // dim == 3
131 {
132 return internal::PermuteFace3D(local_face_id, orient, size1d, index);
133 }
134 };
135
136 auto permute_face_2 = [=] MFEM_HOST_DEVICE(int local_face_1, int local_face_2,
137 int orient, int size1d, int index)
138 {
139 if (dim == 2)
140 {
141 return internal::PermuteFace2D(local_face_1, local_face_2, orient,
142 size1d, index);
143 }
144 else // dim == 3
145 {
146 return internal::PermuteFace3D(local_face_1, local_face_2, orient,
147 size1d, index);
148 }
149 };
150
151 if (mesh.Conforming())
152 {
153 mfem::forall_3D(nf, ndof_face, ndof_face, 2, [=] MFEM_HOST_DEVICE (int f)
154 {
155 MFEM_FOREACH_THREAD(el_i, z, 2)
156 {
157 const int lf_i = d_face_info(0, el_i, f);
158 const int orient = d_face_info(1, el_i, f);
159 // Loop over face indices in "native ordering"
160 MFEM_FOREACH_THREAD(i_lex, x, ndof_face)
161 {
162 // Convert to lexicographic relative to the face itself
163 const int i_face = permute_face(lf_i, orient, d1d, i_lex);
164 // Convert from lexicographic face DOF to volume DOF
165 const int i = d_face_maps(i_lex, lf_i);
166 MFEM_FOREACH_THREAD(j, y, ndof_face)
167 {
168 el_mats(i, j, el_i, f) += face_mats(i_face, j, f);
169 }
170 }
171 }
172 });
173 }
174 else
175 {
176 const InterpolationManager &interp =
178
179 auto interp_configs = interp.GetFaceInterpConfig().Read();
180 const int nc_size = interp.GetNumInterpolators();
181 auto d_interp = Reshape(interp.GetInterpolators().Read(),
182 ndof_face, ndof_face, nc_size);
183
184 mfem::forall(nf, [=] MFEM_HOST_DEVICE (int f)
185 {
186 const InterpConfig conf = interp_configs[f];
187 const int master_side = conf.master_side;
188 const int interp_index = conf.index;
189
190 const int lf_0 = d_face_info(0, 0, f);
191
192 for (int el_i = 0; el_i < 2; ++el_i)
193 {
194 const int lf_i = d_face_info(0, el_i, f);
195 const int orient = d_face_info(1, el_i, f);
196
197 for (int j = 0; j < ndof_face; j++)
198 {
199 for (int i_lex = 0; i_lex < ndof_face; i_lex++)
200 {
201 real_t val = 0.0;
202 if (conf.is_non_conforming && el_i == master_side)
203 {
204 // Interpolate from el_i (coarse element) to the fine face.
205 // The mapping is given by d_interp, which uses indices
206 // relative to element 0.
207
208 // i0 is lexicographic relative to element 0
209 const int i0 = permute_face_2(lf_i, lf_0, orient, d1d, i_lex);
210
211 // k0 is lexicographic relative to element 0
212 for (int k0 = 0; k0 < ndof_face; k0++)
213 {
214 // k is relative to the face itself
215 const int k = permute_face(lf_0, orient, d1d, k0);
216 val += d_interp(k0, i0, interp_index)
217 * face_mats(k, j, f);
218 }
219 }
220 else
221 {
222 // Convert to lexicographic relative to the face itself
223 const int i_face = permute_face(lf_i, orient, d1d, i_lex);
224 val = face_mats(i_face, j, f);
225 }
226 // Convert from lexicographic face DOF to volume DOF
227 const int i = d_face_maps(i_lex, lf_i);
228 el_mats(i, j, el_i, f) += val;
229 }
230 }
231 }
232 });
233 }
234}
235
236}
int Size() const
Return the logical size of the array.
Definition array.hpp:192
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:410
@ TENSOR
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
Definition fe_base.hpp:165
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
const InterpolationManager & GetInterpolationManager(ElementDofOrdering f_ordering, FaceType type) const
Definition fespace.cpp:1547
const FiniteElement * GetTypicalTraceElement() const
Return a "typical" trace element.
Definition fespace.cpp:3999
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:639
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Definition fespace.cpp:3896
virtual int GetMaxElementOrder() const
Return the maximum polynomial order over all elements.
Definition fespace.hpp:669
Abstract class for all finite elements.
Definition fe_base.hpp:294
virtual const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
Definition fe_base.cpp:373
virtual void GetFaceMap(const int face_id, Array< int > &face_map) const
Return the mapping from lexicographic face DOFs to lexicographic element DOFs for the given local fac...
Definition fe_base.cpp:511
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:410
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
const Array< real_t > & GetWeights() const
Return the quadrature weights in a contiguous array.
Definition intrules.cpp:98
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
const IntegrationRule * IntRule
This class manages the storage and computation of the interpolations from master (coarse) face to sla...
int GetNumInterpolators() const
Return the total number of interpolators.
const Vector & GetInterpolators() const
Return an mfem::Vector containing the interpolators in the following format: face_dofs x face_dofs x ...
const Array< InterpConfig > & GetFaceInterpConfig() const
Return an array containing the interpolation configuration for each face registered with RegisterFace...
Mesh data type.
Definition mesh.hpp:67
bool Conforming() const
Definition mesh.cpp:16102
virtual int GetNFbyType(FaceType type) const
Returns the number of faces according to the requested type, does not count master nonconforming face...
Definition mesh.cpp:7318
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
FaceInformation GetFaceInformation(int f) const
Definition mesh.cpp:1368
int GetNumFacesWithGhost() const
Return the number of faces (3D), edges (2D) or vertices (1D) including ghost faces.
Definition mesh.cpp:7313
Geometry::Type GetTypicalFaceGeometry() const
If the local mesh is not empty, return GetFaceGeometry(0); otherwise return a typical face geometry p...
Definition mesh.cpp:1671
void AssembleEAInteriorFaces(const FiniteElementSpace &trial_fes, const FiniteElementSpace &test_fes, Vector &emat, const bool add=true) override
Method defining element assembly for mixed trace integrators.
Vector data type.
Definition vector.hpp:82
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:520
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:536
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:528
int dim
Definition ex24.cpp:53
int index(int i, int j, int nx, int ny)
Definition life.cpp:236
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition dtensor.hpp:138
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
Definition forall.hpp:1244
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
void forall(int N, lambda &&body)
Definition forall.hpp:1134
FaceType
Definition mesh.hpp:49
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:549
This structure is used as a human readable output format that deciphers the information contained in ...
Definition mesh.hpp:2098
bool IsNonconformingCoarse() const
Return true if the face is a nonconforming coarse face.
Definition mesh.hpp:2182
struct mfem::Mesh::FaceInformation::@15 element[2]
Information about the adjacent elements.
bool IsInterior() const
return true if the face is an interior face to the computation domain, either a local or shared inter...
Definition mesh.hpp:2138