// MFEM Fosls 1 // // Compile with: make blkfosls // // - Δ u = f, in Ω // u = 0, on ∂Ω // First Order System // ∇ u - σ = 0, in Ω // - ∇⋅σ = f, in Ω // u = 0, in ∂Ω // FOSLS: // minimize 1/2(||∇u - σ||^2 + ||∇ ⋅ σ - f||^2) // ------------------------------------------------- // | | u | σ | RHS | // ------------------------------------------------- // | v | (∇u,∇v) | -(σ,∇v) | 0 | // | | | | | // | τ | -(∇u,τ) | (∇⋅σ, ∇⋅τ) + (σ,τ) | -(f,∇⋅τ ) | // where (u,τ) ∈ H^1(Ω) × H(div,Ω) #include "mfem.hpp" #include #include using namespace std; using namespace mfem; int main(int argc, char *argv[]) { // 1. Parse command-line options. const char *mesh_file = "../../../data/inline-quad.mesh"; int order = 1; bool visualization = true; OptionsParser args(argc, argv); args.AddOption(&mesh_file, "-m", "--mesh", "Mesh file to use."); args.AddOption(&order, "-o", "--order", "Finite element order (polynomial degree) or -1 for" " isoparametric space."); args.AddOption(&visualization, "-vis", "--visualization", "-no-vis", "--no-visualization", "Enable or disable GLVis visualization."); args.Parse(); if (!args.Good()) { args.PrintUsage(cout); return 1; } args.PrintOptions(cout); // 3. Read the mesh from the given mesh file. We can handle triangular, // quadrilateral, tetrahedral, hexahedral, surface and volume meshes with // the same code. Mesh mesh(mesh_file, 1, 1); int dim = mesh.Dimension(); // 5. Define a finite element space on the mesh. Here we use continuous // Lagrange finite elements of the specified order. If order < 1, we // instead use an isoparametric/isogeometric space. FiniteElementCollection *fec0 = new H1_FECollection(order, dim); FiniteElementCollection *fec1 = new RT_FECollection(order-1, dim); FiniteElementSpace fespace0(&mesh, fec0); FiniteElementSpace fespace1(&mesh, fec1); Array fespaces(2); fespaces[0] = &fespace0; fespaces[1] = &fespace1; Array ess_bdr; Array ess_tdof_list; if (mesh.bdr_attributes.Size()) { ess_bdr.SetSize(mesh.bdr_attributes.Max()); ess_bdr = 1; fespaces[0]->GetEssentialTrueDofs(ess_bdr, ess_tdof_list); } BlockBilinearForm a(fespaces); a.SetDiagonalPolicy(mfem::Operator::DIAG_KEEP); cout << "H1 fespace = " << fespace0.GetVSize() << endl; cout << "RT fespace = " << fespace1.GetVSize() << endl; FiniteElementCollection *fec2 = new RT_Trace_FECollection(order-1, dim); FiniteElementSpace RT_trace_fes(&mesh, fec2); cout << "RT trace = " << RT_trace_fes.GetVSize() << endl; // for (int i = 0; i faces, ori; // mesh.GetElementEdges(i, faces, ori); // for (int f = 0; fGetDof() << endl; // Array face_dofs; // RT_trace_fes.GetFaceDofs(faces[f],face_dofs); // cout << "face dofs = " << endl; // face_dofs.Print(); // } // // cout << fe->GetGeomType() << endl; // Array vdofs; // RT_trace_fes.GetElementVDofs(i, vdofs); // cout << "trace dofs = " << endl; // vdofs.Print(); // fespace1.GetElementVDofs(i, vdofs); // cout << "elem dofs = " << endl; // vdofs.Print(); // cin.get(); // } ConstantCoefficient one(1.0); ConstantCoefficient negone(-1.0); Array2D blfi(2,2); blfi(0,0) = new DiffusionIntegrator(one); blfi(0,1) = new MixedVectorWeakDivergenceIntegrator(one); blfi(1,0) = new MixedVectorGradientIntegrator(negone); BilinearFormIntegrator * divdiv = new DivDivIntegrator(one); BilinearFormIntegrator * mass = new VectorFEMassIntegrator(one); SumIntegrator * suminteg = new SumIntegrator(); suminteg->AddIntegrator(divdiv); suminteg->AddIntegrator(mass); blfi(1,1) = suminteg; TestBlockBilinearFormIntegrator * integ = new TestBlockBilinearFormIntegrator(); integ->SetIntegrators(blfi); a.AddDomainIntegrator(integ); a.Assemble(); BlockLinearForm b(fespaces); TestBlockLinearFormIntegrator * lininteg = new TestBlockLinearFormIntegrator(); Array lfi(2); lfi[0] = nullptr; lfi[1] = new VectorFEDomainLFDivIntegrator(negone); lininteg->SetIntegrators(lfi); b.AddDomainIntegrator(lininteg); b.Assemble(); // need to implement blkgridfunction later but for now Vector would do int size = 0; for (int i = 0; iGetVSize(); } Vector x(size); x = 0.0; OperatorPtr A; Vector X,B; a.FormLinearSystem(ess_tdof_list,x,b,A,X,B); GSSmoother M((SparseMatrix&)(*A)); CGSolver cg; cg.SetRelTol(1e-6); cg.SetMaxIter(200); cg.SetPrintLevel(1); cg.SetPreconditioner(M); cg.SetOperator(*A); cg.Mult(B, X); a.RecoverFEMSolution(X,b,x); GridFunction u_gf, sigma_gf; double *data = x.GetData(); u_gf.MakeRef(fespaces[0],&data[0]); sigma_gf.MakeRef(fespaces[1],&data[fespaces[0]->GetVSize()]); if (visualization) { char vishost[] = "localhost"; int visport = 19916; socketstream solu_sock(vishost, visport); solu_sock.precision(8); solu_sock << "solution\n" << mesh << u_gf << "window_title 'Numerical u' " << flush; socketstream sols_sock(vishost, visport); sols_sock.precision(8); sols_sock << "solution\n" << mesh << sigma_gf << "window_title 'Numerical sigma' " << flush; } delete fec0; return 0; }