// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #include "fem.hpp" namespace mfem { void DofTransformation::TransformPrimal(real_t *v) const { if (IsIdentity()) { return; } int size = dof_trans_->Size(); if (vdim_ == 1 || (Ordering::Type)ordering_ == Ordering::byNODES) { for (int i=0; iTransformPrimal(Fo_, &v[i*size]); } } else { Vector vec(size); for (int i=0; iTransformPrimal(Fo_, vec); for (int j=0; jHeight(); if (vdim_ == 1 || (Ordering::Type)ordering_ == Ordering::byNODES) { for (int i=0; iInvTransformPrimal(Fo_, &v[i*size]); } } else { Vector vec(size); for (int i=0; iInvTransformPrimal(Fo_, vec); for (int j=0; jSize(); if (vdim_ == 1 || (Ordering::Type)ordering_ == Ordering::byNODES) { for (int i=0; iTransformDual(Fo_, &v[i*size]); } } else { Vector vec(size); for (int i=0; iTransformDual(Fo_, vec); for (int j=0; jSize(); if (vdim_ == 1 || (Ordering::Type)ordering_ == Ordering::byNODES) { for (int i=0; iInvTransformDual(Fo_, &v[i*size]); } } else { Vector vec(size); for (int i=0; iInvTransformDual(Fo_, vec); for (int j=0; j(ND_DofTransformation::T_data), 2, 2, 6); // ordering (i0j0, i1j0, i0j1, i1j1), each row is a column major matrix const real_t ND_DofTransformation::TInv_data[24] = { 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 0.0, 1.0, -1.0, -1.0, 1.0, 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0 }; const DenseTensor ND_DofTransformation ::TInv(const_cast(TInv_data), 2, 2, 6); ND_DofTransformation::ND_DofTransformation(int size, int p, int num_edges, int num_faces, int face_types[]) : StatelessDofTransformation(size) , order(p) , nedofs(p) , ntdofs(p*(p-1)) , nqdofs(2*p*(p-1)) , nedges(num_edges) , nfaces(num_faces) , ftypes(face_types) { } void ND_DofTransformation::TransformPrimal(const Array & Fo, real_t *v) const { // Return immediately when no face DoFs are present if (IsIdentity()) { return; } MFEM_VERIFY(Fo.Size() >= nfaces, "Face orientation array is shorter than the number of faces in " "ND_DofTransformation"); int of = 0; real_t data[2]; Vector v2(data, 2); DenseMatrix T2; // Transform face DoFs for (int f=0; f(T.GetData(Fo[f])), 2, 2); T2.Mult(v2, &v[nedges*nedofs + of + 2*i]); } of += ntdofs; } else { of += nqdofs; } } } void ND_DofTransformation::InvTransformPrimal(const Array & Fo, real_t *v) const { // Return immediately when no face DoFs are present if (IsIdentity()) { return; } MFEM_VERIFY(Fo.Size() >= nfaces, "Face orientation array is shorter than the number of faces in " "ND_DofTransformation"); int of = 0; real_t data[2]; Vector v2(data, 2); DenseMatrix T2Inv; // Transform face DoFs for (int f=0; f(TInv.GetData(Fo[f])), 2, 2); T2Inv.Mult(v2, &v[nedges*nedofs + of + 2*i]); } of += ntdofs; } else { of += nqdofs; } } } void ND_DofTransformation::TransformDual(const Array & Fo, real_t *v) const { // Return immediately when no face DoFs are present if (IsIdentity()) { return; } MFEM_VERIFY(Fo.Size() >= nfaces, "Face orientation array is shorter than the number of faces in " "ND_DofTransformation"); int of = 0; real_t data[2]; Vector v2(data, 2); DenseMatrix T2Inv; // Transform face DoFs for (int f=0; f(TInv.GetData(Fo[f])), 2, 2); T2Inv.MultTranspose(v2, &v[nedges*nedofs + of + 2*i]); } of += ntdofs; } else { of += nqdofs; } } } void ND_DofTransformation::InvTransformDual(const Array & Fo, real_t *v) const { // Return immediately when no face DoFs are present if (IsIdentity()) { return; } MFEM_VERIFY(Fo.Size() >= nfaces, "Face orientation array is shorter than the number of faces in " "ND_DofTransformation"); int of = 0; real_t data[2]; Vector v2(data, 2); DenseMatrix T2; // Transform face DoFs for (int f=0; f(T.GetData(Fo[f])), 2, 2); T2.MultTranspose(v2, &v[nedges*nedofs + of + 2*i]); } of += ntdofs; } else { of += nqdofs; } } } } // namespace mfem