def coarsen_vectorspacebasis(basis, self, coefficient_mapping=None): coarse_vecs = [ self(vec, self, coefficient_mapping=coefficient_mapping) for vec in basis._vecs ] vsb = firedrake.VectorSpaceBasis(coarse_vecs, constant=basis._constant) vsb.orthonormalize() return vsb
def nullspace(self): """Inform solver that pressure solution is not unique. It is only defined up to adding an arbitrary constant. """ W = self.solution_space return fe.MixedVectorSpaceBasis( W, [W.sub(0), fe.VectorSpaceBasis(constant=True)])
def nullspace(self): """Inform solver that pressure solution is not unique. It is only defined up to adding an arbitrary constant. """ return fe.MixedVectorSpaceBasis( self.solution_space, (fe.VectorSpaceBasis(constant=True), self.solution_subspaces["u"]))
def get_nullspace(self): """Specify nullspace of state/adjoint equation.""" if len(self.outflow_bids) > 0: # If the pressure is fixed (anywhere) by a Dirichlet bc, nsp = None nsp = None else: nsp = fd.MixedVectorSpaceBasis( self.V, [self.V.sub(0), fd.VectorSpaceBasis(constant=True)]) return nsp
def __init__(self, Q, fixed_bids=[], extra_bcs=[], direct_solve=False): if isinstance(extra_bcs, fd.DirichletBC): extra_bcs = [extra_bcs] self.direct_solve = direct_solve self.fixed_bids = fixed_bids # fixed parts of bdry self.params = self.get_params() # solver parameters self.Q = Q """ V: type fd.FunctionSpace I: type PETSc.Mat, interpolation matrix between V and ControlSpace """ (V, I_interp) = Q.get_space_for_inner() free_bids = list(V.mesh().topology.exterior_facets.unique_markers) self.free_bids = [int(i) for i in free_bids] # np.int->int for bid in self.fixed_bids: self.free_bids.remove(bid) # Some weak forms have a nullspace. We import the nullspace if no # parts of the bdry are fixed (we assume that a DirichletBC is # sufficient to empty the nullspace). nsp = None if len(self.fixed_bids) == 0: nsp_functions = self.get_nullspace(V) if nsp_functions is not None: nsp = fd.VectorSpaceBasis(nsp_functions) nsp.orthonormalize() bcs = [] # impose homogeneous Dirichlet bcs on bdry parts that are fixed. if len(self.fixed_bids) > 0: dim = V.value_size if dim == 2: zerovector = fd.Constant((0, 0)) elif dim == 3: zerovector = fd.Constant((0, 0, 0)) else: raise NotImplementedError bcs.append(fd.DirichletBC(V, zerovector, self.fixed_bids)) if len(extra_bcs) > 0: bcs += extra_bcs if len(bcs) == 0: bcs = None a = self.get_weak_form(V) A = fd.assemble(a, mat_type='aij', bcs=bcs) ls = fd.LinearSolver(A, solver_parameters=self.params, nullspace=nsp, transpose_nullspace=nsp) self.ls = ls self.A = A.petscmat self.interpolated = False # If the matrix I is passed, replace A with transpose(I)*A*I # and set up a ksp solver for self.riesz_map if I_interp is not None: self.interpolated = True ITAI = self.A.PtAP(I_interp) from firedrake.petsc import PETSc import numpy as np zero_rows = [] # if there are zero-rows, replace them with rows that # have 1 on the diagonal entry for row in range(*ITAI.getOwnershipRange()): (cols, vals) = ITAI.getRow(row) valnorm = np.linalg.norm(vals) if valnorm < 1e-13: zero_rows.append(row) for row in zero_rows: ITAI.setValue(row, row, 1.0) ITAI.assemble() # overwrite the self.A created by get_impl self.A = ITAI # create ksp solver for self.riesz_map Aksp = PETSc.KSP().create(comm=V.comm) Aksp.setOperators(ITAI) Aksp.setType("preonly") Aksp.pc.setType("cholesky") Aksp.pc.setFactorSolverType("mumps") Aksp.setFromOptions() Aksp.setUp() self.Aksp = Aksp
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)