def __init__(self, mesh, lame, model): def sigmaLaw(u): return lame[0] * nabla_div(u) * df.Identity( 2) + 2 * lame[1] * symgrad(u) self.sigmaLaw = sigmaLaw self.mesh = mesh self.model = model self.coord_min = np.min(self.mesh.coordinates(), axis=0) self.coord_max = np.max(self.mesh.coordinates(), axis=0) # it should be modified before computing tangent (if needed) self.others = { 'polyorder': 1, 'x0': self.coord_min[0], 'x1': self.coord_max[0], 'y0': self.coord_min[1], 'y1': self.coord_max[1] } self.multiscaleModel = listMultiscaleModels[model] self.x = df.SpatialCoordinate(self.mesh) self.ndim = 2 self.nvoigt = int(self.ndim * (self.ndim + 1) / 2) self.Chom_ = np.zeros((self.nvoigt, self.nvoigt)) # in the first run should compute self.getTangent = self.computeTangent
def _CenterVector(mesh, Center): '''DLT vector pointing on each facet from one Center to the other''' # Cell-cell distance for the interior facet is defined as a distance # of circumcenters. For exterior it is facet centor to circumcenter # For facet centers we use DLT projection if mesh.topology().dim() > 1: L = df.VectorFunctionSpace(mesh, 'Discontinuous Lagrange Trace', 0) else: L = df.VectorFunctionSpace(mesh, 'CG', 1) fK = df.FacetArea(mesh) l = df.TestFunction(L) x = df.SpatialCoordinate(mesh) facet_centers = df.Function(L) df.assemble((1 / fK) * df.inner(x, l) * df.ds, tensor=facet_centers.vector()) cell_centers = Center(mesh) cc = df.Function(L) # Finally we assemble magniture of the vector that is determined by the # two centers df.assemble( (1 / fK('+')) * df.inner(cell_centers('+') - cell_centers('-'), l('+')) * df.dS + (1 / fK) * df.inner(cell_centers - facet_centers, l) * df.ds, tensor=cc.vector()) return cc
def get_volume(geometry, u=None, chamber="lv"): if "ENDO" in geometry.markers: lv_endo_marker = geometry.markers["ENDO"] rv_endo_marker = None else: lv_endo_marker = geometry.markers["ENDO_LV"] rv_endo_marker = geometry.markers["ENDO_RV"] marker = lv_endo_marker if chamber == "lv" else rv_endo_marker if marker is None: return None if hasattr(marker, "__len__"): marker = marker[0] ds = df.Measure( "exterior_facet", subdomain_data=geometry.ffun, domain=geometry.mesh )(marker) X = df.SpatialCoordinate(geometry.mesh) N = df.FacetNormal(geometry.mesh) if u is None: vol = df.assemble((-1.0 / 3.0) * df.dot(X, N) * ds) else: F = df.grad(u) + df.Identity(3) J = df.det(F) vol = df.assemble((-1.0 / 3.0) * df.dot(X + u, J * df.inv(F).T * N) * ds) return vol
def setUp(self): self.mesh = mesh = dolfin.UnitIntervalMesh(30) self.element = element = dolfin.FiniteElement("CG", mesh.ufl_cell(), 3) self.W = W = dolfin.FunctionSpace(mesh, element) self.u = dolfin.Function(W, name='u') self.v = dolfin.TestFunction(W) self.x = dolfin.SpatialCoordinate(mesh)[0]
def __init__(self, Vh, nu, ds_ff, u_ff, inletMomentun, inletWidth): """ Contructor INPUTS: - Vh: the mixed finite element space for the state variable - nu: the kinetic viscosity - ds_ff: the integrator on the farfield boundary (where we impose the swithcing Dir/Neu conditions - u_ff: the farfield Dirichlet condition for the normal component of the velocity field u (when backflow is detected) - inletMomentun, inletWidth: the standard parameters in the algebraic closure model """ self.Vh = Vh self.mesh = Vh.mesh() self.nu = nu self.ds_ff = ds_ff self.u_ff = u_ff self.inletMomentun = inletMomentun self.inletWidth = inletWidth self.metric = mesh_metric(self.mesh) self.n = dl.FacetNormal(self.mesh) self.tg = dl.perp(self.n) self.reg_norm = dl.Constant(1e-1) self.Cd = dl.Constant(1e5) #self.xfun = dl.Expression("x[0]", element = self.Vh.sub(1).ufl_element()) self.xfun, self.yfun = dl.SpatialCoordinate(self.mesh)
def setUp(self): from dolfin import (MixedElement as MixE, Function, FunctionSpace, FiniteElement, VectorElement, UnitSquareMesh) self.mesh = mesh = UnitSquareMesh(10, 10) muc = mesh.ufl_cell self.fe1 = FiniteElement("CG", muc(), 1) self.fe2 = FiniteElement("CG", muc(), 2) self.ve1 = VectorElement("CG", muc(), 2, 2) self.me = ( MixE([self.fe1, self.fe2]), MixE([MixE([self.ve1, self.fe2]), self.fe1, self.ve1, self.fe2]), # MixE([self.fe1]), # broken ) self.W = [FunctionSpace(mesh, me) for me in self.me] self.w = [Function(W) for W in self.W] self.reg = FunctionSubspaceRegistry() self.x = dolfin.SpatialCoordinate(mesh) for W in self.W: self.reg.register(W)
def main(): fsr = FunctionSubspaceRegistry() deg = 2 mesh = dolfin.UnitSquareMesh(100, 3) muc = mesh.ufl_cell() el_w = dolfin.FiniteElement('DG', muc, deg - 1) el_j = dolfin.FiniteElement('BDM', muc, deg) el_DG0 = dolfin.FiniteElement('DG', muc, 0) el = dolfin.MixedElement([el_w, el_j]) space = dolfin.FunctionSpace(mesh, el) DG0 = dolfin.FunctionSpace(mesh, el_DG0) fsr.register(space) facet_normal = dolfin.FacetNormal(mesh) xyz = dolfin.SpatialCoordinate(mesh) trial = dolfin.Function(space) test = dolfin.TestFunction(space) w, c = dolfin.split(trial) v, phi = dolfin.split(test) sympy_exprs = derive_exprs() exprs = { k: sympy_dolfin_printer.to_ufl(sympy_exprs['R'], mesh, v) for k, v in sympy_exprs['quantities'].items() } f = exprs['f'] w0 = dolfin.project(dolfin.conditional(dolfin.gt(xyz[0], 0.5), 1.0, 0.3), DG0) w_BC = exprs['w'] dx = dolfin.dx() form = (+v * dolfin.div(c) * dx - v * f * dx + dolfin.exp(w + w0) * dolfin.dot(phi, c) * dx + dolfin.div(phi) * w * dx - (w_BC - w0) * dolfin.dot(phi, facet_normal) * dolfin.ds() - (w0('-') - w0('+')) * dolfin.dot(phi('+'), facet_normal('+')) * dolfin.dS()) solver = NewtonSolver(form, trial, [], parameters=dict(relaxation_parameter=1.0, maximum_iterations=15, extra_iterations=10, relative_tolerance=1e-6, absolute_tolerance=1e-7)) solver.solve() with closing(XdmfPlot("out/qflop_test.xdmf", fsr)) as X: CG1 = dolfin.FunctionSpace(mesh, dolfin.FiniteElement('CG', muc, 1)) X.add('w0', 1, w0, CG1) X.add('w_c', 1, w + w0, CG1) X.add('w_e', 1, exprs['w'], CG1) X.add('f', 1, f, CG1) X.add('cx_c', 1, c[0], CG1) X.add('cx_e', 1, exprs['c'][0], CG1)
def _setup_energy(self, rho, vel, gvec, x0): """ Calculate kinetic and potential energy """ x = df.SpatialCoordinate(self.mesh) self._form_E_k = Form(1 / 2 * rho * dot(vel, vel) * dx(domain=self.mesh)) self._form_E_p = Form(rho * dot(-gvec, x - x0) * dx(domain=self.mesh))
def sympy_to_ufl(R, mesh, expr, syms=None, **kwargs): syms = syms or dict() dim = mesh.geometry().dim() coord = dolfin.SpatialCoordinate(mesh) syms.update(zip(R.varlist, coord)) kwargs.setdefault('dim', dim) kwargs.setdefault('reference_frame', R) return sympy_to_ufl_base(expr, syms, **kwargs)
def test_assemble_functional(): mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 12, 12) M = 1.0 * dx(domain=mesh) value = dolfin.fem.assemble(M) assert value == pytest.approx(1.0, 1e-12) x = dolfin.SpatialCoordinate(mesh) M = x[0] * dx(domain=mesh) value = dolfin.fem.assemble(M) assert value == pytest.approx(0.5, 1e-12)
def test_probes(x, mesh1): el = dolfin.FiniteElement('BDM', mesh1.ufl_cell(), 2) W = dolfin.FunctionSpace(mesh1, el) z = dolfin.SpatialCoordinate(mesh1) expr = dolfin.as_vector((z[0], z[1])) w = dolfin.project(expr, W) ps = Probes(W) p = ps.probe(x) print(x, p(w), w(x)) assert (p(w) == w(x)).all()
def CellCentroid(mesh): '''[DG0]^d function that evals on cell to its center of mass''' V = df.VectorFunctionSpace(mesh, 'DG', 0) v = df.TestFunction(V) hK = df.CellVolume(mesh) x = df.SpatialCoordinate(mesh) c = df.Function(V) df.assemble((1 / hK) * df.inner(x, v) * df.dx, tensor=c.vector()) return c
def rigid_motion_term(mesh, u, r): position = dolfin.SpatialCoordinate(mesh) RM = [ Constant((1, 0, 0)), Constant((0, 1, 0)), Constant((0, 0, 1)), dolfin.cross(position, Constant((1, 0, 0))), dolfin.cross(position, Constant((0, 1, 0))), dolfin.cross(position, Constant((0, 0, 1))), ] return sum(dolfin.dot(u, zi) * r[i] * dolfin.dx for i, zi in enumerate(RM))
def setUp(self): self.mesh = mesh = dolfin.UnitSquareMesh(20, 2, "left") self.DG0_element = DG0e = dolfin.FiniteElement("DG", mesh.ufl_cell(), 0) self.DG0v_element = DG0ve = dolfin.VectorElement( "DG", mesh.ufl_cell(), 0) self.DG0 = DG0 = dolfin.FunctionSpace(mesh, DG0e) self.DG0v = DG0v = dolfin.FunctionSpace(mesh, DG0ve) self.fsr = fsr = FunctionSubspaceRegistry() fsr.register(DG0) fsr.register(DG0v) self.cellmid = cm = CellMidpointExpression(mesh, element=DG0ve) self.n = n = dolfin.FacetNormal(mesh) self.u = u = dolfin.Function(DG0) self.v = v = dolfin.TestFunction(DG0) u_bc = dolfin.Expression('x[0]', degree=2) x = dolfin.SpatialCoordinate(mesh) self.rho = rho = dolfin.conditional( dolfin.lt((x[0] - 0.5)**2 + (x[1] - 0.5)**2, 0.2**2), 0.0, 0.0) dot = dolfin.dot cellsize = dolfin.CellSize(mesh) self.h = h = cm('+') - cm('-') self.h_boundary = h_boundary = 2 * n * dot(x - cm, n) self.E = E = h / dot(h, h) * (u('-') - u('+')) self.E_boundary = E_boundary = h_boundary / dot( h_boundary, h_boundary) * (u - u_bc) dS = dolfin.dS eps = 1e-8 class BL(dolfin.SubDomain): def inside(self, x, on_boundary): return abs(x[0]) < eps class BR(dolfin.SubDomain): def inside(self, x, on_boundary): return abs(x[0] - 1) < eps ff = dolfin.FacetFunction('size_t', mesh, 0) BL().mark(ff, 1) BR().mark(ff, 1) ds = dolfin.Measure('ds', domain=mesh, subdomain_data=ff) self.F = (dot(E, n('+')) * v('+') * dS + dot(E, n('-')) * v('-') * dS - v * rho * dolfin.dx + dot(E_boundary, n) * v * ds(1))
def helper_test_roundtrip(self, dedup): mesh0 = dolfin.UnitSquareMesh(3, 5) uc0 = mesh0.ufl_cell() el0 = dolfin.FiniteElement('CG', uc0, 2) W0 = dolfin.FunctionSpace(mesh0, el0) u0 = dolfin.Function(W0) mf0 = dolfin.MeshFunction("size_t", mesh0, 1, 0) mf0.array()[:] = range(len(mf0.array())) x = dolfin.SpatialCoordinate(mesh0) dolfin.project(x[0] - x[1]**2, W0, function=u0) outdir = tempfile.mkdtemp('.solution_io') # atexit.register(partial(shutil.rmtree, outdir)) outfile = os.path.join(outdir, 'test.yaml') man = DolfinH5Manager(outfile) with open(outfile, 'wt') as stream: yaml.dump( dict(mesh=mesh0, u=u0, mf=mf0), stream, Dumper=partial(XDumper, x_attr_dict=dict( dolfin_h5_manager=man))) with open(outfile, 'rt') as h: print(h.read()) if dedup: from h5dedup.dedup import DedupRepository repo = DedupRepository(outdir) repo.deduplicate_file_tree(outdir) with open(outfile, 'rt') as stream: r = yaml.load(stream, Loader=partial(XLoader, x_attr_dict=dict( dolfin_h5_manager=man))) mesh1 = dolfin.Mesh() r['mesh'].load_into(mesh1) W1 = dolfin.FunctionSpace(mesh1, el0) u1 = dolfin.Function(W1) r['u'].load_into(u1) mf1 = dolfin.MeshFunction("size_t", mesh1, 1, 0) r['mf'].load_into(mf1) u1_ = dolfin.project(u1, W0) self.assertLess(dolfin.assemble((u0-u1_)**2*dolfin.dx), 1e-26) self.assertEqual(tuple(mf0.array()), tuple(mf1.array()))
def Grad(u): '''Gradient in cylinderical (z, r, theta) coords''' z, r, th = df.SpatialCoordinate(u.ufl_domain().ufl_cargo()) # Scalar if u.ufl_shape == (): return df.as_vector((u.dx(0), u.dx(1), (1/r)*u.dx(2))) # Ignore tensors for now assert len(u.ufl_shape) == 1 # z r theta uz, ur, uth = u[0], u[1], u[2] return df.as_matrix(((uz.dx(0), uz.dx(1), (1/r)*uz.dx(2)), (ur.dx(0), ur.dx(1), (1/r)*ur.dx(2) - uth/r), (uth.dx(0), uth.dx(1), (1/r)*uth.dx(2) + ur/r)))
def GradAxisym(u): '''Gradient in cylinderical axisymmetric (z, r) coords''' z, r = df.SpatialCoordinate(u.ufl_domain().ufl_cargo()) # Scalar if u.ufl_shape == (): return df.as_vector((u.dx(0), u.dx(1), df.Constant(0)*u)) # Ignore tensors for now assert len(u.ufl_shape) == 1 # z r theta uz, ur = u[0], u[1] return df.as_matrix(((uz.dx(0), uz.dx(1), df.Constant(0)*uz), (ur.dx(0), ur.dx(1), df.Constant(0)*ur), (df.Constant(0)*uz, df.Constant(0)*ur, ur/r)))
def test_complex_assembly_solve(): """Solve a positive definite helmholtz problem and verify solution with the method of manufactured solutions """ degree = 3 mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 20, 20) P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), degree) V = dolfin.function.functionspace.FunctionSpace(mesh, P) x = dolfin.SpatialCoordinate(mesh) # Define source term A = 1 + 2 * (2 * np.pi)**2 f = (1. + 1j) * A * ufl.cos(2 * np.pi * x[0]) * ufl.cos(2 * np.pi * x[1]) # Variational problem u = dolfin.function.argument.TrialFunction(V) v = dolfin.function.argument.TestFunction(V) C = 1 + 1j a = C * inner(grad(u), grad(v)) * dx + C * inner(u, v) * dx L = inner(f, v) * dx # Assemble A = dolfin.fem.assemble(a) b = dolfin.fem.assemble(L) # Create solver solver = dolfin.cpp.la.PETScKrylovSolver(mesh.mpi_comm()) dolfin.cpp.la.PETScOptions.set("ksp_type", "preonly") dolfin.cpp.la.PETScOptions.set("pc_type", "lu") solver.set_from_options() x = dolfin.cpp.la.PETScVector() solver.set_operator(A) solver.solve(x, b) # Reference Solution @dolfin.function.expression.numba_eval def ref_eval(values, x, cell_idx): values[:, 0] = np.cos(2 * np.pi * x[:, 0]) * np.cos(2 * np.pi * x[:, 1]) u_ref = dolfin.interpolate(dolfin.Expression(ref_eval), V) xnorm = x.norm(dolfin.cpp.la.Norm.l2) x_ref_norm = u_ref.vector().norm(dolfin.cpp.la.Norm.l2) assert np.isclose(xnorm, x_ref_norm)
def get_cavity_volume_form(mesh, u=None, xshift=0.0): from . import kinematics shift = Constant((xshift, 0.0, 0.0)) X = dolfin.SpatialCoordinate(mesh) - shift N = dolfin.FacetNormal(mesh) if u is None: vol_form = (-1.0 / 3.0) * dolfin.dot(X, N) else: F = kinematics.DeformationGradient(u) J = kinematics.Jacobian(F) vol_form = (-1.0 / 3.0) * dolfin.dot(X + u, J * dolfin.inv(F).T * N) return vol_form
def strain_rate_tensor(self, u): r"""Define the symmetric strain-rate tensor :param u: The velocity field (2D). :return: The strain rate tensor. """ r = dolfin.SpatialCoordinate(self._mesh)[0] ur = u[0] uz = u[1] ur_r = ur.dx(0) ur_z = ur.dx(1) uz_r = uz.dx(0) uz_z = uz.dx(1) return dolfin.sym( dolfin.as_tensor([[ur_r, 0, 0.5 * (uz_r + ur_z)], [0, ur / r, 0], [0.5 * (uz_r + ur_z), 0, uz_z]]))
def wind_number(mesh, points): '''Of a loop''' assert is_loop(mesh) assert mesh.geometry().dim() == 2 assert points.ndim == 2 x = df.SpatialCoordinate(mesh) tan = TangentCurve(mesh) c = df.Constant([0, 0]) R = df.Constant(((0, 1), (-1, 0))) L = df.inner( (x - c) / (2 * df.pi) / df.dot(x - c, x - c), df.dot(R, tan)) * df.dx return np.fromiter(((c.assign(df.Constant(point)), df.assemble(L))[-1] for point in points), dtype=float)
def computeTangent(self): dy = df.Measure('dx', self.mesh) vol = df.assemble(df.Constant(1.0) * dy) y = df.SpatialCoordinate(self.mesh) Eps = df.Constant(((0., 0.), (0., 0.))) # just placeholder form = self.multiscaleModel(self.mesh, self.sigmaLaw, Eps, self.others) a, f, bcs, W = form() start = timer() A = mp.block_assemble(a) if (len(bcs) > 0): bcs.apply(A) # decompose just once (the faster for single process) solver = df.PETScLUSolver('superlu') sol = mp.BlockFunction(W) end = timer() print('time assembling system', end - start) for i in range(self.nvoigt): start = timer() Eps.assign(df.Constant(macro_strain(i))) F = mp.block_assemble(f) if (len(bcs) > 0): bcs.apply(F) solver.solve(A, sol.block_vector(), F) sol.block_vector().block_function().apply("to subfunctions") sig_mu = self.sigmaLaw(df.dot(Eps, y) + sol[0]) sigma_hom = Integral(sig_mu, dy, (2, 2)) / vol self.Chom_[:, i] = sigma_hom.flatten()[[0, 3, 1]] end = timer() print('time in solving system', end - start) print(self.Chom_) # from the second run onwards, just returns self.getTangent = self.getTangent_ return self.Chom_
def test_extract_nodal_CG1(self): mesh = dolfin.UnitSquareMesh(16, 16) el = dolfin.VectorElement("CG", mesh.ufl_cell(), 1) CG1 = dolfin.FunctionSpace(mesh, el) e_expr = dolfin.Expression(("x[0]-2*exp(x[1])", "x[0]*x[1]"), degree=1) x = dolfin.SpatialCoordinate(mesh) e_ufl = dolfin.as_vector((x[0] - 2 * dolfin.exp(x[1]), x[0] * x[1])) u0 = dolfin.interpolate(e_expr, CG1) u_nodal = interpolate(e_ufl, CG1) # nodal values u_proj = dolfin.project(e_ufl, CG1) # projection/averaging maxdiff = self.maxdiff self.assertLess(maxdiff(u0, u_nodal), 2 * dolfin.DOLFIN_EPS) self.assertGreater(maxdiff(u0, u_proj), 2 * dolfin.DOLFIN_EPS)
def __init__( self, mesh, dmu, approx="project", displacement_space="CG_2", interpolation_space="CG_1", description="", ): ModelObservation.__init__(self, mesh, target_space="R_0", description=description) approxs = ["project", "interpolate", "original"] msg = 'Expected "approx" for be one of {}, got {}'.format( approxs, approx) assert approx in approxs, msg self._approx = approx # These spaces are only used if you want to project # or interpolate the displacement before assigning it # Space for interpolating the displacement if needed family, degree = interpolation_space.split("_") self._interpolation_space = dolfin.VectorFunctionSpace( mesh, family, int(degree)) # Displacement space family, degree = displacement_space.split("_") self._displacement_space = dolfin.VectorFunctionSpace( mesh, family, int(degree)) self._X = dolfin.SpatialCoordinate(mesh) self._N = dolfin.FacetNormal(mesh) assert isinstance(dmu, dolfin.Measure) self._dmu = dmu name = "EndoArea {}".format(self) self._endoarea = dolfin_adjoint.Constant(dolfin.assemble( dolfin.Constant(1.0) * dmu), name=name)
def test_complex_assembly(): """Test assembly of complex matrices and vectors""" mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 10, 10) P2 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 2) V = dolfin.function.functionspace.FunctionSpace(mesh, P2) u = dolfin.function.argument.TrialFunction(V) v = dolfin.function.argument.TestFunction(V) g = dolfin.function.constant.Constant(-2 + 3.0j) j = dolfin.function.constant.Constant(1.0j) a_real = inner(u, v) * dx L1 = inner(g, v) * dx bnorm = dolfin.fem.assemble(L1).norm(dolfin.cpp.la.Norm.l1) b_norm_ref = abs(-2 + 3.0j) assert np.isclose(bnorm, b_norm_ref) A0_norm = dolfin.fem.assemble(a_real).norm(dolfin.cpp.la.Norm.frobenius) x = dolfin.SpatialCoordinate(mesh) a_imag = j * inner(u, v) * dx f = 1j * ufl.sin(2 * np.pi * x[0]) L0 = inner(f, v) * dx A1_norm = dolfin.fem.assemble(a_imag).norm(dolfin.cpp.la.Norm.frobenius) assert np.isclose(A0_norm, A1_norm) b1_norm = dolfin.fem.assemble(L0).norm(dolfin.cpp.la.Norm.l2) a_complex = (1 + j) * inner(u, v) * dx f = ufl.sin(2 * np.pi * x[0]) L2 = inner(f, v) * dx A2_norm = dolfin.fem.assemble(a_complex).norm(dolfin.cpp.la.Norm.frobenius) assert np.isclose(A1_norm, A2_norm / np.sqrt(2)) b2_norm = dolfin.fem.assemble(L2).norm(dolfin.cpp.la.Norm.l2) assert np.isclose(b2_norm, b1_norm)
def comp_axisymmetric_pure_neumann(mat_obj, mesh_obj, bc, omega, save_path): E = mat_obj.E rho = mat_obj.rho nu = mat_obj.nu mesh = mesh_obj.create() Rext = mesh_obj.Rext Rint = mesh_obj.Rint # rename x[0], x[1] by x, y x, y = df.SpatialCoordinate(mesh) dim = mesh.topology().dim() cell_markers = df.MeshFunction("size_t", mesh, dim) facet_markers = df.MeshFunction("size_t", mesh, dim - 1) coord = mesh.coordinates() class OuterRadius(df.SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0]**2 + x[1]**2 >= Rext**2 - 1e-3 class InnerRadius(df.SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0]**2 + x[1]**2 <= Rint**2 + 1e-3 OuterRadius().mark(facet_markers, 1) InnerRadius().mark(facet_markers, 2) df.File(save_path + 'cell_markers.pvd') << cell_markers df.File(save_path + 'facet_markers.pvd') << facet_markers # Create mesh and define function space V = df.FunctionSpace(mesh, "CG", 1) # =========================== Define Finite Element =========================== degree = 1 #P1 table of periodic # CG: Continuous Galerkin V_ele = df.FiniteElement("CG", mesh.ufl_cell(), degree) # scalar, Ex: u R_ele = df.FiniteElement("R", mesh.ufl_cell(), 0) # scalar, Ex: u # Vector element # akternative : manually define vector function : better for 3D adaptation than above total_ele = df.MixedElement([V_ele, R_ele]) W = df.FunctionSpace(mesh, total_ele) # Define trial function dunks = df.TrialFunction(W) (du, dc) = df.split(dunks) # Define variational problem tunks = df.TestFunction(W) (tu, tc) = df.split(tunks) # displacement in radial direction u(x,y) unks = df.Function(W) #(u, c) = df.split(unks) class THETA(df.UserExpression): def eval(self, values, x): values[0] = math.atan2(x[1], x[0]) def value_shape(self): #return (1,) # vector return () # scalar theta = THETA(degree=1) #theta_int = df.interpolate(theta, df.FunctionSpace(mesh, "DG", 0)) #df.File(save_path + 'theta.pvd') << theta_int class RADIUS(df.UserExpression): def eval(self, values, x): values[0] = df.sqrt(x[0] * x[0] + x[1] * x[1]) def value_shape(self): return () # scalar r = RADIUS(degree=1) # strain radial def epsilon_r(du): return 1.0 / r * (x * df.Dx(du, 0) + y * df.Dx(du, 1)) # strain circumferential def epsilon_theta(du): return du / df.sqrt(x**2 + y**2) # radial stress # train-stress relation def sigma_r(du): return E / (1.0 - nu**2) * (epsilon_r(du) + nu * epsilon_theta(du)) # circumferential stress def sigma_theta(du): return E / (1.0 - nu**2) * (nu * epsilon_r(du) + epsilon_theta(du)) # Weak form dFu = r * sigma_r(du) * epsilon_r(tu) * df.dx(0) dFu = dFu + sigma_theta(du) * tu * df.dx(0) dFu = dFu + dc * tu * df.dx(0) dFu = dFu - rho * omega**2 * r**2 * tu * df.dx(0) dFc = du * tc * df.dx(1) dFu = r * sigma_r(du) * epsilon_r(tu) * df.dx dFu = dFu + sigma_theta(du) * tu * df.dx dFu = dFu + dc * tu * df.dx dFu = dFu - rho * omega**2 * r**2 * tu * df.dx dFc = du * tc * df.dx dF = dFu + dFc # residual #F = df.action(dF, unks) a = df.lhs(dF) L = df.rhs(dF) df.solve(a == L, unks) (_u, _c) = unks.split(True) u_pro = df.project(_u, V) u_pro.rename('dis u [m]', 'dis u [m]') # displacement df.File(save_path + 'displacement.pvd') << u_pro # compute stresses sigma_r_pro = df.project(sigma_r(_u), V) sigma_r_pro.rename('sigma_r [Pa]', 'sigma_r [Pa]') df.File(save_path + 'sigma_r.pvd') << sigma_r_pro sigma_theta_pro = df.project(sigma_theta(_u), V) sigma_theta_pro.rename('sigma_theta [Pa]', 'sigma_theta [Pa]') df.File(save_path + 'sigma_theta.pvd') << sigma_theta_pro # compute von Mises stress def von_mises_stress(sigma_r, sigma_theta): return df.sqrt(sigma_r**2 + sigma_theta**2 - sigma_r * sigma_theta) von_stress_pro = df.project(von_mises_stress(sigma_r(_u), sigma_theta(_u)), V) von_stress_pro.rename('von Mises Stress [Pa]', 'von Mises Stress [Pa]') df.File(save_path + 'von_mises_stress.pvd') << von_stress_pro
def define_dg_equations( u, v, p, q, lm_trial, lm_test, simulation, include_hydrostatic_pressure, incompressibility_flux_type, use_grad_q_form, use_grad_p_form, use_stress_divergence_form, velocity_continuity_factor_D12=0, pressure_continuity_factor=0, ): """ Define the coupled equations. Also used by the SIMPLE and IPCS-A solvers Weak form of the Navier-Stokes eq. with discontinuous elements :type simulation: ocellaris.Simulation """ sim = simulation show = sim.log.info show(' Creating DG weak form with BCs') show(' include_hydrostatic_pressure = %r' % include_hydrostatic_pressure) show(' incompressibility_flux_type = %s' % incompressibility_flux_type) show(' use_grad_q_form = %r' % use_grad_q_form) show(' use_grad_p_form = %r' % use_grad_p_form) show(' use_stress_divergence_form = %r' % use_stress_divergence_form) show(' velocity_continuity_factor_D12 = %r' % velocity_continuity_factor_D12) show(' pressure_continuity_factor = %r' % pressure_continuity_factor) mpm = sim.multi_phase_model mesh = sim.data['mesh'] u_conv = sim.data['u_conv'] dx = dolfin.dx(domain=mesh) dS = dolfin.dS(domain=mesh) c1, c2, c3 = sim.data['time_coeffs'] dt = sim.data['dt'] g = sim.data['g'] n = dolfin.FacetNormal(mesh) x = dolfin.SpatialCoordinate(mesh) # Fluid properties rho = mpm.get_density(0) nu = mpm.get_laminar_kinematic_viscosity(0) mu = mpm.get_laminar_dynamic_viscosity(0) # Hydrostatic pressure correction if include_hydrostatic_pressure: p += sim.data['p_hydrostatic'] # Start building the coupled equations eq = 0 # ALE mesh velocities if sim.mesh_morpher.active: u_mesh = sim.data['u_mesh'] # Either modify the convective velocity or just include the mesh # velocity on cell integral form. Only activate one of the lines below # PS: currently the UFL form splitter (used in e.g. IPCS-A) has a # problem with line number 2, but the Coupled solver handles # both options with approximately the same resulting convergence # errors on the Taylor-Green test case (TODO: fix form splitter) u_conv -= u_mesh # eq -= dot(div(rho * dolfin.outer(u, u_mesh)), v) * dx # Divergence of u should balance expansion/contraction of the cell K # ∇⋅u = -∂x/∂t (See below for definition of the ∇⋅u term) # THIS IS SOMEWHAT EXPERIMENTAL cvol_new = dolfin.CellVolume(mesh) cvol_old = sim.data['cvolp'] eq += (cvol_new - cvol_old) / dt * q * dx # Elliptic penalties penalty_dS, penalty_ds, D11, D12 = navier_stokes_stabilization_penalties( sim, nu, velocity_continuity_factor_D12, pressure_continuity_factor) yh = 1 / penalty_ds # Upwind and downwind velocities w_nU = (dot(u_conv, n) + abs(dot(u_conv, n))) / 2.0 w_nD = (dot(u_conv, n) - abs(dot(u_conv, n))) / 2.0 # Lagrange multiplicator to remove the pressure null space # ∫ p dx = 0 if lm_trial is not None: eq = (p * lm_test + q * lm_trial) * dx # Momentum equations for d in range(sim.ndim): up = sim.data['up%d' % d] upp = sim.data['upp%d' % d] # Divergence free criterion # ∇⋅u = 0 if incompressibility_flux_type == 'central': u_hat_p = avg(u[d]) elif incompressibility_flux_type == 'upwind': assert use_grad_q_form, 'Upwind only implemented for grad_q_form' switch = dolfin.conditional(dolfin.gt(w_nU('+'), 0.0), 1.0, 0.0) u_hat_p = switch * u[d]('+') + (1 - switch) * u[d]('-') if use_grad_q_form: eq -= u[d] * q.dx(d) * dx eq += (u_hat_p + D12[d] * jump(u, n)) * jump(q) * n[d]('+') * dS else: eq += q * u[d].dx(d) * dx eq -= (avg(q) - dot(D12, jump(q, n))) * jump(u[d]) * n[d]('+') * dS # Time derivative # ∂(ρu)/∂t eq += rho * (c1 * u[d] + c2 * up + c3 * upp) / dt * v[d] * dx # Convection: # -w⋅∇(ρu) flux_nU = u[d] * w_nU flux = jump(flux_nU) eq -= u[d] * dot(grad(rho * v[d]), u_conv) * dx eq += flux * jump(rho * v[d]) * dS # Stabilizing term when w is not divergence free eq += 1 / 2 * div(u_conv) * u[d] * v[d] * dx # Diffusion: # -∇⋅μ∇u eq += mu * dot(grad(u[d]), grad(v[d])) * dx # Symmetric Interior Penalty method for -∇⋅μ∇u eq -= avg(mu) * dot(n('+'), avg(grad(u[d]))) * jump(v[d]) * dS eq -= avg(mu) * dot(n('+'), avg(grad(v[d]))) * jump(u[d]) * dS # Symmetric Interior Penalty coercivity term eq += penalty_dS * jump(u[d]) * jump(v[d]) * dS # -∇⋅μ(∇u)^T if use_stress_divergence_form: eq += mu * dot(u.dx(d), grad(v[d])) * dx eq -= avg(mu) * dot(n('+'), avg(u.dx(d))) * jump(v[d]) * dS eq -= avg(mu) * dot(n('+'), avg(v.dx(d))) * jump(u[d]) * dS # Pressure # ∇p if use_grad_p_form: eq += v[d] * p.dx(d) * dx eq -= (avg(v[d]) + D12[d] * jump(v, n)) * jump(p) * n[d]('+') * dS else: eq -= p * v[d].dx(d) * dx eq += (avg(p) - dot(D12, jump(p, n))) * jump(v[d]) * n[d]('+') * dS # Pressure continuity stabilization. Needed for equal order discretization if D11 is not None: eq += D11 * dot(jump(p, n), jump(q, n)) * dS # Body force (gravity) # ρ g eq -= rho * g[d] * v[d] * dx # Other sources for f in sim.data['momentum_sources']: eq -= f[d] * v[d] * dx # Penalty forcing zones for fz in sim.data['forcing_zones'].get('u', []): eq += fz.penalty * fz.beta * (u[d] - fz.target[d]) * v[d] * dx # Boundary conditions that do not couple the velocity components # The BCs are imposed for each velocity component u[d] separately eq += add_dirichlet_bcs(sim, d, u, p, v, q, rho, mu, n, w_nU, w_nD, penalty_ds, use_grad_q_form, use_grad_p_form) eq += add_neumann_bcs(sim, d, u, p, v, q, rho, mu, n, w_nU, w_nD, penalty_ds, use_grad_q_form, use_grad_p_form) eq += add_robin_bcs(sim, d, u, p, v, q, rho, mu, n, w_nU, w_nD, yh, use_grad_q_form, use_grad_p_form) eq += add_outlet_bcs(sim, d, u, p, v, q, rho, mu, n, w_nU, w_nD, g, x, use_grad_q_form, use_grad_p_form) # Boundary conditions that couple the velocity components # Decomposing the velocity into wall normal and parallel parts eq += add_slip_bcs(sim, u, p, v, q, rho, mu, n, w_nU, w_nD, penalty_ds, use_grad_q_form, use_grad_p_form) return eq
def x(self): try: return self._x except AttributeError: self._x = dolfin.SpatialCoordinate(self.mesh) return self._x
if really_squished_mesh: extent, NM = (0., 0., 0.02, 1.0), (1, 20) else: extent, NM = (0., 0., 1.0, 1.0), (30, 30) mesh = dolfin.RectangleMesh(tuple_to_point(extent[:2]), tuple_to_point(extent[2:]), *NM) muc = mesh.ufl_cell() I_el = dolfin.FiniteElement('CG', muc, 2) space = dolfin.FunctionSpace(mesh, I_el) u = dolfin.Function(space) test_function = dolfin.TestFunction(space) facet_normal = dolfin.FacetNormal(mesh) x = dolfin.SpatialCoordinate(mesh) def lower_boundary(x, on_boundary): return on_boundary and (abs(x[1] - 0) < 1e-10) def left_boundary(x, on_boundary): return on_boundary and (abs(x[0] - 0) < 1e-10) def right_boundary(x, on_boundary): return on_boundary and (abs(x[0] - 1) < 1e-10) def make_form(I, v, omega, beta, S):
print("start0") import dolfin as df print("start") mesh = df.RectangleMesh(df.Point(1.0, 1.0), df.Point(2.0, 2.0), 10, 10) # mesh = UnitIntervalMesh(10) el = df.FiniteElement("Lagrange", mesh.ufl_cell(), degree=1) V = df.FunctionSpace(mesh, el) x = df.SpatialCoordinate(mesh) p_code = """ #include <pybind11/pybind11.h> #include <pybind11/eigen.h> #include <cmath> #include <boost/math/special_functions/bessel.hpp> using namespace std; using namespace boost::math; namespace py = pybind11; #include <dolfin/function/Expression.h> class Pressure : public dolfin::Expression { public: