def __init__(self, mesh_r, refinements=1, order=1): mh = fd.MeshHierarchy(mesh_r, refinements) self.mesh_hierarchy = mh # Control space on coarsest mesh self.mesh_r_coarse = self.mesh_hierarchy[0] self.V_r_coarse = fd.VectorFunctionSpace(self.mesh_r_coarse, "CG", order) # Create self.id and self.T on refined mesh. element = self.V_r_coarse.ufl_element() self.intermediate_Ts = [] for i in range(refinements - 1): mesh = self.mesh_hierarchy[i + 1] V = fd.FunctionSpace(mesh, element) self.intermediate_Ts.append(fd.Function(V)) self.mesh_r = self.mesh_hierarchy[-1] element = self.V_r_coarse.ufl_element() self.V_r = fd.FunctionSpace(self.mesh_r, element) X = fd.SpatialCoordinate(self.mesh_r) self.id = fd.Function(self.V_r).interpolate(X) self.T = fd.Function(self.V_r, name="T") self.T.assign(self.id) self.mesh_m = fda.Mesh(self.T) self.V_m = fd.FunctionSpace(self.mesh_m, element)
def setupMesh(meshFile, degree=2, meshOversample=None, savegmsh=False): """ Read argus mesh file and return mesh alongw ith function spaces Parameters ---------- meshFile : str argus meshfile name degree : int, optional degree of function spaces, by default 2 Returns ------- mesh firedrake mesh Q, V firedrake scalar and vectory functions """ # Input the mesh maxOversample = 4 # Arbitrary could be increased mesh, opts = argusToFiredrakeMesh(meshFile, savegmsh=savegmsh) if meshOversample is not None: numLevels = meshOversample - 1 if numLevels < 0 or numLevels > (maxOversample - 1): myerror(f'meshOverample={meshOversample} but 0 < ' 'meshOversample < 4') mesh = firedrake.MeshHierarchy(mesh, numLevels)[numLevels] # Create scalar and vector function spaces Q = firedrake.FunctionSpace(mesh, family='CG', degree=degree) V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=degree) return mesh, Q, V, opts
import firedrake as fd import fireshape as fs import fireshape.zoo as fsz import ROL n = 30 # mesh = fd.UnitSquareMesh(n, n) mesh = fd.Mesh("UnitSquareCrossed.msh") mesh = fd.MeshHierarchy(mesh, 1)[-1] Q = fs.FeMultiGridControlSpace(mesh, refinements=3, order=2) inner = fs.LaplaceInnerProduct(Q) mesh_m = Q.mesh_m V_m = fd.FunctionSpace(mesh_m, "CG", 1) f_m = fd.Function(V_m) (x, y) = fd.SpatialCoordinate(mesh_m) f = (pow(x - 0.5, 2)) + pow(y - 0.5, 2) - 2. out = fd.File("domain.pvd") J = fsz.LevelsetFunctional(f, Q, cb=lambda: out.write(mesh_m.coordinates)) q = fs.ControlVector(Q, inner) params_dict = { 'General': { 'Secant': { 'Type': 'Limited-Memory BFGS', 'Maximum Storage': 5 } }, 'Step': {
import argparse import firedrake import icepack.plot parser = argparse.ArgumentParser() parser.add_argument('--input') parser.add_argument('--level', type=int) parser.add_argument('--output') args = parser.parse_args() Lx, Ly = 640e3, 80e3 ny = 20 nx = int(Lx / Ly) * ny coarse_mesh = firedrake.RectangleMesh(nx, ny, Lx, Ly) mesh_hierarchy = firedrake.MeshHierarchy(coarse_mesh, args.level) mesh = mesh_hierarchy[args.level] Q = firedrake.FunctionSpace(mesh, family='CG', degree=1) V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=1) h = firedrake.Function(Q) u = firedrake.Function(V) input_name = os.path.splitext(args.input)[0] with firedrake.DumbCheckpoint(input_name, mode=firedrake.FILE_READ) as chk: timesteps, indices = chk.get_timesteps() chk.set_timestep(timesteps[-1], idx=indices[-1]) chk.load(h, name='h') chk.load(u, name='u')
base_level = args.base_level nrefs = args.ref_level - base_level name = args.filename deg = args.coords_degree distribution_parameters = { "partition": True, "overlap_type": (fd.DistributedMeshOverlapType.VERTEX, 2) } if args.tlblock == "mg": basemesh = fd.IcosahedralSphereMesh( radius=R0, refinement_level=base_level, degree=deg, distribution_parameters=distribution_parameters) mh = fd.MeshHierarchy(basemesh, nrefs) for mesh in mh: x = fd.SpatialCoordinate(mesh) mesh.init_cell_orientations(x) mesh = mh[-1] else: mesh = fd.IcosahedralSphereMesh( radius=R0, refinement_level=args.ref_level, degree=deg, distribution_parameters=distribution_parameters) x = fd.SpatialCoordinate(mesh) mesh.init_cell_orientations(x) R0 = fd.Constant(R0) cx, cy, cz = fd.SpatialCoordinate(mesh)
def compliance(): parser = argparse.ArgumentParser(description="Compliance problem with MMA") parser.add_argument( "--nref", action="store", dest="nref", type=int, help="Number of mesh refinements", default=2, ) parser.add_argument( "--uniform", action="store", dest="uniform", type=int, help="Use uniform mesh", default=0, ) parser.add_argument( "--inner_product", action="store", dest="inner_product", type=str, help="Inner product, euclidean or L2", default="L2", ) parser.add_argument( "--output_dir", action="store", dest="output_dir", type=str, help="Directory for all the output", default="./", ) args = parser.parse_args() nref = args.nref inner_product = args.inner_product output_dir = args.output_dir assert inner_product == "L2" or inner_product == "euclidean" mesh = fd.Mesh("./beam_uniform.msh") #mh = fd.MeshHierarchy(mesh, 2) #mesh = mh[-1] if nref > 0: mh = fd.MeshHierarchy(mesh, nref) mesh = mh[-1] elif nref < 0: raise RuntimeError("Non valid mesh argument") V = fd.VectorFunctionSpace(mesh, "CG", 1) u, v = fd.TrialFunction(V), fd.TestFunction(V) # Elasticity parameters E, nu = 1e0, 0.3 mu, lmbda = fd.Constant(E / (2 * (1 + nu))), fd.Constant( E * nu / ((1 + nu) * (1 - 2 * nu)) ) # Helmholtz solver RHO = fd.FunctionSpace(mesh, "CG", 1) rho = fd.interpolate(fd.Constant(0.1), RHO) af, b = fd.TrialFunction(RHO), fd.TestFunction(RHO) #filter_radius = fd.Constant(0.2) #x, y = fd.SpatialCoordinate(mesh) #x_ = fd.interpolate(x, RHO) #y_ = fd.interpolate(y, RHO) #aH = filter_radius * inner(grad(af), grad(b)) * dx + af * b * dx #LH = rho * b * dx rhof = fd.Function(RHO) solver_params = { "ksp_type": "preonly", "pc_type": "lu", "pc_factor_mat_solver_type": "mumps", "mat_mumps_icntl_14": 200, "mat_mumps_icntl_24": 1, } #fd.solve(aH == LH, rhof, solver_parameters=solver_params) rhof.assign(rho) rhofControl = fda.Control(rhof) eps = fd.Constant(1e-5) p = fd.Constant(3.0) def simp(rho): return eps + (fd.Constant(1.0) - eps) * rho ** p def epsilon(v): return sym(nabla_grad(v)) def sigma(v): return 2.0 * mu * epsilon(v) + lmbda * tr(epsilon(v)) * Identity(2) DIRICHLET = 3 NEUMANN = 4 a = inner(simp(rhof) * sigma(u), epsilon(v)) * dx load = fd.Constant((0.0, -1.0)) L = inner(load, v) * ds(NEUMANN) u_sol = fd.Function(V) bcs = fd.DirichletBC(V, fd.Constant((0.0, 0.0)), DIRICHLET) fd.solve(a == L, u_sol, bcs=bcs, solver_parameters=solver_params) c = fda.Control(rho) J = fd.assemble(fd.Constant(1e-4) * inner(u_sol, load) * ds(NEUMANN)) Vol = fd.assemble(rhof * dx) VolControl = fda.Control(Vol) with fda.stop_annotating(): Vlimit = fd.assemble(fd.Constant(1.0) * dx(domain=mesh)) * 0.5 rho_viz_f = fd.Function(RHO, name="rho") plot_file = f"{output_dir}/design_{inner_product}.pvd" controls_f = fd.File(plot_file) def deriv_cb(j, dj, rho): with fda.stop_annotating(): rho_viz_f.assign(rhofControl.tape_value()) controls_f.write(rho_viz_f) Jhat = fda.ReducedFunctional(J, c, derivative_cb_post=deriv_cb) Volhat = fda.ReducedFunctional(Vol, c) class VolumeConstraint(fda.InequalityConstraint): def __init__(self, Vhat, Vlimit, VolControl): self.Vhat = Vhat self.Vlimit = float(Vlimit) self.VolControl = VolControl def function(self, m): # Compute the integral of the control over the domain integral = self.VolControl.tape_value() with fda.stop_annotating(): value = -integral / self.Vlimit + 1.0 return [value] def jacobian(self, m): with fda.stop_annotating(): gradients = self.Vhat.derivative() with gradients.dat.vec as v: v.scale(-1.0 / self.Vlimit) return [gradients] def output_workspace(self): return [0.0] def length(self): """Return the number of components in the constraint vector (here, one).""" return 1 lb = 1e-5 ub = 1.0 problem = fda.MinimizationProblem( Jhat, bounds=(lb, ub), constraints=[VolumeConstraint(Volhat, Vlimit, VolControl)], ) parameters_mma = { "move": 0.2, "maximum_iterations": 200, "m": 1, "IP": 0, "tol": 1e-6, "accepted_tol": 1e-4, "norm": inner_product, #"norm": "euclidean", "gcmma": False, } solver = MMASolver(problem, parameters=parameters_mma) rho_opt = solver.solve() with open(f"{output_dir}/finished_{inner_product}.txt", "w") as f: f.write("Done")
def compliance_optimization(n_iters=200): output_dir = "cantilever/" path = os.path.abspath(__file__) dir_path = os.path.dirname(path) m = fd.Mesh(f"{dir_path}/mesh_cantilever.msh") mesh = fd.MeshHierarchy(m, 0)[-1] # 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) lx = 2.0 ly = 1.0 phi_expr = ( -cos(6.0 / lx * pi * x) * cos(4.0 * pi * y) - 0.6 + max_value(200.0 * (0.01 - x ** 2 - (y - ly / 2) ** 2), 0.0) + max_value(100.0 * (x + y - lx - ly + 0.1), 0.0) + max_value(100.0 * (x - y - lx + 0.1), 0.0) ) # 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. Elasticity rho_min = 1e-5 beta = fd.Constant(200.0) def hs(phi, beta): return fd.Constant(1.0) / ( fd.Constant(1.0) + exp(-beta * phi) ) + fd.Constant(rho_min) H1_elem = fd.VectorElement("CG", mesh.ufl_cell(), 1) W = fd.FunctionSpace(mesh, H1_elem) u = fd.TrialFunction(W) v = fd.TestFunction(W) # Elasticity parameters E, nu = 1.0, 0.3 mu, lmbda = fd.Constant(E / (2 * (1 + nu))), fd.Constant( E * nu / ((1 + nu) * (1 - 2 * nu)) ) def epsilon(u): return sym(nabla_grad(u)) def sigma(v): return 2.0 * mu * epsilon(v) + lmbda * tr(epsilon(v)) * Identity(2) a = inner(hs(-phi, beta) * sigma(u), nabla_grad(v)) * dx t = fd.Constant((0.0, -75.0)) L = inner(t, v) * ds(2) bc = fd.DirichletBC(W, fd.Constant((0.0, 0.0)), 1) parameters = { "ksp_type": "preonly", "pc_type": "lu", "mat_type": "aij", "ksp_converged_reason": None, "pc_factor_mat_solver_type": "mumps", } u_sol = fd.Function(W) F = fd.action(a, u_sol) - L problem = fd.NonlinearVariationalProblem(F, u_sol, bcs=bc) solver = fd.NonlinearVariationalSolver( problem, solver_parameters=parameters ) solver.solve() # fd.solve( # a == L, u_sol, bcs=[bc], solver_parameters=parameters # ) # , nullspace=nullspace) with fda.stop_annotating(): fd.File("u_sol.pvd").write(u_sol) # Cost function: Compliance J = fd.assemble( fd.Constant(1e-2) * inner(hs(-phi, beta) * sigma(u_sol), epsilon(u_sol)) * dx ) # Constraint: Volume with fda.stop_annotating(): total_volume = fd.assemble(fd.Constant(1.0) * dx(domain=mesh)) VolPen = fd.assemble(hs(-phi, beta) * dx) # Needed to track the value of the volume VolControl = fda.Control(VolPen) Vval = total_volume / 2.0 phi_pvd = fd.File("phi_evolution.pvd", target_continuity=fd.H1) def deriv_cb(phi): with fda.stop_annotating(): phi_pvd.write(phi[0]) c = fda.Control(s) Jhat = LevelSetFunctional(J, c, phi, derivative_cb_pre=deriv_cb) Vhat = LevelSetFunctional(VolPen, c, phi) beta_param = 0.1 # Boundary conditions for the shape derivatives. # They must be zero at the boundary conditions. bcs_vel = fd.DirichletBC(S, fd.Constant((0.0, 0.0)), (1, 2)) # Regularize the shape derivatives reg_solver = RegularizationSolver( S, mesh, beta=beta_param, gamma=1.0e5, dx=dx, bcs=bcs_vel, output_dir=None, ) # Hamilton-Jacobi equation to advect the level set dt = 0.05 tol = 1e-5 # Optimization problem vol_constraint = Constraint(Vhat, Vval, VolControl) problem = InfDimProblem(Jhat, reg_solver, ineqconstraints=vol_constraint) parameters = { "ksp_type": "preonly", "pc_type": "lu", "mat_type": "aij", "ksp_converged_reason": None, "pc_factor_mat_solver_type": "mumps", } params = { "alphaC": 3.0, "K": 0.1, "debug": 5, "alphaJ": 1.0, "dt": dt, "maxtrials": 10, "maxit": n_iters, "itnormalisation": 50, "tol": tol, } results = nlspace_solve(problem, params) return results
def main(): mesh = fd.Mesh("./mesh_stokes.msh") mh = fd.MeshHierarchy(mesh, 1) mesh = mh[-1] # mesh = fd.Mesh("./mesh_stokes_inlets.msh") S = fd.VectorFunctionSpace(mesh, "CG", 1) s = fd.Function(S, name="deform") mesh.coordinates.assign(mesh.coordinates + s) x, y = fd.SpatialCoordinate(mesh) PHI = fd.FunctionSpace(mesh, "DG", 1) lx = 1.0 # phi_expr = -0.5 * cos(3.0 / lx * pi * x + 1.0) * cos(3.0 * pi * y) - 0.3 lx = 2.0 phi_expr = -cos(6.0 / lx * pi * x + 1.0) * cos(4.0 * pi * y) - 0.6 with stop_annotating(): phi = fd.interpolate(phi_expr, PHI) phi.rename("LevelSet") nu = fd.Constant(1.0) V = fd.VectorFunctionSpace(mesh, "CG", 1) P = fd.FunctionSpace(mesh, "CG", 1) W = V * P w_sol = fd.Function(W) brinkmann_penalty = 1e6 F = NavierStokesBrinkmannForm(W, w_sol, phi, nu, brinkmann_penalty=brinkmann_penalty) x, y = fd.SpatialCoordinate(mesh) u_inflow = 1.0 y_inlet_1_1 = 0.2 y_inlet_1_2 = 0.4 inflow1 = fd.as_vector([ u_inflow * 100 * (y - y_inlet_1_1) * (y - y_inlet_1_2), 0.0, ]) y_inlet_2_1 = 0.6 y_inlet_2_2 = 0.8 inflow2 = fd.as_vector([ u_inflow * 100 * (y - y_inlet_2_1) * (y - y_inlet_2_2), 0.0, ]) noslip = fd.Constant((0.0, 0.0)) bc1 = fd.DirichletBC(W.sub(0), noslip, 5) bc2 = fd.DirichletBC(W.sub(0), inflow1, (1)) bc3 = fd.DirichletBC(W.sub(0), inflow2, (2)) bcs = [bc1, bc2, bc3] problem = fd.NonlinearVariationalProblem(F, w_sol, bcs=bcs) solver_parameters = { "ksp_type": "preonly", "pc_type": "lu", "mat_type": "aij", "ksp_converged_reason": None, "pc_factor_mat_solver_type": "mumps", } # solver_parameters = { # "ksp_type": "fgmres", # "pc_type": "hypre", # "pc_hypre_type": "euclid", # "pc_hypre_euclid_level": 5, # "mat_type": "aij", # "ksp_converged_reason": None, # "ksp_atol": 1e-3, # "ksp_rtol": 1e-3, # "snes_atol": 1e-3, # "snes_rtol": 1e-3, # } solver = NavierStokesBrinkmannSolver(problem, solver_parameters=solver_parameters) solver.solve() pvd_file = fd.File("ns_solution.pvd") u, p = w_sol.split() pvd_file.write(u, p) u, p = fd.split(w_sol) Vol = fd.assemble(hs(-phi) * fd.Constant(1.0) * dx(0, domain=mesh)) VControl = fda.Control(Vol) Vval = fd.assemble(fd.Constant(0.5) * dx(domain=mesh), annotate=False) with stop_annotating(): print("Initial constraint function value {}".format(Vol)) J = fd.assemble( fd.Constant(brinkmann_penalty) * hs(phi) * inner(u, u) * dx(0) + nu / fd.Constant(2.0) * inner(grad(u), grad(u)) * dx) c = fda.Control(s) phi_pvd = fd.File("phi_evolution_euclid.pvd", target_continuity=fd.H1) def deriv_cb(phi): with stop_annotating(): phi_pvd.write(phi[0]) Jhat = LevelSetFunctional(J, c, phi, derivative_cb_pre=deriv_cb) Vhat = LevelSetFunctional(Vol, c, phi) bcs_vel_1 = fd.DirichletBC(S, noslip, (1, 2, 3, 4)) bcs_vel = [bcs_vel_1] reg_solver = RegularizationSolver(S, mesh, beta=0.5, gamma=1e5, dx=dx, bcs=bcs_vel, design_domain=0) tol = 1e-5 dt = 0.0002 params = { "alphaC": 1.0, "debug": 5, "alphaJ": 1.0, "dt": dt, "K": 0.1, "maxit": 2000, "maxtrials": 5, "itnormalisation": 10, "tol_merit": 1e-4, # new merit can be within 5% of the previous merit # "normalize_tol" : -1, "tol": tol, } problem = InfDimProblem( Jhat, reg_solver, ineqconstraints=[Constraint(Vhat, Vval, VControl)], ) _ = nullspace_shape(problem, params)
def compliance_bridge(): parser = argparse.ArgumentParser(description="Heat exchanger") 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 directory", ) opts = parser.parse_args() output_dir = opts.output_dir # Elasticity parameters E, nu = 1.0, 0.3 rho_min = fd.Constant(1e-4) # Min Vol fraction eps = fd.Constant(100.0) # Heaviside parameter mu, lmbda = fd.Constant(E / (2 * (1 + nu))), fd.Constant( E * nu / ((1 + nu) * (1 - 2 * nu))) mesh = fd.RectangleMesh(20, 40, 0.5, 1, quadrilateral=True) mh = fd.MeshHierarchy(mesh, 1) m = fd.ExtrudedMeshHierarchy(mh, height=1, base_layer=40) mesh = m[-1] S = fd.VectorFunctionSpace(mesh, "CG", 1) s = fd.Function(S, name="deform") mesh.coordinates.assign(mesh.coordinates + s) x, y, z = fd.SpatialCoordinate(mesh) PHI = fd.FunctionSpace(mesh, "CG", 1) lx = 1.0 ly = 2.0 lz = ly phi_expr = (-cos(4.0 / lx * pi * x) * cos(4.0 * pi / ly * y) * cos(4.0 / lz * pi * z) - 0.6) with fda.stop_annotating(): phi = fd.interpolate(-phi_expr, PHI) phi.rename("LevelSet") H1 = fd.VectorElement("CG", mesh.ufl_cell(), 1) W = fd.FunctionSpace(mesh, H1) print(f"DOFS: {W.dim()}") modes = [fd.Function(W) for _ in range(6)] modes[0].interpolate(fd.Constant([1, 0, 0])) modes[1].interpolate(fd.Constant([0, 1, 0])) modes[2].interpolate(fd.Constant([0, 0, 1])) modes[3].interpolate(fd.as_vector([0, z, -y])) modes[4].interpolate(fd.as_vector([-z, 0, x])) modes[5].interpolate(fd.as_vector([y, -x, 0])) nullmodes = fd.VectorSpaceBasis(modes) # Make sure they're orthonormal. nullmodes.orthonormalize() u = fd.TrialFunction(W) v = fd.TestFunction(W) def epsilon(u): return sym(nabla_grad(u)) def sigma(v): return 2.0 * mu * epsilon(v) + lmbda * tr(epsilon(v)) * Identity(3) # Variational forms a = inner(hs(phi, eps, min_value=rho_min) * sigma(u), nabla_grad(v)) * dx(degree=2) t = fd.Constant((0.0, 0.0, -1.0e-1)) L = inner(t, v) * ds_t # Dirichlet BCs ylimits = (0.2, 1.8) xlimits = (0.4, 0.6) I_BC = create_function_marker(PHI, W, xlimits, ylimits) bc1 = MyBC(W, 0, I_BC) bc2 = fd.DirichletBC(W.sub(0), fd.Constant(0.0), 2) bc3 = fd.DirichletBC(W.sub(1), fd.Constant(0.0), 4) u_sol = fd.Function(W) fd.solve( a == L, u_sol, bcs=[bc1, bc2, bc3], solver_parameters=gamg_parameters, near_nullspace=nullmodes, ) # Cost function Jform = fd.assemble( inner(hs(phi, eps, min_value=rho_min) * sigma(u_sol), epsilon(u_sol)) * dx(degree=2)) # Constraint VolPen = fd.assemble(hs(phi, eps, min_value=rho_min) * dx(degree=2)) total_vol = fd.assemble(fd.Constant(1.0) * dx(domain=mesh), annotate=False) VolControl = fda.Control(VolPen) Vval = 0.15 * total_vol # Plotting global_counter1 = itertools.count() phi_pvd = fd.File(f"{output_dir}/level_set_evolution.pvd") def deriv_cb(phi): iter = next(global_counter1) if iter % 10 == 0: phi_pvd.write(phi[0]) c = fda.Control(s) Jhat = LevelSetFunctional(Jform, c, phi, derivative_cb_pre=deriv_cb) Vhat = LevelSetFunctional(VolPen, c, phi) # Regularization solver. Zero on the BCs boundaries beta_param = 0.005 bcs_vel_1 = MyBC(S, 0, I_BC) bcs_vel_2 = fd.DirichletBC(S, fd.Constant((0.0, 0.0, 0.0)), "top") bcs_vel = [bcs_vel_1, bcs_vel_2] reg_solver = RegularizationSolver( S, mesh, beta=beta_param, gamma=1.0e4, dx=dx, bcs=bcs_vel, output_dir=None, solver_parameters=gamg_parameters, ) dt = 0.05 tol = 1e-5 params = { "alphaC": 1.0, "K": 0.0001, "debug": 5, "maxit": opts.n_iters, "alphaJ": 2.0, "dt": dt, "maxtrials": 500, "tol_merit": 5e-2, # new merit can be within 0.5% of the previous merit "itnormalisation": 50, "tol": tol, } hj_solver_parameters["ts_dt"] = dt / 50.0 solver_parameters = { "hj_solver": hj_solver_parameters, "reinit_solver": reinit_solver_parameters, } vol_constraint = Constraint(Vhat, Vval, VolControl) problem = InfDimProblem( Jhat, reg_solver, ineqconstraints=vol_constraint, solver_parameters=solver_parameters, ) _ = nlspace_solve(problem, params)
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()