MFEM v4.7.0 Finite element discretization library
Searching...
No Matches
doftrans.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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_tri_faces)
206 , order(p)
207 , nedofs(p)
208 , nfdofs(p*(p-1))
209 , nedges(num_edges)
210 , nfaces(num_tri_faces)
211{
212}
213
215 real_t *v) const
216{
217 // Return immediately when no face DoFs are present
218 if (IsIdentity()) { return; }
219
220 MFEM_VERIFY(Fo.Size() >= nfaces,
221 "Face orientation array is shorter than the number of faces in "
222 "ND_DofTransformation");
223
224 real_t data[2];
225 Vector v2(data, 2);
226 DenseMatrix T2;
227
228 // Transform face DoFs
229 for (int f=0; f<nfaces; f++)
230 {
231 for (int i=0; i<nfdofs/2; i++)
232 {
233 v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
234 T2.UseExternalData(const_cast<real_t *>(T.GetData(Fo[f])), 2, 2);
235 T2.Mult(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
236 }
237 }
238}
239
241 real_t *v) const
242{
243 // Return immediately when no face DoFs are present
244 if (IsIdentity()) { return; }
245
246 MFEM_VERIFY(Fo.Size() >= nfaces,
247 "Face orientation array is shorter than the number of faces in "
248 "ND_DofTransformation");
249
250 real_t data[2];
251 Vector v2(data, 2);
252 DenseMatrix T2Inv;
253
254 // Transform face DoFs
255 for (int f=0; f<nfaces; f++)
256 {
257 for (int i=0; i<nfdofs/2; i++)
258 {
259 v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
260 T2Inv.UseExternalData(const_cast<real_t *>(TInv.GetData(Fo[f])), 2, 2);
261 T2Inv.Mult(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
262 }
263 }
264}
265
267{
268 // Return immediately when no face DoFs are present
269 if (IsIdentity()) { return; }
270
271 MFEM_VERIFY(Fo.Size() >= nfaces,
272 "Face orientation array is shorter than the number of faces in "
273 "ND_DofTransformation");
274
275 real_t data[2];
276 Vector v2(data, 2);
277 DenseMatrix T2Inv;
278
279 // Transform face DoFs
280 for (int f=0; f<nfaces; f++)
281 {
282 for (int i=0; i<nfdofs/2; i++)
283 {
284 v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
285 T2Inv.UseExternalData(const_cast<real_t *>(TInv.GetData(Fo[f])), 2, 2);
286 T2Inv.MultTranspose(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
287 }
288 }
289}
290
292 real_t *v) const
293{
294 // Return immediately when no face DoFs are present
295 if (IsIdentity()) { return; }
296
297 MFEM_VERIFY(Fo.Size() >= nfaces,
298 "Face orientation array is shorter than the number of faces in "
299 "ND_DofTransformation");
300
301 real_t data[2];
302 Vector v2(data, 2);
303 DenseMatrix T2;
304
305 // Transform face DoFs
306 for (int f=0; f<nfaces; f++)
307 {
308 for (int i=0; i<nfdofs/2; i++)
309 {
310 v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
311 T2.UseExternalData(const_cast<real_t *>(T.GetData(Fo[f])), 2, 2);
312 T2.MultTranspose(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
313 }
314 }
315}
316
317} // namespace mfem
int Size() const
Return the logical size of the array.
Definition: array.hpp:144
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:220
void MultTranspose(const real_t *x, real_t *y) const
Multiply a vector with the transpose matrix.
Definition: densemat.cpp:262
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)
Definition: densemat.hpp:1208
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
ND_DofTransformation(int size, int order, int num_edges, int num_tri_faces)
Definition: doftrans.cpp:203
bool IsIdentity() const override
If the DofTransformation performs no transformation.
Definition: doftrans.hpp:325
void InvTransformDual(const Array< int > &Fo, real_t *v) const override
Definition: doftrans.cpp:291
void TransformPrimal(const Array< int > &Fo, real_t *v) const override
Definition: doftrans.cpp:214
void TransformDual(const Array< int > &Fo, real_t *v) const override
Definition: doftrans.cpp:266
void InvTransformPrimal(const Array< int > &Fo, real_t *v) const override
Definition: doftrans.cpp:240
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:80
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)
Definition: navier_mms.cpp:53