// Copyright (c) 2010-2022, 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 "mfem.hpp" #include "catch.hpp" using namespace mfem; namespace doftrans { TEST_CASE("DoF Transformation Classes", "[DofTransformation]" "[ND_TetDofTransformation]") { int p = 4; int seed = 123; double tol = 1e-13; SECTION("Nedelec Tetrahedral Transformations") { ND_TetDofTransformation T(p); Array ori(4); ori[0] = 1; ori[1] = 3; ori[2] = 5; ori[3] = 1; T.SetFaceOrientations(ori); Vector u(T.Width()); Vector v(T.Width()); Vector f(T.Width()); Vector ut; Vector vt; Vector ft; u.Randomize(seed); v.Randomize(seed+1); f.Randomize(seed+2); SECTION("Inverse DoF transformation") { Vector w; ut = u; T.TransformPrimal(ut); w = ut; T.InvTransformPrimal(w); w -= u; REQUIRE(w.Norml2() < tol * u.Norml2()); } SECTION("Inverse Dual DoF transformation") { Vector w; ut = u; T.TransformDual(ut); w = ut; T.InvTransformDual(w); w -= u; REQUIRE(w.Norml2() < tol * u.Norml2()); } SECTION("Inner product with linear form f(v)") { vt = v; T.TransformPrimal(vt); ft = f; T.TransformDual(ft); double fv = f * v; REQUIRE(fabs(fv - ft * vt) < tol * fabs(fv)); } DenseMatrix A(T.Width()); { Vector Ac; for (int i=0; i ori(4); ori[0] = 1; ori[1] = 3; ori[2] = 5; ori[3] = 1; Tp.SetFaceOrientations(ori); Tq.SetFaceOrientations(ori); DenseMatrix A(Tp.Width(), Tq.Width()); { Vector Ac; for (int i=0; i ori(4); ori[0] = 1; ori[1] = 3; ori[2] = 5; ori[3] = 1; Tnd.SetFaceOrientations(ori); SECTION("VDim == 1") { VDofTransformation T(Tnd); Vector v(T.Width()); Vector f(T.Width()); Vector vt; Vector ft; v.Randomize(seed); f.Randomize(seed+1); SECTION("Inverse DoF transformation") { Vector w; vt = v; T.TransformPrimal(vt); w = vt; T.InvTransformPrimal(w); w -= v; REQUIRE(w.Norml2() < tol * v.Norml2()); } SECTION("Inverse Dual DoF transformation") { Vector w; vt = v; T.TransformDual(vt); w = vt; T.InvTransformDual(w); w -= v; REQUIRE(w.Norml2() < tol * v.Norml2()); } SECTION("Inner product with linear form f(v)") { vt = v; T.TransformPrimal(vt); ft = f; T.TransformDual(ft); double fv = f * v; REQUIRE(fabs(fv - ft * vt) < tol * fabs(fv)); } } SECTION("VDim > 1") { Vector v(vdim * Tnd.Width()); Vector f(vdim * Tnd.Width()); Vector vt; Vector ft; v.Randomize(seed); f.Randomize(seed+1); SECTION("Ordering == byNODES") { VDofTransformation T(Tnd, vdim, Ordering::byNODES); SECTION("Inverse DoF transformation") { Vector w; vt = v; T.TransformPrimal(vt); w = vt; T.InvTransformPrimal(w); w -= v; REQUIRE(w.Norml2() < tol * v.Norml2()); } SECTION("Inverse Dual DoF transformation") { Vector w; vt = v; T.TransformDual(vt); w = vt; T.InvTransformDual(w); w -= v; REQUIRE(w.Norml2() < tol * v.Norml2()); } SECTION("Inner product with linear form f(v)") { vt = v; T.TransformPrimal(vt); ft = f; T.TransformDual(ft); double fv = f * v; REQUIRE(fabs(fv - ft * vt) < tol * fabs(fv)); } } SECTION("Ordering == byVDIM") { VDofTransformation T(Tnd, vdim, Ordering::byVDIM); SECTION("Inverse DoF transformation") { Vector w; vt = v; T.TransformPrimal(vt); w = vt; T.InvTransformPrimal(w); w -= v; REQUIRE(w.Norml2() < tol * v.Norml2()); } SECTION("Inverse Dual DoF transformation") { Vector w; vt = v; T.TransformDual(vt); w = vt; T.InvTransformDual(w); w -= v; REQUIRE(w.Norml2() < tol * v.Norml2()); } SECTION("Inner product with linear form f(v)") { vt = v; T.TransformPrimal(vt); ft = f; T.TransformDual(ft); double fv = f * v; REQUIRE(fabs(fv - ft * vt) < tol * fabs(fv)); } } } } } // namespace doftrans