// 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 "unit_tests.hpp" #include "mfem.hpp" using namespace mfem; namespace hptransfer_test { int order=1; double u(const Vector & x) { return pow(x.Sum(),order); } void vecu(const Vector & x, Vector & U) { for (int i = 0; iGetNE(); i++) { if ((double) rand() / RAND_MAX < 0.5) { const int eorder = fes.GetElementOrder(i); fes.SetElementOrder(i,eorder+1); } } fes.Update(false); } /* This function randomly selects elements to be de-refined and sets the order of the elements that share the same parent to their minimum */ void PreprocessRandomDerefinement(FiniteElementSpace & fes, Array &drefs, double prob=0.5) { Mesh * mesh = fes.GetMesh(); const Table & dereftable = mesh->ncmesh->GetDerefinementTable(); int dref = dereftable.Size(); for (int i = 0; i < dref; i++) { if ((double) rand() / RAND_MAX < prob) { drefs.Append(i); } } // Go through the possible derefinements and set the orders to minimum Array row; for (int i = 0; i &drefs) { const Table & dereftable = mesh.ncmesh->GetDerefinementTable(); Array row; Vector errors(mesh.GetNE()); errors = infinity(); for (int i = 0; iHeight()); fes.GetHpRestrictionMatrix()->Mult(err_gf,tmp0); fes.GetProlongationMatrix()->Mult(tmp0,err_gf); } // 3a. Check if the prolonged GridFunction to the h-refined // mesh exactly reproduces the polynomial GridFunction REQUIRE(err_gf.Norml2() < 1e-11); // 4. Randomly p-refine the mesh and transfer the GridFunction Mesh cmesh(mesh); FiniteElementSpace cfes(&cmesh, fec, dimc); cfes.SetRelaxedHpConformity(relax_conformity); for (int i = 0; iHeight()); fes.GetHpRestrictionMatrix()->Mult(err_gf,tmp); fes.GetProlongationMatrix()->Mult(tmp,err_gf); } // 4a. Check if the prolonged GridFunction to the p-refined // mesh exactly reproduces the polynomial GridFunction REQUIRE(err_gf.Norml2() < 1e-11); // 5. Before randomly de-refining the mesh ensure that the elements // (of the same parent) that are going to be de-refined // have the same order Mesh fmesh(mesh); FiniteElementSpace ffes(&fmesh, fec, dimc); ffes.SetRelaxedHpConformity(relax_conformity); for (int i = 0; i drefs; // lower the order of the children to their minimum PreprocessRandomDerefinement(fes, drefs); PRefinementTransferOperator T2(ffes, fes); gf.SetSpace(&fes); T2.Mult(hpgf, gf); err_gf.SetSpace(&fes); if (space<=Space::L2) { err_gf.ProjectCoefficient(f); } else { err_gf.ProjectCoefficient(vf); } err_gf-= gf; if (fes.GetHpRestrictionMatrix()) { Vector temp(fes.GetHpRestrictionMatrix()->Height()); fes.GetHpRestrictionMatrix()->Mult(err_gf,temp); fes.GetProlongationMatrix()->Mult(temp,err_gf); } // 5a. Check if the restricted GridFunction to the p-derefined // mesh exactly reproduces the polynomial GridFunction REQUIRE(err_gf.Norml2() < 1e-11); // 6. De-refine the mesh and transfer the GridFunction Derefine(mesh,drefs); fes.Update(); gf.Update(); err_gf.SetSpace(&fes); err_gf = 0.0; if (space<=Space::L2) { err_gf.ProjectCoefficient(f); } else { err_gf.ProjectCoefficient(vf); } err_gf-= gf; if (fes.GetHpRestrictionMatrix()) { Vector temp(fes.GetHpRestrictionMatrix()->Height()); fes.GetHpRestrictionMatrix()->Mult(err_gf,temp); fes.GetProlongationMatrix()->Mult(temp,err_gf); } // 6a. Check if the restricted GridFunction to the de-refined // mesh exactly reproduces the polynomial GridFunction REQUIRE(err_gf.Norml2() < 1e-11); delete fec; } }