def get_functionspace(self): """Construct trial/test space for state and adjoint equations.""" if self.mini: # MINI elements mini = fd.FiniteElement("CG", fd.triangle, 1) \ + fd.FiniteElement("B", fd.triangle, 3) Vvel = fd.VectorFunctionSpace(self.mesh_m, mini) else: # P2/P1 Taylor-Hood elements Vvel = fd.VectorFunctionSpace(self.mesh_m, "Lagrange", 2) Vpres = fd.FunctionSpace(self.mesh_m, "CG", 1) return Vvel * Vpres
def wave_solver(model, mesh, comm, output=False): method = model["opts"]["method"] degree = model['opts']['degree'] element = fire.FiniteElement(method, mesh.ufl_cell(), degree=degree, variant="KMV") V = fire.FunctionSpace(mesh, element) vp = fire.Constant(1.429) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print("Finding sources and receivers", flush=True) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print("Starting simulation", flush=True) wavelet = spyro.full_ricker_wavelet( dt=model["timeaxis"]["dt"], tf=model["timeaxis"]["tf"], freq=model["acquisition"]["frequency"], ) p, p_r = spyro.solvers.forward(model, mesh, comm, vp, sources, wavelet, receivers, output=output) return p_r
def __init__(self, *args, element_degree = 1, stefan_number = 1., liquidus_temperature = 0., liquidus_smoothing_factor = 0.01, solver_parameters = {"ksp_type": "cg"}, **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element)) self.stefan_number = fe.Constant(stefan_number) self.liquidus_temperature = fe.Constant(liquidus_temperature) self.liquidus_smoothing_factor = fe.Constant( liquidus_smoothing_factor) super().__init__(*args, solver_parameters = solver_parameters, **kwargs)
def element(cell, degree): scalar = fe.FiniteElement("P", cell, degree) vector = fe.VectorElement("P", cell, degree) return fe.MixedElement(scalar, vector, scalar)
def _build_space(mesh, el, space, deg): if el == "tria": V = fd.FunctionSpace(mesh, space, deg) elif el == "quad": if space == "spectral": element = fd.FiniteElement( "CG", mesh.ufl_cell(), degree=deg, variant="spectral" ) V = fd.FunctionSpace(mesh, element) elif space == "S": V = fd.FunctionSpace(mesh, "S", deg) else: raise ValueError("Space not supported yet") return V
def plotvars(sim, solution=None): if solution is None: solution = sim.solution V = fe.FunctionSpace(solution.function_space().mesh(), fe.FiniteElement("P", sim.mesh.ufl_cell(), 1)) p, u, T = solution.split() phil = fe.interpolate(liquid_volume_fraction(sim=sim, temperature=T), V) return (p, u, T, phil), \ ("p", "\\mathbf{u}", "T", "\\phi_l"), \ ("p", "u", "T", "phil")
def __init__(self, *args, element_degree=1, solver_parameters={"ksp_type": "cg"}, **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element)) super().__init__(*args, solver_parameters=solver_parameters, **kwargs)
def test_solver_no_flow_region(): mesh = fd.Mesh("./2D_mesh.msh") no_flow = [2] no_flow_markers = [1] mesh = mark_no_flow_regions(mesh, no_flow, no_flow_markers) P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1) P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1) TH = P2 * P1 W = fd.FunctionSpace(mesh, TH) (v, q) = fd.TestFunctions(W) # Stokes 1 w_sol1 = fd.Function(W) nu = fd.Constant(0.05) F = NavierStokesBrinkmannForm(W, w_sol1, nu, beta_gls=2.0) x, y = fd.SpatialCoordinate(mesh) u_mms = fd.as_vector( [sin(2.0 * pi * x) * sin(pi * y), sin(pi * x) * sin(2.0 * pi * y)]) p_mms = -0.5 * (u_mms[0]**2 + u_mms[1]**2) f_mms_u = (grad(u_mms) * u_mms + grad(p_mms) - 2.0 * nu * div(sym(grad(u_mms)))) f_mms_p = div(u_mms) F += -inner(f_mms_u, v) * dx - f_mms_p * q * dx bc1 = fd.DirichletBC(W.sub(0), u_mms, "on_boundary") bc2 = fd.DirichletBC(W.sub(1), p_mms, "on_boundary") bc_no_flow = InteriorBC(W.sub(0), fd.Constant((0.0, 0.0)), no_flow_markers) solver_parameters = {"ksp_max_it": 500, "ksp_monitor": None} problem1 = fd.NonlinearVariationalProblem(F, w_sol1, bcs=[bc1, bc2, bc_no_flow]) solver1 = NavierStokesBrinkmannSolver( problem1, options_prefix="navier_stokes", solver_parameters=solver_parameters, ) solver1.solve() u_sol, _ = w_sol1.split() u_mms_func = fd.interpolate(u_mms, W.sub(0)) error = fd.errornorm(u_sol, u_mms_func) assert error < 0.07
def compute_space_accuracy_via_mms( grid_sizes, element_degree, quadrature_degree, smoothing): dx = fe.dx(degree = quadrature_degree) parameters["smoothing"].assign(smoothing) h, e, order = [], [], [] for gridsize in grid_sizes: mesh = fe.UnitIntervalMesh(gridsize) element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) V = fe.FunctionSpace(mesh, element) u_m = manufactured_solution(mesh) bc = fe.DirichletBC(V, u_m, "on_boundary") u = fe.TrialFunction(V) v = fe.TestFunction(V) u_h = fe.Function(V) fe.solve(F(u, v)*dx == v*R(u_m)*dx, u_h, bcs = bc) e.append(math.sqrt(fe.assemble(fe.inner(u_h - u_m, u_h - u_m)*dx))) h.append(1./float(gridsize)) if len(e) > 1: r = h[-2]/h[-1] log = math.log order = log(e[-2]/e[-1])/log(r) print("{0: <4}, {1: .3f}, {2: .5f}, {3: .3f}, {4: .3f}".format( str(quadrature_degree), smoothing, h[-1], e[-1], order))
def run_solver(r): mesh = fd.UnitSquareMesh(2**r, 2**r) P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1) P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1) TH = P2 * P1 W = fd.FunctionSpace(mesh, TH) (v, q) = fd.TestFunctions(W) # Stokes 1 w_sol1 = fd.Function(W) nu = fd.Constant(0.05) F = NavierStokesBrinkmannForm(W, w_sol1, nu, beta_gls=2.0) from firedrake import sin, grad, pi, sym, div, inner x, y = fd.SpatialCoordinate(mesh) u_mms = fd.as_vector( [sin(2.0 * pi * x) * sin(pi * y), sin(pi * x) * sin(2.0 * pi * y)]) p_mms = -0.5 * (u_mms[0]**2 + u_mms[1]**2) f_mms_u = (grad(u_mms) * u_mms + grad(p_mms) - 2.0 * nu * div(sym(grad(u_mms)))) f_mms_p = div(u_mms) F += -inner(f_mms_u, v) * dx - f_mms_p * q * dx bc1 = fd.DirichletBC(W.sub(0), u_mms, "on_boundary") bc2 = fd.DirichletBC(W.sub(1), p_mms, "on_boundary") solver_parameters = {"ksp_max_it": 200} problem1 = fd.NonlinearVariationalProblem(F, w_sol1, bcs=[bc1, bc2]) solver1 = NavierStokesBrinkmannSolver( problem1, options_prefix="navier_stokes", solver_parameters=solver_parameters, ) solver1.solve() u_sol, _ = w_sol1.split() fd.File("test_u_sol.pvd").write(u_sol) u_mms_func = fd.interpolate(u_mms, W.sub(0)) error = fd.errornorm(u_sol, u_mms_func) print(f"Error: {error}") return error
def __init__(self, *args, reynolds_number, element_degrees = (2, 1), **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] element = fe.MixedElement( fe.VectorElement("P", mesh.ufl_cell(), element_degrees[0]), fe.FiniteElement("P", mesh.ufl_cell(), element_degrees[1])) kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element)) self.reynolds_number = fe.Constant(reynolds_number) super().__init__(*args, **kwargs)
def __init__(self, *args, advection_velocity, diffusion_coefficient=1., element_degree=1, **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element)) self.diffusion_coefficient = fe.Constant(diffusion_coefficient) self.advection_velocity = advection_velocity(mesh) super().__init__(*args, **kwargs)
def compute_space_accuracy_via_mms(grid_sizes, element_degree): print("h, L2_norm_error") h, e = [], [] for gridsize in grid_sizes: mesh = fe.UnitIntervalMesh(gridsize) element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) V = fe.FunctionSpace(mesh, element) u_m = manufactured_solution(mesh) bc = fe.DirichletBC(V, u_m, "on_boundary") u = fe.TrialFunction(V) v = fe.TestFunction(V) u_h = fe.Function(V) fe.solve(F(u, v) == v*R(u_m)*dx, u_h, bcs = bc) e.append(math.sqrt(fe.assemble(fe.inner(u_h - u_m, u_h - u_m)*dx))) h.append(1./float(gridsize)) print(str(h[-1]) + ", " + str(e[-1])) r = h[-2]/h[-1] log = math.log order = log(e[-2]/e[-1])/log(r) return order
def __init__(self, *args, reynolds_number, taylor_hood_pressure_degree = 1, **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] d = taylor_hood_pressure_degree element = fe.MixedElement( fe.FiniteElement("P", mesh.ufl_cell(), d), fe.VectorElement("P", mesh.ufl_cell(), d + 1)) kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element)) self.reynolds_number = fe.Constant(reynolds_number) super().__init__(*args, fieldnames=("p", "u"), **kwargs)
def depth_average(q3d, weight=firedrake.Constant(1)): r"""Return the weighted depth average of a function on an extruded mesh""" element3d = q3d.ufl_element() # Create the element `E x DG0` where `E` is the horizontal element for the # input field element_z = firedrake.FiniteElement(family='DG', cell='interval', degree=0) shape = q3d.ufl_shape if len(shape) == 0: element_xy = element3d.sub_elements()[0] element_avg = firedrake.TensorProductElement(element_xy, element_z) element2d = element_xy elif len(shape) == 1: element_xy = element3d.sub_elements()[0].sub_elements()[0] element_u = firedrake.TensorProductElement(element_xy, element_z) element_avg = firedrake.VectorElement(element_u, dim=shape[0]) element2d = firedrake.VectorElement(element_xy, dim=shape[0]) else: raise NotImplementedError('Depth average of tensor fields not yet ' 'implemented!') # Project the weighted 3D field onto vertical DG0 mesh3d = q3d.ufl_domain() Q_avg = firedrake.FunctionSpace(mesh3d, element_avg) q_avg = firedrake.project(weight * q3d, Q_avg) # Create a function space on the 2D mesh and a 2D function defined on this # space, then copy the raw vector of expansion coefficients from the 3D DG0 # field into the coefficients of the 2D field. TODO: Get some assurance # from the firedrake folks that this will always work. mesh2d = mesh3d._base_mesh Q2D = firedrake.FunctionSpace(mesh2d, element2d) q2d = firedrake.Function(Q2D) q2d.dat.data[:] = q_avg.dat.data_ro[:] return q2d
def __init__(self, *args, element_degree=1, stefan_number=1., liquidus_temperature=0., liquidus_smoothing_factor=0.01, solver_parameters={'ksp_type': 'cg'}, **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element)) self.stefan_number = fe.Constant(stefan_number) self.liquidus_temperature = fe.Constant(liquidus_temperature) self.liquidus_smoothing_factor = fe.Constant(liquidus_smoothing_factor) super().__init__(*args, solver_parameters=solver_parameters, fieldnames='T', **kwargs) self.time_discrete_terms['phi_l'] = sapphire.time_discretization.bdf( [ self.liquid_volume_fraction(temperature=T_n) for T_n in self.solutions ], timestep_size=self.timestep_size)
def heat_exchanger_optimization(mu=0.03, n_iters=1000): output_dir = "2D/" path = os.path.abspath(__file__) dir_path = os.path.dirname(path) mesh = fd.Mesh(f"{dir_path}/2D_mesh.msh") # Perturb the mesh coordinates. Necessary to calculate shape derivatives S = fd.VectorFunctionSpace(mesh, "CG", 1) s = fd.Function(S, name="deform") mesh.coordinates.assign(mesh.coordinates + s) # Initial level set function x, y = fd.SpatialCoordinate(mesh) PHI = fd.FunctionSpace(mesh, "CG", 1) phi_expr = sin(y * pi / 0.2) * cos(x * pi / 0.2) - fd.Constant(0.8) # Avoid recording the operation interpolate into the tape. # Otherwise, the shape derivatives will not be correct with fda.stop_annotating(): phi = fd.interpolate(phi_expr, PHI) phi.rename("LevelSet") fd.File(output_dir + "phi_initial.pvd").write(phi) # Physics mu = fd.Constant(mu) # viscosity alphamin = 1e-12 alphamax = 2.5 / (2e-4) parameters = { "mat_type": "aij", "ksp_type": "preonly", "ksp_converged_reason": None, "pc_type": "lu", "pc_factor_mat_solver_type": "mumps", } stokes_parameters = parameters temperature_parameters = parameters u_inflow = 2e-3 tin1 = fd.Constant(10.0) tin2 = fd.Constant(100.0) P2 = fd.VectorElement("CG", mesh.ufl_cell(), 2) P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1) TH = P2 * P1 W = fd.FunctionSpace(mesh, TH) U = fd.TrialFunction(W) u, p = fd.split(U) V = fd.TestFunction(W) v, q = fd.split(V) epsilon = fd.Constant(10000.0) def hs(phi, epsilon): return fd.Constant(alphamax) * fd.Constant(1.0) / ( fd.Constant(1.0) + exp(-epsilon * phi)) + fd.Constant(alphamin) def stokes(phi, BLOCK_INLET_MOUTH, BLOCK_OUTLET_MOUTH): a_fluid = mu * inner(grad(u), grad(v)) - div(v) * p - q * div(u) darcy_term = inner(u, v) return (a_fluid * dx + hs(phi, epsilon) * darcy_term * dx(0) + alphamax * darcy_term * (dx(BLOCK_INLET_MOUTH) + dx(BLOCK_OUTLET_MOUTH))) # Dirichlet boundary conditions inflow1 = fd.as_vector([ u_inflow * sin( ((y - (line_sep - (dist_center + inlet_width))) * pi) / inlet_width), 0.0, ]) inflow2 = fd.as_vector([ u_inflow * sin(((y - (line_sep + dist_center)) * pi) / inlet_width), 0.0, ]) noslip = fd.Constant((0.0, 0.0)) # Stokes 1 bcs1_1 = fd.DirichletBC(W.sub(0), noslip, WALLS) bcs1_2 = fd.DirichletBC(W.sub(0), inflow1, INLET1) bcs1_3 = fd.DirichletBC(W.sub(1), fd.Constant(0.0), OUTLET1) bcs1_4 = fd.DirichletBC(W.sub(0), noslip, INLET2) bcs1_5 = fd.DirichletBC(W.sub(0), noslip, OUTLET2) bcs1 = [bcs1_1, bcs1_2, bcs1_3, bcs1_4, bcs1_5] # Stokes 2 bcs2_1 = fd.DirichletBC(W.sub(0), noslip, WALLS) bcs2_2 = fd.DirichletBC(W.sub(0), inflow2, INLET2) bcs2_3 = fd.DirichletBC(W.sub(1), fd.Constant(0.0), OUTLET2) bcs2_4 = fd.DirichletBC(W.sub(0), noslip, INLET1) bcs2_5 = fd.DirichletBC(W.sub(0), noslip, OUTLET1) bcs2 = [bcs2_1, bcs2_2, bcs2_3, bcs2_4, bcs2_5] # Forward problems U1, U2 = fd.Function(W), fd.Function(W) L = inner(fd.Constant((0.0, 0.0, 0.0)), V) * dx problem = fd.LinearVariationalProblem(stokes(-phi, INMOUTH2, OUTMOUTH2), L, U1, bcs=bcs1) solver_stokes1 = fd.LinearVariationalSolver( problem, solver_parameters=stokes_parameters, options_prefix="stokes_1") solver_stokes1.solve() problem = fd.LinearVariationalProblem(stokes(phi, INMOUTH1, OUTMOUTH1), L, U2, bcs=bcs2) solver_stokes2 = fd.LinearVariationalSolver( problem, solver_parameters=stokes_parameters, options_prefix="stokes_2") solver_stokes2.solve() # Convection difussion equation ks = fd.Constant(1e0) cp_value = 5.0e5 cp = fd.Constant(cp_value) T = fd.FunctionSpace(mesh, "DG", 1) t = fd.Function(T, name="Temperature") w = fd.TestFunction(T) # Mesh-related functions n = fd.FacetNormal(mesh) h = fd.CellDiameter(mesh) u1, p1 = fd.split(U1) u2, p2 = fd.split(U2) def upwind(u): return (dot(u, n) + abs(dot(u, n))) / 2.0 u1n = upwind(u1) u2n = upwind(u2) # Penalty term alpha = fd.Constant(500.0) # Bilinear form a_int = dot(grad(w), ks * grad(t) - cp * (u1 + u2) * t) * dx a_fac = (fd.Constant(-1.0) * ks * dot(avg(grad(w)), jump(t, n)) * dS + fd.Constant(-1.0) * ks * dot(jump(w, n), avg(grad(t))) * dS + ks("+") * (alpha("+") / avg(h)) * dot(jump(w, n), jump(t, n)) * dS) a_vel = (dot( jump(w), cp * (u1n("+") + u2n("+")) * t("+") - cp * (u1n("-") + u2n("-")) * t("-"), ) * dS + dot(w, cp * (u1n + u2n) * t) * ds) a_bnd = (dot(w, cp * dot(u1 + u2, n) * t) * (ds(INLET1) + ds(INLET2)) + w * t * (ds(INLET1) + ds(INLET2)) - w * tin1 * ds(INLET1) - w * tin2 * ds(INLET2) + alpha / h * ks * w * t * (ds(INLET1) + ds(INLET2)) - ks * dot(grad(w), t * n) * (ds(INLET1) + ds(INLET2)) - ks * dot(grad(t), w * n) * (ds(INLET1) + ds(INLET2))) aT = a_int + a_fac + a_vel + a_bnd LT_bnd = (alpha / h * ks * tin1 * w * ds(INLET1) + alpha / h * ks * tin2 * w * ds(INLET2) - tin1 * ks * dot(grad(w), n) * ds(INLET1) - tin2 * ks * dot(grad(w), n) * ds(INLET2)) problem = fd.LinearVariationalProblem(derivative(aT, t), LT_bnd, t) solver_temp = fd.LinearVariationalSolver( problem, solver_parameters=temperature_parameters, options_prefix="temperature", ) solver_temp.solve() # fd.solve(eT == 0, t, solver_parameters=temperature_parameters) # Cost function: Flux at the cold outlet scale_factor = 4e-4 Jform = fd.assemble( fd.Constant(-scale_factor * cp_value) * inner(t * u1, n) * ds(OUTLET1)) # Constraints: Pressure drop on each fluid power_drop = 1e-2 Power1 = fd.assemble(p1 / power_drop * ds(INLET1)) Power2 = fd.assemble(p2 / power_drop * ds(INLET2)) phi_pvd = fd.File("phi_evolution.pvd") def deriv_cb(phi): with stop_annotating(): phi_pvd.write(phi[0]) c = fda.Control(s) # Reduced Functionals Jhat = LevelSetFunctional(Jform, c, phi, derivative_cb_pre=deriv_cb) P1hat = LevelSetFunctional(Power1, c, phi) P1control = fda.Control(Power1) P2hat = LevelSetFunctional(Power2, c, phi) P2control = fda.Control(Power2) Jhat_v = Jhat(phi) print("Initial cost function value {:.5f}".format(Jhat_v), flush=True) print("Power drop 1 {:.5f}".format(Power1), flush=True) print("Power drop 2 {:.5f}".format(Power2), flush=True) beta_param = 0.08 # Regularize the shape derivatives only in the domain marked with 0 reg_solver = RegularizationSolver(S, mesh, beta=beta_param, gamma=1e5, dx=dx, design_domain=0) tol = 1e-5 dt = 0.05 params = { "alphaC": 1.0, "debug": 5, "alphaJ": 1.0, "dt": dt, "K": 1e-3, "maxit": n_iters, "maxtrials": 5, "itnormalisation": 10, "tol_merit": 5e-3, # new merit can be within 0.5% of the previous merit # "normalize_tol" : -1, "tol": tol, } solver_parameters = { "reinit_solver": { "h_factor": 2.0, } } # Optimization problem problem = InfDimProblem( Jhat, reg_solver, ineqconstraints=[ Constraint(P1hat, 1.0, P1control), Constraint(P2hat, 1.0, P2control), ], solver_parameters=solver_parameters, ) results = nlspace_solve(problem, params) return results
def compute_time_accuracy_via_mms( gridsize, element_degree, timestep_sizes, endtime): mesh = fe.UnitIntervalMesh(gridsize) element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) V = fe.FunctionSpace(mesh, element) u_h = fe.Function(V) v = fe.TestFunction(V) un = fe.Function(V) u_m = manufactured_solution(mesh) bc = fe.DirichletBC(V, u_m, "on_boundary") _F = F(u_h, v, un) problem = fe.NonlinearVariationalProblem( _F - v*R(u_m)*dx, u_h, bc, fe.derivative(_F, u_h)) solver = fe.NonlinearVariationalSolver(problem) t.assign(0.) initial_values = fe.interpolate(u_m, V) L2_norm_errors = [] print("Delta_t, L2_norm_error") for timestep_size in timestep_sizes: Delta_t.assign(timestep_size) un.assign(initial_values) time = 0. t.assign(time) while time < (endtime - TIME_EPSILON): time += timestep_size t.assign(time) solver.solve() un.assign(u_h) L2_norm_errors.append( math.sqrt(fe.assemble(fe.inner(u_h - u_m, u_h - u_m)*dx))) print(str(timestep_size) + ", " + str(L2_norm_errors[-1])) r = timestep_sizes[-2]/timestep_sizes[-1] e = L2_norm_errors log = math.log order = log(e[-2]/e[-1])/log(r) return order
def element(cell, taylor_hood_pressure_degree, temperature_degree): return fe.MixedElement( fe.FiniteElement("P", cell, taylor_hood_pressure_degree), fe.VectorElement("P", cell, taylor_hood_pressure_degree + 1), fe.FiniteElement("P", cell, temperature_degree))
def element(cell, degrees): return fe.MixedElement(fe.FiniteElement("P", cell, degrees[0]), fe.VectorElement("P", cell, degrees[1]), fe.FiniteElement("P", cell, degrees[2]))
def vectorspaces(mesh, vertical_higher_order=0): '''On an extruded mesh, build finite element spaces for velocity u, pressure p, and vertical displacement c. Construct component spaces by explicitly applying TensorProductElement(). Elements are Q2 prisms [P2(triangle)xP2(interval)] for velocity, Q1 prisms [P1(triangle)xP1(interval)] for pressure, and Q1 prisms [P1(triangle)xP1(interval)] for displacement. Optionally the base mesh can be built from quadrilaterals and/or the vertical factors can be higher order for velocity and pressure.''' if mesh._base_mesh.cell_dimension() not in {1, 2}: raise ValueError('only 2D and 3D extruded meshes are allowed') ThreeD = (mesh._base_mesh.cell_dimension() == 2) quad = (mesh._base_mesh.ufl_cell() == fd.quadrilateral) if quad and not ThreeD: raise ValueError('base mesh from quadilaterals only possible in 3D') zudeg, zpdeg = _degreexz[vertical_higher_order] # velocity u (vector) if ThreeD: if quad: xuE = fd.FiniteElement('Q', fd.quadrilateral, 2) else: xuE = fd.FiniteElement('P', fd.triangle, 2) else: xuE = fd.FiniteElement('P', fd.interval, 2) zuE = fd.FiniteElement('P', fd.interval, zudeg) uE = fd.TensorProductElement(xuE, zuE) Vu = fd.VectorFunctionSpace(mesh, uE) # pressure p (scalar) # Note Isaac et al (2015) recommend discontinuous pressure space # to get mass conservation. Switching base mesh elements to dP0 # (or dQ0 for base quads) is inconsistent w.r.t. velocity result; # (unstable?) and definitely more expensive. if ThreeD: if quad: xpE = fd.FiniteElement('Q', fd.quadrilateral, 1) else: xpE = fd.FiniteElement('P', fd.triangle, 1) else: xpE = fd.FiniteElement('P', fd.interval, 1) zpE = fd.FiniteElement('P', fd.interval, zpdeg) pE = fd.TensorProductElement(xpE, zpE) Vp = fd.FunctionSpace(mesh, pE) # vertical displacement c (scalar) if ThreeD: if quad: xcE = fd.FiniteElement('Q', fd.quadrilateral, 1) else: xcE = fd.FiniteElement('P', fd.triangle, 1) else: xcE = fd.FiniteElement('P', fd.interval, 1) zcE = fd.FiniteElement('P', fd.interval, 1) cE = fd.TensorProductElement(xcE, zcE) Vc = fd.FunctionSpace(mesh, cE) return Vu, Vp, Vc
def element(cell, degree): return fe.FiniteElement("P", cell, degree)
Ly = Ny * Delta_y Lz = Nz * Delta_z mesh = fd.utility_meshes.RectangleMesh(nx=Nx, ny=Ny, Lx=Lx, Ly=Ly, quadrilateral=True) mesh = fd.ExtrudedMesh(mesh, layers=Nz, layer_height=Delta_z) # We need to decide on the function space in which we'd like to solve the # problem. Let's use piecewise linear functions continuous between # elements:: # Create extruded mesh element horiz_elt = fd.FiniteElement("DG", fd.quadrilateral, 0) vert_elt = fd.FiniteElement("DG", fd.interval, 0) elt = fd.TensorProductElement(horiz_elt, vert_elt) # Create function space V = fd.FunctionSpace(mesh, elt) Vvec = fd.VectorFunctionSpace(mesh, "DG", 0) # We'll also need the test and trial functions corresponding to this # function space:: u = fd.TrialFunction(V) v = fd.TestFunction(V) # We declare a function over our function space and give it the # value of our right hand side function::
def executing_gridsweep(sweep_parameters): # IO parameters mesh_generation = sweep_parameters['IO']['generate_meshes'] saving_results = sweep_parameters['IO'][ 'output_pickle_of_wave_propagator_results'] loading_results = sweep_parameters['IO'][ 'load_existing_pickle_of_wave_propagator_results'] loading_reference = sweep_parameters['IO'][ 'use_precomputed_reference_case'] filenameprefix = sweep_parameters['IO']['grid_sweep_data_filename_prefix'] calculate_dt = sweep_parameters['IO']['calculate_maximum_timestep'] save_receiver_location = sweep_parameters['IO']['save_receiver_location'] # Reference case for error comparison G_reference = sweep_parameters['reference']['G'] P_reference = sweep_parameters['reference']['P'] # Degrees and Gs for sweep Gs = sweep_parameters['sweep_list']['DoFs'] degrees = sweep_parameters['sweep_list']['Ps'] # Experiment parameters experiment_type = sweep_parameters['experiment']['velocity_type'] method = sweep_parameters['experiment']['method'] frequency = sweep_parameters['experiment']['frequency'] receiver_type = sweep_parameters['experiment']['receiver_disposition'] if experiment_type == 'homogeneous': minimum_mesh_velocity = sweep_parameters['experiment'][ 'minimum_mesh_velocity'] elif experiment_type == 'heterogeneous': minimum_mesh_velocity = False ## Generating comm model = spyro.tools.create_model_for_grid_point_calculation( frequency, 1, method, minimum_mesh_velocity, experiment_type=experiment_type, receiver_type=receiver_type) comm = spyro.utils.mpi_init(model) ## Output file for saving data date = datetime.today().strftime('%Y_%m_%d') filename = filenameprefix + date text_file = open(filename + ".txt", "w") text_file.write(experiment_type + ' and ' + method + ' \n') ## Generating csv file for visualizing receiver and source position in paraview if save_receiver_location == True: saving_source_and_receiver_location_in_csv(model) if loading_reference == False: model = spyro.tools.create_model_for_grid_point_calculation( frequency, P_reference, method, minimum_mesh_velocity, experiment_type=experiment_type, receiver_type=receiver_type) print('Calculating reference solution of G = ' + str(G_reference) + ' and p = ' + str(P_reference), flush=True) p_exact = spyro.tools.wave_solver(model, G=G_reference, comm=comm) save_pickle( "experiment/" + filenameprefix + "_heterogeneous_reference_p" + str(P_reference) + "g" + str(G_reference) + ".pck", p_exact) else: p_exact = load_pickle("experiment/" + filenameprefix + "_heterogeneous_reference_p" + str(P_reference) + "g" + str(G_reference) + ".pck") ## Starting sweep for degree in degrees: if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print('\nFor p of ' + str(degree), flush=True) text_file.write('For p of ' + str(degree) + '\n') print('Starting sweep:', flush=True) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: text_file.write('\tG\t\tError \n') for G in Gs: model = create_model_for_grid_point_calculation3D(degree) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print('G of ' + str(G), flush=True) comm.comm.barrier() if mesh_generation == True: mesh = generate_mesh3D(model, G, comm) else: mesh = read_mesh(G) comm.comm.barrier() if calculate_dt == True: method = model["opts"]["method"] degree = model['opts']['degree'] element = fire.FiniteElement(method, mesh.ufl_cell(), degree=degree, variant="KMV") V = fire.FunctionSpace(mesh, element) vp = fire.Constant(1.429) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print("Calculating new dt", flush=True) new_dt = 0.2 * estimate_timestep( mesh, V, vp, estimate_max_eigenvalue=True) comm.comm.barrier() model['timeaxis']['dt'] = comm.comm.allreduce(new_dt, op=MPI.MIN) else: model['timeaxis']['dt'] = dt_to_use(degree, G) comm.comm.barrier() if loading_results == True: p_0 = load_pickle("experiment/" + filenameprefix + "_heterogeneous_p" + str(P_reference) + "g" + str(G_reference) + ".pck") elif loading_results == False: p_0 = wave_solver(model, mesh, G=G, comm=comm) if saving_results == True: save_pickle( "experiment/" + filenameprefix + "_heterogeneous_p" + str(P_reference) + "g" + str(G_reference) + ".pck", p_0) comm.comm.barrier() error = spyro.tools.error_calc(p_exact, p_0, model, comm=comm) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print('With P of ' + str(degree) + ' and G of ' + str(G) + ' Error = ' + str(error), flush=True) text_file.write('\t' + str(G) + '\t\t' + str(error) + ' \n') text_file.close()
def element(cell, degree): return fe.MixedElement(fe.VectorElement("P", cell, degree + 1), fe.FiniteElement("P", cell, degree))
mesh = fire.Mesh( "meshes/benchmark_2d.msh", distribution_parameters={ "overlap_type": (fire.DistributedMeshOverlapType.NONE, 0) }, ) method = model["opts"]["method"] degree = model["opts"]["degree"] if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print(f"Setting up {method} a {degree}tetra element", flush=True) element = fire.FiniteElement(method, mesh.ufl_cell(), degree=degree, variant="KMV") V = fire.FunctionSpace(mesh, element) vp = fire.Constant(1.429) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print("Finding sources and receivers", flush=True) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print("Starting simulation", flush=True)
def heat_exchanger_3D(): parser = argparse.ArgumentParser(description="Level set method parameters") parser.add_argument( "--nu", action="store", dest="nu", type=float, help="Kinematic Viscosity", default=1.0, ) parser.add_argument( "--brinkmann_penalty", action="store", dest="brinkmann_penalty", type=float, help="Brinkmann term", default=1e5, ) parser.add_argument( "--refinement", action="store", dest="refinement", type=int, help="Level of refinement", default=0, ) parser.add_argument( "--pressure_drop_constraint", action="store", dest="pressure_drop_constraint", type=float, help="Pressure drop constraint", default=10.0, ) parser.add_argument( "--n_iters", dest="n_iters", type=int, action="store", default=1000, help="Number of optimization iterations", ) parser.add_argument( "--output_dir", dest="output_dir", type=str, action="store", default="./", help="Output folder", ) parser.add_argument( "--type", dest="type_he", type=str, action="store", default="parallel", help="Type of heat exchanger: parallel or counter", ) opts = parser.parse_args() print(f"Parameters used: {opts}") beta_param = 0.4 mesh = fd.Mesh("./box_heat_exch.msh") from parameters_box import ( INLET2, INLET1, OUTLET1, OUTLET2, INMOUTH1, INMOUTH2, OUTMOUTH1, OUTMOUTH2, ) if opts.type_he == "counter": INLET1, OUTLET1 = OUTLET1, INLET1 elif opts.type_he == "u_flow": INLET2, OUTLET1 = OUTLET1, INLET2 OUTMOUTH1, INMOUTH2 = INMOUTH2, OUTMOUTH1 markers = { "WALLS": WALLS, "INLET1": INLET1, "INLET2": INLET2, "OUTLET1": OUTLET1, "OUTLET2": OUTLET2, } no_flow_domain_1 = [INMOUTH2, OUTMOUTH2] no_flow_domain_2 = [INMOUTH1, OUTMOUTH1] no_flow = no_flow_domain_1.copy() no_flow.extend(no_flow_domain_2) mesh = mark_no_flow_regions(mesh, no_flow, no_flow) mh = fd.MeshHierarchy(mesh, opts.refinement) mesh = mh[-1] pressure_drop_constraint = opts.pressure_drop_constraint pressure_drop_1 = pressure_drop_constraint pressure_drop_2 = pressure_drop_constraint S = fd.VectorFunctionSpace(mesh, "CG", 1) PHI = fd.FunctionSpace(mesh, "CG", 1) phi = fd.Function(PHI, name="LevelSet") x, y, z = fd.SpatialCoordinate(mesh) ω = 0.25 phi_expr = sin(y * pi / ω) * cos(x * pi / ω) * sin( z * pi / ω) - fd.Constant(0.2) checkpoints = is_checkpoint(opts.output_dir) if checkpoints: current_iter = read_checkpoint(checkpoints, phi) with open(f"{opts.output_dir}/brinkmann_penalty.txt", "r") as txt_brinkmann: brinkmann_penalty_initial = fd.Constant(txt_brinkmann.read()) print( f"Current brinkmann term: {brinkmann_penalty_initial.values()[0]}") else: with stop_annotating(): phi.interpolate(phi_expr) current_iter = 0 brinkmann_penalty_initial = fd.Constant(opts.brinkmann_penalty) P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1) P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1) TH = P2 * P1 W = fd.FunctionSpace(mesh, TH) print(f"DOFS: {W.dim()}") T = fd.FunctionSpace(mesh, "CG", 1) global_counter = count(current_iter) def receive_signal(signum, stack): iter_current = next(copy(global_counter)) print(f"Received: {signum}, iter: {iter_current}") with fd.HDF5File( f"{opts.output_dir}/checkpoint_iter_{iter_current}.h5", "w") as checkpoint: checkpoint.write(phi, "/checkpoint") with open(f"{opts.output_dir}/brinkmann_penalty.txt", "w") as txt_brinkmann: txt_brinkmann.write(str(brinkmann_penalty.values()[0])) signal.signal(signal.SIGHUP, receive_signal) phi_pvd = fd.File( f"{opts.output_dir}/phi_evolution.pvd", target_degree=1, target_continuity=fd.H1, mode="a", ) ns1 = fd.File(f"{opts.output_dir}/navier_stokes_1.pvd", mode="a") ns2 = fd.File(f"{opts.output_dir}/navier_stokes_2.pvd", mode="a") temperature = fd.File(f"{opts.output_dir}/temperature.pvd", mode="a") temperature_pvd = fd.Function(T) def termination_event_1(): p1_constraint = P1control.tape_value() - 1 p2_constraint = P2control.tape_value() - 1 event_value = max(p1_constraint, p2_constraint) print(f"Value event: {event_value}") return event_value def termination_event_2(): iter_current = next(copy(global_counter)) print(f"Value event iter count: {iter_current}") return float(iter_current % 500) brinkmann_penalty_initial_value = brinkmann_penalty_initial.values()[0] if brinkmann_penalty_initial_value > opts.brinkmann_penalty: termination_events = [termination_event_2, termination_event_2] brinkmann_pen_terms = [ brinkmann_penalty_initial, fd.Constant(brinkmann_penalty_initial_value * 10), ] else: termination_events = [termination_event_1, None] brinkmann_pen_terms = [ brinkmann_penalty_initial, fd.Constant(brinkmann_penalty_initial_value * 5), ] for termination_event, brinkmann_penalty in zip(termination_events, brinkmann_pen_terms): s = fd.Function(S, name="deform") mesh.coordinates.assign(mesh.coordinates + s) # w_sol1, w_sol2, t = forward(brinkmann_penalty) w_sol1, w_sol2, t = forward( W, T, phi, opts, brinkmann_penalty, no_flow_domain_1=no_flow_domain_1, no_flow_domain_2=no_flow_domain_2, markers=markers, ) w_sol1_control = fda.Control(w_sol1) w_sol2_control = fda.Control(w_sol2) t_control = fda.Control(t) J = heat_flux(w_sol2, t, OUTLET2) J_hot = heat_flux(w_sol1, t, OUTLET1) Pdrop1 = pressure_drop(w_sol1, INLET1, OUTLET1, pressure_drop_1) Pdrop2 = pressure_drop(w_sol2, INLET2, OUTLET2, pressure_drop_2) print(f"Cold flux: {J}, hot flux: {J_hot}") c = fda.Control(s) J_hot_control = fda.Control(J_hot) def deriv_cb(phi): with stop_annotating(): iter = next(global_counter) print(f"Hot flux: {J_hot_control.tape_value()}") if iter % 15 == 0: u_sol1, p_sol1 = w_sol1_control.tape_value().split() u_sol2, p_sol2 = w_sol2_control.tape_value().split() u_sol1.rename("Velocity1") p_sol1.rename("Pressure1") u_sol2.rename("Velocity2") p_sol2.rename("Pressure2") ns1.write(u_sol1, p_sol1, time=iter) ns2.write(u_sol2, p_sol2, time=iter) phi_pvd.write(phi[0], time=iter) temperature_pvd.assign(t_control.tape_value()) temperature_pvd.rename("temperature") temperature.write(temperature_pvd, time=iter) # Reduced Functionals Jhat = LevelSetFunctional(J, c, phi, derivative_cb_pre=deriv_cb) P1hat = LevelSetFunctional(Pdrop1, c, phi) P1control = fda.Control(Pdrop1) P2hat = LevelSetFunctional(Pdrop2, c, phi) P2control = fda.Control(Pdrop2) print("Pressure drop 1 {:.5f}".format(Pdrop1)) print("Pressure drop 2 {:.5f}".format(Pdrop2)) reg_solver = RegularizationSolver( S, mesh, beta=beta_param, gamma=1e6, dx=dx, design_domain=DESIGN_DOMAIN, solver_parameters=regularization_solver_parameters, ) tol = 1e-7 dt = 0.02 params = { "alphaC": 0.1, "debug": 5, "alphaJ": 0.1, "dt": dt, "K": 1e-3, "maxit": opts.n_iters, "maxtrials": 10, "itnormalisation": 10, "tol_merit": 1e-2, # new merit can be within 1% of the previous merit # "normalize_tol" : -1, "tol": tol, } hj_solver_parameters["ts_dt"] = dt / 50.0 solver_parameters = { "hj_solver": hj_solver_parameters, "reinit_solver": reinit_solver_parameters, } problem = InfDimProblem( Jhat, reg_solver, ineqconstraints=[ Constraint(P1hat, 1.0, P1control), Constraint(P2hat, 1.0, P2control), ], reinit_distance=0.08, solver_parameters=solver_parameters, ) problem.set_termination_event(termination_event, termination_tolerance=1e-1) _ = nlspace_solve(problem, params) fda.get_working_tape().clear_tape()
""" Solve a nonlinear variational problem with Firedrake. """ import firedrake as fe mesh = fe.UnitIntervalMesh(4) element = fe.FiniteElement("P", mesh.ufl_cell(), 1) V = fe.FunctionSpace(mesh, element) u = fe.Function(V) v = fe.TestFunction(V) bc = fe.DirichletBC(V, 0., "on_boundary") alpha = 1 + u/10. x = fe.SpatialCoordinate(mesh)[0] div, grad, dot, sin, pi, dx = fe.div, fe.grad, fe.dot, fe.sin, fe.pi, fe.dx f = 10.*sin(pi*x) R = (-dot(grad(v), alpha*grad(u)) - v*f)*dx problem = fe.NonlinearVariationalProblem(R, u, bc, fe.derivative(R, u)) solver = fe.NonlinearVariationalSolver( problem, solver_parameters = {"snes_monitor": True})