def compute_operators(self): u = fa.TrialFunction(self.V) v = fa.TestFunction(self.V) form_a = fa.inner(fa.grad(u), fa.grad(v)) * fa.dx form_b = u * v * fa.dx A = da.assemble(form_a) B = da.assemble(form_b) A_np = np.array(A.array()) B_np = np.array(B.array()) return A_np, B_np
def J(self, A: dolfin.PETScMatrix, x: dolfin.PETScVector): assemble(self._J, tensor=A) for bc in self.bcs: bc.apply(A) if self.output_matrix: filename = Path("{self.output_matrix_path}/J_{self.n:04d}.mtx") filename.parent.mkdir(exist_ok=True, parents=True) dump_matrix_to_mtx(A, filename) if self.verbose: print(f"Assembled matrix written to {filename}") self.n = self.n + 1
def __call__(self, f, u): """ Carry out projection of ufl Expression f and store result in the function u. The user must make sure that u lives in the right space. *Arguments* f (:py:class:`ufl.Expr`) The thing to be projected into this function space u (:py:class:`dolfin.Function`) The result of the projection """ L = dolfin.inner(f, self.v)*dolfin.dx() assemble(L, tensor=self.b) self.solver.solve(u.vector(), self.b)
def __init__(self, V, params=None): # Set parameters self.parameters = self.default_parameters() if params is not None: self.parameters.update(params) # Set-up mass matrix for L^2 projection self.V = V self.u = dolfin.TrialFunction(self.V) self.v = dolfin.TestFunction(self.V) self.m = dolfin.inner(self.u, self.v)*dolfin.dx() self.M = assemble(self.m) self.b = dolfin.Vector(V.mesh().mpi_comm(), V.dim()) solver_type = self.parameters["linear_solver_type"] assert(solver_type == "lu" or solver_type == "cg"), \ "Expecting 'linear_solver_type' to be 'lu' or 'cg'" if solver_type == "lu": dolfin.debug("Setting up direct solver for projecter") # Customize LU solver (reuse everything) solver = LUSolver(self.M) solver.parameters["same_nonzero_pattern"] = True solver.parameters["reuse_factorization"] = True else: dolfin.debug("Setting up iterative solver for projecter") # Customize Krylov solver (reuse everything) solver = KrylovSolver("cg", "ilu") solver.set_operator(self.M) solver.parameters["preconditioner"]["structure"] = "same" # solver.parameters["nonzero_initial_guess"] = True self.solver = solver
def get_cavity_volume(geometry, unload=False, chamber="lv", u=None, xshift=0.0): if unload: mesh = geometry.original_geometry ffun = dolfin.MeshFunction("size_t", mesh, 2, mesh.domains()) else: mesh = geometry.mesh ffun = geometry.ffun if chamber == "lv": if "ENDO_LV" in geometry.markers: endo_marker = geometry.markers["ENDO_LV"] else: endo_marker = geometry.markers["ENDO"] else: endo_marker = geometry.markers["ENDO_RV"] if hasattr(endo_marker, "__len__"): endo_marker = endo_marker[0] ds = dolfin.Measure("exterior_facet", subdomain_data=ffun, domain=mesh)(endo_marker) vol_form = get_cavity_volume_form(geometry.mesh, u, xshift) return assemble(vol_form * ds)
def forward(control, annotate=True): self.reset_problem() annotation.annotate = annotate states = [] functional_values = [] functional = self.create_functional() functionals_time = [] gen = self.iteration(control) for count in gen: # Collect stuff states.append(dolfin.Vector(self.problem.state.vector())) functional_values.append(functional) functionals_time.append(functional) return forward_result( functional=dolfin_adjoint.assemble( list_sum(functionals_time) / self._meshvol * dolfin.dx(domain=self.problem.geometry.mesh)), converged=True, )
def debug(self): _, B_np = self.compute_operators() dof_data = np.random.rand(self.num_dofs) u = da.Function(self.V) u.vector()[:] = dof_data L1 = da.assemble(u * u * fa.dx) L2 = (np.matmul(B_np, dof_data) * dof_data).sum() print(L1) print(L2)
def _obj(self, x): f = da.Function(self.poisson.V) f.vector()[:] = x self.poisson.source = f u = self.poisson.solve_problem_variational_form() L_tape = da.assemble( (0.5 * fa.inner(u - self.target_u, u - self.target_u) + 0.5 * self.alpha * fa.inner(f, f)) * fa.dx) L = float(L_tape) return L, L_tape, f
degree=3), W) else: g = da.interpolate(da.Expression(("sin(2*pi*x[0])"), degree=3), W) f = da.interpolate(da.Expression(("sin(2*pi*x[0])"), degree=3), W) u = da.Function(V, name='State') v = fa.TestFunction(V) F = (fa.inner(fa.grad(u), fa.grad(v)) - f * v) * fa.dx bc = da.DirichletBC(V, 0.0, "on_boundary") da.solve(F == 0, u, bc) d = da.Function(V) d.vector()[:] = u.vector()[:] J = da.assemble((0.5 * fa.inner(u - d, u - d)) * fa.dx + alpha / 2 * f**2 * fa.dx) control = da.Control(f) rf = da.ReducedFunctional(J, control) # set the initial value to be zero for optimization f.vector()[:] = 0 # N = len(f.vector()[:]) # f.vector()[:] = np.random.rand(N)*2 -1 problem = da.MoolaOptimizationProblem(rf) f_moola = moola.DolfinPrimalVector(f) solver = moola.BFGS(problem, f_moola, options={ 'jtol': 0, 'gtol': 1e-9,
def compute_meshvolume(domain=None, dx=dolfin.dx, subdomain_id=None): return Constant( assemble( Constant(1.0) * dx(domain=domain, subdomain_id=subdomain_id), ), )
def cost_function(u_model, u_data): norm = lambda f: da.assemble(df.inner(f, f) * df.dx) return norm(u_model - u_data)
def F(self, b: dolfin.PETScVector, x: dolfin.PETScVector): assemble(self._F, tensor=b) for bc in self.bcs: bc.apply(b, x)
def __init__(self, turbine, flow): # add radius to model params if model_parameters is None: model_parameters = {"radius": turbine_radius} else: model_parameters.update({"radius": turbine_radius}) # check if gradient required if "compute_gradient" in model_parameters: compute_gradient = model_parameters["compute_gradient"] else: compute_gradient = True # check if a wake and wake gradients are provided if "wake" in model_parameters: if "wake_gradients" in model_parameters: gradients = model_parameters["wake_gradients"] else: gradients = None self.wake = ADDolfinExpression(model_parameters["wake"], compute_gradient=compute_gradient, gradients=gradients) # compute wake and gradients else: # mimic a SteadyConfiguration but change a few things along the way config = otf.DefaultConfiguration() config.params['steady_state'] = True config.params[ 'initial_condition'] = otf.ConstantFlowInitialCondition(config) config.params['include_advection'] = True config.params['include_diffusion'] = True config.params['diffusion_coef'] = 3.0 config.params['quadratic_friction'] = True config.params['newton_solver'] = True config.params['friction'] = dolfin.Constant(0.0025) config.params['theta'] = 1.0 config.params["dump_period"] = 0 xmin, ymin = -100, -200 xsize, ysize = 1000, 400 xcells, ycells = 400, 160 mesh = dolfin.RectangleMesh(xmin, ymin, xmin + xsize, ymin + ysize, xcells, ycells) V, H = config.finite_element(mesh) config.function_space = dolfin.MixedFunctionSpace([V, H]) config.turbine_function_space = dolfin.FunctionSpace(mesh, 'CG', 2) class Domain(object): """ Domain object used for setting boundary conditions etc later on """ def __init__(self, mesh): class InFlow(dolfin.SubDomain): def inside(self, x, on_boundary): return dolfin.near(x[0], -100) class OutFlow(dolfin.SubDomain): def inside(self, x, on_boundary): return dolfin.near(x[0], 900) inflow = InFlow() outflow = OutFlow() self.mesh = mesh self.boundaries = dolfin.FacetFunction("size_t", mesh) self.boundaries.set_all(0) inflow.mark(self.boundaries, 1) outflow.mark(self.boundaries, 2) self.ds = dolfin.Measure('ds')[self.boundaries] config.domain = Domain(mesh) config.set_domain(config.domain, warning=False) # Boundary conditions bc = otf.DirichletBCSet(config) bc.add_constant_flow(1, 1.0 + 1e-10) bc.add_zero_eta(2) config.params['bctype'] = 'strong_dirichlet' config.params['strong_bc'] = bc config.params['free_slip_on_sides'] = True # Optimisation settings config.params['functional_final_time_only'] = True config.params['automatic_scaling'] = False # Turbine settings config.params['turbine_pos'] = [] config.params['turbine_friction'] = [] config.params['turbine_x'] = turbine_radius * 2 config.params['turbine_y'] = turbine_radius * 2 config.params['controls'] = ['turbine_pos'] # Finally set some DOLFIN optimisation flags dolfin.parameters['form_compiler']['cpp_optimize'] = True dolfin.parameters['form_compiler']['cpp_optimize_flags'] = '-O3' dolfin.parameters['form_compiler']['optimize'] = True # place a turbine with default friction turbine = [(0., 0.)] config.set_turbine_pos(turbine) # solve the shallow water equations rf = otf.ReducedFunctional(config, plot=False) dolfin.info_blue("Generating the wake model...") rf.j(rf.initial_control()) # get state state = rf.last_state V = dolfin.VectorFunctionSpace(config.function_space.mesh(), "CG", 2, dim=2) u_out = dolfin.TrialFunction(V) v_out = dolfin.TestFunction(V) M_out = dolfin_adjoint.assemble( dolfin.inner(v_out, u_out) * dolfin.dx) out_state = dolfin.Function(V) rhs = dolfin_adjoint.assemble( dolfin.inner(v_out, state.split()[0]) * dolfin.dx) dolfin_adjoint.solve(M_out, out_state.vector(), rhs, "cg", "sor", annotate=False) dolfin.info_green("Wake model generated.") self.wake = ADDolfinExpression(out_state.split()[0], compute_gradient) super(ApproximateShallowWater, self).__init__("ApproximateShallowWater", flow_field, model_parameters)
def energy(self, u): return da.assemble(self._energy_density(u) * fa.dx)