MFEM  v4.6.0
Finite element discretization library
doftrans.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, 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 
14 namespace mfem
15 {
16 
17 void TransformPrimal(const DofTransformation *ran_dof_trans,
18  const DofTransformation *dom_dof_trans,
19  DenseMatrix &elmat)
20 {
21  if (ran_dof_trans && dom_dof_trans)
22  {
23  ran_dof_trans->TransformPrimalCols(elmat);
24  dom_dof_trans->TransformDualRows(elmat);
25  }
26  else if (ran_dof_trans)
27  {
28  ran_dof_trans->TransformPrimalCols(elmat);
29  }
30  else if (dom_dof_trans)
31  {
32  dom_dof_trans->TransformDualRows(elmat);
33  }
34  else
35  {
36  // If both transformations are NULL this function should not be called
37  }
38 }
39 
40 void TransformDual(const DofTransformation *ran_dof_trans,
41  const DofTransformation *dom_dof_trans,
42  DenseMatrix &elmat)
43 {
44  if (ran_dof_trans && dom_dof_trans)
45  {
46  ran_dof_trans->TransformDualCols(elmat);
47  dom_dof_trans->TransformDualRows(elmat);
48  }
49  else if (ran_dof_trans)
50  {
51  ran_dof_trans->TransformDualCols(elmat);
52  }
53  else if (dom_dof_trans)
54  {
55  dom_dof_trans->TransformDualRows(elmat);
56  }
57  else
58  {
59  // If both transformations are NULL this function should not be called
60  }
61 }
62 
64  double *v) const
65 {
66  int size = sdoftrans_->Size();
67 
69  {
70  for (int i=0; i<vdim_; i++)
71  {
72  sdoftrans_->TransformPrimal(face_ori, &v[i*size]);
73  }
74  }
75  else
76  {
77  Vector vec(size);
78  for (int i=0; i<vdim_; i++)
79  {
80  for (int j=0; j<size; j++)
81  {
82  vec(j) = v[j*vdim_+i];
83  }
84  sdoftrans_->TransformPrimal(face_ori, vec);
85  for (int j=0; j<size; j++)
86  {
87  v[j*vdim_+i] = vec(j);
88  }
89  }
90  }
91 }
92 
94  const Array<int> & face_ori,
95  double *v) const
96 {
97  int size = sdoftrans_->Height();
98 
100  {
101  for (int i=0; i<vdim_; i++)
102  {
103  sdoftrans_->InvTransformPrimal(face_ori, &v[i*size]);
104  }
105  }
106  else
107  {
108  Vector vec(size);
109  for (int i=0; i<vdim_; i++)
110  {
111  for (int j=0; j<size; j++)
112  {
113  vec(j) = v[j*vdim_+i];
114  }
115  sdoftrans_->InvTransformPrimal(face_ori, vec);
116  for (int j=0; j<size; j++)
117  {
118  v[j*vdim_+i] = vec(j);
119  }
120  }
121  }
122 }
123 
125  double *v) const
126 {
127  int size = sdoftrans_->Size();
128 
130  {
131  for (int i=0; i<vdim_; i++)
132  {
133  sdoftrans_->TransformDual(face_ori, &v[i*size]);
134  }
135  }
136  else
137  {
138  Vector vec(size);
139  for (int i=0; i<vdim_; i++)
140  {
141  for (int j=0; j<size; j++)
142  {
143  vec(j) = v[j*vdim_+i];
144  }
145  sdoftrans_->TransformDual(face_ori, vec);
146  for (int j=0; j<size; j++)
147  {
148  v[j*vdim_+i] = vec(j);
149  }
150  }
151  }
152 }
153 
155  double *v) const
156 {
157  int size = sdoftrans_->Size();
158 
160  {
161  for (int i=0; i<vdim_; i++)
162  {
163  sdoftrans_->InvTransformDual(face_ori, &v[i*size]);
164  }
165  }
166  else
167  {
168  Vector vec(size);
169  for (int i=0; i<vdim_; i++)
170  {
171  for (int j=0; j<size; j++)
172  {
173  vec(j) = v[j*vdim_+i];
174  }
175  sdoftrans_->InvTransformDual(face_ori, vec);
176  for (int j=0; j<size; j++)
177  {
178  v[j*vdim_+i] = vec(j);
179  }
180  }
181  }
182 }
183 
184 // ordering (i0j0, i1j0, i0j1, i1j1), each row is a column major matrix
185 const double ND_StatelessDofTransformation::T_data[24] =
186 {
187  1.0, 0.0, 0.0, 1.0,
188  -1.0, -1.0, 0.0, 1.0,
189  0.0, 1.0, -1.0, -1.0,
190  1.0, 0.0, -1.0, -1.0,
191  -1.0, -1.0, 1.0, 0.0,
192  0.0, 1.0, 1.0, 0.0
193 };
194 
195 const DenseTensor ND_StatelessDofTransformation
196 ::T(const_cast<double*>(ND_StatelessDofTransformation::T_data), 2, 2, 6);
197 
198 // ordering (i0j0, i1j0, i0j1, i1j1), each row is a column major matrix
199 const double ND_StatelessDofTransformation::TInv_data[24] =
200 {
201  1.0, 0.0, 0.0, 1.0,
202  -1.0, -1.0, 0.0, 1.0,
203  -1.0, -1.0, 1.0, 0.0,
204  1.0, 0.0, -1.0, -1.0,
205  0.0, 1.0, -1.0, -1.0,
206  0.0, 1.0, 1.0, 0.0
207 };
208 
209 const DenseTensor ND_StatelessDofTransformation
210 ::TInv(const_cast<double*>(TInv_data), 2, 2, 6);
211 
213  int num_edges,
214  int num_tri_faces)
216  , order(p)
217  , nedofs(p)
218  , nfdofs(p*(p-1))
219  , nedges(num_edges)
220  , nfaces(num_tri_faces)
221 {
222 }
223 
225  double *v) const
226 {
227  // Return immediately when no face DoFs are present
228  if (nfdofs < 2) { return; }
229 
230  MFEM_VERIFY(Fo.Size() >= nfaces,
231  "Face orientation array is shorter than the number of faces in "
232  "ND_StatelessDofTransformation");
233 
234  double data[2];
235  Vector v2(data, 2);
236 
237  // Transform face DoFs
238  for (int f=0; f<nfaces; f++)
239  {
240  for (int i=0; i<nfdofs/2; i++)
241  {
242  v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
243  T(Fo[f]).Mult(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
244  }
245  }
246 }
247 
249  double *v) const
250 {
251  // Return immediately when no face DoFs are present
252  if (nfdofs < 2) { return; }
253 
254  MFEM_VERIFY(Fo.Size() >= nfaces,
255  "Face orientation array is shorter than the number of faces in "
256  "ND_StatelessDofTransformation");
257 
258  double data[2];
259  Vector v2(data, 2);
260 
261  // Transform face DoFs
262  for (int f=0; f<nfaces; f++)
263  {
264  for (int i=0; i<nfdofs/2; i++)
265  {
266  v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
267  TInv(Fo[f]).Mult(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
268  }
269  }
270 }
271 
273  double *v) const
274 {
275  // Return immediately when no face DoFs are present
276  if (nfdofs < 2) { return; }
277 
278  MFEM_VERIFY(Fo.Size() >= nfaces,
279  "Face orientation array is shorter than the number of faces in "
280  "ND_StatelessDofTransformation");
281 
282  double data[2];
283  Vector v2(data, 2);
284 
285  // Transform face DoFs
286  for (int f=0; f<nfaces; f++)
287  {
288  for (int i=0; i<nfdofs/2; i++)
289  {
290  v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
291  TInv(Fo[f]).MultTranspose(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
292  }
293  }
294 }
295 
297  double *v) const
298 {
299  // Return immediately when no face DoFs are present
300  if (nfdofs < 2) { return; }
301 
302  MFEM_VERIFY(Fo.Size() >= nfaces,
303  "Face orientation array is shorter than the number of faces in "
304  "ND_StatelessDofTransformation");
305 
306  double data[2];
307  Vector v2(data, 2);
308 
309  // Transform face DoFs
310  for (int f=0; f<nfaces; f++)
311  {
312  for (int i=0; i<nfdofs/2; i++)
313  {
314  v2 = &v[nedges*nedofs + f*nfdofs + 2*i];
315  T(Fo[f]).MultTranspose(v2, &v[nedges*nedofs + f*nfdofs + 2*i]);
316  }
317  }
318 }
319 
320 } // namespace mfem
virtual void TransformDual(const Array< int > &face_orientation, double *v) const =0
void TransformPrimalCols(DenseMatrix &V) const
Transform groups of DoFs stored as dense matrices.
Definition: doftrans.hpp:169
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
void InvTransformDual(const Array< int > &face_ori, double *v) const
Definition: doftrans.cpp:154
ND_StatelessDofTransformation(int size, int order, int num_edges, int num_tri_faces)
Definition: doftrans.cpp:212
std::function< double(const Vector &)> f(double mass_coeff)
Definition: lor_mms.hpp:30
void TransformPrimal(const DofTransformation *ran_dof_trans, const DofTransformation *dom_dof_trans, DenseMatrix &elmat)
Definition: doftrans.cpp:17
void InvTransformDual(const Array< int > &face_orientation, double *v) const
Definition: doftrans.cpp:296
Type
Ordering methods:
Definition: fespace.hpp:33
virtual void TransformPrimal(const Array< int > &face_orientation, double *v) const =0
virtual void InvTransformPrimal(const Array< int > &face_orientation, double *v) const =0
void TransformDual(const Array< int > &face_ori, double *v) const
Definition: doftrans.cpp:124
void InvTransformPrimal(const Array< int > &face_orientation, double *v) const
Definition: doftrans.cpp:248
void InvTransformPrimal(const Array< int > &face_ori, double *v) const
Definition: doftrans.cpp:93
void TransformDual(const Array< int > &face_orientation, double *v) const
Definition: doftrans.cpp:272
void TransformDualCols(DenseMatrix &V) const
Transform columns of a dense matrix containing dual DoFs.
Definition: doftrans.hpp:221
int Size() const
Return the logical size of the array.
Definition: array.hpp:141
void TransformDualRows(DenseMatrix &V) const
Transform rows of a dense matrix containing dual DoFs.
Definition: doftrans.hpp:209
Vector data type.
Definition: vector.hpp:58
virtual void InvTransformDual(const Array< int > &face_orientation, double *v) const =0
void TransformDual(const DofTransformation *ran_dof_trans, const DofTransformation *dom_dof_trans, DenseMatrix &elmat)
Definition: doftrans.cpp:40
void TransformPrimal(const Array< int > &face_ori, double *v) const
Definition: doftrans.cpp:63
void TransformPrimal(const Array< int > &face_orientation, double *v) const
Definition: doftrans.cpp:224
StatelessDofTransformation * sdoftrans_
Definition: doftrans.hpp:257