Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
 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
Пример #4
0
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
Пример #5
0
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
Пример #6
0
    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
Пример #7
0
    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)
Пример #8
0
    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)