#include "mfem.hpp" #include #include #include using namespace std; using namespace mfem; void f_exact(const Vector &x, Vector &f) { double kappa = 2*M_PI; if (x.Size() == 3) { f(0) = (1. + kappa * kappa) * sin(kappa * x(1)); f(1) = (1. + kappa * kappa) * sin(kappa * x(2)); f(2) = (1. + kappa * kappa) * sin(kappa * x(0)); } else if (x.Size() == 2) { f(0) = (1. + kappa * kappa) * sin(kappa * x(1)); f(1) = (1. + kappa * kappa) * sin(kappa * x(0)); } else { f(0) = (1. + kappa * kappa) * sin(kappa * x(0)); } } struct HybridizationSolver : Solver { Solver &solv; Hybridization &h; mutable Vector b_r, x_r; HybridizationSolver(Solver &solv_, Hybridization &h_) : Solver(solv_.Height()), solv(solv_), h(h_) { } void SetOperator(const Operator&) { } void Mult(const Vector &b, Vector &x) const { h.ReduceRHS(b, b_r); x_r.SetSize(b_r.Size()); x_r = 0.0; solv.Mult(b_r, x_r); h.ComputeSolution(b, x_r, x); } }; struct PermutedSolver : Solver { Solver &solv; Array p; mutable Vector bp, xp; PermutedSolver(Solver &solv_, const Array &p_) : Solver(solv_.Height()), solv(solv_), p(p_), bp(p.Size()), xp(p.Size()) { } void SetOperator(const Operator&) { } void Mult(const Vector &b, Vector &x) const { for (int i=0; i &GetDofMap(FiniteElementSpace &fes, int i) { const FiniteElement *fe = fes.GetFE(i); auto tfe = dynamic_cast(fe); MFEM_ASSERT(tfe != NULL, ""); return tfe->GetDofMap(); } Array ComputeVectorFE_LORPermutation( FiniteElementSpace &fes_ho, FiniteElementSpace &fes_lor, FiniteElement::MapType type) { // Given an index `i` of a LOR dof, `perm[i]` is the index of the // corresponding HO dof. Array perm(fes_lor.GetVSize()); Array vdof_ho, vdof_lor; Mesh &mesh_lor = *fes_lor.GetMesh(); int dim = mesh_lor.Dimension(); const CoarseFineTransformations &cf_tr = mesh_lor.GetRefinementTransforms(); for (int ilor=0; ilor &dofmap_ho = GetDofMap(fes_ho, iho); const Array &dofmap_lor = GetDofMap(fes_lor, ilor); int off_x = lor_index % p; int off_y = (lor_index / p) % p; int off_z = (lor_index / p) / p; auto absdof = [](int i) { return i < 0 ? -1-i : i; }; auto set_perm = [&](int off_lor, int off_ho, int n1, int n2) { for (int i1=0; i1<2; ++i1) { int m = (dim == 2 || type == FiniteElement::H_DIV) ? 1 : 2; for (int i2=0; i2 fec_ho, fec_lor, fec_h; unique_ptr fes_h; if (ND) { fec_ho.reset(new ND_FECollection(order, dim, BasisType::GaussLobatto, BasisType::Integrated)); fec_lor.reset(new ND_FECollection(1, dim, BasisType::GaussLobatto, BasisType::Integrated)); } else { fec_ho.reset(new RT_FECollection(order-1, dim, BasisType::GaussLobatto, BasisType::Integrated)); fec_lor.reset(new RT_FECollection(0, dim, BasisType::GaussLobatto, BasisType::Integrated)); if (hybridization) { fec_h.reset(new DG_Interface_FECollection(0, dim)); fes_h.reset(new ParFiniteElementSpace(&mesh_lor, fec_h.get())); } } ParFiniteElementSpace fes_ho(&mesh, fec_ho.get()); ParFiniteElementSpace fes_lor(&mesh_lor, fec_lor.get()); Array ess_tdof_list; ConstantCoefficient one(1.0); Vector ones_vec(dim); ones_vec = 1.0; VectorFunctionCoefficient coeff(dim, f_exact); ParBilinearForm a_ho(&fes_ho), a_lor(&fes_lor); // ParBilinearForm a_ho(&fes_lor), a_lor(&fes_lor); a_ho.AddDomainIntegrator(new VectorFEMassIntegrator); a_lor.AddDomainIntegrator(new VectorFEMassIntegrator); if (ND) { a_ho.AddDomainIntegrator(new CurlCurlIntegrator); a_lor.AddDomainIntegrator(new CurlCurlIntegrator); } else { a_ho.AddDomainIntegrator(new DivDivIntegrator); a_lor.AddDomainIntegrator(new DivDivIntegrator); if (hybridization) { a_lor.EnableHybridization(fes_h.get(), new NormalTraceJumpIntegrator, ess_tdof_list); } } a_ho.SetAssemblyLevel(AssemblyLevel::PARTIAL); a_ho.Assemble(); a_lor.Assemble(); a_lor.Finalize(); LinearForm b_lor(&fes_lor); b_lor.AddDomainIntegrator(new VectorFEDomainLFIntegrator(coeff)); b_lor.Assemble(); LinearForm b_ho(&fes_ho); b_ho.AddDomainIntegrator(new VectorFEDomainLFIntegrator(coeff)); b_ho.Assemble(); GridFunction x_ho(&fes_ho), x_lor(&fes_lor); x_ho = 0.0; x_lor = 0.0; Vector X_ho, B_ho, X_lor, B_lor; OperatorHandle A_ho, A_lor; a_ho.FormLinearSystem(ess_tdof_list, x_ho, b_ho, A_ho, X_ho, B_ho); a_lor.FormLinearSystem(ess_tdof_list, x_lor, b_lor, A_lor, X_lor, B_lor); unique_ptr solv_lor, amg; SparseMatrix diag; A_lor.As()->GetDiag(diag); if (RT && hybridization) { amg.reset(new HypreBoomerAMG(*A_lor.As())); // amg.reset(new UMFPackSolver(diag)); solv_lor.reset(new HybridizationSolver(*amg, *a_lor.GetHybridization())); } else if (RT && dim == 3) { solv_lor.reset(new HypreADS(&fes_lor)); } else { solv_lor.reset(new HypreAMS(&fes_lor)); } solv_lor->SetOperator(*A_lor); FiniteElement::MapType t = ND ? FiniteElement::H_CURL : FiniteElement::H_DIV; Array perm = ComputeVectorFE_LORPermutation(fes_ho, fes_lor, t); // TEMP // for (int i=0; i