def Q(mesh): W = VectorElement('CG', mesh.ufl_cell(), 1) V = FiniteElement('CG', mesh.ufl_cell(), 1) return FunctionSpace(mesh, W * V)
def __init__(self, nxs, bcs, name='singleblockmesh', coordelem=None): assert (len(nxs) == len(bcs)) self.ndim = len(nxs) self.nxs = [ nxs, ] self.bcs = bcs self.npatches = 1 self.patchlist = [] self._name = name self._blist = [] for bc in bcs: if bc == 'periodic': self._blist.append(PETSc.DM.BoundaryType.PERIODIC) else: self._blist.append(PETSc.DM.BoundaryType.GHOSTED) bdx = 0 bdy = 0 bdz = 0 edgex_nxs = list(nxs) if (bcs[0] == 'nonperiodic'): edgex_nxs[0] = edgex_nxs[0] + 1 bdx = 1 if self.ndim >= 2: edgey_nxs = list(nxs) if (bcs[1] == 'nonperiodic'): edgey_nxs[1] = edgey_nxs[1] + 1 bdy = 1 if self.ndim >= 3: edgez_nxs = list(nxs) if (bcs[2] == 'nonperiodic'): edgez_nxs[2] = edgez_nxs[2] + 1 bdz = 1 # generate mesh cell_da = PETSc.DMDA().create() #THIS SHOULD REALLY BE AN OPTIONS PREFIX THING TO MESH... #MAIN THING IS THE ABILITY TO CONTROL DECOMPOSITION AT COMMAND LINE #BUT WE WANT TO BE ABLE TO IGNORE DECOMPOSITION WHEN RUNNING WITH A SINGLE PROCESSOR #WHICH ALLOWS THE SAME OPTIONS LIST TO BE USED TO RUN SOMETHING IN PARALLEL, AND THEN DO PLOTTING IN SERIAL! if PETSc.COMM_WORLD.size > 1: #this allows the same options list to be used to run something in parallel, but then plot it in serial! cell_da.setOptionsPrefix(self._name + '0_') cell_da.setFromOptions() ############# cell_da.setDim(self.ndim) cell_da.setDof(1) cell_da.setSizes(nxs) cell_da.setBoundaryType(self._blist) cell_da.setStencil(PETSc.DMDA.StencilType.BOX, 1) cell_da.setUp() #print self.cell_da.getProcSizes() edgex_da = PETSc.DMDA().create(dim=self.ndim, dof=1, sizes=edgex_nxs, proc_sizes=cell_da.getProcSizes(), boundary_type=self._blist, stencil_type=PETSc.DMDA.StencilType.BOX, stencil_width=1, setup=False) #THIS IS AN UGLY HACK NEEDED BECAUSE OWNERSHIP RANGES ARGUMENT TO petc4py DMDA_CREATE is BROKEN decompfunction(cell_da, edgex_da, self.ndim, 1, 1, 1, bdx, 0, 0) edgex_da.setUp() if self.ndim >= 2: edgey_da = PETSc.DMDA().create( dim=self.ndim, dof=1, sizes=edgey_nxs, proc_sizes=cell_da.getProcSizes(), boundary_type=self._blist, stencil_type=PETSc.DMDA.StencilType.BOX, stencil_width=1, setup=False) #THIS IS AN UGLY HACK NEEDED BECAUSE OWNERSHIP RANGES ARGUMENT TO petc4py DMDA_CREATE is BROKEN decompfunction(cell_da, edgey_da, self.ndim, 1, 1, 1, 0, bdy, 0) edgey_da.setUp() if self.ndim >= 3: edgez_da = PETSc.DMDA().create( dim=self.ndim, dof=1, sizes=edgez_nxs, proc_sizes=cell_da.getProcSizes(), boundary_type=self._blist, stencil_type=PETSc.DMDA.StencilType.BOX, stencil_width=1, setup=False) #THIS IS AN UGLY HACK NEEDED BECAUSE OWNERSHIP RANGES ARGUMENT TO petc4py DMDA_CREATE is BROKEN decompfunction(cell_da, edgez_da, self.ndim, 1, 1, 1, 0, 0, bdz) edgez_da.setUp() self._cell_das = [ cell_da, ] self._edgex_das = [ edgex_da, ] self._edgex_nxs = [ edgex_nxs, ] if self.ndim >= 2: self._edgey_das = [ edgey_da, ] self._edgey_nxs = [ edgey_nxs, ] if self.ndim >= 3: self._edgez_das = [ edgez_da, ] self._edgez_nxs = [ edgez_nxs, ] #ADD ACTUAL COORDINATE FUNCTION INITIALIZATION HERE #construct coordelem #FIX THIS- SHOULD USE H1 FOR NON-PERIODIC! #Use DG for periodic boundaries to avoid wrapping issues h1elem = FiniteElement("CG", interval, 1) #1 dof per element = linear l2elem = FiniteElement("DG", interval, 1) #2 dofs per element = linear elemlist = [] dxs = [] pxs = [] lxs = [] for i in range(len(nxs)): dxs.append(2.) pxs.append(0.) lxs.append(2. * nxs[i]) #if bcs[i] == 'periodic': elemlist.append(l2elem) #else: # elemlist.append(h1elem) celem = TensorProductElement(*elemlist) if len(nxs) == 1: celem = elemlist[0] if not (coordelem == None): celem = coordelem celem = VectorElement(celem, dim=self.ndim) Mesh.__init__(self, celem) #THIS BREAKS FOR COORDELEM NOT DG1... #construct and set coordsvec coordsspace = FunctionSpace(self, celem) self.coordinates = Function(coordsspace, name='coords') localnxs = self.get_local_nxny(0) newcoords = create_uniform_nodal_coords(self.get_cell_da(0), nxs, pxs, lxs, dxs, bcs, localnxs) coordsdm = coordsspace.get_da(0, 0) coordsarr = coordsdm.getVecArray(self.coordinates._vector)[:] if len(pxs) == 1: coordsarr[:] = np.squeeze(newcoords[:]) else: coordsarr[:] = newcoords[:] self.coordinates.scatter()
xdmf = XDMFFile(MPI.comm_world, "../dolfin_fine.xdmf") mesh = xdmf.read_mesh(dolfin.cpp.mesh.GhostMode.none) sub_domains = xdmf.read_mf_size_t(mesh) cmap = dolfin.fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap # Next, we define a :py:class:`FunctionSpace # <dolfin.functions.functionspace.FunctionSpace>` built on a mixed # finite element ``TH`` which consists of continuous # piecewise quadratics and continuous piecewise # linears:: # Define function spaces P2 = VectorElement("Lagrange", mesh.ufl_cell(), 2) P1 = FiniteElement("Lagrange", mesh.ufl_cell(), 1) TH = P2 * P1 W = FunctionSpace(mesh, TH) # The mixed finite element space is known as Taylor–Hood. # It is a stable, standard element pair for the Stokes # equations. Now we can define boundary conditions:: # No-slip boundary condition for velocity # x1 = 0, x1 = 1 and around the dolphin class NoSlip: """Evaluate the no-slip condition"""
def test_save_and_checkpoint_vector(tempdir, encoding, fe_degree, fe_family, mesh_tdim, mesh_n): if invalid_fe(fe_family, fe_degree): pytest.skip("Trivial finite element") filename = os.path.join(tempdir, "u2_checkpoint.xdmf") mesh = mesh_factory(mesh_tdim, mesh_n) FE = VectorElement(fe_family, mesh.ufl_cell(), fe_degree) V = FunctionSpace(mesh, FE) u_in = Function(V) u_out = Function(V) if has_petsc_complex: if mesh.geometry.dim == 1: @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = x[:, 0] + 1.0j * x[:, 0] u_out.interpolate(Expression(expr_eval, shape=(1,))) elif mesh.geometry.dim == 2: @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = 1.0j * x[:, 0] * x[:, 1] values[:, 1] = x[:, 0] + 1.0j * x[:, 0] u_out.interpolate(Expression(expr_eval, shape=(2,))) elif mesh.geometry.dim == 3: @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = x[:, 0] * x[:, 1] values[:, 1] = x[:, 0] + 1.0j * x[:, 0] values[:, 2] = x[:, 2] u_out.interpolate(Expression(expr_eval, shape=(3,))) else: if mesh.geometry.dim == 1: @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = x[:, 0] u_out.interpolate(Expression(expr_eval, shape=(1,))) elif mesh.geometry.dim == 2: @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = x[:, 0] * x[:, 1] values[:, 1] = x[:, 0] u_out.interpolate(Expression(expr_eval, shape=(2,))) elif mesh.geometry.dim == 3: @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = x[:, 0] * x[:, 1] values[:, 1] = x[:, 0] values[:, 2] = x[:, 2] u_out.interpolate(Expression(expr_eval, shape=(3,))) with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: file.write_checkpoint(u_out, "u_out", 0) with XDMFFile(mesh.mpi_comm(), filename) as file: u_in = file.read_checkpoint(V, "u_out", 0) u_in.vector().axpy(-1.0, u_out.vector()) assert u_in.vector().norm() < 1.0e-12
def mass_cg(cell, degree): m = Mesh(VectorElement('Q', cell, 1)) V = FunctionSpace(m, FiniteElement('Q', cell, degree, variant='spectral')) u = TrialFunction(V) v = TestFunction(V) return u * v * dx(rule=gll_quadrature_rule(cell, degree))
def laplace(cell, degree): m = Mesh(VectorElement('Q', cell, 1)) V = FunctionSpace(m, FiniteElement('Q', cell, degree, variant='spectral')) u = TrialFunction(V) v = TestFunction(V) return dot(grad(u), grad(v)) * dx(rule=gll_quadrature_rule(cell, degree))
def V(mesh): return FunctionSpace(mesh, VectorElement("DP", triangle, 1))
# # Harmonic map demo using one mixed function u to represent x and y. # Author: Martin Alnes # Date: 2009-04-09 # from ufl import (Coefficient, FiniteElement, VectorElement, derivative, dot, dx, grad, inner, split, triangle) cell = triangle X = VectorElement("Lagrange", cell, 1) Y = FiniteElement("Lagrange", cell, 1) M = X * Y u = Coefficient(M) x, y = split(u) L = inner(grad(x), grad(x)) * dx + dot(x, x) * y * dx F = derivative(L, u) J = derivative(F, u) forms = [L, F, J]
def mesh(): return Mesh(VectorElement("P", triangle, 1))
from ufl import (MixedElement, TestFunctions, TrialFunctions, VectorElement, as_vector, div, dot, dx, inner, skew, tetrahedron, tr) def skw(tau): """Define vectorized skew operator""" sk = 2 * skew(tau) return as_vector((sk[0, 1], sk[0, 2], sk[1, 2])) cell = tetrahedron n = 3 # Finite element exterior calculus syntax r = 1 S = VectorElement("P Lambda", cell, r, form_degree=n - 1) V = VectorElement("P Lambda", cell, r - 1, form_degree=n) Q = VectorElement("P Lambda", cell, r - 1, form_degree=n) # Alternative syntax: # S = VectorElement("BDM", cell, r) # V = VectorElement("Discontinuous Lagrange", cell, r-1) # Q = VectorElement("Discontinuous Lagrange", cell, r-1) W = MixedElement(S, V, Q) (sigma, u, gamma) = TrialFunctions(W) (tau, v, eta) = TestFunctions(W) a = (inner(sigma, tau) - tr(sigma) * tr(tau) + dot(div(tau), u) - dot(div(sigma), v) +
# # Author: Martin Sandve Alnes # Date: 2008-10-03 # from ufl import (Coefficient, TestFunction, TrialFunction, VectorElement, dx, i, j, triangle) element = VectorElement("Lagrange", triangle, 1) u = TrialFunction(element) v = TestFunction(element) w = Coefficient(element) a = (u[j] * w[i].dx(j) + w[j] * u[i].dx(j)) * v[i] * dx
# # Modified by Garth N. Wells, 2009 from ufl import (Coefficient, Constant, FacetNormal, FiniteElement, Identity, SpatialCoordinate, TensorElement, TestFunction, TrialFunction, VectorElement, derivative, det, diff, dot, ds, dx, exp, grad, inner, inv, tetrahedron, tr, variable) # Cell and its properties cell = tetrahedron d = cell.geometric_dimension() N = FacetNormal(cell) x = SpatialCoordinate(cell) # Elements u_element = VectorElement("CG", cell, 2) p_element = FiniteElement("CG", cell, 1) A_element = TensorElement("CG", cell, 1) # Test and trial functions v = TestFunction(u_element) w = TrialFunction(u_element) # Displacement at current and two previous timesteps u = Coefficient(u_element) up = Coefficient(u_element) upp = Coefficient(u_element) # Time parameters dt = Constant(cell)
def __init__(self, io_params, time_params, fem_params, constitutive_models, bc_dict, time_curves, io, comm=None): problem_base.__init__(self, io_params, time_params, comm) self.problem_physics = 'fluid' self.simname = io_params['simname'] self.io = io # number of distinct domains (each one has to be assigned a own material model) self.num_domains = len(constitutive_models) self.order_vel = fem_params['order_vel'] self.order_pres = fem_params['order_pres'] self.quad_degree = fem_params['quad_degree'] # collect domain data self.dx_, self.rho = [], [] for n in range(self.num_domains): # integration domains self.dx_.append( dx(subdomain_data=self.io.mt_d, subdomain_id=n + 1, metadata={'quadrature_degree': self.quad_degree})) # data for inertial forces: density self.rho.append(constitutive_models['MAT' + str(n + 1) + '']['inertia']['rho']) self.incompressible_2field = True # always true! self.localsolve = False # no idea what might have to be solved locally... self.prestress_initial = False # guess prestressing in fluid is somehow senseless... self.p11 = as_ufl( 0 ) # can't think of a fluid case with non-zero 11-block in system matrix... # type of discontinuous function spaces if str(self.io.mesh.ufl_cell()) == 'tetrahedron' or str( self.io.mesh.ufl_cell()) == 'triangle3D': dg_type = "DG" if (self.order_vel > 1 or self.order_pres > 1) and self.quad_degree < 3: raise ValueError( "Use at least a quadrature degree of 3 or more for higher-order meshes!" ) elif str(self.io.mesh.ufl_cell()) == 'hexahedron' or str( self.io.mesh.ufl_cell()) == 'quadrilateral3D': dg_type = "DQ" if (self.order_vel > 1 or self.order_pres > 1) and self.quad_degree < 4: raise ValueError( "Use at least a quadrature degree of 4 or more for higher-order meshes!" ) else: raise NameError("Unknown cell/element type!") # create finite element objects for v and p self.P_v = VectorElement("CG", self.io.mesh.ufl_cell(), self.order_vel) self.P_p = FiniteElement("CG", self.io.mesh.ufl_cell(), self.order_pres) # function spaces for v and p self.V_v = FunctionSpace(self.io.mesh, self.P_v) self.V_p = FunctionSpace(self.io.mesh, self.P_p) # a discontinuous tensor, vector, and scalar function space self.Vd_tensor = TensorFunctionSpace(self.io.mesh, (dg_type, self.order_vel - 1)) self.Vd_vector = VectorFunctionSpace(self.io.mesh, (dg_type, self.order_vel - 1)) self.Vd_scalar = FunctionSpace(self.io.mesh, (dg_type, self.order_vel - 1)) # functions self.dv = TrialFunction(self.V_v) # Incremental velocity self.var_v = TestFunction(self.V_v) # Test function self.dp = TrialFunction(self.V_p) # Incremental pressure self.var_p = TestFunction(self.V_p) # Test function self.v = Function(self.V_v, name="Velocity") self.p = Function(self.V_p, name="Pressure") # values of previous time step self.v_old = Function(self.V_v) self.a_old = Function(self.V_v) self.p_old = Function(self.V_p) self.ndof = self.v.vector.getSize() + self.p.vector.getSize() # initialize fluid time-integration class self.ti = timeintegration.timeintegration_fluid( time_params, fem_params, time_curves, self.t_init, self.comm) # initialize kinematics_constitutive class self.ki = fluid_kinematics_constitutive.kinematics() # initialize material/constitutive class self.ma = [] for n in range(self.num_domains): self.ma.append( fluid_kinematics_constitutive.constitutive( self.ki, constitutive_models['MAT' + str(n + 1) + ''])) # initialize fluid variational form class self.vf = fluid_variationalform.variationalform( self.var_v, self.dv, self.var_p, self.dp, self.io.n0) # initialize boundary condition class self.bc = boundaryconditions.boundary_cond_fluid( bc_dict, fem_params, self.io, self.ki, self.vf, self.ti) self.bc_dict = bc_dict # Dirichlet boundary conditions if 'dirichlet' in self.bc_dict.keys(): self.bc.dirichlet_bcs(self.V_v) self.set_variational_forms_and_jacobians()