def __call__(self, u=None): if u is None: u = dolfin.Function( self._displacement_space, name="Zero displacement from strain observation", ) u_int = map_displacement( u, self._displacement_space, self._interpolation_space, self._approx ) # We need to correct for th reference deformation F = pulse.kinematics.DeformationGradient(u_int) * dolfin.inv(self._F_ref) # Compute the strains if self._tensor == "gradu": tensor = pulse.kinematics.EngineeringStrain(F, isochoric=self._isochoric) elif self._tensor == "E": tensor = pulse.kinematics.GreenLagrangeStrain(F, isochoric=self._isochoric) elif self._tensor == "almansi": tensor = pulse.kinematics.EulerAlmansiStrain(F, isochoric=self._isochoric) form = dolfin.inner(tensor * self.field, self.field) strain = dolfin_adjoint.Function(self._V, name="Simulated Strain") dolfin_adjoint.solve( dolfin.inner(self._trial, self._test) / self._vol * self._dmu == dolfin.inner(self._test, form) * self._dmu, strain, solver_parameters={"linear_solver": "gmres"}, ) return strain
def __call__(self, u=None): """ Arguments --------- u : :py:class:`dolfin.Function` The displacement """ if u is None: volume_form = (-1.0 / 3.0) * dolfin.dot(self._X, self._N) else: u_int = map_displacement( u, self._displacement_space, self._interpolation_space, self._approx ) # Compute volume F = pulse.kinematics.DeformationGradient(u_int) J = pulse.kinematics.Jacobian(F) volume_form = (-1.0 / 3.0) * dolfin.dot( self._X + u_int, J * dolfin.inv(F).T * self._N ) volume = dolfin_adjoint.Function(self._V, name="Simulated volume") # Make a project for dolfin-adjoint recording dolfin_adjoint.solve( dolfin.inner(self._trial, self._test) / self._endoarea * self._dmu == dolfin.inner(volume_form, self._test) * self._dmu, volume, ) return volume
def solve_problem_variational_form(self): u = da.Function(self.V) du = fa.TrialFunction(self.V) v = fa.TestFunction(self.V) E = self._energy_density(u) * fa.dx dE = fa.derivative(E, u, v) jacE = fa.derivative(dE, u, du) da.solve(dE == 0, u, self.bcs, J=jacE) return u
def moola_problem(): adj_reset() mesh = UnitSquareMesh(256, 256) V = FunctionSpace(mesh, "CG", 1) f = interpolate(Constant(1), V) u = Function(V) phi = TestFunction(V) F = inner(grad(u), grad(phi))*dx - f*phi*dx bc = DirichletBC(V, Constant(0), "on_boundary") solve(F == 0, u, bc) J = Functional(inner(u, u)*dx) m = Control(f) rf = ReducedFunctional(J, m) obj = rf.moola_problem().obj pf = moola.DolfinPrimalVector(f) return obj, pf
def moola_problem(): adj_reset() mesh = UnitSquareMesh(256, 256) V = FunctionSpace(mesh, "CG", 1) f = interpolate(Constant(1), V) u = Function(V) phi = TestFunction(V) F = inner(grad(u), grad(phi)) * dx - f * phi * dx bc = DirichletBC(V, Constant(0), "on_boundary") solve(F == 0, u, bc) J = Functional(inner(u, u) * dx) m = Control(f) rf = ReducedFunctional(J, m) obj = rf.moola_problem().obj pf = moola.DolfinPrimalVector(f) return obj, pf
def assign(self, u=None, annotate=True): """ Assign the model observation and compute the functional Arguments --------- u : :py:class:`dolfin.Function` The input to the model observation, e.g the displacement Returns ------- functional : :py:class:`dolfin_adjoint.Function` A scalar representing the mismatch between model and data defined in the :meth:`OptimizationTarget.form` method. """ # Assign model observation for dolfin-adjoint recording model = self.model(u) self.model_function.assign(model, annotate=annotate) # Assign data observation for dolfin-adjoint recording data = self.dolfin_observations[self.count] self.data_function.assign(data, annotate=annotate) form = self.form() dolfin_adjoint.solve( self._trial * self._test * dolfin.dx == self._test * form * dolfin.dx, self._functional, ) if self.collect: self.collector["model"].append( dolfin.Vector(self.model_function.vector())) self.collector["data"].append( dolfin.Vector(self.data_function.vector())) self.collector["functional"].append( numpy_mpi.gather_broadcast( self._functional.vector().get_local())[0]) return self.weight * self._functional
g = da.interpolate( da.Expression("1/(1+alpha*4*pow(pi, 4))*w", w=w, alpha=alpha, degree=3), W) f = da.interpolate( da.Expression("1/(1+alpha*4*pow(pi, 4))*w", w=w, alpha=alpha, 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)
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)