MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
doftrans.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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
12#include "fem.hpp"
13
14namespace mfem
15{
16
18{
19 MFEM_ASSERT(dof_trans_,
20 "DofTransformation has no local transformation, call "
21 "SetDofTransformation first!");
22 int size = dof_trans_->Size();
23
25 {
26 for (int i=0; i<vdim_; i++)
27 {
28 dof_trans_->TransformPrimal(Fo_, &v[i*size]);
29 }
30 }
31 else
32 {
33 Vector vec(size);
34 for (int i=0; i<vdim_; i++)
35 {
36 for (int j=0; j<size; j++)
37 {
38 vec(j) = v[j*vdim_+i];
39 }
41 for (int j=0; j<size; j++)
42 {
43 v[j*vdim_+i] = vec(j);
44 }
45 }
46 }
47}
48
50{
51 MFEM_ASSERT(dof_trans_,
52 "DofTransformation has no local transformation, call "
53 "SetDofTransformation first!");
54 int size = dof_trans_->Height();
55
57 {
58 for (int i=0; i<vdim_; i++)
59 {
60 dof_trans_->InvTransformPrimal(Fo_, &v[i*size]);
61 }
62 }
63 else
64 {
65 Vector vec(size);
66 for (int i=0; i<vdim_; i++)
67 {
68 for (int j=0; j<size; j++)
69 {
70 vec(j) = v[j*vdim_+i];
71 }
73 for (int j=0; j<size; j++)
74 {
75 v[j*vdim_+i] = vec(j);
76 }
77 }
78 }
79}
80
82{
83 MFEM_ASSERT(dof_trans_,
84 "DofTransformation has no local transformation, call "
85 "SetDofTransformation first!");
86 int size = dof_trans_->Size();
87
89 {
90 for (int i=0; i<vdim_; i++)
91 {
92 dof_trans_->TransformDual(Fo_, &v[i*size]);
93 }
94 }
95 else
96 {
97 Vector vec(size);
98 for (int i=0; i<vdim_; i++)
99 {
100 for (int j=0; j<size; j++)
101 {
102 vec(j) = v[j*vdim_+i];
103 }
105 for (int j=0; j<size; j++)
106 {
107 v[j*vdim_+i] = vec(j);
108 }
109 }
110 }
111}
112
114{
115 MFEM_ASSERT(dof_trans_,
116 "DofTransformation has no local transformation, call "
117 "SetDofTransformation first!");
118 int size = dof_trans_->Size();
119
121 {
122 for (int i=0; i<vdim_; i++)
123 {
124 dof_trans_->InvTransformDual(Fo_, &v[i*size]);
125 }
126 }
127 else
128 {
129 Vector vec(size);
130 for (int i=0; i<vdim_; i++)
131 {
132 for (int j=0; j<size; j++)
133 {
134 vec(j) = v[j*vdim_+i];
135 }
137 for (int j=0; j<size; j++)
138 {
139 v[j*vdim_+i] = vec(j);
140 }
141 }
142 }
143}
144
145void TransformPrimal(const DofTransformation *ran_dof_trans,
146 const DofTransformation *dom_dof_trans,
147 DenseMatrix &elmat)
148{
149 // No action if both transformations are NULL
150 if (ran_dof_trans)
151 {
152 ran_dof_trans->TransformPrimalCols(elmat);
153 }
154 if (dom_dof_trans)
155 {
156 dom_dof_trans->TransformDualRows(elmat);
157 }
158}
159
160void TransformDual(const DofTransformation *ran_dof_trans,
161 const DofTransformation *dom_dof_trans,
162 DenseMatrix &elmat)
163{
164 // No action if both transformations are NULL
165 if (ran_dof_trans)
166 {
167 ran_dof_trans->TransformDualCols(elmat);
168 }
169 if (dom_dof_trans)
170 {
171 dom_dof_trans->TransformDualRows(elmat);
172 }
173}
174
175// ordering (i0j0, i1j0, i0j1, i1j1), each row is a column major matrix
176const real_t ND_DofTransformation::T_data[24] =
177{
178 1.0, 0.0, 0.0, 1.0,
179 -1.0, -1.0, 0.0, 1.0,
180 0.0, 1.0, -1.0, -1.0,
181 1.0, 0.0, -1.0, -1.0,
182 -1.0, -1.0, 1.0, 0.0,
183 0.0, 1.0, 1.0, 0.0
184};
185
186const DenseTensor ND_DofTransformation
187::T(const_cast<real_t *>(ND_DofTransformation::T_data), 2, 2, 6);
188
189// ordering (i0j0, i1j0, i0j1, i1j1), each row is a column major matrix
190const real_t ND_DofTransformation::TInv_data[24] =
191{
192 1.0, 0.0, 0.0, 1.0,
193 -1.0, -1.0, 0.0, 1.0,
194 -1.0, -1.0, 1.0, 0.0,
195 1.0, 0.0, -1.0, -1.0,
196 0.0, 1.0, -1.0, -1.0,
197 0.0, 1.0, 1.0, 0.0
198};
199
200const DenseTensor ND_DofTransformation
201::TInv(const_cast<real_t *>(TInv_data), 2, 2, 6);
202
204 int num_faces,
205 int face_types[])
207 , order(p)
208 , nedofs(p)
209 , ntdofs(p*(p-1))
210 , nqdofs(2*p*(p-1))
211 , nedges(num_edges)
212 , nfaces(num_faces)
213 , ftypes(face_types)
214{
215}
216
218 real_t *v) const
219{
220 // Return immediately when no face DoFs are present
221 if (IsIdentity()) { return; }
222
223 MFEM_VERIFY(Fo.Size() >= nfaces,
224 "Face orientation array is shorter than the number of faces in "
225 "ND_DofTransformation");
226
227 int of = 0;
228 real_t data[2];
229 Vector v2(data, 2);
230 DenseMatrix T2;
231
232 // Transform face DoFs
233 for (int f=0; f<nfaces; f++)
234 {
236 {
237 for (int i=0; i<ntdofs/2; i++)
238 {
239 v2 = &v[nedges*nedofs + of + 2*i];
240 T2.UseExternalData(const_cast<real_t *>(T.GetData(Fo[f])), 2, 2);
241 T2.Mult(v2, &v[nedges*nedofs + of + 2*i]);
242 }
243 of += ntdofs;
244 }
245 else
246 {
247 of += nqdofs;
248 }
249 }
250}
251
253 real_t *v) const
254{
255 // Return immediately when no face DoFs are present
256 if (IsIdentity()) { return; }
257
258 MFEM_VERIFY(Fo.Size() >= nfaces,
259 "Face orientation array is shorter than the number of faces in "
260 "ND_DofTransformation");
261
262 int of = 0;
263 real_t data[2];
264 Vector v2(data, 2);
265 DenseMatrix T2Inv;
266
267 // Transform face DoFs
268 for (int f=0; f<nfaces; f++)
269 {
271 {
272 for (int i=0; i<ntdofs/2; i++)
273 {
274 v2 = &v[nedges*nedofs + of + 2*i];
275 T2Inv.UseExternalData(const_cast<real_t *>(TInv.GetData(Fo[f])), 2, 2);
276 T2Inv.Mult(v2, &v[nedges*nedofs + of + 2*i]);
277 }
278 of += ntdofs;
279 }
280 else
281 {
282 of += nqdofs;
283 }
284 }
285}
286
288{
289 // Return immediately when no face DoFs are present
290 if (IsIdentity()) { return; }
291
292 MFEM_VERIFY(Fo.Size() >= nfaces,
293 "Face orientation array is shorter than the number of faces in "
294 "ND_DofTransformation");
295
296 int of = 0;
297 real_t data[2];
298 Vector v2(data, 2);
299 DenseMatrix T2Inv;
300
301 // Transform face DoFs
302 for (int f=0; f<nfaces; f++)
303 {
305 {
306 for (int i=0; i<ntdofs/2; i++)
307 {
308 v2 = &v[nedges*nedofs + of + 2*i];
309 T2Inv.UseExternalData(const_cast<real_t *>(TInv.GetData(Fo[f])), 2, 2);
310 T2Inv.MultTranspose(v2, &v[nedges*nedofs + of + 2*i]);
311 }
312 of += ntdofs;
313 }
314 else
315 {
316 of += nqdofs;
317 }
318
319 }
320}
321
323 real_t *v) const
324{
325 // Return immediately when no face DoFs are present
326 if (IsIdentity()) { return; }
327
328 MFEM_VERIFY(Fo.Size() >= nfaces,
329 "Face orientation array is shorter than the number of faces in "
330 "ND_DofTransformation");
331
332 int of = 0;
333 real_t data[2];
334 Vector v2(data, 2);
335 DenseMatrix T2;
336
337 // Transform face DoFs
338 for (int f=0; f<nfaces; f++)
339 {
341 {
342 for (int i=0; i<ntdofs/2; i++)
343 {
344 v2 = &v[nedges*nedofs + of + 2*i];
345 T2.UseExternalData(const_cast<real_t *>(T.GetData(Fo[f])), 2, 2);
346 T2.MultTranspose(v2, &v[nedges*nedofs + of + 2*i]);
347 }
348 of += ntdofs;
349 }
350 else
351 {
352 of += nqdofs;
353 }
354 }
355}
356
357} // namespace mfem
int Size() const
Return the logical size of the array.
Definition array.hpp:147
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
Definition densemat.cpp:125
void MultTranspose(const real_t *x, real_t *y) const
Multiply a vector with the transpose matrix.
Definition densemat.cpp:172
void UseExternalData(real_t *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition densemat.hpp:80
real_t * GetData(int k)
void TransformDual(real_t *v) const
Definition doftrans.cpp:81
void InvTransformPrimal(real_t *v) const
Definition doftrans.cpp:49
void TransformPrimalCols(DenseMatrix &V) const
Transform groups of DoFs stored as dense matrices.
Definition doftrans.hpp:215
const StatelessDofTransformation * dof_trans_
Definition doftrans.hpp:145
void TransformDualRows(DenseMatrix &V) const
Transform rows of a dense matrix containing dual DoFs.
Definition doftrans.hpp:252
void InvTransformDual(real_t *v) const
Definition doftrans.cpp:113
void TransformDualCols(DenseMatrix &V) const
Transform columns of a dense matrix containing dual DoFs.
Definition doftrans.hpp:264
void TransformPrimal(real_t *v) const
Definition doftrans.cpp:17
bool IsIdentity() const override
If the DofTransformation performs no transformation.
Definition doftrans.hpp:328
void InvTransformDual(const Array< int > &Fo, real_t *v) const override
Definition doftrans.cpp:322
void TransformPrimal(const Array< int > &Fo, real_t *v) const override
Definition doftrans.cpp:217
void TransformDual(const Array< int > &Fo, real_t *v) const override
Definition doftrans.cpp:287
ND_DofTransformation(int size, int order, int num_edges, int num_faces, int *face_types)
Definition doftrans.cpp:203
void InvTransformPrimal(const Array< int > &Fo, real_t *v) const override
Definition doftrans.cpp:252
Type
Ordering methods:
Definition fespace.hpp:34
virtual void InvTransformPrimal(const Array< int > &face_orientation, real_t *v) const =0
virtual void TransformPrimal(const Array< int > &face_orientation, real_t *v) const =0
virtual void InvTransformDual(const Array< int > &face_orientation, real_t *v) const =0
virtual void TransformDual(const Array< int > &face_orientation, real_t *v) const =0
Vector data type.
Definition vector.hpp:82
void TransformDual(const DofTransformation *ran_dof_trans, const DofTransformation *dom_dof_trans, DenseMatrix &elmat)
Definition doftrans.cpp:160
void TransformPrimal(const DofTransformation *ran_dof_trans, const DofTransformation *dom_dof_trans, DenseMatrix &elmat)
Definition doftrans.cpp:145
float real_t
Definition config.hpp:43
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
real_t p(const Vector &x, real_t t)