// Copyright (c) 2010-2020, 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 lin_interp { double f3(const Vector & x) { return 2.345 * x[0] + 3.579 * x[1] + 4.680 * x[2]; } void F3(const Vector & x, Vector & v) { v.SetSize(3); v[0] = 1.234 * x[0] - 2.357 * x[1] + 3.572 * x[2]; v[1] = 2.537 * x[0] + 4.321 * x[1] - 1.234 * x[2]; v[2] = -2.572 * x[0] + 1.321 * x[1] + 3.234 * x[2]; } double g3(const Vector & x) { return 4.234 * x[0] + 3.357 * x[1] + 1.572 * x[2]; } void G3(const Vector & x, Vector & v) { v.SetSize(3); v[0] = 4.234 * x[0] + 3.357 * x[1] + 1.572 * x[2]; v[1] = 4.537 * x[0] + 1.321 * x[1] + 2.234 * x[2]; v[2] = 1.572 * x[0] + 2.321 * x[1] + 3.234 * x[2]; } double fg3(const Vector & x) { return f3(x) * g3(x); } void fG3(const Vector & x, Vector & v) { G3(x, v); v *= f3(x); } void Fg3(const Vector & x, Vector & v) { F3(x, v); v *= g3(x); } void FcrossG3(const Vector & x, Vector & FxG) { Vector F; F3(x, F); Vector G; G3(x, G); FxG.SetSize(3); FxG(0) = F(1) * G(2) - F(2) * G(1); FxG(1) = F(2) * G(0) - F(0) * G(2); FxG(2) = F(0) * G(1) - F(1) * G(0); } double FdotG3(const Vector & x) { Vector F; F3(x, F); Vector G; G3(x, G); return F * G; } TEST_CASE("Linear Interpolators") { int order_h1 = 1, order_nd = 2, order_rt = 2, n = 3, dim = 3; double tol = 1e-9; Mesh mesh(n, n, n, Element::HEXAHEDRON, 1, 2.0, 3.0, 5.0); FunctionCoefficient fCoef(f3); VectorFunctionCoefficient FCoef(dim, F3); FunctionCoefficient gCoef(g3); VectorFunctionCoefficient GCoef(dim, G3); FunctionCoefficient fgCoef(fg3); FunctionCoefficient FGCoef(FdotG3); VectorFunctionCoefficient fGCoef(dim, fG3); VectorFunctionCoefficient FgCoef(dim, Fg3); VectorFunctionCoefficient FxGCoef(dim, FcrossG3); SECTION("Operators on H1") { H1_FECollection fec_h1(order_h1, dim); FiniteElementSpace fespace_h1(&mesh, &fec_h1); GridFunction g0(&fespace_h1); g0.ProjectCoefficient(gCoef); SECTION("Mapping H1 to H1") { GridFunction f0(&fespace_h1); f0.ProjectCoefficient(fCoef); H1_FECollection fec_h1p(2*order_h1, dim); FiniteElementSpace fespace_h1p(&mesh, &fec_h1p); DiscreteLinearOperator Opf0(&fespace_h1,&fespace_h1p); Opf0.AddDomainInterpolator(new ScalarProductInterpolator(fCoef)); Opf0.Assemble(); GridFunction fg0(&fespace_h1p); Opf0.Mult(g0,fg0); REQUIRE( fg0.ComputeL2Error(fgCoef) < tol ); } SECTION("Mapping to HCurl") { ND_FECollection fec_nd(order_nd, dim); FiniteElementSpace fespace_nd(&mesh, &fec_nd); GridFunction F1(&fespace_nd); F1.ProjectCoefficient(FCoef); ND_FECollection fec_ndp(order_h1+order_nd, dim); FiniteElementSpace fespace_ndp(&mesh, &fec_ndp); DiscreteLinearOperator OpF1(&fespace_h1,&fespace_ndp); OpF1.AddDomainInterpolator(new VectorScalarProductInterpolator(FCoef)); OpF1.Assemble(); GridFunction Fg1(&fespace_ndp); OpF1.Mult(g0,Fg1); REQUIRE( Fg1.ComputeL2Error(FgCoef) < tol ); } } SECTION("Operators on HCurl") { ND_FECollection fec_nd(order_nd, dim); FiniteElementSpace fespace_nd(&mesh, &fec_nd); GridFunction G1(&fespace_nd); G1.ProjectCoefficient(GCoef); SECTION("Mapping HCurl to HCurl") { H1_FECollection fec_h1(order_h1, dim); FiniteElementSpace fespace_h1(&mesh, &fec_h1); GridFunction f0(&fespace_h1); f0.ProjectCoefficient(fCoef); ND_FECollection fec_ndp(order_nd+order_h1, dim); FiniteElementSpace fespace_ndp(&mesh, &fec_ndp); DiscreteLinearOperator Opf0(&fespace_nd,&fespace_ndp); Opf0.AddDomainInterpolator(new ScalarVectorProductInterpolator(fCoef)); Opf0.Assemble(); GridFunction fG1(&fespace_ndp); Opf0.Mult(G1,fG1); REQUIRE( fG1.ComputeL2Error(fGCoef) < tol ); } SECTION("Mapping to HDiv") { GridFunction F1(&fespace_nd); F1.ProjectCoefficient(FCoef); RT_FECollection fec_rtp(2*order_nd, dim); FiniteElementSpace fespace_rtp(&mesh, &fec_rtp); DiscreteLinearOperator OpF1(&fespace_nd,&fespace_rtp); OpF1.AddDomainInterpolator(new VectorCrossProductInterpolator(FCoef)); OpF1.Assemble(); GridFunction FxG2(&fespace_rtp); OpF1.Mult(G1,FxG2); REQUIRE( FxG2.ComputeL2Error(FxGCoef) < tol ); } SECTION("Mapping to L2") { RT_FECollection fec_rt(order_rt, dim); FiniteElementSpace fespace_rt(&mesh, &fec_rt); GridFunction F2(&fespace_rt); F2.ProjectCoefficient(FCoef); L2_FECollection fec_l2p(order_nd+order_rt, dim); FiniteElementSpace fespace_l2p(&mesh, &fec_l2p); DiscreteLinearOperator OpF2(&fespace_nd,&fespace_l2p); OpF2.AddDomainInterpolator(new VectorInnerProductInterpolator(FCoef)); OpF2.Assemble(); GridFunction FG3(&fespace_l2p); OpF2.Mult(G1,FG3); REQUIRE( FG3.ComputeL2Error(FGCoef) < tol ); } } SECTION("Operators on HDiv") { RT_FECollection fec_rt(order_rt, dim); FiniteElementSpace fespace_rt(&mesh, &fec_rt); GridFunction G2(&fespace_rt); G2.ProjectCoefficient(GCoef); SECTION("Mapping to L2") { ND_FECollection fec_nd(order_nd, dim); FiniteElementSpace fespace_nd(&mesh, &fec_nd); GridFunction F1(&fespace_nd); F1.ProjectCoefficient(FCoef); L2_FECollection fec_l2p(order_nd+order_rt, dim); FiniteElementSpace fespace_l2p(&mesh, &fec_l2p); DiscreteLinearOperator OpF1(&fespace_rt,&fespace_l2p); OpF1.AddDomainInterpolator(new VectorInnerProductInterpolator(FCoef)); OpF1.Assemble(); GridFunction FG3(&fespace_l2p); OpF1.Mult(G2,FG3); REQUIRE( FG3.ComputeL2Error(FGCoef) < tol ); } } } } // namespace lin_interp