def make_mesh(R, δx): geometry = pygmsh.built_in.Geometry() x1 = geometry.add_point([-R, 0, 0], lcar=δx) x2 = geometry.add_point([+R, 0, 0], lcar=δx) center1 = geometry.add_point([0, 0, 0,], lcar=δx) arcs = [geometry.add_circle_arc(x1, center1, x2), geometry.add_circle_arc(x2, center1, x1)] line_loop = geometry.add_line_loop(arcs) plane_surface = geometry.add_plane_surface(line_loop) physical_lines = [geometry.add_physical(arc) for arc in arcs] physical_surface = geometry.add_physical(plane_surface) with open('shallow-ice.geo', 'w') as geo_file: geo_file.write(geometry.get_code()) transform_file = "gmsh -v 0 -2 -format msh2 -o shallow-ice.msh shallow-ice.geo" os.system(transform_file) mesh = firedrake.Mesh('shallow-ice.msh') remove_geo = "rm shallow-ice.geo" remove_mesh = "rm shallow-ice.msh" os.system(remove_geo) os.system(remove_mesh) return mesh
import firedrake import thetis from hrds import HRDS mesh2d = firedrake.Mesh('test_mesh.msh') # mesh file P1_2d = firedrake.FunctionSpace(mesh2d, 'CG', 1) bathymetry2d = firedrake.Function(P1_2d, name="bathymetry") bvector = bathymetry2d.dat.data bathy = HRDS("gebco_uk.tif", rasters=("emod_utm.tif", "inspire_data.tif"), distances=(700, 200)) bathy.set_bands() for i, (xy) in enumerate(mesh2d.coordinates.dat.data): bvector[i] = bathy.get_val(xy) thetis.File('bathy.pvd').write(bathymetry2d)
# "snes_monitor": None, "ksp_monitor": None, } def solve(self): super().solve() self.failed_to_solve = False u_old = self.solution.copy(deepcopy=True) try: fd.solve(self.F == 0, self.solution, bcs=self.bcs, solver_parameters=self.params) except fd.ConvergenceError: self.failed_to_solve = True self.solution.assign(u_old) if __name__ == "__main__": mesh = fd.Mesh("pipe.msh") if mesh.topological_dimension() == 2: # in 2D viscosity = fd.Constant(1. / 400.) elif mesh.topological_dimension() == 3: # in 3D viscosity = fd.Constant(1 / 10.) # simpler problem in 3D else: raise NotImplementedError e = NavierStokesSolver(mesh, viscosity) e.solve() print(e.failed_to_solve) out = fd.File("temp_PDEConstrained_u.pvd") out.write(e.solution.split()[0])
def generate_mesh2D(model, G, comm): print('Entering mesh generation', flush=True) M = grid_point_to_mesh_point_converter_for_seismicmesh(model, G) method = model["opts"]["method"] Lz = model["mesh"]['Lz'] lz = model['BCs']['lz'] Lx = model["mesh"]['Lx'] lx = model['BCs']['lx'] Real_Lz = Lz + lz Real_Lx = Lx + 2 * lx if model['testing_parameters']['experiment_type'] == 'homogeneous': minimum_mesh_velocity = model['testing_parameters'][ 'minimum_mesh_velocity'] frequency = model["acquisition"]['frequency'] lbda = minimum_mesh_velocity / frequency Real_Lz = Lz + lz Real_Lx = Lx + 2 * lx edge_length = lbda / M bbox = (-Real_Lz, 0.0, -lx, Real_Lx - lx) rec = SeismicMesh.Rectangle(bbox) if comm.comm.rank == 0: # Creating rectangular mesh points, cells = SeismicMesh.generate_mesh(domain=rec, edge_length=edge_length, mesh_improvement=False, comm=comm.ensemble_comm, verbose=0) print('entering spatial rank 0 after mesh generation') points, cells = SeismicMesh.geometry.delete_boundary_entities( points, cells, min_qual=0.6) a = np.amin(SeismicMesh.geometry.simp_qual(points, cells)) meshio.write_points_cells("meshes/2Dhomogeneous" + str(G) + ".msh", points, [("triangle", cells)], file_format="gmsh22", binary=False) meshio.write_points_cells("meshes/2Dhomogeneous" + str(G) + ".vtk", points, [("triangle", cells)], file_format="vtk") comm.comm.barrier() if method == "CG" or method == "KMV": mesh = fire.Mesh( "meshes/2Dhomogeneous" + str(G) + ".msh", distribution_parameters={ "overlap_type": (fire.DistributedMeshOverlapType.NONE, 0) }, ) elif model['testing_parameters']['experiment_type'] == 'heterogeneous': # Name of SEG-Y file containg velocity model. fname = "vel_z6.25m_x12.5m_exact.segy" # Bounding box describing domain extents (corner coordinates) bbox = (-12000.0, 0.0, 0.0, 67000.0) rectangle = SeismicMesh.Rectangle(bbox) # Desired minimum mesh size in domain frequency = model["acquisition"]['frequency'] hmin = 1429.0 / (M * frequency) # Construct mesh sizing object from velocity model ef = SeismicMesh.get_sizing_function_from_segy( fname, bbox, hmin=hmin, wl=M, freq=5.0, grade=0.15, domain_pad=model["BCs"]["lz"], pad_style="edge", ) points, cells = SeismicMesh.generate_mesh(domain=rectangle, edge_length=ef, verbose=0, mesh_improvement=False) meshio.write_points_cells("meshes/2Dheterogeneous" + str(G) + ".msh", points / 1000, [("triangle", cells)], file_format="gmsh22", binary=False) meshio.write_points_cells("meshes/2Dheterogeneous" + str(G) + ".vtk", points / 1000, [("triangle", cells)], file_format="vtk") comm.comm.barrier() if method == "CG" or method == "KMV": mesh = fire.Mesh( "meshes/2Dheterogeneous" + str(G) + ".msh", distribution_parameters={ "overlap_type": (fire.DistributedMeshOverlapType.NONE, 0) }, ) print('Finishing mesh generation', flush=True) return mesh
def test_dt(): solver_parameters = copy.deepcopy(default_solver_parameters) class pde_solver(PDESystem): def __init__(self, comp, mesh, parameters): PDESystem.__init__(self, comp, mesh, parameters) def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) c0 = fd.exp(x * y * self.t) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (10, 12)), # top-bottom and cylinder fd.DirichletBC(self.V['u'], ((1.0 * (y - 1) * (2 - y)) / (0.5**2), 0), 9) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 11)] # outflow bcc1 = [fd.DirichletBC(self.V['c'].sub(0), c0, 'on_boundary')] self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']] self.bc['c'][0] = [bcc1, c0, 'on_boundary', 0, 'update'] def setup_constants(self): x, y = fd.SpatialCoordinate(self.mesh) self.constants = { 'deltat': fd.Constant(self.prm['dt']), 'Kd': fd.Constant(0.01), 'k1': fd.Constant(0.005), 'k2': fd.Constant(0.00005), 'lamd1': fd.Constant(0.000005), 'lamd2': fd.Constant(0.0), 'rho_s': fd.Constant(1.), 'L': fd.Constant(1.), 'phi': fd.Constant(0.3), 'n': fd.FacetNormal(self.mesh), 'f': fd.Constant((0.0, 0.0)), 'nu': fd.Constant(0.001), 'frac': fd.Constant(1.), } solver_parameters = recursive_update( solver_parameters, { 'space': { 'u': fd.VectorFunctionSpace, 'c': fd.MixedFunctionSpace, 'd': fd.MixedFunctionSpace }, 'degree': { 'u': 2 }, 'order': { 'c': 3, 'd': 3 }, 'ksp_type': { 'u': 'gmres', 'p': 'gmres', 'c': 'gmres', 'd': 'gmres' }, 'precond': { 'u': 'sor', 'p': 'sor', 'c': 'sor', 'd': 'gmres' }, 'dt': 0.01, 'T': 0.1 }) #load mesh mesh = fd.Mesh("meshes/step1.msh") deltat = [0.01 / (2**i) for i in range(1)] # add subsystems for navier stokes and radio_transport solver = pde_solver([['u', 'p']], mesh, solver_parameters) # solver.add_subsystem(['cd', 'cs', 'as'], solver_parameters) solver.add_subsystem(['c', 'd'], solver_parameters) #setup constants solver.setup_constants() # define subsystems and variable sequence solver.define(['u', 'p', 'u'], 'up', navier_stokes) solver.define(['c', 'd'], 'cd', radio_transport_coupled_mms) # setup boundary conditions solver.setup_bcs() x, y, t = sy.symbols(('x', 'y', 't')) expr = sy.exp(x * y * t) solver.test_mms('c', expr, temporal=True, f_dict={"exp": fd.exp}, dt_list=deltat, plot=False, index=0)
def test_rxn_demo(): solver_parameters = copy.deepcopy(default_solver_parameters) class pde_solver(PDESystem): def __init__(self, comp, mesh, parameters): PDESystem.__init__(self, comp, mesh, parameters) def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (1, 4)), # top-bottom and cylinder fd.DirichletBC(self.V['u'], ((4.0 * 1.5 * y * (0.41 - y) / 0.41**2), 0), 2) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 3)] # outflow self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']] def setup_constants(self): x, y = fd.SpatialCoordinate(self.mesh) self.constants = { 'deltat': fd.Constant(self.prm['dt']), 'n': fd.FacetNormal(self.mesh), 'f': fd.Constant((0.0, 0.0)), 'nu': fd.Constant(0.001), 'eps': fd.Constant(0.01), 'K': fd.Constant(10.0), 'f_1': fd.conditional( pow(x - 0.1, 2) + pow(y - 0.1, 2) < 0.05 * 0.05, 0.1, 0), 'f_2': fd.conditional( pow(x - 0.1, 2) + pow(y - 0.3, 2) < 0.05 * 0.05, 0.1, 0), 'f_3': fd.Constant(0.0) } solver_parameters = recursive_update( solver_parameters, { 'space': { 'u': fd.VectorFunctionSpace, 'c': fd.MixedFunctionSpace }, 'degree': { 'u': 2 }, 'order': { 'c': 3 }, 'ksp_type': { 'u': 'gmres', 'p': 'gmres', 'c': 'gmres' }, 'precond': { 'u': 'sor', 'p': 'sor', 'c': 'sor' }, 'dt': 0.0005, 'T': 1.0 }) mesh = fd.Mesh("meshes/cylinder.msh") solver = pde_solver([['u', 'p']], mesh, solver_parameters) solver.add_subsystem('c', solver_parameters) solver.setup_constants() solver.define(['u', 'p', 'u'], 'up', navier_stokes) solver.define(['c'], 'c', reactions) solver.setup_bcs() solver_parameters = recursive_update( solver_parameters, { 'space': { 'u': fd.VectorFunctionSpace, 'c1': fd.FunctionSpace, 'c2': fd.FunctionSpace, 'c3': fd.FunctionSpace }, 'degree': { 'u': 2 }, 'ksp_type': { 'u': 'gmres', 'p': 'gmres', 'c1': 'gmres', 'c2': 'gmres', 'c3': 'gmres' }, 'subsystem_class': { 'up': navier_stokes, 'c1c2c3': reactions_uncoupled }, #also a new system is declared 'precond': { 'u': 'sor', 'p': 'sor', 'c1': 'sor', 'c2': 'sor', 'c3': 'sor' }, 'dt': 0.0005, 'T': 1.0 }) # test uncoupled solver2 = pde_solver([['u', 'p']], mesh, solver_parameters) solver2.add_subsystem(['c1', 'c2', 'c3'], solver_parameters) solver2.setup_constants() solver2.define(['u', 'p', 'u'], 'up', navier_stokes) solver2.define(['c1', 'c2', 'c3'], 'c1c2c3', reactions_uncoupled) solver2.setup_bcs()
import os import argparse parser = argparse.ArgumentParser() parser.add_argument("--base-inner", type=str, default="elasticity", choices=["elasticity", "laplace"]) parser.add_argument("--alpha", type=float, default=None) parser.add_argument("--clscale", type=float, default=0.1) parser.add_argument("--maxiter", type=int, default=50) parser.add_argument("--weighted", default=False, action="store_true") parser.add_argument("--rstar", type=float, default=0.79) args = parser.parse_args() mesh = fd.Mesh("annulus.msh") R = 1.0 r = 0.5 print("Harmonic map exists for r^*/R^* = %.2f" % ((0.5 * (R / r + r / R))**-1)) Rs = 1.0 rs = args.rstar Q = fs.FeControlSpace(mesh) d = distance_function(Q.get_space_for_inner()[0].mesh(), boundary_ids=[1, 2]) if args.weighted: mu_base = 0.01 / (0.01 + d) else: mu_base = fd.Constant(1.) # mu_base = fd.Constant(1.0) if args.base_inner == "elasticity":
ambient_dim = 3 degree = 1 fine_order = 4 * degree # Parameter to tune accuracy of pytential fmm_order = 5 # This should be (order of convergence = qbx_order + 1) qbx_order = degree qbx_kwargs = {'fine_order': fine_order, 'fmm_order': fmm_order, 'qbx_order': qbx_order} with_refinement = True # Let's compute some layer potentials! m = fd.Mesh("meshes/ball.msh") V = fd.FunctionSpace(m, 'DG', degree) Vdim = fd.VectorFunctionSpace(m, 'DG', degree) mesh_analog = fd2mm.MeshAnalog(m) fspace_analog = fd2mm.FunctionSpaceAnalog(cl_ctx, mesh_analog, V) x, y, z = fd.SpatialCoordinate(m) r""" ..math: \f{1}{4\pi \sqrt{(x-2)^2 + (y-2)^2 + (z-2)^2)}} i.e. a shift of the fundamental solution """ expr = fd.Constant(1 / 4 / fd.pi) * 1 / fd.sqrt(
def test_spectral_constraint(pytestconfig): n = 5 mesh = fd.UnitSquareMesh(n, n) T = fd.Function(fd.VectorFunctionSpace( mesh, "CG", 1)).interpolate(fd.SpatialCoordinate(mesh) - fd.Constant((0.5, 0.5))) mesh = fd.Mesh(T) Q = fs.FeControlSpace(mesh) inner = fs.LaplaceInnerProduct(Q) mesh_m = Q.mesh_m q = fs.ControlVector(Q, inner) if pytestconfig.getoption("verbose"): out = fd.File("domain.pvd") def cb(): out.write(mesh_m.coordinates) else: def cb(): pass J = fsz.MoYoSpectralConstraint(0.5, fd.Constant(0.1), Q, cb=cb) q.fun += Q.T g = q.clone() J.update(q, None, -1) J.gradient(g, q, None) cb() taylor_result = J.checkGradient(q, g, 7, 1) for i in range(len(taylor_result) - 1): assert taylor_result[i + 1][3] <= taylor_result[i][3] * 0.11 params_dict = { 'General': { 'Secant': { 'Type': 'Limited-Memory BFGS', 'Maximum Storage': 2 } }, 'Step': { 'Type': 'Line Search', 'Line Search': { 'Descent Method': { 'Type': 'Quasi-Newton Step' } } }, 'Status Test': { 'Gradient Tolerance': 1e-10, 'Step Tolerance': 1e-10, 'Iteration Limit': 150 } } params = ROL.ParameterList(params_dict, "Parameters") problem = ROL.OptimizationProblem(J, q) solver = ROL.OptimizationSolver(problem, params) solver.solve() Tvec = Q.T.vector()[:, :] for i in range(Tvec.shape[0]): assert abs(Tvec[i, 0]) < 0.55 + 1e-4 assert abs(Tvec[i, 1]) < 0.55 + 1e-4 assert np.any(np.abs(Tvec) > 0.55 - 1e-4)
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)
import numpy as np from mpl_toolkits.axes_grid1 import make_axes_locatable import firedrake from firedrake import sqrt, inner import icepack.plot def colorbar(figure, axes, mappable, *args, **kwargs): divider = make_axes_locatable(axes) cax = divider.append_axes('right', size='5%', pad=0.05) return figure.colorbar(mappable, *args, cax=cax, **kwargs) mesh = firedrake.Mesh('ice-shelf.msh') Q = firedrake.FunctionSpace(mesh, family='CG', degree=2) V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=2) Δ = firedrake.FunctionSpace(mesh, family='DG', degree=1) filename = 'steady-state-undamaged' with firedrake.DumbCheckpoint(filename, mode=firedrake.FILE_READ) as chk: h_undamaged = firedrake.Function(Q) u_undamaged = firedrake.Function(V) chk.load(h_undamaged, name='h') chk.load(u_undamaged, name='u') filename = 'steady-state-damaged' with firedrake.DumbCheckpoint(filename, mode=firedrake.FILE_READ) as chk: h_damaged = firedrake.Function(Q) u_damaged = firedrake.Function(V) D = firedrake.Function(Δ) chk.load(h_damaged, name='h')
queue = cl.CommandQueue(cl_ctx) import pytest # This has been my convention since both firedrake and pytential # have some similar names. This makes defining bilinear forms really # unpleasant. import firedrake as fd from sumpy.kernel import LaplaceKernel from pytential import sym # The user should only need to interact with firedrake_to_pytential.op import fd2mm cwd = abspath(dirname(__file__)) mesh2d = fd.Mesh(join(cwd, 'meshes', 'circle.msh')) mesh3d = fd.Mesh(join(cwd, 'meshes', 'ball.msh')) @pytest.mark.parametrize('family', ['DG', 'CG']) @pytest.mark.parametrize('degree', [1, 3]) @pytest.mark.parametrize('ambient_dim', [2, 3]) def test_greens_formula(degree, family, ambient_dim): fine_order = 4 * degree # Parameter to tune accuracy of pytential fmm_order = 5 # This should be (order of convergence = qbx_order + 1) qbx_order = degree with_refinement = True
import fireshape.zoo as fsz from cr_inner_product import CauchyRiemannAugmentation, distance_function import ROL import numpy as np import os import argparse parser = argparse.ArgumentParser() parser.add_argument("--use_cr", type=int, default=0) parser.add_argument("--base_inner", type=str, default="elasticity") args = parser.parse_args() use_cr = bool(args.use_cr) base_inner = args.base_inner mesh = fd.Mesh("Sphere2D.msh") Q = fs.FeControlSpace(mesh) d = distance_function(Q.get_space_for_inner()[0].mesh(), eps=fd.Constant(0.1)) mu_base = 0.01 / (0.01 + d) if base_inner == "elasticity": inner = fs.ElasticityInnerProduct(Q, fixed_bids=[1, 2, 3], mu=mu_base, direct_solve=True) elif base_inner == "laplace": inner = fs.LaplaceInnerProduct(Q, fixed_bids=[1, 2, 3], mu=mu_base, direct_solve=True) else:
def __init__(self, mesh, bbox, orders, levels, fixed_dims=[], boundary_regularities=None): """ bbox: a list of tuples describing [(xmin, xmax), (ymin, ymax), ...] of a Cartesian grid that extends around the shape to be optimised orders: describe the orders (one integer per geometric dimension) of the tensor-product B-spline basis. A univariate B-spline has order "o" if it is a piecewise polynomial of degree "o-1". For instance, a hat function is a B-spline of order 2 and thus degree 1. levels: describe the subdivision levels (one integers per geometric dimension) used to construct the knots of univariate B-splines fixed_dims: dimensions in which the deformation should be zero boundary_regularities: how fast the splines go to zero on the boundary for each dimension [0,..,0] : they don't go to zero [1,..,1] : they go to zero with C^0 regularity [2,..,2] : they go to zero with C^1 regularity """ self.boundary_regularities = [o - 1 for o in orders] \ if boundary_regularities is None else boundary_regularities # information on B-splines self.dim = len(bbox) # geometric dimension self.bbox = bbox self.orders = orders self.levels = levels if isinstance(fixed_dims, int): fixed_dims = [fixed_dims] self.fixed_dims = fixed_dims self.construct_knots() self.comm = mesh.mpi_comm() # create temporary self.mesh_r and self.V_r to assemble innerproduct if self.dim == 2: nx = len(self.knots[0]) - 1 ny = len(self.knots[1]) - 1 Lx = self.bbox[0][1] - self.bbox[0][0] Ly = self.bbox[1][1] - self.bbox[1][0] meshloc = fd.RectangleMesh(nx, ny, Lx, Ly, quadrilateral=True, comm=self.comm) # quads or triangle? # shift in x- and y-direction meshloc.coordinates.dat.data[:, 0] += self.bbox[0][0] meshloc.coordinates.dat.data[:, 1] += self.bbox[1][0] # inner_product.fixed_bids = [1,2,3,4] elif self.dim == 3: # maybe use extruded meshes, quadrilateral not available nx = len(self.knots[0]) - 1 ny = len(self.knots[1]) - 1 nz = len(self.knots[2]) - 1 Lx = self.bbox[0][1] - self.bbox[0][0] Ly = self.bbox[1][1] - self.bbox[1][0] Lz = self.bbox[2][1] - self.bbox[2][0] meshloc = fd.BoxMesh(nx, ny, nz, Lx, Ly, Lz, comm=self.comm) # shift in x-, y-, and z-direction meshloc.coordinates.dat.data[:, 0] += self.bbox[0][0] meshloc.coordinates.dat.data[:, 1] += self.bbox[1][0] meshloc.coordinates.dat.data[:, 2] += self.bbox[2][0] # inner_product.fixed_bids = [1,2,3,4,5,6] self.mesh_r = meshloc maxdegree = max(self.orders) - 1 # self.V_r = # self.inner_product = inner_product # self.inner_product.get_impl(self.V_r, self.FullIFW) # is this the proper space? self.V_control = fd.VectorFunctionSpace(self.mesh_r, "CG", maxdegree) self.I_control = self.build_interpolation_matrix(self.V_control) # standard construction of ControlSpace self.mesh_r = mesh element = fd.VectorElement("CG", mesh.ufl_cell(), maxdegree) 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 = fd.Mesh(self.T) self.V_m = fd.FunctionSpace(self.mesh_m, element) assert self.dim == self.mesh_r.geometric_dimension() # assemble correct interpolation matrix self.FullIFW = self.build_interpolation_matrix(self.V_r)
def MeshHierarchy(mesh, refinement_levels, refinements_per_level=1, reorder=None, distribution_parameters=None, callbacks=None): """Build a hierarchy of meshes by uniformly refining a coarse mesh. :arg mesh: the coarse :func:`~.Mesh` to refine :arg refinement_levels: the number of levels of refinement :arg refinements_per_level: the number of refinements for each level in the hierarchy. :arg distribution_parameters: options controlling mesh distribution, see :func:`~.Mesh` for details. If ``None``, use the same distribution parameters as were used to distribute the coarse mesh, otherwise, these options override the default. :arg reorder: optional flag indicating whether to reorder the refined meshes. :arg callbacks: A 2-tuple of callbacks to call before and after refinement of the DM. The before callback receives the DM to be refined (and the current level), the after callback receives the refined DM (and the current level). """ cdm = mesh._plex cdm.setRefinementUniform(True) dms = [] if mesh.comm.size > 1 and mesh._grown_halos: raise RuntimeError( "Cannot refine parallel overlapped meshes " "(make sure the MeshHierarchy is built immediately after the Mesh)" ) parameters = {} if distribution_parameters is not None: parameters.update(distribution_parameters) else: parameters.update(mesh._distribution_parameters) parameters["partition"] = False distribution_parameters = parameters if callbacks is not None: before, after = callbacks else: before = after = lambda dm, i: None for i in range(refinement_levels * refinements_per_level): if i % refinements_per_level == 0: before(cdm, i) rdm = cdm.refine() if i % refinements_per_level == 0: after(rdm, i) # Remove interior facet label (re-construct from # complement of exterior facets). Necessary because the # refinement just marks points "underneath" the refined # facet with the appropriate label. This works for # exterior, but not marked interior facets rdm.removeLabel("interior_facets") # Remove vertex (and edge) points from labels on exterior # facets. Interior facets will be relabeled in Mesh # construction below. impl.filter_exterior_facet_labels(rdm) rdm.removeLabel("pyop2_core") rdm.removeLabel("pyop2_owned") rdm.removeLabel("pyop2_ghost") dms.append(rdm) cdm = rdm # Fix up coords if refining embedded circle or sphere if hasattr(mesh, '_radius'): # FIXME, really we need some CAD-like representation # of the boundary we're trying to conform to. This # doesn't DTRT really for cubed sphere meshes (the # refined meshes are no longer gnonomic). coords = cdm.getCoordinatesLocal().array.reshape( -1, mesh.geometric_dimension()) scale = mesh._radius / np.linalg.norm(coords, axis=1).reshape( -1, 1) coords *= scale meshes = [mesh] + [ firedrake.Mesh(dm, dim=mesh.ufl_cell().geometric_dimension(), distribution_parameters=distribution_parameters, reorder=reorder) for dm in dms ] lgmaps = [] for i, m in enumerate(meshes): no = impl.create_lgmap(m._plex) m.init() o = impl.create_lgmap(m._plex) m._plex.setRefineLevel(i) lgmaps.append((no, o)) coarse_to_fine_cells = [] fine_to_coarse_cells = [None] for (coarse, fine), (clgmaps, flgmaps) in zip(zip(meshes[:-1], meshes[1:]), zip(lgmaps[:-1], lgmaps[1:])): c2f, f2c = impl.coarse_to_fine_cells(coarse, fine, clgmaps, flgmaps) coarse_to_fine_cells.append(c2f) fine_to_coarse_cells.append(f2c) coarse_to_fine_cells = dict((Fraction(i, refinements_per_level), c2f) for i, c2f in enumerate(coarse_to_fine_cells)) fine_to_coarse_cells = dict((Fraction(i, refinements_per_level), f2c) for i, f2c in enumerate(fine_to_coarse_cells)) return HierarchyBase(meshes, coarse_to_fine_cells, fine_to_coarse_cells, refinements_per_level, nested=True)
verbose=0) points, cells = SeismicMesh.geometry.delete_boundary_entities(points, cells, min_qual=0.6) meshio.write_points_cells("meshes/benchmark_2d.msh", points, [("triangle", cells)], file_format="gmsh22", binary=False) ## Mesh generation finishes here. 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)
def mesh_for_sensors(dim, n): mesh = uniform_mesh(dim, n, l=2) coords = firedrake.Function(mesh.coordinates) coords -= 1.0 return firedrake.Mesh(coords)
# boundary conditions c0 = 0.0 # boundary concentration # problem parameters verbose = False Dm = 1.0 # diffusion (m²/s) c = (25, 25) # %% # Process section (simulation) # ----------------------------- # 2) Define mesh print('* define mesh') if from_file: mesh = fd.Mesh("nguyen.msh") mesh.init() else: mesh = fd.SquareMesh(n, n, L, quadrilateral=quad_mesh, diagonal="right") x, y = fd.SpatialCoordinate(mesh) if verbose: fd.triplot(mesh) plt.legend() plt.savefig("plots/cd_hdg_mesh.png") # 3) Setting problem (FunctionSpace, Init.Bound.Condition, VariationalForms) # 3.1) Set Function spaces if quad_mesh: DG1 = fd.FunctionSpace(mesh, "DQ", order)
degree = 1 fine_order = 4 * degree # Parameter to tune accuracy of pytential fmm_order = 10 # This should be (order of convergence = qbx_order + 1) qbx_order = degree qbx_kwargs = {'fine_order': fine_order, 'fmm_order': fmm_order, 'qbx_order': qbx_order} with_refinement = True # Let's compute some layer potentials! m = fd.Mesh('meshes/circle.msh') V = fd.FunctionSpace(m, 'DG', degree) Vdim = fd.VectorFunctionSpace(m, 'DG', degree) mesh_analog = fd2mm.MeshAnalog(m) fspace_analog = fd2mm.FunctionSpaceAnalog(cl_ctx, mesh_analog, V) xx = fd.SpatialCoordinate(m) r""" ..math: \ln(\sqrt{(x+1)^2 + (y+1)^2}) i.e. a shift of the fundamental solution """ expr = fd.ln(fd.sqrt((xx[0] + 2)**2 + (xx[1] + 2)**2))
def test_objective_plus_box_constraint(pytestconfig): n = 10 mesh = fd.UnitSquareMesh(n, n) T = mesh.coordinates.copy(deepcopy=True) (x, y) = fd.SpatialCoordinate(mesh) T.interpolate(T + fd.Constant((0, 0))) mesh = fd.Mesh(T) Q = fs.FeControlSpace(mesh) inner = fs.LaplaceInnerProduct(Q) mesh_m = Q.mesh_m q = fs.ControlVector(Q, inner) if pytestconfig.getoption("verbose"): out = fd.File("domain.pvd") def cb(): out.write(mesh_m.coordinates) else: def cb(): pass lower_bound = Q.T.copy(deepcopy=True) lower_bound.interpolate(fd.Constant((-0.2, -0.2))) upper_bound = Q.T.copy(deepcopy=True) upper_bound.interpolate(fd.Constant((+1.2, +1.2))) # levelset test case (x, y) = fd.SpatialCoordinate(Q.mesh_m) f = (pow(x - 0.5, 2)) + pow(y - 0.5, 2) - 4. J1 = fsz.LevelsetFunctional(f, Q, cb=cb, quadrature_degree=10) J2 = fsz.MoYoBoxConstraint(10., [1, 2, 3, 4], Q, lower_bound=lower_bound, upper_bound=upper_bound, cb=cb, quadrature_degree=10) J3 = fsz.MoYoSpectralConstraint(100, fd.Constant(0.6), Q, cb=cb, quadrature_degree=100) J = 0.1 * J1 + J2 + J3 g = q.clone() J.gradient(g, q, None) taylor_result = J.checkGradient(q, g, 9, 1) for i in range(len(taylor_result) - 1): if taylor_result[i][3] > 1e-6 and taylor_result[i][3] < 1e-3: assert taylor_result[i + 1][3] <= taylor_result[i][3] * 0.15 params_dict = { 'Step': { 'Type': 'Line Search', 'Line Search': { 'Descent Method': { 'Type': 'Quasi-Newton Step' } } }, 'General': { 'Secant': { 'Type': 'Limited-Memory BFGS', 'Maximum Storage': 2 } }, 'Status Test': { 'Gradient Tolerance': 1e-10, 'Step Tolerance': 1e-10, 'Iteration Limit': 10 } } params = ROL.ParameterList(params_dict, "Parameters") problem = ROL.OptimizationProblem(J, q) solver = ROL.OptimizationSolver(problem, params) solver.solve() Tvec = Q.T.vector() nodes = fd.DirichletBC(Q.V_r, fd.Constant((0.0, 0.0)), [2]).nodes assert np.all(Tvec[nodes, 0] <= 1.2 + 1e-1) assert np.all(Tvec[nodes, 1] <= 1.2 + 1e-1)
def BaryMeshHierarchy(mesh, refinement_levels, distribution_parameters=None, callbacks=None, reorder=None, refinements_per_level=1): cdm = mesh._topology_dm cdm.setRefinementUniform(True) dms = [] if mesh.comm.size > 1 and mesh._grown_halos: raise RuntimeError("Cannot refine parallel overlapped meshes " "(make sure the MeshHierarchy is built immediately after the Mesh)") parameters = {} if distribution_parameters is not None: parameters.update(distribution_parameters) else: parameters.update(mesh._distribution_parameters) parameters["partition"] = False distribution_parameters = parameters if callbacks is not None: before, after = callbacks else: before = after = lambda dm, i: None for i in range(refinement_levels*refinements_per_level): if i % refinements_per_level == 0: before(cdm, i) rdm = cdm.refine() if i % refinements_per_level == 0: after(rdm, i) # Remove interior facet label (re-construct from # complement of exterior facets). Necessary because the # refinement just marks points "underneath" the refined # facet with the appropriate label. This works for # exterior, but not marked interior facets rdm.removeLabel("interior_facets") # Remove vertex (and edge) points from labels on exterior # facets. Interior facets will be relabeled in Mesh # construction below. impl.filter_labels(rdm, rdm.getHeightStratum(1), "exterior_facets", "boundary_faces", FACE_SETS_LABEL) rdm.removeLabel("pyop2_core") rdm.removeLabel("pyop2_owned") rdm.removeLabel("pyop2_ghost") dms.append(rdm) cdm = rdm # Fix up coords if refining embedded circle or sphere if hasattr(mesh, '_radius'): # FIXME, really we need some CAD-like representation # of the boundary we're trying to conform to. This # doesn't DTRT really for cubed sphere meshes (the # refined meshes are no longer gnonomic). coords = cdm.getCoordinatesLocal().array.reshape(-1, mesh.geometric_dimension()) scale = mesh._radius / np.linalg.norm(coords, axis=1).reshape(-1, 1) coords *= scale barydms = (bary(mesh._topology_dm), ) + tuple(bary(dm) for dm in dms) for bdm in barydms: impl.filter_labels(bdm, bdm.getHeightStratum(1), "exterior_facets", "boundary_faces", FACE_SETS_LABEL) barymeshes = [firedrake.Mesh(dm, dim=mesh.ufl_cell().geometric_dimension(), distribution_parameters=distribution_parameters, reorder=reorder) for dm in barydms] meshes = [mesh] + [firedrake.Mesh(dm, dim=mesh.ufl_cell().geometric_dimension(), distribution_parameters=distribution_parameters, reorder=reorder) for dm in dms] lgmaps = [] for i, m in enumerate(meshes): no = impl.create_lgmap(m._topology_dm) m.init() o = impl.create_lgmap(m._topology_dm) m._topology_dm.setRefineLevel(i) lgmaps.append((no, o)) coarse_to_fine_cells = [] fine_to_coarse_cells = [None] for (coarse, fine), (clgmaps, flgmaps) in zip(zip(meshes[:-1], meshes[1:]), zip(lgmaps[:-1], lgmaps[1:])): c2f, f2c = impl.coarse_to_fine_cells(coarse, fine, clgmaps, flgmaps) coarse_to_fine_cells.append(c2f) fine_to_coarse_cells.append(f2c) lgmaps = [] for i, m in enumerate(barymeshes): no = impl.create_lgmap(m._topology_dm) m.init() o = impl.create_lgmap(m._topology_dm) m._topology_dm.setRefineLevel(i) lgmaps.append((no, o)) d = mesh.topological_dimension() bary_coarse_to_fine_cells = [] bary_fine_to_coarse_cells = [None] for (coarseu, fineu), (coarse, fine), (clgmaps, flgmaps), uniform_coarse_to_fine \ in zip(zip(meshes[:-1], meshes[1:]), zip(barymeshes[:-1], barymeshes[1:]), zip(lgmaps[:-1], lgmaps[1:]), coarse_to_fine_cells): cdm = coarseu._topology_dm fdm = fineu._topology_dm _, cn2o = impl.get_entity_renumbering(cdm, coarseu._cell_numbering, "cell") _, fn2o = impl.get_entity_renumbering(fdm, fineu._cell_numbering, "cell") plex_uniform_coarse_to_fine = numpy.empty_like(uniform_coarse_to_fine) for i, cells in enumerate(uniform_coarse_to_fine): plexcells = fn2o[cells] plex_uniform_coarse_to_fine[cn2o[i], :] = plexcells ncoarse, nfine = plex_uniform_coarse_to_fine.shape plex_coarse_bary_to_fine_bary = numpy.full((ncoarse*(d+1), nfine*(d+1)), -1, dtype=PETSc.IntType) for c in range(ncoarse*(d+1)): uniform = c // (d+1) fine_cells = plex_uniform_coarse_to_fine[uniform] bary_cells = [] for fc in fine_cells: bary_cells.extend(list(range(fc*(d+1), (fc+1)*(d+1)))) plex_coarse_bary_to_fine_bary[c] = bary_cells cdm = coarse._topology_dm fdm = fine._topology_dm co2n, _ = impl.get_entity_renumbering(cdm, coarse._cell_numbering, "cell") fo2n, _ = impl.get_entity_renumbering(fdm, fine._cell_numbering, "cell") coarse_bary_to_fine_bary = numpy.empty_like(plex_coarse_bary_to_fine_bary) # Translate plex numbering to firedrake numbering for i, plex_cells in enumerate(plex_coarse_bary_to_fine_bary): coarse_bary_to_fine_bary[co2n[i]] = fo2n[plex_cells] bary_coarse_to_fine_cells.append(coarse_bary_to_fine_bary) # Not fast but seems to work fine_bary_to_coarse_bary = [[]] for i in range(numpy.max(coarse_bary_to_fine_bary)): fine_bary_to_coarse_bary.append([]) for coarse in range(coarse_bary_to_fine_bary.shape[0]): for ifine in range(coarse_bary_to_fine_bary.shape[1]): # the coarse cell `coarse` is contained in the fine cell # `bary_coarse_to_fine_cells[0][coarse, ifine]` so we # should add it to the corresponding list fine_bary_to_coarse_bary[coarse_bary_to_fine_bary[coarse, ifine]].append(coarse) fine_bary_to_coarse_bary = numpy.asarray(fine_bary_to_coarse_bary, dtype=PETSc.IntType) bary_fine_to_coarse_cells.append(fine_bary_to_coarse_bary) #print(bary_coarse_to_fine_cells) #print(bary_fine_to_coarse_cells) coarse_to_fine_cells = dict((Fraction(i, refinements_per_level), c2f) for i, c2f in enumerate(bary_coarse_to_fine_cells)) fine_to_coarse_cells = dict((Fraction(i, refinements_per_level), f2c) for i, f2c in enumerate(bary_fine_to_coarse_cells)) return HierarchyBase(barymeshes, coarse_to_fine_cells, fine_to_coarse_cells, refinements_per_level, nested=False)
def test_box_constraint(pytestconfig): n = 5 mesh = fd.UnitSquareMesh(n, n) T = mesh.coordinates.copy(deepcopy=True) (x, y) = fd.SpatialCoordinate(mesh) T.interpolate(T + fd.Constant((1, 0)) * x * y) mesh = fd.Mesh(T) Q = fs.FeControlSpace(mesh) inner = fs.LaplaceInnerProduct(Q, fixed_bids=[1]) mesh_m = Q.mesh_m q = fs.ControlVector(Q, inner) if pytestconfig.getoption("verbose"): out = fd.File("domain.pvd") def cb(): out.write(mesh_m.coordinates) else: def cb(): pass lower_bound = Q.T.copy(deepcopy=True) lower_bound.interpolate(fd.Constant((-0.0, -0.0))) upper_bound = Q.T.copy(deepcopy=True) upper_bound.interpolate(fd.Constant((+1.3, +0.9))) J = fsz.MoYoBoxConstraint(1, [2], Q, lower_bound=lower_bound, upper_bound=upper_bound, cb=cb, quadrature_degree=100) g = q.clone() J.gradient(g, q, None) taylor_result = J.checkGradient(q, g, 9, 1) for i in range(len(taylor_result) - 1): if taylor_result[i][3] > 1e-7: assert taylor_result[i + 1][3] <= taylor_result[i][3] * 0.11 params_dict = { 'Step': { 'Type': 'Line Search', 'Line Search': { 'Descent Method': { 'Type': 'Quasi-Newton Step' } } }, 'General': { 'Secant': { 'Type': 'Limited-Memory BFGS', 'Maximum Storage': 2 } }, 'Status Test': { 'Gradient Tolerance': 1e-10, 'Step Tolerance': 1e-10, 'Iteration Limit': 150 } } params = ROL.ParameterList(params_dict, "Parameters") problem = ROL.OptimizationProblem(J, q) solver = ROL.OptimizationSolver(problem, params) solver.solve() Tvec = Q.T.vector() nodes = fd.DirichletBC(Q.V_r, fd.Constant((0.0, 0.0)), [2]).nodes assert np.all(Tvec[nodes, 0] <= 1.3 + 1e-4) assert np.all(Tvec[nodes, 1] <= 0.9 + 1e-4)
def test_radio_transport(): solver_parameters = copy.deepcopy(default_solver_parameters) class pde_solver(PDESystem): def __init__(self, comp, mesh, parameters): PDESystem.__init__(self, comp, mesh, parameters) def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (10, 12)), # top-bottom fd.DirichletBC(self.V['u'], ((1.0 * (y - 1) * (2 - y)) / (0.5**2), 0), 9) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 11)] # outflow self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']] def setup_constants(self): x, y = fd.SpatialCoordinate(self.mesh) self.constants = { 'deltat': fd.Constant(self.prm['dt']), 'Kd': fd.Constant(0.01), 'k1': fd.Constant(0.005), 'k2': fd.Constant(0.00005), 'lamd1': fd.Constant(0.000005), 'lamd2': fd.Constant(0.0), 'rho_s': fd.Constant(1.), 'L': fd.Constant(1.), 'phi': fd.Constant(0.3), 'n': fd.FacetNormal(self.mesh), 'f': fd.Constant((0.0, 0.0)), 'nu': fd.Constant(0.001), 'frac': fd.Constant(1.), 'source1': fd.conditional( pow(x - 1, 2) + pow(y - 1.5, 2) < 0.25 * 0.25, 10.0, 0) } # update the parameters solver_parameters = recursive_update( solver_parameters, { 'space': { 'u': fd.VectorFunctionSpace, 'c': fd.MixedFunctionSpace, 'd': fd.MixedFunctionSpace }, 'degree': { 'u': 2 }, 'order': { 'c': 3, 'd': 3 }, 'ksp_type': { 'u': 'gmres', 'p': 'gmres', 'c': 'gmres', 'd': 'gmres' }, 'precond': { 'u': 'sor', 'p': 'sor', 'c': 'sor', 'd': 'gmres' }, 'dt': 0.05, 'T': 5.0 }) #load mesh mesh = fd.Mesh("meshes/step10.msh") solver = pde_solver([['u', 'p']], mesh, solver_parameters) solver.add_subsystem(['c', 'd'], solver_parameters) solver.setup_constants() solver.define(['u', 'p', 'u'], 'up', navier_stokes) solver.define(['c', 'd'], 'cd', radio_transport_coupled) solver.setup_bcs()
from firedrake import sqrt, inner import icepack.plot parser = argparse.ArgumentParser() parser.add_argument('--mesh') parser.add_argument('--undamaged') parser.add_argument('--damaged') parser.add_argument('--output') args = parser.parse_args() def colorbar(figure, axes, mappable, *args, **kwargs): divider = make_axes_locatable(axes) cax = divider.append_axes('right', size='5%', pad=0.05) return figure.colorbar(mappable, *args, cax=cax, **kwargs) mesh = firedrake.Mesh(args.mesh) Q = firedrake.FunctionSpace(mesh, family='CG', degree=2) V = firedrake.VectorFunctionSpace(mesh, family='CG', degree=2) Δ = firedrake.FunctionSpace(mesh, family='DG', degree=1) with firedrake.DumbCheckpoint(args.undamaged, mode=firedrake.FILE_READ) as chk: h_undamaged = firedrake.Function(Q) u_undamaged = firedrake.Function(V) chk.load(h_undamaged, name='h') chk.load(u_undamaged, name='u') with firedrake.DumbCheckpoint(args.damaged, mode=firedrake.FILE_READ) as chk: h_damaged = firedrake.Function(Q) u_damaged = firedrake.Function(V) D = firedrake.Function(Δ) chk.load(h_damaged, name='h')
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 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 generate_mesh3D(model, G, comm): print('Entering mesh generation', flush=True) M = grid_point_to_mesh_point_converter_for_seismicmesh(model, G) method = model["opts"]["method"] Lz = model["mesh"]['Lz'] lz = model['BCs']['lz'] Lx = model["mesh"]['Lx'] lx = model['BCs']['lx'] Ly = model["mesh"]['Ly'] ly = model['BCs']['ly'] Real_Lz = Lz + lz Real_Lx = Lx + 2 * lx Real_Ly = Ly + 2 * ly minimum_mesh_velocity = model['testing_parameters'][ 'minimum_mesh_velocity'] frequency = model["acquisition"]['frequency'] lbda = minimum_mesh_velocity / frequency edge_length = lbda / M #print(Real_Lz) bbox = (-Real_Lz, 0.0, -lx, Real_Lx - lx, -ly, Real_Ly - ly) cube = SeismicMesh.Cube(bbox) if comm.comm.rank == 0: # Creating rectangular mesh points, cells = SeismicMesh.generate_mesh(domain=cube, edge_length=edge_length, mesh_improvement=False, max_iter=75, comm=comm.ensemble_comm, verbose=0) points, cells = SeismicMesh.sliver_removal(points=points, bbox=bbox, domain=cube, edge_length=edge_length, preserve=True, max_iter=200) print('entering spatial rank 0 after mesh generation') meshio.write_points_cells("meshes/3Dhomogeneous" + str(G) + ".msh", points, [("tetra", cells)], file_format="gmsh22", binary=False) meshio.write_points_cells("meshes/3Dhomogeneous" + str(G) + ".vtk", points, [("tetra", cells)], file_format="vtk") comm.comm.barrier() if method == "CG" or method == "KMV": mesh = fire.Mesh( "meshes/3Dhomogeneous" + str(G) + ".msh", distribution_parameters={ "overlap_type": (fire.DistributedMeshOverlapType.NONE, 0) }, ) print('Finishing mesh generation', flush=True) return 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")
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': {
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()