def Mult(self, x, y): globals()['max_char_speed'] = 0.; num_equation = globals()['num_equation'] # 1. Create the vector z with the face terms -<F.n(u), [w]>. self.A.Mult(x, self.z); # 2. Add the element terms. # i. computing the flux approximately as a grid function by interpolating # at the solution nodes. # ii. multiplying this grid function by a (constant) mixed bilinear form for # each of the num_equation, computing (F(u), grad(w)) for each equation. xmat = mfem.DenseMatrix(x.GetData(), self.vfes.GetNDofs(), num_equation) self.GetFlux(xmat, self.flux) for k in range(num_equation): fk = mfem.Vector(self.flux[k].GetData(), self.dim * self.vfes.GetNDofs()) o = k * self.vfes.GetNDofs() zk = self.z[o: o+self.vfes.GetNDofs()] self.Aflux.AddMult(fk, zk) # 3. Multiply element-wise by the inverse mass matrices. zval = mfem.Vector() vdofs = mfem.intArray() dof = self.vfes.GetFE(0).GetDof() zmat = mfem.DenseMatrix() ymat = mfem.DenseMatrix(dof, num_equation) for i in range(self.vfes.GetNE()): # Return the vdofs ordered byNODES vdofs = mfem.intArray(self.vfes.GetElementVDofs(i)) self.z.GetSubVector(vdofs, zval) zmat.UseExternalData(zval.GetData(), dof, num_equation) mfem.Mult(self.Me_inv[i], zmat, ymat); y.SetSubVector(vdofs, ymat.GetData())
def make_mask(values, X, Y, Z, mask_start=0, logfile=None): ''' mask for interpolation ''' mask = np.zeros(len(X.flatten()), dtype=int) - 1 for kk, data in enumerate(values): ptx, ret, gfr = data xmax = np.max(ptx[:, 0]) xmin = np.min(ptx[:, 0]) ymax = np.max(ptx[:, 1]) ymin = np.min(ptx[:, 1]) zmax = np.max(ptx[:, 2]) zmin = np.min(ptx[:, 2]) i1 = np.logical_and(xmax >= X.flatten(), xmin <= X.flatten()) i2 = np.logical_and(ymax >= Y.flatten(), ymin <= Y.flatten()) i3 = np.logical_and(zmax >= Z.flatten(), zmin <= Z.flatten()) ii = np.logical_and(np.logical_and(i1, i2), i3) mesh = gfr.FESpace().GetMesh() XX = X.flatten()[ii] YY = Y.flatten()[ii] ZZ = Z.flatten()[ii] size = len(XX) m = mfem.DenseMatrix(3, size) ptx = np.vstack([XX, YY, ZZ]) if logfile is not None: txt = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) logfile.write(txt + "\n") logfile.write("calling FindPoints : size = " + str(XX.shape) + " " + str(kk + 1) + '/' + str(len(values)) + "\n") m.Assign(ptx) ips = mfem.IntegrationPointArray() elem_ids = mfem.intArray() pts_found = mesh.FindPoints(m, elem_ids, ips) ii = np.where(ii)[0][np.array(elem_ids.ToList()) != -1] mask[ii] = kk + mask_start if logfile is not None: logfile.write("done\n") return mask
def __init__(self, fespace, alpha, kappa, u): mfem.PyTimeDependentOperator.__init__(self, fespace.GetTrueVSize(), 0.0) rel_tol = 1e-8 self.alpha = alpha self.kappa = kappa self.T = None self.K = None self.M = None self.fespace = fespace self.ess_tdof_list = intArray() self.Mmat = mfem.SparseMatrix() self.Kmat = mfem.SparseMatrix() self.M_solver = mfem.CGSolver() self.M_prec = mfem.DSmoother() self.T_solver = mfem.CGSolver() self.T_prec = mfem.DSmoother() self.z = mfem.Vector(self.Height()) self.M = mfem.BilinearForm(fespace) self.M.AddDomainIntegrator(mfem.MassIntegrator()) self.M.Assemble() self.M.FormSystemMatrix(self.ess_tdof_list, self.Mmat) self.M_solver.iterative_mode = False self.M_solver.SetRelTol(rel_tol) self.M_solver.SetAbsTol(0.0) self.M_solver.SetMaxIter(30) self.M_solver.SetPrintLevel(0) self.M_solver.SetPreconditioner(self.M_prec) self.M_solver.SetOperator(self.Mmat) self.T_solver.iterative_mode = False self.T_solver.SetRelTol(rel_tol) self.T_solver.SetAbsTol(0.0) self.T_solver.SetMaxIter(100) self.T_solver.SetPrintLevel(0) self.T_solver.SetPreconditioner(self.T_prec) self.SetParameters(u)
if (mesh.NURBSext): mesh.SetCurvature(order) # 4. Define a DG vector finite element space on the mesh. Here, we use # Gauss-Lobatto nodal basis because it gives rise to a sparser matrix # compared to the default Gauss-Legendre nodal basis. fec = mfem.DG_FECollection(order, dim, mfem.BasisType.GaussLobatto) fespace = mfem.FiniteElementSpace(mesh, fec, dim) print('Number of finite element unknowns: '+ str(fespace.GetVSize())) print('Assembling:') # 5. In this example, the Dirichlet boundary conditions are defined by # marking boundary attributes 1 and 2 in the marker Array 'dir_bdr'. # These b.c. are imposed weakly, by adding the appropriate boundary # integrators over the marked 'dir_bdr' to the bilinear and linear forms. # With this DG formulation, there are no essential boundary conditions. ess_tdof_list = intArray() dir_bdr = intArray(mesh.bdr_attributes.Max()) dir_bdr.Assign(0) dir_bdr[0] = 1 # boundary attribute 1 is Dirichlet dir_bdr[1] = 1 # boundary attribute 2 is Dirichlet # 6. Define the DG solution vector 'x' as a finite element grid function # corresponding to fespace. Initialize 'x' using the 'InitDisplacement' # function. x = mfem.GridFunction(fespace) init_x = InitDisplacement(dim) x.ProjectCoefficient(init_x) # 7. Set up the Lame constants for the two materials. They are defined as # piece-wise (with respect to the element attributes) constant # coefficients, i.e. type PWConstCoefficient.
mesh.ReorientTetMesh(); # 4. Define a finite element space on the mesh. Here we use the Nedelec # finite elements of the specified order. fec = mfem.ND_FECollection(order, dim) fespace = mfem.FiniteElementSpace(mesh, fec) print("Number of finite element unknowns: " + str(fespace.GetTrueVSize())) # 5. Determine the list of true (i.e. conforming) essential boundary dofs. # In this example, the boundary conditions are defined by marking all # the boundary attributes from the mesh as essential (Dirichlet) and # converting them to a list of true dofs. ess_tdof_list = intArray(); if mesh.bdr_attributes.Size(): ess_bdr = intArray(mesh.bdr_attributes.Max()) ess_bdr = intArray([1]*mesh.bdr_attributes.Max()) fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list); # 6. Set up the linear form b(.) which corresponds to the right-hand side # of the FEM linear system, which in this case is (f,phi_i) where f is # given by the function f_exact and phi_i are the basis functions in the # finite element fespace. b = mfem.LinearForm(fespace); f = f_exact() dd = mfem.VectorFEDomainLFIntegrator(f); b.AddDomainIntegrator(dd) b.Assemble();
# associated with the mesh nodes. if order > 0: fec = mfem.H1_FECollection(order, dim) elif mesh.GetNodes(): fec = mesh.GetNodes().OwnFEC() prinr("Using isoparametric FEs: " + str(fec.Name())) else: order = 1 fec = mfem.H1_FECollection(order, dim) fespace = mfem.FiniteElementSpace(mesh, fec) print('Number of finite element unknowns: ' + str(fespace.GetTrueVSize())) # 5. Determine the list of true (i.e. conforming) essential boundary dofs. # In this example, the boundary conditions are defined by marking all # the boundary attributes from the mesh as essential (Dirichlet) and # converting them to a list of true dofs. ess_tdof_list = mfem.intArray() if mesh.bdr_attributes.Size() > 0: ess_bdr = mfem.intArray([1] * mesh.bdr_attributes.Max()) ess_bdr = mfem.intArray(mesh.bdr_attributes.Max()) ess_bdr.Assign(1) fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list) #6. Set up the linear form b(.) which corresponds to the right-hand side of # the FEM linear system, which in this case is (1,phi_i) where phi_i are # the basis functions in the finite element fespace. b = mfem.LinearForm(fespace) one = mfem.ConstantCoefficient(1.0) b.AddDomainIntegrator(mfem.DomainLFIntegrator(one)) b.Assemble() #7. Define the solution vector x as a finite element grid function # corresponding to fespace. Initialize x with initial guess of zero, # which satisfies the boundary conditions.
hdiv_coll = mfem.RT_FECollection(order, dim) l2_coll = mfem.L2_FECollection(order, dim) R_space = mfem.FiniteElementSpace(mesh, hdiv_coll) W_space = mfem.FiniteElementSpace(mesh, l2_coll) dimR = R_space.GetVSize() dimW = W_space.GetVSize() print("***********************************************************") print("dim(R) = " + str(dimR)) print("dim(W) = " + str(dimW)) print("dim(R+W) = " + str(dimR + dimW)) print("***********************************************************") block_offsets = intArray([0, dimR, dimW]) block_offsets.PartialSum() k = mfem.ConstantCoefficient(1.0) fcoeff = fFunc(dim) fnatcoeff = f_natural() gcoeff = gFunc() ucoeff = uFunc_ex(dim) pcoeff = pFunc_ex() x = mfem.BlockVector(block_offsets) rhs = mfem.BlockVector(block_offsets) fform = mfem.LinearForm() fform.Update(R_space, rhs.GetBlock(0), 0)
def run(order=1, static_cond=False, meshfile=def_meshfile, visualization=False): mesh = mfem.Mesh(meshfile, 1, 1) dim = mesh.Dimension() # 3. Refine the mesh to increase the resolution. In this example we do # 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the # largest number that gives a final mesh with no more than 50,000 # elements. ref_levels = int(np.floor( np.log(50000. / mesh.GetNE()) / np.log(2.) / dim)) for x in range(ref_levels): mesh.UniformRefinement() #5. Define a finite element space on the mesh. Here we use vector finite # elements, i.e. dim copies of a scalar finite element space. The vector # dimension is specified by the last argument of the FiniteElementSpace # constructor. For NURBS meshes, we use the (degree elevated) NURBS space # associated with the mesh nodes. if order > 0: fec = mfem.H1_FECollection(order, dim) elif mesh.GetNodes(): fec = mesh.GetNodes().OwnFEC() prinr("Using isoparametric FEs: " + str(fec.Name())) else: order = 1 fec = mfem.H1_FECollection(order, dim) fespace = mfem.FiniteElementSpace(mesh, fec) print('Number of finite element unknowns: ' + str(fespace.GetTrueVSize())) # 5. Determine the list of true (i.e. conforming) essential boundary dofs. # In this example, the boundary conditions are defined by marking all # the boundary attributes from the mesh as essential (Dirichlet) and # converting them to a list of true dofs. ess_tdof_list = mfem.intArray() if mesh.bdr_attributes.Size() > 0: ess_bdr = mfem.intArray([1] * mesh.bdr_attributes.Max()) ess_bdr = mfem.intArray(mesh.bdr_attributes.Max()) ess_bdr.Assign(1) fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list) #6. Set up the linear form b(.) which corresponds to the right-hand side of # the FEM linear system, which in this case is (1,phi_i) where phi_i are # the basis functions in the finite element fespace. b = mfem.LinearForm(fespace) one = mfem.ConstantCoefficient(1.0) b.AddDomainIntegrator(mfem.DomainLFIntegrator(one)) b.Assemble() #7. Define the solution vector x as a finite element grid function # corresponding to fespace. Initialize x with initial guess of zero, # which satisfies the boundary conditions. x = mfem.GridFunction(fespace) x.Assign(0.0) #8. Set up the bilinear form a(.,.) on the finite element space # corresponding to the Laplacian operator -Delta, by adding the Diffusion # domain integrator. a = mfem.BilinearForm(fespace) a.AddDomainIntegrator(mfem.DiffusionIntegrator(one)) #9. Assemble the bilinear form and the corresponding linear system, # applying any necessary transformations such as: eliminating boundary # conditions, applying conforming constraints for non-conforming AMR, # static condensation, etc. if static_cond: a.EnableStaticCondensation() a.Assemble() A = mfem.OperatorPtr() B = mfem.Vector() X = mfem.Vector() a.FormLinearSystem(ess_tdof_list, x, b, A, X, B) print("Size of linear system: " + str(A.Height())) # 10. Solve AA = mfem.OperatorHandle2SparseMatrix(A) M = mfem.GSSmoother(AA) mfem.PCG(AA, M, B, X, 1, 200, 1e-12, 0.0) # 11. Recover the solution as a finite element grid function. a.RecoverFEMSolution(X, b, x) # 12. Save the refined mesh and the solution. This output can be viewed later # using GLVis: "glvis -m refined.mesh -g sol.gf". mesh.Print('refined.mesh', 8) x.Save('sol.gf', 8) #13. Send the solution by socket to a GLVis server. if (visualization): sol_sock = mfem.socketstream("localhost", 19916) sol_sock.precision(8) sol_sock.send_solution(mesh, x)
import sys import numpy as np from scipy.sparse import csr_matrix if len(sys.argv) < 2: import mfem.ser as mfem elif sys.argv[1] == 'par': import mfem.par as mfem smat = csr_matrix([[ 1, 2, 3, ], [0, 0, 1], [2, 0, 0]]) mmat = mfem.SparseMatrix(smat) offset1 = mfem.intArray([0, 3, 6]) offset2 = mfem.intArray([0, 3, 6]) m = mfem.BlockMatrix(offset1, offset2) m.SetBlock(0, 0, mmat) print m._offsets print m._linked_mat m = mfem.BlockMatrix(offset1) m.SetBlock(0, 1, mmat) m.SetBlock(1, 0, mmat) print m._offsets print m._linked_mat
def ex19_main(args): ref_levels = args.refine order = args.order visualization = args.visualization mu = args.shear_modulus newton_rel_tol = args.relative_tolerance newton_abs_tol = args.absolute_tolerance newton_iter = args.newton_iterations parser.print_options(args) meshfile = expanduser(join(path, 'data', args.mesh)) mesh = mfem.Mesh(meshfile, 1, 1) dim = mesh.Dimension() for lev in range(ref_levels): mesh.UniformRefinement() # 4. Define the shear modulus for the incompressible Neo-Hookean material c_mu = mfem.ConstantCoefficient(mu) # 5. Define the finite element spaces for displacement and pressure # (Taylor-Hood elements). By default, the displacement (u/x) is a second # order vector field, while the pressure (p) is a linear scalar function. quad_coll = mfem.H1_FECollection(order, dim) lin_coll = mfem.H1_FECollection(order - 1, dim) R_space = mfem.FiniteElementSpace(mesh, quad_coll, dim, mfem.Ordering.byVDIM) W_space = mfem.FiniteElementSpace(mesh, lin_coll) spaces = [R_space, W_space] R_size = R_space.GetVSize() W_size = W_space.GetVSize() # 6. Define the Dirichlet conditions (set to boundary attribute 1 and 2) ess_bdr_u = mfem.intArray(R_space.GetMesh().bdr_attributes.Max()) ess_bdr_p = mfem.intArray(W_space.GetMesh().bdr_attributes.Max()) ess_bdr_u.Assign(0) ess_bdr_u[0] = 1 ess_bdr_u[1] = 1 ess_bdr_p.Assign(0) ess_bdr = [ess_bdr_u, ess_bdr_p] print("***********************************************************") print("dim(u) = " + str(R_size)) print("dim(p) = " + str(W_size)) print("dim(u+p) = " + str(R_size + W_size)) print("***********************************************************") block_offsets = intArray([0, R_size, W_size]) block_offsets.PartialSum() xp = mfem.BlockVector(block_offsets) # 9. Define grid functions for the current configuration, reference # configuration, final deformation, and pressure x_gf = mfem.GridFunction(R_space) x_ref = mfem.GridFunction(R_space) x_def = mfem.GridFunction(R_space) p_gf = mfem.GridFunction(W_space) x_gf.MakeRef(R_space, xp.GetBlock(0), 0) p_gf.MakeRef(W_space, xp.GetBlock(1), 0) deform = InitialDeformation(dim) refconfig = ReferenceConfiguration(dim) x_gf.ProjectCoefficient(deform) x_ref.ProjectCoefficient(refconfig) p_gf.Assign(0.0) # 10. Initialize the incompressible neo-Hookean operator oper = RubberOperator(spaces, ess_bdr, block_offsets, newton_rel_tol, newton_abs_tol, newton_iter, mu) # 11. Solve the Newton system oper.Solve(xp) # 12. Compute the final deformation mfem.subtract_vector(x_gf, x_ref, x_def) # 13. Visualize the results if requested if (visualization): vis_u = mfem.socketstream("localhost", 19916) visualize(vis_u, mesh, x_gf, x_def, "Deformation", True) vis_p = mfem.socketstream("localhost", 19916) visualize(vis_p, mesh, x_gf, p_gf, "Deformation", True) # 14. Save the displaced mesh, the final deformation, and the pressure nodes = x_gf owns_nodes = 0 nodes, owns_nodes = mesh.SwapNodes(nodes, owns_nodes) mesh.Print('deformed.mesh', 8) p_gf.Save('pressure.sol', 8) x_def.Save("deformation.sol", 8)
fes = mfem.FiniteElementSpace(mesh, fec) # Finite element space for a mesh-dim vector quantity (momentum) dfes = mfem.FiniteElementSpace(mesh, fec, dim, mfem.Ordering.byNODES) # Finite element space for all variables together (total thermodynamic state) vfes = mfem.FiniteElementSpace(mesh, fec, num_equation, mfem.Ordering.byNODES) assert fes.GetOrdering() == mfem.Ordering.byNODES, "Ordering must be byNODES" print("Number of unknowns: " + str(vfes.GetVSize())) # 6. Define the initial conditions, save the corresponding mesh and grid # functions to a file. This can be opened with GLVis with the -gc option. # The solution u has components {density, x-momentum, y-momentum, energy}. # These are stored contiguously in the BlockVector u_block. offsets = [k * vfes.GetNDofs() for k in range(num_equation + 1)] offsets = mfem.intArray(offsets) u_block = mfem.BlockVector(offsets) mom = mfem.GridFunction(dfes, u_block, offsets[1]) # # Define coefficient using VecotrPyCoefficient and PyCoefficient # A user needs to define EvalValue method # u0 = InitialCondition(num_equation) sol = mfem.GridFunction(vfes, u_block.GetData()) sol.ProjectCoefficient(u0) mesh.PrintToFile("vortex.mesh", 8) for k in range(num_equation): uk = mfem.GridFunction(fes, u_block.GetBlock(k).GetData()) sol_name = "vortex-" + str(k) + "-init.gf"
#5. Define a finite element space on the mesh. Here we use vector finite # elements, i.e. dim copies of a scalar finite element space. The vector # dimension is specified by the last argument of the FiniteElementSpace # constructor. For NURBS meshes, we use the (degree elevated) NURBS space # associated with the mesh nodes. fec = mfem.H1_FECollection(order, dim) fespace = mfem.FiniteElementSpace(mesh, fec, dim) print("Number of finite element unknowns: " + str(fespace.GetTrueVSize())) # 6. Determine the list of true (i.e. conforming) essential boundary dofs. # In this example, the boundary conditions are defined by marking only # boundary attribute 1 from the mesh as essential and converting it to a # list of true dofs. ess_tdof_list = intArray() ess_bdr = intArray([1] + [0] * (mesh.bdr_attributes.Max() - 1)) fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list) # 7. Set up the linear form b(.) which corresponds to the right-hand side of # the FEM linear system. In this case, b_i equals the boundary integral # of f*phi_i where f represents a "pull down" force on the Neumann part # of the boundary and phi_i are the basis functions in the finite element # fespace. The force is defined by the VectorArrayCoefficient object f, # which is a vector of Coefficient objects. The fact that f is non-zero # on boundary attribute 2 is indicated by the use of piece-wise constants # coefficient for its last component. f = mfem.VectorArrayCoefficient(dim) for i in range(dim - 1): f.Set(i, mfem.ConstantCoefficient(0.0)) pull_force = mfem.Vector([0] * mesh.bdr_attributes.Max())
for lev in range(ref_levels): mesh.UniformRefinement() # 5. Define the vector finite element spaces representing the mesh # deformation x, the velocity v, and the initial configuration, x_ref. # Define also the elastic energy density, w, which is in a discontinuous # higher-order space. Since x and v are integrated in time as a system, # we group them together in block vector vx, with offsets given by the # fe_offset array. fec = mfem.H1_FECollection(order, dim) fespace = mfem.FiniteElementSpace(mesh, fec, dim) fe_size = fespace.GetVSize() print("Number of velocity/deformation unknowns: " + str(fe_size)) fe_offset = intArray([0, fe_size, 2 * fe_size]) vx = mfem.BlockVector(fe_offset) x = mfem.GridFunction() v = mfem.GridFunction() v.MakeRef(fespace, vx.GetBlock(0), 0) x.MakeRef(fespace, vx.GetBlock(1), 0) x_ref = mfem.GridFunction(fespace) mesh.GetNodes(x_ref) w_fec = mfem.L2_FECollection(order + 1, dim) w_fespace = mfem.FiniteElementSpace(mesh, w_fec) w = mfem.GridFunction(w_fespace)
x0_space = mfem.FiniteElementSpace(mesh, x0_fec) xhat_space = mfem.FiniteElementSpace(mesh, xhat_fec) test_space = mfem.FiniteElementSpace(mesh, test_fec) # 5. Define the block structure of the problem, by creating the offset # variables. Also allocate two BlockVector objects to store the solution # and rhs. x0_var = 0; xhat_var = 1; NVAR = 2 s0 = x0_space.GetVSize() s1 = xhat_space.GetVSize() s_test = test_space.GetVSize() offsets = mfem.intArray([0, s0, s0+s1]) offsets_test = mfem.intArray([0, s_test]) print('\n'.join(["nNumber of Unknowns", " Trial space, X0 : " + str(s0) + " (order " + str(trial_order) + ")", " Interface space, Xhat : " + str(s1) + " (order " + str(trace_order) + ")", " Test space, Y : " + str(s_test) + " (order " + str(test_order) + ")"])) x = mfem.BlockVector(offsets) b = mfem.BlockVector(offsets) x.Assign(0.0) # 6. Set up the linear form F(.) which corresponds to the right-hand side of # the FEM linear system, which in this case is (f,phi_i) where f=1.0 and
# corresponding to fespace. Initialize x with initial guess of zero. x = mfem.GridFunction(fespace) x.Assign(0.0) # 7. Set up the bilinear form a(.,.) on the finite element space # corresponding to the Laplacian operator -Delta, by adding the Diffusion # and Mass domain integrators. a = mfem.BilinearForm(fespace) a.AddDomainIntegrator(mfem.DiffusionIntegrator(one)) a.AddDomainIntegrator(mfem.MassIntegrator(one)) # 8. Assemble the linear system, apply conforming constraints, etc. a.Assemble() A = mfem.SparseMatrix() B = mfem.Vector() X = mfem.Vector() empty_tdof_list = mfem.intArray() a.FormLinearSystem(empty_tdof_list, x, b, A, X, B) M = mfem.GSSmoother(A) mfem.PCG(A, M, B, X, 1, 200, 1e-12, 0.0) # 10. Recover the solution as a finite element grid function. a.RecoverFEMSolution(X, b, x) # 12. Compute and print the L^2 norm of the error. print("L2 norm of error = " + str(x.ComputeL2Error(sol_coef))) mesh.PrintToFile('sphere_refined.mesh', 8) x.SaveToFile('sol.gf', 8)
def RequestData(self, request, inInfo, outInfo): output = dsa.WrapDataObject(vtkUnstructuredGrid.GetData(outInfo)) import os import json import mfem.ser as mfem _, ext = os.path.splitext(self._filename) cwd = os.path.dirname(self._filename) if ext == ".mfem_root": with open(self._filename) as f: root = json.load(f) cycle = int(root['dsets']['main']['cycle']) mesh_filename = root['dsets']['main']['mesh']['path'] mesh_filename = format(mesh_filename % cycle) mesh_filename = os.path.join(cwd, mesh_filename) else: mesh_filename = self._filename mesh = mfem.Mesh(mesh_filename) dim = mesh.SpaceDimension() nelem = mesh.GetNE() # Points mesh_fes = mesh.GetNodalFESpace() nodes = mesh.GetNodes() if nodes is None: nnode = mesh.GetNV() points = np.array(mesh.GetVertexArray()) else: nnode = mesh.GetNodes().Size() // dim points = np.array(mesh.GetNodes().GetDataArray()) if mesh_fes.GetOrdering() == 0: points = points.reshape((dim, nnode)).T elif mesh_fes.GetOrdering() == 1: points = points.reshape((nnode, dim)) else: raise NotImplementedError if dim == 1: points = np.hstack([points, np.zeros((nnode, 2))]) elif dim == 2: points = np.hstack([points, np.zeros((nnode, 1))]) output.SetPoints(points) # Cells cell_attributes = np.empty((nelem), dtype=int) cell_types = np.empty((nelem), dtype=np.ubyte) cell_offsets = np.empty((nelem), dtype=int) cell_conn = [] offset = 0 if nodes is None: for i in range(nelem): v = mesh.GetElementVertices(i) geom = mesh.GetElementBaseGeometry(i) perm = VTKGeometry_VertexPermutation[geom] if perm: v = [v[i] for i in perm] cell_types[i] = VTKGeometry_Map[geom] cell_offsets[i] = offset offset += len(v) + 1 cell_conn.append(len(v)) cell_conn.extend(v) else: for i in range(nelem): v = mesh_fes.GetElementDofs(i) geom = mesh.GetElementBaseGeometry(i) order = mesh_fes.GetOrder(i) if order == 1: perm = VTKGeometry_VertexPermutation[geom] cell_types[i] = VTKGeometry_Map[geom] elif order == 2: perm = VTKGeometry_QuadraticVertexPermutation[geom] cell_types[i] = VTKGeometry_QuadraticMap[geom] else: # FIXME: this needs more work... # See CreateVTKMesh for reading VTK Lagrange elements and # invert that process to create VTK Lagrange elements. # https://github.com/mfem/mfem/blob/master/mesh/mesh_readers.cpp parray = mfem.intArray() mfem.CreateVTKElementConnectivity(parray, geom, order) perm = parray.ToList() cell_types[i] = VTKGeometry_HighOrderMap[geom] if perm: v = [v[i] for i in perm] cell_offsets[i] = offset offset += len(v) + 1 cell_conn.append(len(v)) cell_conn.extend(v) output.SetCells(cell_types, cell_offsets, cell_conn) # Attributes for i in range(nelem): cell_attributes[i] = mesh.GetAttribute(i) output.CellData.append(cell_attributes, "attribute") # Read fields if ext == ".mfem_root": fields = root['dsets']['main']['fields'] for name, prop in fields.items(): filename = prop['path'] filename = format(filename % cycle) filename = os.path.join(cwd, filename) gf = mfem.GridFunction(mesh, filename) gf_fes = gf.FESpace() gf_vdim = gf.VectorDim() gf_nnode = gf_fes.GetNDofs() // gf_vdim gf_nelem = gf_fes.GetNBE() data = np.array(gf.GetDataArray()) if prop['tags']['assoc'] == 'nodes': assert gf_nnode == nnode, "Mesh and grid function have different number of nodes" if gf_fes.GetOrdering() == 0: data = data.reshape((gf_vdim, gf_nnode)).T elif gf_fes.GetOrdering() == 1: data = data.reshape((gf_nnode, gf_vdim)) else: raise NotImplementedError output.PointData.append(data, name) elif prop['tags']['assoc'] == 'elements': assert gf_nelem == nelem, "Mesh and grid function have different number of elements" if gf_fes.GetOrdering() == 0: data = data.reshape((gf_vdim, gf_nelem)).T elif gf_fes.GetOrdering() == 1: data = data.reshape((gf_nelem, gf_vdim)) else: raise NotImplementedError output.CellData.append(data, name) else: raise NotImplementedError("assoc: '{}'".format( prop['tags']['assoc'])) return 1