def test_save_and_read_function(tempdir): filename = os.path.join(tempdir, "function.h5") mesh = UnitSquareMesh(MPI.comm_world, 10, 10) Q = FunctionSpace(mesh, ("CG", 3)) F0 = Function(Q) F1 = Function(Q) def E(values, x): values[:, 0] = x[:, 0] F0.interpolate(E) # Save to HDF5 File hdf5_file = HDF5File(mesh.mpi_comm(), filename, "w") hdf5_file.write(F0, "/function") hdf5_file.close() # Read back from file hdf5_file = HDF5File(mesh.mpi_comm(), filename, "r") F1 = hdf5_file.read_function(Q, "/function") F0.vector().axpy(-1.0, F1.vector()) assert F0.vector().norm() < 1.0e-12 hdf5_file.close()
def test_p4_parallel_3d(): mesh = UnitCubeMesh(MPI.comm_world, 3, 5, 8) Q = FunctionSpace(mesh, ("CG", 5)) F = Function(Q) @function.expression.numba_eval def x0(values, x, cell_idx): values[:, 0] = x[:, 0] F.interpolate(Expression(x0)) # Generate random points in this mesh partition (one per cell) x = numpy.zeros(4) tree = cpp.geometry.BoundingBoxTree(mesh, mesh.geometry.dim) for c in Cells(mesh): x[0] = random() x[1] = random() * (1 - x[0]) x[2] = random() * (1 - x[0] - x[1]) x[3] = 1 - x[0] - x[1] - x[2] p = Point(0.0, 0.0, 0.0) for i, v in enumerate(VertexRange(c)): p += v.point() * x[i] p = p.array() assert numpy.isclose(F(p, tree)[0], p[0])
def test_vector_p1_3d(): meshc = UnitCubeMesh(MPI.comm_world, 2, 3, 4) meshf = UnitCubeMesh(MPI.comm_world, 3, 4, 5) Vc = VectorFunctionSpace(meshc, ("CG", 1)) Vf = VectorFunctionSpace(meshf, ("CG", 1)) def u(x): values0 = x[:, 0] + 2.0 * x[:, 1] values1 = 4.0 * x[:, 0] values2 = 3.0 * x[:, 2] + x[:, 0] return np.stack([values0, values1, values2], axis=1) uc, uf = Function(Vc), Function(Vf) uc.interpolate(u) uf.interpolate(u) mat = PETScDMCollection.create_transfer_matrix(Vc._cpp_object, Vf._cpp_object) Vuc = Function(Vf) mat.mult(uc.vector, Vuc.vector) diff = Vuc.vector diff.axpy(-1, uf.vector) assert diff.norm() < 1.0e-12
def test_save_and_read_function(tempdir): filename = os.path.join(tempdir, "function.h5") mesh = UnitSquareMesh(MPI.comm_world, 10, 10) Q = FunctionSpace(mesh, ("CG", 3)) F0 = Function(Q) F1 = Function(Q) @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = x[:, 0] E = Expression(expr_eval) F0.interpolate(E) # Save to HDF5 File hdf5_file = HDF5File(mesh.mpi_comm(), filename, "w") hdf5_file.write(F0, "/function") hdf5_file.close() # Read back from file hdf5_file = HDF5File(mesh.mpi_comm(), filename, "r") F1 = hdf5_file.read_function(Q, "/function") F0.vector().axpy(-1.0, F1.vector()) assert F0.vector().norm(dolfin.cpp.la.Norm.l2) < 1.0e-12 hdf5_file.close()
def step(self, u0, t, dt, bcs1, tol=1.0e-10, verbose=True ): u1 = Function(self.problem.V) u1.interpolate(u0) return u1
def test_interpolation_mismatch_rank1(W): def f(values, x): return np.ones((x.shape[0], 2)) u = Function(W) with pytest.raises(RuntimeError): u.interpolate(f)
def test_interpolation_old(V, W, mesh): class F0(UserExpression): def eval(self, values, x): values[:, 0] = 1.0 class F1(UserExpression): def eval(self, values, x): values[:, 0] = 1.0 values[:, 1] = 1.0 values[:, 2] = 1.0 def value_shape(self): return (3, ) # Scalar interpolation f0 = F0(degree=0) f = Function(V) f = interpolate(f0, V) assert round(f.vector().norm(cpp.la.Norm.l1) - mesh.num_vertices(), 7) == 0 # Vector interpolation f1 = F1(degree=0) f = Function(W) f.interpolate(f1) assert round(f.vector().norm(cpp.la.Norm.l1) - 3 * mesh.num_vertices(), 7) == 0
def mk_scheme(N, Vname, Vorder, cpp_expr, expr_args, convection_inp, dim=2, comm=None): if comm is None: comm = MPI.comm_world parameters['ghost_mode'] = 'shared_vertex' if dim == 2: mesh = UnitSquareMesh(comm, N, N) else: mesh = UnitCubeMesh(comm, N, N, N) V = FunctionSpace(mesh, Vname, Vorder) C = Function(V) e = Expression(cpp_expr, element=V.ufl_element(), **expr_args) C.interpolate(e) D = Function(V) D.assign(C) sim = Simulation() sim.set_mesh(mesh) sim.data['constrained_domain'] = None sim.data['C'] = C for key, value in convection_inp.items(): sim.input.set_value('convection/C/%s' % key, value) scheme_name = convection_inp['convection_scheme'] return get_convection_scheme(scheme_name)(sim, 'C')
def test_mixed_parallel(): mesh = UnitSquareMesh(MPI.comm_world, 5, 8) V = VectorElement("Lagrange", triangle, 4) Q = FiniteElement("Lagrange", triangle, 5) W = FunctionSpace(mesh, Q * V) F = Function(W) @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, 0] = x[:, 0] values[:, 1] = x[:, 1] values[:, 2] = numpy.sin(x[:, 0] + x[:, 1]) F.interpolate(Expression(expr_eval, shape=(3, ))) # Generate random points in this mesh partition (one per cell) x = numpy.zeros(3) for c in Cells(mesh): x[0] = random() x[1] = random() * (1 - x[0]) x[2] = (1 - x[0] - x[1]) p = Point(0.0, 0.0) for i, v in enumerate(VertexRange(c)): p += v.point() * x[i] p = p.array()[:2] val = F(p) assert numpy.allclose(val[0], p[0]) assert numpy.isclose(val[1], p[1]) assert numpy.isclose(val[2], numpy.sin(p[0] + p[1]))
def test_l2projection(polynomial_order, in_expression): # Test l2 projection for scalar and vector valued expression interpolate_expression = Expression(in_expression, degree=3) xmin, xmax = 0., 1. ymin, ymax = 0., 1. property_idx = 5 mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), 40, 40) if len(interpolate_expression.ufl_shape) == 0: V = FunctionSpace(mesh, "DG", polynomial_order) elif len(interpolate_expression.ufl_shape) == 1: V = VectorFunctionSpace(mesh, "DG", polynomial_order) v_exact = Function(V) v_exact.interpolate(interpolate_expression) x = RandomRectangle(Point(xmin, ymin), Point(xmax, ymax)).generate([500, 500]) s = assign_particle_values(x, interpolate_expression) # Just make a complicated particle, possibly with scalars and vectors mixed p = particles(x, [x, s, x, x, s], mesh) vh = Function(V) lstsq_rho = l2projection(p, V, property_idx) lstsq_rho.project(vh) error_sq = abs(assemble(dot(v_exact - vh, v_exact - vh) * dx)) assert error_sq < 1e-15
def initialize(self, warp, istart): self.istart = istart for i in xrange(istart, istart + self.N): rad = 0.0 ist = 0 for n, d in zip(self.Ns, self.Dias): for j in xrange(n): print j fib = warp.fibrils[i * np.sum(self.Ns) + ist] qhh = Geometry_Curves.qhh_stockinette2 temp_field = Function(fib.problem.spaces['V']) p1 = rad * np.cos(2.0 * np.pi * float(j) / float(n)) p2 = rad * np.sin(2.0 * np.pi * float(j) / float(n)) for fix in xrange(3): temp_field.interpolate( Expression(qhh[fix], sq=-(self.restL - self.setL) / self.restL, p=np.pi / self.restL * (4.0), o=self.setL / 3.5, A1=1.3 * self.width / self.N, A2=self.width / self.N, y1=p1, y2=p2)) assign(fib.problem.fields['wx'].sub(fix), temp_field) temp_field.interpolate(Constant((0.0, 0.0, 0.0))) assign(fib.problem.fields['wv'].sub(fix), temp_field) ist += 1 rad += d
def test_save_and_checkpoint_scalar(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, "u1_checkpoint.xdmf") mesh = mesh_factory(mesh_tdim, mesh_n) FE = FiniteElement(fe_family, mesh.ufl_cell(), fe_degree) V = FunctionSpace(mesh, FE) u_in = Function(V) u_out = Function(V) if has_petsc_complex: def expr_eval(values, x): values[:, 0] = x[:, 0] + 1.0j * x[:, 0] u_out.interpolate(expr_eval) else: def expr_eval(values, x): values[:, 0] = x[:, 0] u_out.interpolate(expr_eval) 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 test_save_and_checkpoint_scalar(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, "u1_checkpoint.xdmf") mesh = mesh_factory(mesh_tdim, mesh_n) FE = FiniteElement(fe_family, mesh.ufl_cell(), fe_degree) V = FunctionSpace(mesh, FE) u_in = Function(V) u_out = Function(V) if has_petsc_complex: u_out.interpolate(Expression("x[0] + j*x[0]", degree=1)) else: u_out.interpolate(Expression("x[0]", degree=1)) 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(cpp.la.Norm.l2) < 1.0e-12
def test_taylor_hood_cube(): pytest.xfail("Problem with Mixed Function Spaces") meshc = UnitCubeMesh(MPI.comm_world, 2, 2, 2) meshf = UnitCubeMesh(MPI.comm_world, 3, 4, 5) Ve = VectorElement("CG", meshc.ufl_cell(), 2) Qe = FiniteElement("CG", meshc.ufl_cell(), 1) Ze = MixedElement([Ve, Qe]) Zc = FunctionSpace(meshc, Ze) Zf = FunctionSpace(meshf, Ze) def z(x): values = np.array([x.shape[0], 3]) values[:, 0] = x[:, 0] * x[:, 1] values[:, 1] = x[:, 1] * x[:, 2] values[:, 2] = x[:, 2] * x[:, 0] values[:, 3] = x[:, 0] + 3.0 * x[:, 1] + x[:, 2] return values zc, zf = Function(Zc), Function(Zf) zc.interpolate(z) zf.interpolate(z) mat = PETScDMCollection.create_transfer_matrix(Zc, Zf) Zuc = Function(Zf) mat.mult(zc.vector, Zuc.vector) Zuc.vector.update_ghost_values() diff = Function(Zf) diff.assign(Zuc - zf) assert diff.vector.norm("l2") < 1.0e-12
def test_save_2d_vector(tempdir, encoding): filename = os.path.join(tempdir, "u_2dv.xdmf") mesh = UnitSquareMesh(MPI.comm_world, 16, 16) V = VectorFunctionSpace(mesh, ("Lagrange", 2)) u = Function(V) c = Constant((1.0 + (1j if has_petsc_complex else 0), 2.0)) u.interpolate(c) with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: file.write(u)
def test_save_3d_vector(tempdir, encoding): filename = os.path.join(tempdir, "u_3Dv.xdmf") mesh = UnitCubeMesh(MPI.comm_world, 2, 2, 2) u = Function(VectorFunctionSpace(mesh, ("Lagrange", 1))) A = 1.0 + (1j if has_petsc_complex else 0) c = Constant((1.0 + A, 2.0 + 2 * A, 3.0 + 3 * A)) u.interpolate(c) with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: file.write(u)
def test_numba_expression_address(V): @function.expression.numba_eval def expr_eval(values, x, cell_idx): values[:, :] = 1.0 # Handle C func address by hand f1 = Expression(expr_eval.address) f = Function(V) f.interpolate(f1) assert (f.vector().get_local() == 1.0).all()
def mk_vel(sim, Vname, Vorder, cpp_exprs): mesh = sim.data['mesh'] V = FunctionSpace(mesh, Vname, Vorder) vel = [] for cpp in cpp_exprs: u = Function(V) u.interpolate(Expression(cpp, element=V.ufl_element())) vel.append(u) return as_vector(vel)
def test_save_3d_vector(tempdir, encoding): if invalid_config(encoding): pytest.skip("XDMF unsupported in current configuration") filename = os.path.join(tempdir, "u_3Dv.xdmf") mesh = UnitCubeMesh(MPI.comm_world, 2, 2, 2) u = Function(VectorFunctionSpace(mesh, "Lagrange", 1)) c = Constant((1.0, 2.0, 3.0)) u.interpolate(c) with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: file.write(u)
def test_save_2d_vector(tempdir, encoding): if invalid_config(encoding): pytest.skip("XDMF unsupported in current configuration") filename = os.path.join(tempdir, "u_2dv.xdmf") mesh = UnitSquareMesh(MPI.comm_world, 16, 16) V = VectorFunctionSpace(mesh, "Lagrange", 2) u = Function(V) c = Constant((1.0 + (1j if has_petsc_complex() else 0), 2.0)) u.interpolate(c) with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: file.write(u)
def test_numba_expression_address(V): @function.expression.numba_eval def expr_eval(values, x, t): values[:, :] = 1.0 # Handle C func address by hand f1 = Expression(expr_eval.address) f = Function(V) f.interpolate(f1) with f.vector().localForm() as lf: assert (lf[:] == 1.0).all()
def test_interpolation_rank1(W): def f(x): values = np.empty((x.shape[0], 3)) values[:, 0] = 1.0 values[:, 1] = 1.0 values[:, 2] = 1.0 return values w = Function(W) w.interpolate(f) x = w.vector assert x.max()[1] == 1.0 assert x.min()[1] == 1.0
def test_read_write_p2_function(tempdir): mesh = cpp.generation.UnitDiscMesh.create(MPI.comm_world, 3, cpp.mesh.GhostMode.none) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap Q = FunctionSpace(mesh, ("Lagrange", 2)) F = Function(Q) if has_petsc_complex: F.interpolate(Expression("x[0] + j*x[0]", degree=1)) else: F.interpolate(Expression("x[0]", degree=1)) filename = os.path.join(tempdir, "tri6_function.xdmf") with XDMFFile(mesh.mpi_comm(), filename, encoding=XDMFFile.Encoding.HDF5) as xdmf: xdmf.write(F) Q = VectorFunctionSpace(mesh, ("Lagrange", 1)) F = Function(Q) if has_petsc_complex: F.interpolate(Expression(("x[0] + j*x[0]", "x[1] + j*x[1]"), degree=1)) else: F.interpolate(Expression(("x[0]", "x[1]"), degree=1)) filename = os.path.join(tempdir, "tri6_vector_function.xdmf") with XDMFFile(mesh.mpi_comm(), filename, encoding=XDMFFile.Encoding.HDF5) as xdmf: xdmf.write(F)
class MockFunctionField(Field): def __init__(self, Q, params=None, **args): Field.__init__(self, params, **args) self.f = Function(Q) def before_first_compute(self, get): t = get('t') self.expr = Expression("1+x[0]*x[1]*t", degree=1, t=t) def compute(self, get): t = get('t') self.expr.t = t self.f.interpolate(self.expr) return self.f
def initialize(self, warp, istart): self.istart = istart for i in xrange(istart, istart + self.NX): for j in xrange(np.sum(self.pattern)): fib = warp.fibrils[i * np.sum(self.pattern) + j] qhh = Geometry_Curves.qhh_plain_0 temp_field = Function(fib.problem.spaces['V']) for fix in xrange(3): temp_field.interpolate( Expression(qhh[fix], sq=-(self.restX - self.setX) / self.restX, p=np.pi / self.restX * (self.NY) / 2.0, A1=(-1.0 if i % 2 == 0 else 1.0) * self.height)) assign(fib.problem.fields['wx'].sub(fix), temp_field) temp_field.interpolate(Constant((0.0, 0.0, 0.0))) assign(fib.problem.fields['wv'].sub(fix), temp_field) for i in xrange(istart + self.NX, istart + (self.NX + self.NY)): for j in xrange(np.sum(self.pattern)): fib = warp.fibrils[i * np.sum(self.pattern) + j] qhh = Geometry_Curves.qhh_plain_1 temp_field = Function(fib.problem.spaces['V']) for fix in xrange(3): temp_field.interpolate( Expression(qhh[fix], sq=-(self.restY - self.setY) / self.restY, p=np.pi / self.restY * (self.NX) / 2.0, A1=(-1.0 if i % 2 == 1 else 1.0) * self.height)) assign(fib.problem.fields['wx'].sub(fix), temp_field) temp_field.interpolate(Constant((0.0, 0.0, 0.0))) assign(fib.problem.fields['wv'].sub(fix), temp_field)
def test_cffi_expression(V): code_h = """ void eval(double* values, const double* x, const int64_t* cell_idx, int num_points, int value_size, int gdim, int num_cells); """ code_c = """ void eval(double* values, const double* x, const int64_t* cell_idx, int num_points, int value_size, int gdim, int num_cells) { for (int i = 0; i < num_points; ++i) { values[i*value_size + 0] = x[i*gdim + 0] + x[i*gdim + 1]; } } """ module = "_expr_eval" + str(MPI.comm_world.rank) # Build the kernel ffi = cffi.FFI() ffi.set_source(module, code_c) ffi.cdef(code_h) ffi.compile() # Import the compiled kernel kernel_mod = importlib.import_module(module) ffi, lib = kernel_mod.ffi, kernel_mod.lib # Get pointer to the compiled function eval_ptr = ffi.cast("uintptr_t", ffi.addressof(lib, "eval")) # Handle C func address by hand ex1 = Expression(int(eval_ptr)) f1 = Function(V) f1.interpolate(ex1) @function.expression.numba_eval def expr_eval2(values, x, cell_idx): values[:, 0] = x[:, 0] + x[:, 1] ex2 = Expression(expr_eval2) f2 = Function(V) f2.interpolate(ex2) assert (f1.vector().get_local() == f2.vector().get_local()).all()
def test_interpolation_old(V, W, mesh): def f0(x): return np.ones(x.shape[0]) def f1(x): return np.ones((x.shape[0], mesh.geometry.dim)) # Scalar interpolation f = Function(V) f.interpolate(f0) assert round(f.vector.norm(PETSc.NormType.N1) - mesh.num_entities(0), 7) == 0 # Vector interpolation f = Function(W) f.interpolate(f1) assert round( f.vector.norm(PETSc.NormType.N1) - 3 * mesh.num_entities(0), 7) == 0
def test_p4_parallel_2d(): mesh = UnitSquareMesh(MPI.comm_world, 5, 8) Q = FunctionSpace(mesh, ("CG", 4)) F = Function(Q) F.interpolate(Expression("x[0]", degree=4)) # Generate random points in this mesh partition (one per cell) x = numpy.zeros(3) for c in Cells(mesh): x[0] = random() x[1] = random() * (1 - x[0]) x[2] = 1 - x[0] - x[1] p = Point(0.0, 0.0) for i, v in enumerate(VertexRange(c)): p += v.point() * x[i] p = p.array()[:2] assert numpy.isclose(F(p)[0], p[0])
def test_interpolation_old(V, W, mesh): def f0(values, x): values[:, 0] = 1.0 def f1(values, x): values[:, :] = 1.0 # Scalar interpolation f = Function(V) f.interpolate(f0) assert round(f.vector().norm(PETSc.NormType.N1) - mesh.num_entities(0), 7) == 0 # Vector interpolation f = Function(W) f.interpolate(f1) assert round(f.vector().norm(PETSc.NormType.N1) - 3 * mesh.num_entities(0), 7) == 0
def test_interpolation_rank0(V): class MyExpression: def __init__(self): self.t = 0.0 def eval(self, x): return np.full(x.shape[0], self.t) f = MyExpression() f.t = 1.0 w = Function(V) w.interpolate(f.eval) with w.vector.localForm() as x: assert (x[:] == 1.0).all() f.t = 2.0 w.interpolate(f.eval) with w.vector.localForm() as x: assert (x[:] == 2.0).all()
class MockVectorFunctionField(Field): def __init__(self, V, params=None): Field.__init__(self, params) self.f = Function(V) def before_first_compute(self, get): t = get('t') D = self.f.function_space().mesh().geometry().dim() if D == 2: self.expr = Expression(("1+x[0]*t", "3+x[1]*t"), degree=1, t=t) elif D == 3: self.expr = Expression(("1+x[0]*t", "3+x[1]*t", "10+x[2]*t"), degree=1, t=t) def compute(self, get): t = get('t') self.expr.t = t self.f.interpolate(self.expr) return self.f
def run_with_params(Tb, mu_value, k_s, path): run_time_init = clock() mesh = BoxMesh(Point(0.0, 0.0, 0.0), Point(mesh_width, mesh_width, mesh_height), nx, ny, nz) pbc = PeriodicBoundary() WE = VectorElement('CG', mesh.ufl_cell(), 2) SE = FiniteElement('CG', mesh.ufl_cell(), 1) WSSS = FunctionSpace(mesh, MixedElement(WE, SE, SE, SE), constrained_domain=pbc) # W = FunctionSpace(mesh, WE, constrained_domain=pbc) # S = FunctionSpace(mesh, SE, constrained_domain=pbc) W = WSSS.sub(0).collapse() S = WSSS.sub(1).collapse() temperature_vals = [27.0 + 273, Tb + 273, 1300.0 + 273, 1305.0 + 273] temp_prof = TemperatureProfile(temperature_vals, element=S.ufl_element()) mu_a = mu_value # this was taken from the Blankenbach paper, can change Ep = b / temp_prof.delta mu_bot = exp(-Ep * (temp_prof.bottom * temp_prof.delta - 1573.0) + cc) * mu_a # TODO: verify exponentiation Ra = rho_0 * alpha * g * temp_prof.delta * h ** 3 / (kappa_0 * mu_a) w0 = rho_0 * alpha * g * temp_prof.delta * h ** 2 / mu_a tau = h / w0 p0 = mu_a * w0 / h log(mu_a, mu_bot, Ra, w0, p0) slip_vx = 1.6E-09 / w0 # Non-dimensional slip_velocity = Constant((slip_vx, 0.0, 0.0)) zero_slip = Constant((0.0, 0.0, 0.0)) time_step = 3.0E11 / tau * 2 dt = Constant(time_step) t_end = 3.0E15 / tau / 5.0 # Non-dimensional times u = Function(WSSS) # Instead of TrialFunctions, we use split(u) for our non-linear problem v, p, T, Tf = split(u) v_t, p_t, T_t, Tf_t = TestFunctions(WSSS) T0 = interpolate(temp_prof, S) mu_exp = Expression('exp(-Ep * (T_val * dTemp - 1573.0) + cc * x[2] / mesh_height)', Ep=Ep, dTemp=temp_prof.delta, cc=cc, mesh_height=mesh_height, T_val=T0, element=S.ufl_element()) Tf0 = interpolate(temp_prof, S) mu = Function(S) v0 = Function(W) v_theta = (1.0 - theta) * v0 + theta * v T_theta = (1.0 - theta) * T0 + theta * T Tf_theta = (1.0 - theta) * Tf0 + theta * Tf # TODO: Verify forms r_v = (inner(sym(grad(v_t)), 2.0 * mu * sym(grad(v))) - div(v_t) * p - T * v_t[2]) * dx r_p = p_t * div(v) * dx heat_transfer = Constant(k_s) * (Tf_theta - T_theta) * dt r_T = (T_t * ((T - T0) + dt * inner(v_theta, grad(T_theta))) # TODO: Inner vs dot + (dt / Ra) * inner(grad(T_t), grad(T_theta)) - T_t * heat_transfer) * dx v_melt = Function(W) z_hat = Constant((0.0, 0.0, 1.0)) # TODO: inner -> dot, take out Tf_t r_Tf = (Tf_t * ((Tf - Tf0) + dt * inner(v_melt, grad(Tf_theta))) + Tf_t * heat_transfer) * dx r = r_v + r_p + r_T + r_Tf bcv0 = DirichletBC(WSSS.sub(0), zero_slip, top) bcv1 = DirichletBC(WSSS.sub(0), slip_velocity, bottom) bcv2 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), back) bcv3 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), front) bcp0 = DirichletBC(WSSS.sub(1), Constant(0.0), bottom) bct0 = DirichletBC(WSSS.sub(2), Constant(temp_prof.surface), top) bct1 = DirichletBC(WSSS.sub(2), Constant(temp_prof.bottom), bottom) bctf1 = DirichletBC(WSSS.sub(3), Constant(temp_prof.bottom), bottom) bcs = [bcv0, bcv1, bcv2, bcv3, bcp0, bct0, bct1, bctf1] t = 0 count = 0 files = DefaultDictByKey(partial(create_xdmf, path)) while t < t_end: mu.interpolate(mu_exp) rhosolid = rho_0 * (1.0 - alpha * (T0 * temp_prof.delta - 1573.0)) deltarho = rhosolid - rho_melt # TODO: project (accuracy) vs interpolate assign(v_melt, project(v0 - darcy * (grad(p) * p0 / h - deltarho * z_hat * g) / w0, W)) # TODO: Written out one step later? # v_melt.assign(v0 - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0) # TODO: use nP after to avoid projection? solve(r == 0, u, bcs) nV, nP, nT, nTf = u.split() # TODO: write with Tf, ... etc if count % output_every == 0: time_left(count, t_end / time_step, run_time_init) # TODO: timestep vs dt # TODO: Make sure all writes are to the same function for each time step files['T_fluid'].write(nTf, t) files['p'].write(nP, t) files['v_solid'].write(nV, t) files['T_solid'].write(nT, t) files['mu'].write(mu, t) files['v_melt'].write(v_melt, t) files['gradp'].write(project(grad(nP), W), t) files['rho'].write(project(rhosolid, S), t) files['Tf_grad'].write(project(grad(Tf), W), t) files['advect'].write(project(dt * dot(v_melt, grad(nTf))), t) files['ht'].write(project(heat_transfer, S), t) assign(T0, nT) assign(v0, nV) assign(Tf0, nTf) t += time_step count += 1 log('Case mu={}, Tb={}, k={} complete. Run time = {:.2f} minutes'.format(mu_a, Tb, k_s, (clock() - run_time_init) / 60.0))
def _pressure_poisson(self, p1, p0, mu, ui, u, p_bcs=None, rotational_form=False, tol=1.0e-10, verbose=True ): '''Solve the pressure Poisson equation -1/r \div(r \nabla (p1-p0)) = -1/r div(r*u), boundary conditions, for \nabla p = u. ''' r = Expression('x[0]', degree=1, domain=self.W.mesh()) Q = p1.function_space() p = TrialFunction(Q) q = TestFunction(Q) a2 = dot(r * grad(p), grad(q)) * 2 * pi * dx # The boundary conditions # n.(p1-p0) = 0 # are implicitly included. # # L2 = -div(r*u) * q * 2*pi*dx div_u = 1/r * (r * u[0]).dx(0) + u[1].dx(1) L2 = -div_u * q * 2*pi*r*dx if p0: L2 += r * dot(grad(p0), grad(q)) * 2*pi*dx # In the Cartesian variant of the rotational form, one makes use of the # fact that # # curl(curl(u)) = grad(div(u)) - div(grad(u)). # # The same equation holds true in cylindrical form. Hence, to get the # rotational form of the splitting scheme, we need to # # rotational form if rotational_form: # If there is no dependence of the angular coordinate, what is # div(grad(div(u))) in Cartesian coordinates becomes # # 1/r div(r * grad(1/r div(r*u))) # # in cylindrical coordinates (div and grad are in cylindrical # coordinates). Unfortunately, we cannot write it down that # compactly since u_phi is in the game. # When using P2 elements, this value will be 0 anyways. div_ui = 1/r * (r * ui[0]).dx(0) + ui[1].dx(1) grad_div_ui = as_vector((div_ui.dx(0), div_ui.dx(1))) L2 -= r * mu * dot(grad_div_ui, grad(q)) * 2*pi*dx #div_grad_div_ui = 1/r * (r * grad_div_ui[0]).dx(0) \ # + (grad_div_ui[1]).dx(1) #L2 += mu * div_grad_div_ui * q * 2*pi*r*dx #n = FacetNormal(Q.mesh()) #L2 -= mu * (n[0] * grad_div_ui[0] + n[1] * grad_div_ui[1]) \ # * q * 2*pi*r*ds if p_bcs: solve( a2 == L2, p1, bcs=p_bcs, solver_parameters={ 'linear_solver': 'iterative', 'symmetric': True, 'preconditioner': 'amg', 'krylov_solver': {'relative_tolerance': tol, 'absolute_tolerance': 0.0, 'maximum_iterations': 100, 'monitor_convergence': verbose} } ) else: # If we're dealing with a pure Neumann problem here (which is the # default case), this doesn't hurt CG if the system is consistent, # cf. :cite:`vdV03`. And indeed it is consistent if and only if # # \int_\Gamma r n.u = 0. # # This makes clear that for incompressible Navier-Stokes, one # either needs to make sure that inflow and outflow always add up # to 0, or one has to specify pressure boundary conditions. # # If the right-hand side is very small, round-off errors may impair # the consistency of the system. Make sure the system we are # solving remains consistent. A = assemble(a2) b = assemble(L2) # Assert that the system is indeed consistent. e = Function(Q) e.interpolate(Constant(1.0)) evec = e.vector() evec /= norm(evec) alpha = b.inner(evec) normB = norm(b) # Assume that in every component of the vector, a round-off error # of the magnitude DOLFIN_EPS is present. This leads to the # criterion # |<b,e>| / (||b||*||e||) < DOLFIN_EPS # as a check whether to consider the system consistent up to # round-off error. # # TODO think about condition here #if abs(alpha) > normB * DOLFIN_EPS: if abs(alpha) > normB * 1.0e-12: divu = 1 / r * (r * u[0]).dx(0) + u[1].dx(1) adivu = assemble(((r * u[0]).dx(0) + u[1].dx(1)) * 2 * pi * dx) info('\int 1/r * div(r*u) * 2*pi*r = %e' % adivu) n = FacetNormal(Q.mesh()) boundary_integral = assemble((n[0] * u[0] + n[1] * u[1]) * 2 * pi * r * ds) info('\int_Gamma n.u * 2*pi*r = %e' % boundary_integral) message = ('System not consistent! ' '<b,e> = %g, ||b|| = %g, <b,e>/||b|| = %e.') \ % (alpha, normB, alpha / normB) info(message) # Plot the stuff, and project it to a finer mesh with linear # elements for the purpose. plot(divu, title='div(u_tentative)') #Vp = FunctionSpace(Q.mesh(), 'CG', 2) #Wp = MixedFunctionSpace([Vp, Vp]) #up = project(u, Wp) fine_mesh = Q.mesh() for k in range(1): fine_mesh = refine(fine_mesh) V = FunctionSpace(fine_mesh, 'CG', 1) W = V * V #uplot = Function(W) #uplot.interpolate(u) uplot = project(u, W) plot(uplot[0], title='u_tentative[0]') plot(uplot[1], title='u_tentative[1]') #plot(u, title='u_tentative') interactive() exit() raise RuntimeError(message) # Project out the roundoff error. b -= alpha * evec # # In principle, the ILU preconditioner isn't advised here since it # might destroy the semidefiniteness needed for CG. # # The system is consistent, but the matrix has an eigenvalue 0. # This does not harm the convergence of CG, but when # preconditioning one has to make sure that the preconditioner # preserves the kernel. ILU might destroy this (and the # semidefiniteness). With AMG, the coarse grid solves cannot be LU # then, so try Jacobi here. # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html> # prec = PETScPreconditioner('hypre_amg') from dolfin import PETScOptions PETScOptions.set('pc_hypre_boomeramg_relax_type_coarse', 'jacobi') solver = PETScKrylovSolver('cg', prec) solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = tol solver.parameters['maximum_iterations'] = 100 solver.parameters['monitor_convergence'] = verbose # Create solver and solve system A_petsc = as_backend_type(A) b_petsc = as_backend_type(b) p1_petsc = as_backend_type(p1.vector()) solver.set_operator(A_petsc) solver.solve(p1_petsc, b_petsc) # This would be the stump for Epetra: #solve(A, p.vector(), b, 'cg', 'ml_amg') return
def compute_pressure( P, p0, mu, ui, u, my_dx, p_bcs=None, rotational_form=False, tol=1.0e-10, verbose=True, ): """Solve the pressure Poisson equation .. math:: \\begin{align} -\\frac{1}{r} \\div(r \\nabla (p_1-p_0)) = -\\frac{1}{r} \\div(r u),\\\\ \\text{(with boundary conditions)}, \\end{align} for :math:`\\nabla p = u`. The pressure correction is based on the update formula .. math:: \\frac{\\rho}{dt} (u_{n+1}-u^*) + \\begin{pmatrix} \\text{d}\\phi/\\text{d}r\\\\ \\text{d}\\phi/\\text{d}z\\\\ \\frac{1}{r} \\text{d}\\phi/\\text{d}\\theta \\end{pmatrix} = 0 with :math:`\\phi = p_{n+1} - p^*` and .. math:: \\frac{1}{r} \\frac{\\text{d}}{\\text{d}r} (r u_r^{(n+1)}) + \\frac{\\text{d}}{\\text{d}z} (u_z^{(n+1)}) + \\frac{1}{r} \\frac{\\text{d}}{\\text{d}\\theta} (u_{\\theta}^{(n+1)}) = 0 With the assumption that u does not change in the direction :math:`\\theta`, one derives .. math:: - \\frac{1}{r} \\div(r \\nabla \\phi) = \\frac{1}{r} \\frac{\\rho}{dt} \\div(r (u_{n+1} - u^*))\\\\ - \\frac{1}{r} \\langle n, r \\nabla \\phi\\rangle = \\frac{1}{r} \\frac{\\rho}{dt} \\langle n, r (u_{n+1} - u^*)\\rangle In its weak form, this is .. math:: \\int r \\langle\\nabla\\phi, \\nabla q\\rangle \\,2 \\pi = - \\frac{\\rho}{dt} \\int \\div(r u^*) q \\, 2 \\pi - \\frac{\\rho}{dt} \\int_{\\Gamma} \\langle n, r (u_{n+1}-u^*)\\rangle q \\, 2\\pi. (The terms :math:`1/r` cancel with the volume elements :math:`2\\pi r`.) If the Dirichlet boundary conditions are applied to both :math:`u^*` and :math:`u_n` (the latter in the velocity correction step), the boundary integral vanishes. If no Dirichlet conditions are given (which is the default case), the system has no unique solution; one eigenvalue is 0. This however, does not hurt CG convergence if the system is consistent, cf. :cite:`vdV03`. And indeed it is consistent if and only if .. math:: \\int_\\Gamma r \\langle n, u\\rangle = 0. This condition makes clear that for incompressible Navier-Stokes, one either needs to make sure that inflow and outflow always add up to 0, or one has to specify pressure boundary conditions. Note that, when using a multigrid preconditioner as is done here, the coarse solver must be chosen such that it preserves the nullspace of the problem. """ W = ui.function_space() r = SpatialCoordinate(W.mesh())[0] p = TrialFunction(P) q = TestFunction(P) a2 = dot(r * grad(p), grad(q)) * 2 * pi * my_dx # The boundary conditions # n.(p1-p0) = 0 # are implicitly included. # # L2 = -div(r*u) * q * 2*pi*my_dx div_u = 1 / r * (r * u[0]).dx(0) + u[1].dx(1) L2 = -div_u * q * 2 * pi * r * my_dx if p0: L2 += r * dot(grad(p0), grad(q)) * 2 * pi * my_dx # In the Cartesian variant of the rotational form, one makes use of the # fact that # # curl(curl(u)) = grad(div(u)) - div(grad(u)). # # The same equation holds true in cylindrical form. Hence, to get the # rotational form of the splitting scheme, we need to # # rotational form if rotational_form: # If there is no dependence of the angular coordinate, what is # div(grad(div(u))) in Cartesian coordinates becomes # # 1/r div(r * grad(1/r div(r*u))) # # in cylindrical coordinates (div and grad are in cylindrical # coordinates). Unfortunately, we cannot write it down that # compactly since u_phi is in the game. # When using P2 elements, this value will be 0 anyways. div_ui = 1 / r * (r * ui[0]).dx(0) + ui[1].dx(1) grad_div_ui = as_vector((div_ui.dx(0), div_ui.dx(1))) L2 -= r * mu * dot(grad_div_ui, grad(q)) * 2 * pi * my_dx # div_grad_div_ui = 1/r * (r * grad_div_ui[0]).dx(0) \ # + (grad_div_ui[1]).dx(1) # L2 += mu * div_grad_div_ui * q * 2*pi*r*dx # n = FacetNormal(Q.mesh()) # L2 -= mu * (n[0] * grad_div_ui[0] + n[1] * grad_div_ui[1]) \ # * q * 2*pi*r*ds p1 = Function(P) if p_bcs: solve( a2 == L2, p1, bcs=p_bcs, solver_parameters={ "linear_solver": "iterative", "symmetric": True, "preconditioner": "hypre_amg", "krylov_solver": { "relative_tolerance": tol, "absolute_tolerance": 0.0, "maximum_iterations": 100, "monitor_convergence": verbose, }, }, ) else: # If we're dealing with a pure Neumann problem here (which is the # default case), this doesn't hurt CG if the system is consistent, # cf. :cite:`vdV03`. And indeed it is consistent if and only if # # \int_\Gamma r n.u = 0. # # This makes clear that for incompressible Navier-Stokes, one # either needs to make sure that inflow and outflow always add up # to 0, or one has to specify pressure boundary conditions. # # If the right-hand side is very small, round-off errors may impair # the consistency of the system. Make sure the system we are # solving remains consistent. A = assemble(a2) b = assemble(L2) # Assert that the system is indeed consistent. e = Function(P) e.interpolate(Constant(1.0)) evec = e.vector() evec /= norm(evec) alpha = b.inner(evec) normB = norm(b) # Assume that in every component of the vector, a round-off error # of the magnitude DOLFIN_EPS is present. This leads to the # criterion # |<b,e>| / (||b||*||e||) < DOLFIN_EPS # as a check whether to consider the system consistent up to # round-off error. # # TODO think about condition here # if abs(alpha) > normB * DOLFIN_EPS: if abs(alpha) > normB * 1.0e-12: # divu = 1 / r * (r * u[0]).dx(0) + u[1].dx(1) adivu = assemble(((r * u[0]).dx(0) + u[1].dx(1)) * 2 * pi * my_dx) info("\\int 1/r * div(r*u) * 2*pi*r = {:e}".format(adivu)) n = FacetNormal(P.mesh()) boundary_integral = assemble((n[0] * u[0] + n[1] * u[1]) * 2 * pi * r * ds) info("\\int_Gamma n.u * 2*pi*r = {:e}".format(boundary_integral)) message = ( "System not consistent! " "<b,e> = {:g}, ||b|| = {:g}, <b,e>/||b|| = {:e}.".format( alpha, normB, alpha / normB ) ) info(message) # # Plot the stuff, and project it to a finer mesh with linear # # elements for the purpose. # plot(divu, title='div(u_tentative)') # # Vp = FunctionSpace(Q.mesh(), 'CG', 2) # # Wp = MixedFunctionSpace([Vp, Vp]) # # up = project(u, Wp) # fine_mesh = Q.mesh() # for k in range(1): # fine_mesh = refine(fine_mesh) # V = FunctionSpace(fine_mesh, 'CG', 1) # W = V * V # # uplot = Function(W) # # uplot.interpolate(u) # uplot = project(u, W) # plot(uplot[0], title='u_tentative[0]') # plot(uplot[1], title='u_tentative[1]') # # plot(u, title='u_tentative') # interactive() # exit() raise RuntimeError(message) # Project out the roundoff error. b -= alpha * evec # # In principle, the ILU preconditioner isn't advised here since it # might destroy the semidefiniteness needed for CG. # # The system is consistent, but the matrix has an eigenvalue 0. # This does not harm the convergence of CG, but when # preconditioning one has to make sure that the preconditioner # preserves the kernel. ILU might destroy this (and the # semidefiniteness). With AMG, the coarse grid solves cannot be LU # then, so try Jacobi here. # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html> # prec = PETScPreconditioner("hypre_amg") from dolfin import PETScOptions PETScOptions.set("pc_hypre_boomeramg_relax_type_coarse", "jacobi") solver = PETScKrylovSolver("cg", prec) solver.parameters["absolute_tolerance"] = 0.0 solver.parameters["relative_tolerance"] = tol solver.parameters["maximum_iterations"] = 100 solver.parameters["monitor_convergence"] = verbose # Create solver and solve system A_petsc = as_backend_type(A) b_petsc = as_backend_type(b) p1_petsc = as_backend_type(p1.vector()) solver.set_operator(A_petsc) solver.solve(p1_petsc, b_petsc) return p1
def _pressure_poisson(self, p1, p0, mu, ui, divu, p_bcs=None, p_n=None, rotational_form=False, tol=1.0e-10, verbose=True ): '''Solve the pressure Poisson equation - \Delta phi = -div(u), boundary conditions, for \nabla p = u. ''' P = p1.function_space() p = TrialFunction(P) q = TestFunction(P) a2 = dot(grad(p), grad(q)) * dx L2 = -divu * q * dx if p0: L2 += dot(grad(p0), grad(q)) * dx if p_n: n = FacetNormal(P.mesh()) L2 += dot(n, p_n) * q * ds if rotational_form: L2 -= mu * dot(grad(div(ui)), grad(q)) * dx if p_bcs: solve(a2 == L2, p1, bcs=p_bcs, solver_parameters={ 'linear_solver': 'iterative', 'symmetric': True, 'preconditioner': 'hypre_amg', 'krylov_solver': {'relative_tolerance': tol, 'absolute_tolerance': 0.0, 'maximum_iterations': 100, 'monitor_convergence': verbose} }) else: # If we're dealing with a pure Neumann problem here (which is the # default case), this doesn't hurt CG if the system is consistent, # cf. # # Iterative Krylov methods for large linear systems, # Henk A. van der Vorst. # # And indeed, it is consistent: Note that # # <1, rhs> = \sum_i 1 * \int div(u) v_i # = 1 * \int div(u) \sum_i v_i # = \int div(u). # # With the divergence theorem, we have # # \int div(u) = \int_\Gamma n.u. # # The latter term is 0 iff inflow and outflow are exactly the same # at any given point in time. This corresponds with the # incompressibility of the liquid. # # In turn, this hints towards penetrable boundaries to require # Dirichlet conditions on the pressure. # A = assemble(a2) b = assemble(L2) # # In principle, the ILU preconditioner isn't advised here since it # might destroy the semidefiniteness needed for CG. # # The system is consistent, but the matrix has an eigenvalue 0. # This does not harm the convergence of CG, but when # preconditioning one has to take care that the preconditioner # preserves the kernel. ILU might destroy this (and the # semidefiniteness). With AMG, the coarse grid solves cannot be LU # then, so try Jacobi here. # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html> # prec = PETScPreconditioner('hypre_amg') PETScOptions.set('pc_hypre_boomeramg_relax_type_coarse', 'jacobi') solver = PETScKrylovSolver('cg', prec) solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = tol solver.parameters['maximum_iterations'] = 100 solver.parameters['monitor_convergence'] = verbose # Create solver and solve system A_petsc = as_backend_type(A) b_petsc = as_backend_type(b) p1_petsc = as_backend_type(p1.vector()) solver.set_operator(A_petsc) try: solver.solve(p1_petsc, b_petsc) except RuntimeError as error: info('') # Check if the system is indeed consistent. # # If the right hand side is flawed (e.g., by round-off errors), # then it may have a component b1 in the direction of the null # space, orthogonal the image of the operator: # # b = b0 + b1. # # When starting with initial guess x0=0, the minimal achievable # relative tolerance is then # # min_rel_tol = ||b1|| / ||b||. # # If ||b|| is very small, which is the case when ui is almost # divergence-free, then min_rel_to may be larger than the # prescribed relative tolerance tol. # # Use this as a consistency check, i.e., bail out if # # tol < min_rel_tol = ||b1|| / ||b||. # # For computing ||b1||, we use the fact that the null space is # one-dimensional, i.e., b1 = alpha e, and # # e.b = e.(b0 + b1) = e.b1 = alpha ||e||^2, # # so alpha = e.b/||e||^2 and # # ||b1|| = |alpha| ||e|| = e.b / ||e|| # e = Function(P) e.interpolate(Constant(1.0)) evec = e.vector() evec /= norm(evec) alpha = b.inner(evec) normB = norm(b) info('Linear system convergence failure.') info(error.message) message = ('Linear system not consistent! ' '<b,e> = %g, ||b|| = %g, <b,e>/||b|| = %e, tol = %e.') \ % (alpha, normB, alpha/normB, tol) info(message) if tol < abs(alpha) / normB: info('\int div(u) = %e' % assemble(divu * dx)) #n = FacetNormal(Q.mesh()) #info('\int_Gamma n.u = %e' % assemble(dot(n, u)*ds)) #info('\int_Gamma u[0] = %e' % assemble(u[0]*ds)) #info('\int_Gamma u[1] = %e' % assemble(u[1]*ds)) ## Now plot the faulty u on a finer mesh (to resolve the ## quadratic trial functions). #fine_mesh = Q.mesh() #for k in range(1): # fine_mesh = refine(fine_mesh) #V1 = FunctionSpace(fine_mesh, 'CG', 1) #W1 = V1*V1 #uplot = project(u, W1) ##uplot = Function(W1) ##uplot.interpolate(u) #plot(uplot, title='u_tentative') #plot(uplot[0], title='u_tentative[0]') #plot(uplot[1], title='u_tentative[1]') plot(divu, title='div(u_tentative)') interactive() exit() raise RuntimeError(message) else: exit() raise RuntimeError('Linear system failed to converge.') except: exit() return
from dolfin import Function, UnitSquare, FunctionSpace, VectorFunctionSpace, Expression from spuq.utils.plot.plotter import Plotter N = 30 mesh = UnitSquare(N,N) V = FunctionSpace(mesh,'CG',1) f = Function(V) ex = Expression("x[0]*x[1]") f.interpolate(ex) Plotter.figure() Plotter.plotMesh(f) Plotter.axes() Plotter.show() VV = VectorFunctionSpace(mesh,'CG',1) ff = Function(VV) exx = Expression(["x[0]*x[1]/10.","sin(2*pi*x[0])/10."]) ff.interpolate(exx) Plotter.figure() Plotter.plotMesh(ff, displacement=True) Plotter.axes() Plotter.show()