def __init__(self, optimization_algorithm):
        """Initializes the line search

		Parameters
		----------
		optimization_algorithm : cashocs._shape_optimization.shape_optimization_algorithm.ShapeOptimizationAlgorithm
			the optimization problem of interest
		"""

        self.optimization_algorithm = optimization_algorithm
        self.config = self.optimization_algorithm.config
        self.optimization_problem = self.optimization_algorithm.optimization_problem
        self.form_handler = self.optimization_problem.form_handler
        self.mesh_handler = self.optimization_problem.mesh_handler
        self.deformation = fenics.Function(self.form_handler.deformation_space)

        self.stepsize = self.config.getfloat('OptimizationRoutine',
                                             'initial_stepsize',
                                             fallback=1.0)
        self.epsilon_armijo = self.config.getfloat('OptimizationRoutine',
                                                   'epsilon_armijo',
                                                   fallback=1e-4)
        self.beta_armijo = self.config.getfloat('OptimizationRoutine',
                                                'beta_armijo',
                                                fallback=2.0)
        self.armijo_stepsize_initial = self.stepsize

        self.cost_functional = self.optimization_problem.reduced_cost_functional

        self.gradient = self.optimization_algorithm.gradient

        self.algorithm = _optimization_algorithm_configuration(self.config)
        self.is_newton_like = (self.algorithm == 'lbfgs')
        self.is_newton = self.algorithm in ['newton']
        self.is_steepest_descent = (self.algorithm == 'gradient_descent')
        if self.is_newton:
            self.stepsize = 1.0
Пример #2
0
 def solve_pde(self, name='pde'):
     u = fe.Function(self.function_space)
     v = fe.TestFunction(self.function_space)
     u_old = fe.project(self.u_0, self.function_space)
     # Todo: Average right hand side if we choose it non-constant
     flux = self.dt * fe.dot(
         self.composed_diff_coef *
         (fe.grad(u) + self.drift_function(u)), fe.grad(v)) * fe.dx
     bilin_part = u * v * fe.dx + flux
     funtional_part = self.rhs * v * self.dt * fe.dx + u_old * v * fe.dx
     full_form = bilin_part - funtional_part
     num_steps = int(self.T / self.dt) + 1
     bc = fe.DirichletBC(self.function_space, self.u_boundary,
                         MembraneSimulator.full_boundary)
     for n in range(num_steps):
         print("Step %d" % n)
         self.time += self.dt
         fe.solve(full_form == 0, u, bc)
         fe.plot(u)
         plt.savefig('images/plt%d.pdf' % n)
         plt.show()
         # print(fe.errornorm(u_old, u))
         u_old.assign(u)
         self.file << (u, self.time)
     plt.figure()
     # u=u+1E-9
     f = fe.plot(u)
     # f = fe.plot(u,norm=colors.LogNorm(vmin=1E-9,vmax=2E-4))
     plt.rc('text', usetex=True)
     plt.colorbar(f, format='%.0e')
     plt.title(r'Macroscopic density $u(x,t=1)$ for $\alpha=%.1f$' %
               MembraneSimulator.alpha)
     plt.xlabel(r'$x_1$')
     plt.ylabel(r'$x_2$')
     plt.savefig('%s.pdf' % name)
     plt.show()
Пример #3
0
    def __call__(self, u_test, return_sol=False, return_permeability=False):

        # Pad with zeros
        u_test = np.pad(u_test, (0, len(self.indices) - len(u_test)))

        # Assembling diffusivity
        log_coeff = sum([ui * fi for ui, fi in zip(u_test, self.functions)], 0)
        if return_permeability:
            return log_coeff

        ccode_coeff = sym.ccode(sym.exp(log_coeff))
        diff = fen.Expression(ccode_coeff, degree=2)

        # Define bilinear form in variational problem
        a_bil = diff * fen.dot(fen.grad(self.trial_f), fen.grad(
            self.test_f)) * fen.dx

        # Compute solution
        sol = fen.Function(self.f_space)
        fen.solve(a_bil == self.lin_func, sol, self.bound_cond)

        evaluations = [sol(xi, yi) for xi, yi in zip(self.x_obs, self.y_obs)]
        # print("Evaluating G...:", np.array(evaluations))
        return sol if return_sol else np.array(evaluations)
Пример #4
0
    def __call__(self, mesh, V=None, Vc=None):

        boundaries, boundarymarkers, domainmarkers, dx, ds, V, Vc = SetupUnitMeshHelper(
            mesh, V, Vc)
        self._ds_markers = boundarymarkers
        self._dx_markers = domainmarkers
        self._dx = dx
        self._ds = ds
        self._boundaries = boundaries
        self._subdomains = self._boundaries

        u = df.TrialFunction(V)
        v = df.TestFunction(V)
        alpha = df.Function(Vc, name='conductivity')
        alpha.vector()[:] = 1

        def set_alpha(x):
            alpha.vector()[:] = x

        self._set_alpha = set_alpha

        a = alpha * df.inner(df.grad(u), df.grad(v)) * dx

        return a, set_alpha, alpha, V, Vc
Пример #5
0
    def __init__(self,
                 mesh: fe.Mesh,
                 density: fe.Expression,
                 constitutive_model: ConstitutiveModelBase,
                 bf: fe.Expression = fe.Expression('0', degree=0)):

        super().__init__(mesh, density, constitutive_model, bf)

        W = fe.VectorFunctionSpace(mesh, "P", 1)

        # Unknowns, values at previous step and test functions
        self.w = fe.Function(W)
        self.u, self.u0 = self.w, fe.Function(W)
        self.v, self.v0 = fe.Function(W), fe.Function(W)
        self.a, self.a0 = fe.Function(W), fe.Function(W)

        # self.a0 = fe.Function(fe.FunctionSpace(mesh, element_v))

        self.ut = fe.TestFunction(W)

        self.F = kin.def_grad(self.u)
        self.F0 = kin.def_grad(self.u0)
Пример #6
0
    def __init__(self,
                 mesh: fe.Mesh,
                 constitutive_model: ConstitutiveModelBase,
                 density: fe.Expression = fe.Expression('0', degree=0),
                 bf: fe.Expression = fe.Expression('0', degree=0),
                 user_output_fn: callable = None):

        W = fe.VectorFunctionSpace(mesh, "P", 1)
        super().__init__(mesh, constitutive_model, W, bf)
        self._density = density

        self.user_output_fn = user_output_fn

        # Unknowns, values at previous step and test functions
        self.w = fe.Function(W)
        self.u, self.u0 = self.w, fe.Function(W)
        self.v, self.v0 = fe.Function(W), fe.Function(W)
        self.a, self.a0 = fe.Function(W), fe.Function(W)

        # self.a0 = fe.Function(fe.FunctionSpace(mesh, element_v))

        self.ut = fe.TestFunction(W)

        self.F = kin.def_grad(self.u)
        self.F0 = kin.def_grad(self.u0)

        self.output_fn_map = {
            Outputs.stress: self.write_stress,
            Outputs.strain: self.write_strain,
            Outputs.displacement: self.write_u
        }

        self.d_LHS = fe.inner(self.F * constitutive_model.stress(self.u),
                              fe.grad(self.ut)) * fe.dx

        self.d_RHS = (fe.inner(fe.Constant((0., 0., 0.)), self.ut) * fe.dx)
Пример #7
0
    def runModelButt(self):
        if len(markers) > 0:
            try:
                self.runButt.setEnabled(False)
                self.dr = float(self.sptlResLineEdit.text())  # dr = 150
                self.pauseButt.setEnabled(True)
                interpolateData(True, self.dr,{})

                ###########################################
                ###  INTERPOLATE DATA SO EVEN INTERVAL  ###
                ###########################################
                '''
                Interpolating data at an even interval so the data points align with the 
                invterval mesh.
                '''
                self.thickness1dInterp = interp1d(thickness.distanceData, thickness.pathData)
                self.bed1dInterp       = interp1d(bed.distanceData, bed.pathData)
                self.surface1dInterp   = interp1d(surface.distanceData, surface.pathData)
                self.smb1dInterp       = interp1d(smb.distanceData, smb.pathData)
                self.velocity1dInterp  = interp1d(velocity.distanceData, velocity.pathData)
                self.t2m1dInterp = interp1d(t2m.distanceData, t2m.pathData)

                # N is the number of total data points including the last
                # Data points on interval [0, N*dr] inclusive on both ends

                self.N = int(np.floor(bed.distanceData[-1] / float(self.dr)))  # length of path / resolution

                self.x = np.arange(0, (self.N + 1) * self.dr, self.dr)  # start point, end point, number of segments. END POINT NOT INCLUDED!
                self.mesh = fc.IntervalMesh(self.N, 0, self.dr * self.N)  # number of cells, start point, end point

                self.thicknessModelData = self.thickness1dInterp(self.x)
                self.bedModelData       = self.bed1dInterp(self.x)
                self.surfaceModelData   = self.surface1dInterp(self.x)
                self.smbModelData       = self.smb1dInterp(self.x)
                self.velocityModelData  = self.velocity1dInterp(self.x)
                self.t2mModelData       = self.t2m1dInterp(self.x)

                self.THICKLIMIT = 10.  # Ice is never less than this thick
                self.H = self.surfaceModelData - self.bedModelData
                self.surfaceModelData[self.H <= self.THICKLIMIT] = self.bedModelData[self.H <= self.THICKLIMIT]

                # FIXME the intervalMesh is consistantly 150 between each datapoint this not true for the data being sent
                self.hdf_name = '.data/latest_profile.h5'
                self.hfile = fc.HDF5File(self.mesh.mpi_comm(), self.hdf_name, "w")
                self.V = fc.FunctionSpace(self.mesh, "CG", 1)

                self.functThickness = fc.Function(self.V, name="Thickness")
                self.functBed       = fc.Function(self.V, name="Bed")
                self.functSurface   = fc.Function(self.V, name="Surface")
                self.functSMB       = fc.Function(self.V, name='SMB')
                self.functVelocity  = fc.Function(self.V, name='Velocity')
                self.functT2m       = fc.Function(self.V, name='T2m')

                surface.pathPlotItem.setData(self.x, self.surfaceModelData)
                pg.QtGui.QApplication.processEvents()

                self.functThickness.vector()[:] = self.thicknessModelData
                self.functBed.vector()[:]       = self.bedModelData
                self.functSurface.vector()[:]   = self.surfaceModelData
                self.functSMB.vector()[:]       = self.smbModelData
                self.functVelocity.vector()[:]  = self.velocityModelData
                self.functT2m.vector()[:]       = self.t2mModelData

                self.hfile.write(self.functThickness.vector(), "/thickness")
                self.hfile.write(self.functBed.vector(), "/bed")
                self.hfile.write(self.functSurface.vector(), "/surface")
                self.hfile.write(self.functSMB.vector(), "/smb")
                self.hfile.write(self.functVelocity.vector(), "/velocity")
                self.hfile.write(self.functT2m.vector(), "/t2m")
                self.hfile.write(self.mesh, "/mesh")
                self.hfile.close()
                self.runModel()

            except ValueError:
                print 'ERROR: Must have valid spatial resolution.'
Пример #8
0
def boundary(x, on_boundary):
    return on_boundary


bc = fex.DirichletBC(V, u_D, boundary)

# Define variational problem
u = fex.TrialFunction(V)
v = fex.TestFunction(V)
f = fex.Constant(-6.0)
a = fex.dot(fex.grad(u), fex.grad(v)) * fex.dx
L = f * v * fex.dx

# Compute solution
u = fex.Function(V)
fex.solve(a == L, u, bc)
print(u)
# Plot solution and mesh
plt.subplot(2, 1, 1)
fex.plot(u)
#define the boundary conditions
plt.subplot(2, 1, 2)
fex.plot(mesh)
plt.savefig('possion_fex2.png')
#define the boundary conditions
# Save solution to file in VTK format
vtkfile = fex.File('poisson/solution.pvd')
vtkfile << u

# Compute error in L2 norm
Пример #9
0
    def staggered_solve(self):
        self.U = fe.VectorFunctionSpace(self.mesh, 'CG', 1)
        self.W = fe.FunctionSpace(self.mesh, 'CG', 1)

        self.WW = fe.FunctionSpace(self.mesh, 'DG', 0)
        self.EE = fe.TensorFunctionSpace(self.mesh, 'DG', 0)
        self.MM = fe.VectorFunctionSpace(self.mesh, 'CG', 1)

        self.eta = fe.TestFunction(self.U)
        self.zeta = fe.TestFunction(self.W)
        q = fe.TestFunction(self.WW)

        del_x = fe.TrialFunction(self.U)
        del_d = fe.TrialFunction(self.W)
        p = fe.TrialFunction(self.WW)

        self.x_new = fe.Function(self.U, name="u")
        self.d_new = fe.Function(self.W, name="d")
        self.d_pre = fe.Function(self.W)
        self.x_pre = fe.Function(self.U)

        x_old = fe.Function(self.U)
        d_old = fe.Function(self.W)

        self.H_old = fe.Function(self.WW)

        self.map_plot = fe.Function(self.MM, name="m")
        e = fe.Function(self.EE, name="e")

        self.create_custom_xdmf_files()

        self.file_results = fe.XDMFFile('data/xdmf/{}/u.xdmf'.format(
            self.case_name))
        self.file_results.parameters["functions_share_mesh"] = True

        vtkfile_e = fe.File('data/pvd/simulation/{}/e.pvd'.format(
            self.case_name))
        vtkfile_u = fe.File('data/pvd/simulation/{}/u.pvd'.format(
            self.case_name))
        vtkfile_d = fe.File('data/pvd/simulation/{}/d.pvd'.format(
            self.case_name))

        for i, (disp, rp) in enumerate(
                zip(self.displacements, self.relaxation_parameters)):
            print('\n')
            print(
                '================================================================================='
            )
            print('>> Step {}, disp boundary condition = {} [mm]'.format(
                i, disp))
            print(
                '================================================================================='
            )
            self.i = i
            self.update_weak_form_due_to_Model_C_bug()

            if self.update_weak_form:
                self.set_bcs_staggered()
                print("Update weak form...")
                self.build_weak_form_staggered()

                print("Taking derivatives of weak form...")
                J_u = fe.derivative(self.G_u, self.x_new, del_x)
                J_d = fe.derivative(self.G_d, self.d_new, del_d)
                print("Define nonlinear problems...")
                p_u = fe.NonlinearVariationalProblem(self.G_u, self.x_new,
                                                     self.BC_u, J_u)
                p_d = fe.NonlinearVariationalProblem(self.G_d, self.d_new,
                                                     self.BC_d, J_d)
                print("Define solvers...")
                solver_u = fe.NonlinearVariationalSolver(p_u)
                solver_d = fe.NonlinearVariationalSolver(p_d)
                self.update_weak_form = False

                print("Update history weak form")
                a = p * q * fe.dx
                L = history(self.H_old, self.update_history(),
                            self.psi_cr) * q * fe.dx

                if self.map_flag:
                    self.interpolate_map()
                    # delta_x = self.x - self.x_hat
                    # self.map_plot.assign(fe.project(delta_x, self.MM))

            self.presLoad.t = disp

            newton_prm = solver_u.parameters['newton_solver']
            newton_prm['maximum_iterations'] = 100
            # newton_prm['absolute_tolerance'] = 1e-8
            newton_prm['relaxation_parameter'] = rp

            newton_prm = solver_d.parameters['newton_solver']
            newton_prm['maximum_iterations'] = 100
            # newton_prm['absolute_tolerance'] = 1e-8
            newton_prm['relaxation_parameter'] = rp

            vtkfile_e_staggered = fe.File(
                'data/pvd/simulation/{}/step{}/e.pvd'.format(
                    self.case_name, i))
            vtkfile_u_staggered = fe.File(
                'data/pvd/simulation/{}/step{}/u.pvd'.format(
                    self.case_name, i))
            vtkfile_d_staggered = fe.File(
                'data/pvd/simulation/{}/step{}/d.pvd'.format(
                    self.case_name, i))
            iteration = 0
            err = 1.
            while err > self.staggered_tol:
                iteration += 1

                solver_d.solve()

                solver_u.solve()

                if self.solution_scheme == 'explicit':
                    break

                # # Remarks(Tianju): self.x_new.vector() does not behave as expected: producing nan values
                # The following lines of codes cause issues
                # We use an error measure similar in https://doi.org/10.1007/s10704-019-00372-y
                # np_x_new = np.asarray(self.x_new.vector())
                # np_d_new = np.asarray(self.d_new.vector())
                # np_x_old = np.asarray(x_old.vector())
                # np_d_old = np.asarray(d_old.vector())
                # err_x = np.linalg.norm(np_x_new - np_x_old) / np.sqrt(len(np_x_new))
                # err_d = np.linalg.norm(np_d_new - np_d_old) / np.sqrt(len(np_d_new))
                # err = max(err_x, err_d)

                # # Remarks(Tianju): dolfin (2019.1.0) errornorm function has severe bugs not behave as expected
                # The bug seems to be fixed in later versions
                # The following sometimes produces nonzero results in dolfin (2019.1.0)
                # print(fe.errornorm(self.d_new, self.d_new, norm_type='l2'))

                err_x = fe.errornorm(self.x_new, x_old, norm_type='l2')
                err_d = fe.errornorm(self.d_new, d_old, norm_type='l2')
                err = max(err_x, err_d)

                x_old.assign(self.x_new)
                d_old.assign(self.d_new)
                e.assign(
                    fe.project(strain(self.mfem_grad(self.x_new)), self.EE))

                print(
                    '---------------------------------------------------------------------------------'
                )
                print(
                    '>> iteration. {}, err_u = {:.5}, err_d = {:.5}, error = {:.5}'
                    .format(iteration, err_x, err_d, err))
                print(
                    '---------------------------------------------------------------------------------'
                )

                # vtkfile_e_staggered << e
                # vtkfile_u_staggered << self.x_new
                # vtkfile_d_staggered << self.d_new

                if err < self.staggered_tol or iteration >= self.staggered_maxiter:
                    print(
                        '================================================================================='
                    )
                    print('\n')
                    break

            print("L2 projection to update the history function...")
            fe.solve(a == L, self.H_old, [])

            # self.d_pre.assign(self.d_new)
            # self.H_old.assign(fe.project(history(self.H_old, self.update_history(), self.psi_cr), self.WW))

            if self.map_flag and not self.finish_flag:
                self.update_map()

            if self.compute_and_save_intermediate_results:
                print("Save files...")
                self.file_results.write(e, i)
                self.file_results.write(self.x_new, i)
                self.file_results.write(self.d_new, i)
                self.file_results.write(self.map_plot, i)

                vtkfile_e << e
                vtkfile_u << self.x_new
                vtkfile_d << self.d_new

                # Assume boundary is not affected by the map.
                # There's no need to use the mfem_grad wrapper so that fe.grad is used for speed-up
                print("Define forces...")
                sigma = cauchy_stress_plus(strain(fe.grad(self.x_new)),
                                           self.psi)
                sigma_minus = cauchy_stress_minus(strain(fe.grad(self.x_new)),
                                                  self.psi_minus)
                sigma_plus = cauchy_stress_plus(strain(fe.grad(self.x_new)),
                                                self.psi_plus)
                sigma_degraded = g_d(self.d_new) * sigma_plus + sigma_minus

                print("Compute forces...")
                if self.case_name == 'pure_shear':
                    f_full = float(fe.assemble(sigma[0, 1] * self.ds(1)))
                    f_degraded = float(
                        fe.assemble(sigma_degraded[0, 1] * self.ds(1)))
                else:
                    f_full = float(fe.assemble(sigma[1, 1] * self.ds(1)))
                    f_degraded = float(
                        fe.assemble(sigma_degraded[1, 1] * self.ds(1)))

                print("Force full is {}".format(f_full))
                print("Force degraded is {}".format(f_degraded))
                self.delta_u_recorded.append(disp)
                self.force_full.append(f_full)
                self.force_degraded.append(f_degraded)

                # if force_upper < 0.5 and i > 10:
                #     break

                if self.display_intermediate_results and i % 10 == 0:
                    self.show_force_displacement()

                self.save_data_in_loop()

        if self.display_intermediate_results:
            plt.ioff()
            plt.show()
Пример #10
0
    def demo64(self, permeability, obs_case=1):
        mesh = UnitSquareMesh(63, 63)
        ak_values = permeability
        flux_order = 3
        s = scenarios.darcy_problem_1()
        DRT = fenics.FiniteElement("DRT", mesh.ufl_cell(), flux_order)
        # Lagrange
        CG = fenics.FiniteElement("CG", mesh.ufl_cell(), flux_order + 1)
        if s.integral_constraint:
            # From https://fenicsproject.org/qa/14184/how-to-solve-linear-system-with-constaint
            R = fenics.FiniteElement("R", mesh.ufl_cell(), 0)
            W = fenics.FunctionSpace(mesh, fenics.MixedElement([DRT, CG, R]))
            # Define trial and test functions
            (sigma, u, r) = fenics.TrialFunctions(W)
            (tau, v, r_) = fenics.TestFunctions(W)
        else:
            W = fenics.FunctionSpace(mesh, DRT * CG)
            # Define trial and test functions
            (sigma, u) = fenics.TrialFunctions(W)
            (tau, v) = fenics.TestFunctions(W)
        f = s.source_function
        g = s.g

        # Define property field function
        W_CG = fenics.FunctionSpace(mesh, "Lagrange", 1)
        if s.ak is None:
            ak = property_field.get_conductivity(W_CG, ak_values)
        else:
            ak = s.ak

        # Define variational form
        a = (fenics.dot(sigma, tau) + fenics.dot(ak * fenics.grad(u), tau) +
             fenics.dot(sigma, fenics.grad(v))) * fenics.dx
        L = -f * v * fenics.dx + g * v * fenics.ds
        # L = 0
        if s.integral_constraint:
            # Lagrange multiplier?  See above link.
            a += r_ * u * fenics.dx + v * r * fenics.dx
        # Define Dirichlet BC
        bc = fenics.DirichletBC(W.sub(1), s.dirichlet_bc, s.gamma_dirichlet)
        # Compute solution

        w = fenics.Function(W)
        fenics.solve(a == L, w, bc)
        # fenics.solve(a == L, w)
        if s.integral_constraint:
            (sigma, u, r) = w.split()
        else:
            (sigma, u) = w.split()
        x = u.compute_vertex_values(mesh)
        x2 = sigma.compute_vertex_values(mesh)
        p = x
        pre = p.reshape((64, 64))
        vx = x2[:4096].reshape((64, 64))
        vy = x2[4096:].reshape((64, 64))

        if obs_case == 1:
            dd = np.zeros([8, 8])
            pos = np.full((8 * 8, 2), 0)
            col = [4, 12, 20, 28, 36, 44, 52, 60]
            position = [4, 12, 20, 28, 36, 44, 52, 60]
            for i in range(8):
                for j in range(8):
                    row = position
                    pos[8 * i + j, :] = [col[i], row[j]]
                    dd[i, j] = pre[col[i], row[j]]
            like = dd.reshape(8 * 8, )
        return like, pre, vx, vy, ak_values, pos
Пример #11
0
b = fe.Expression(('0', '0'), degree=DEG)  # forcing
nu = fe.Constant(2e-6)
rho = fe.Constant(1)
RE = 0.01
lmx = 1  # mixing length
dt = 0.1
# Re = 10 / 1e-4 = 1e5

V = fe.VectorElement("Lagrange", mesh.ufl_cell(), 2)
P = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
NU = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
if MODEL: M = fe.MixedElement([V, P, NU])
else: M = fe.MixedElement([V, P])
W = fe.FunctionSpace(mesh, M)

W0 = fe.Function(W)
We = fe.Function(W)
u0, p0 = fe.split(We)
#u0 = fe.Function((W0[0], W0[1]), 'Velocity000023.vtu')
#p0 = fe.Function(W0[2])
v, q = fe.TestFunctions(W)
#u, p = fe.split(W0)
u, p = (fe.as_vector((W0[0], W0[1])), W0[2])

#-------------------------------------------------------
# Defining essential/Dirichlet boundary conditions
# Step 1: Identify all boundary segments forming Gamma_d
#-------------------------------------------------------
#   (-3., 2.5)
#  |
#  |
    hessp=SR1(),
    tol=1e-7,
    constraints=volume_constraint,
    bounds=((0, 1.0),) * A.dim(),
    options={"verbose": 3, "gtol": 1e-7, "maxiter": 20},
)

q.assign(0.1)
res = minimize(
    min_f,
    res.x,
    method="trust-constr",
    jac=True,
    hessp=SR1(),
    tol=1e-7,
    constraints=volume_constraint,
    bounds=((0, 1.0),) * A.dim(),
    options={"verbose": 3, "gtol": 1e-7, "maxiter": 100},
)

rho_opt_final = from_numpy(res.x, fenics.Function(A))

c = fenics.plot(rho_opt_final)
plt.colorbar(c)
plt.show()

rho_opt_file = fenics.XDMFFile(
    fenics.MPI.comm_world, "output/control_solution_final.xdmf"
)
rho_opt_file.write(rho_opt_final)
Пример #13
0
    def __init__(self, lagrangian, bcs_list, states, controls, adjoints,
                 config, riesz_scalar_products, control_constraints,
                 ksp_options, adjoint_ksp_options,
                 require_control_constraints):
        """Initializes the ControlFormHandler class.

		Parameters
		----------
		lagrangian : cashocs._forms.Lagrangian
			The lagrangian corresponding to the optimization problem.
		bcs_list : list[list[dolfin.fem.dirichletbc.DirichletBC]]
			The list of DirichletBCs for the state equation.
		states : list[dolfin.function.function.Function]
			The function that acts as the state variable.
		controls : list[dolfin.function.function.Function]
			The function that acts as the control variable.
		adjoints : list[dolfin.function.function.Function]
			The function that acts as the adjoint variable.
		config : configparser.ConfigParser
			The configparser object of the config file.
		riesz_scalar_products : list[ufl.form.Form]
			The UFL forms of the scalar products for the control variables.
		control_constraints : list[list[dolfin.function.function.Function]]
			The control constraints of the problem.
		ksp_options : list[list[list[str]]]
			The list of command line options for the KSP for the
			state systems.
		adjoint_ksp_options : list[list[list[str]]]
			The list of command line options for the KSP for the
			adjoint systems.
		require_control_constraints : list[bool]
			A list of boolean flags that indicates, whether the i-th control
			has actual control constraints present.
		"""

        FormHandler.__init__(self, lagrangian, bcs_list, states, adjoints,
                             config, ksp_options, adjoint_ksp_options)

        # Initialize the attributes from the arguments
        self.controls = controls
        self.riesz_scalar_products = riesz_scalar_products
        self.control_constraints = control_constraints
        self.require_control_constraints = require_control_constraints

        self.control_dim = len(self.controls)
        self.control_spaces = [x.function_space() for x in self.controls]

        # Define the necessary functions
        self.states_prime = [fenics.Function(V) for V in self.state_spaces]
        self.adjoints_prime = [fenics.Function(V) for V in self.adjoint_spaces]

        self.test_directions = [
            fenics.Function(V) for V in self.control_spaces
        ]

        self.trial_functions_control = [
            fenics.TrialFunction(V) for V in self.control_spaces
        ]
        self.test_functions_control = [
            fenics.TestFunction(V) for V in self.control_spaces
        ]

        self.temp = [fenics.Function(V) for V in self.control_spaces]

        # Compute the necessary equations
        self.__compute_gradient_equations()

        if self.opt_algo == 'newton' or \
          (self.opt_algo == 'pdas' and self.inner_pdas == 'newton'):
            self.__compute_newton_forms()

        # Initialize the scalar products
        fenics_scalar_product_matrices = [
            fenics.assemble(self.riesz_scalar_products[i], keep_diagonal=True)
            for i in range(self.control_dim)
        ]
        self.scalar_products_matrices = [
            fenics.as_backend_type(fenics_scalar_product_matrices[i]).mat()
            for i in range(self.control_dim)
        ]

        copy_scalar_product_matrices = [
            fenics_scalar_product_matrices[i].copy()
            for i in range(self.control_dim)
        ]
        [
            copy_scalar_product_matrices[i].ident_zeros()
            for i in range(self.control_dim)
        ]
        self.riesz_projection_matrices = [
            fenics.as_backend_type(copy_scalar_product_matrices[i]).mat()
            for i in range(self.control_dim)
        ]

        # Test for symmetry of the scalar products
        for i in range(self.control_dim):
            if not self.riesz_projection_matrices[i].isSymmetric():
                if not self.riesz_projection_matrices[i].isSymmetric(1e-15):
                    if not (self.riesz_projection_matrices[i] -
                            self.riesz_projection_matrices[i].copy().transpose(
                            )).norm() / self.riesz_projection_matrices[i].norm(
                            ) < 1e-15:
                        raise InputError(
                            'cashocs._forms.ControlFormHandler',
                            'riesz_scalar_products',
                            'Supplied scalar product form is not symmetric.')
Пример #14
0
def navierStokes(projectId, mesh, faceSets, boundarySets, config):

    log("Navier Stokes Analysis has started")

    # this is the default directory, when user request for download all files in this directory is being compressed and sent to the user
    resultDir = "./Results/"

    if len(config["steps"]) > 1:
        return "more than 1 step is not supported yet"

    # config is a dictionary containing all the user inputs for solver configurations
    t_init = 0.0
    t_final = float(config['steps'][0]["finalTime"])
    t_num = int(config['steps'][0]["iterationNo"])
    dt = ((t_final - t_init) / t_num)
    t = t_init

    #
    #  Viscosity coefficient.
    #
    nu = float(config['materials'][0]["viscosity"])
    rho = float(config['materials'][0]["density"])

    #
    #  Declare Finite Element Spaces
    # do not use triangle directly
    P2 = fn.VectorElement("P", mesh.ufl_cell(), 2)
    P1 = fn.FiniteElement("P", mesh.ufl_cell(), 1)
    TH = fn.MixedElement([P2, P1])
    V = fn.VectorFunctionSpace(mesh, "P", 2)
    Q = fn.FunctionSpace(mesh, "P", 1)
    W = fn.FunctionSpace(mesh, TH)

    #
    #  Declare Finite Element Functions
    #
    (u, p) = fn.TrialFunctions(W)
    (v, q) = fn.TestFunctions(W)
    w = fn.Function(W)
    u0 = fn.Function(V)
    p0 = fn.Function(Q)

    #
    # Macros needed for weak formulation.
    #
    def contract(u, v):
        return fn.inner(fn.nabla_grad(u), fn.nabla_grad(v))

    def b(u, v, w):
        return 0.5 * (fn.inner(fn.dot(u, fn.nabla_grad(v)), w) -
                      fn.inner(fn.dot(u, fn.nabla_grad(w)), v))

    # Define boundaries
    bcs = []
    for BC in config['BCs']:
        if BC["boundaryType"] == "wall":
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(0),
                                   fn.Constant((0.0, 0.0, 0.0)),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))
        if BC["boundaryType"] == "inlet":
            vel = json.loads(BC['value'])
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(0),
                                   fn.Expression(
                                       (str(vel[0]), str(vel[1]), str(vel[2])),
                                       degree=2),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))
        if BC["boundaryType"] == "outlet":
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(1),
                                   fn.Constant(float(BC['value'])),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))

    f = fn.Constant((0.0, 0.0, 0.0))

    #  weak form NSE
    NSE = (1.0/dt)*fn.inner(u, v)*fn.dx + b(u0, u, v)*fn.dx + nu * \
        contract(u, v)*fn.dx - fn.div(v)*p*fn.dx + q*fn.div(u)*fn.dx
    LNSE = fn.inner(f, v) * fn.dx + (1. / dt) * fn.inner(u0, v) * fn.dx

    velocity_file = fn.XDMFFile(resultDir + "/vel.xdmf")
    pressure_file = fn.XDMFFile(resultDir + "/pressure.xdmf")
    velocity_file.parameters["flush_output"] = True
    velocity_file.parameters["functions_share_mesh"] = True
    pressure_file.parameters["flush_output"] = True
    pressure_file.parameters["functions_share_mesh"] = True
    #
    # code for projecting a boundary condition into a file for visualization
    #
    # for bc in bcs:
    #     bc.apply(w.vector())
    # fn.File("para_plotting/bc.pvd") << w.sub(0)

    for jj in range(0, t_num):
        t = t + dt
        # print('t = ' + str(t))
        A, b = fn.assemble_system(NSE, LNSE, bcs)
        fn.solve(A, w.vector(), b)
        # fn.solve(NSE==LNSE,w,bcs)
        fn.assign(u0, w.sub(0))
        fn.assign(p0, w.sub(1))
        # Save Solutions to Paraview File
        if (jj % 20 == 0):
            velocity_file.write(u0, t)
            pressure_file.write(p0, t)
            sendFile(projectId, resultDir + "vel.xdmf")
            sendFile(projectId, resultDir + "vel.h5")
            sendFile(projectId, resultDir + "pressure.xdmf")
            sendFile(projectId, resultDir + "pressure.h5")
            statusUpdate(projectId, "STARTED", {"progress": jj / t_num * 100})
Пример #15
0
def forward(lmin, pml, steps, Folder):
    """
    Algorithm to solve the forward problem

    *Input arguments
        minl: Minimum lenght of element
        pml: Size of the absorbing layer in km
        steps: Number of timesteps
        Folder: Folder name for results
    *Output arguments
        c: Field of propagation speed in domain
        eta: Field of damping in domain
        histrec: Historical data receivers
    """
    histrec = ''
    # Create and define function space
    V = fn.FunctionSpace(mesh, "CG", 1)
    w = fn.TrialFunction(V)
    v = fn.TestFunction(V)

    # Boundary conditions u0 = 0.0
    bc = fn.DirichletBC(V, 0.0, fn.DomainBoundary())

	# State variable and source space functions
    w = fn.Function(V, name="Veloc")
    w_ant1 = fn.Function(V)
    w_ant2 = fn.Function(V)
    q = fn.Function(V, name="Sourc")

    # Velocity mapping
    c_func = vel_c()
    c = fn.interpolate(c_func, V)
    velp_file = fn.File(Folder + "/Velp.pvd")
    velp_file << c

	# Damping mapping
    damping_func = damping(c.vector().get_local().min())
    eta = fn.interpolate(damping_func, V)
    damp_file = fn.File(Folder + "/Damp.pvd")
    damp_file << eta

    # Current time we are solving for
    t = 0.
    # Number of timesteps solved
    ntimestep = int(0)
	# dt computation
    dt = critical_dt(lmin, c.vector().get_local().max(), steps)
	# Final time
    T = steps*dt
    print("Time step:", dt, "s")

    # "Bilinear term"
    def aterm(u, v, dt, c, eta):
        termgrad = dt**2*fn.inner(c, c)*fn.inner(fn.grad(u), fn.grad(v))*fn.dx
        termvare = (1.0 + dt*eta*fn.inner(c, c))*fn.inner(u, v)*fn.dx
        termboun = (dt**2*c*c)*fn.inner(fn.grad(u), n)*v*fn.ds
        return  termgrad + termvare - termboun

    # Source term
    def lsourc(u_ant1, u_ant2, v, dt, c, q, eta):
        termua1 = (-2. + dt*eta*fn.inner(c, c))*fn.inner(u_ant1, v)*fn.dx
        termua2 = fn.inner(u_ant2, v)*fn.dx
        termsou = (dt**2*fn.inner(c, c))*fn.inner(q, v)*fn.dx
        return  termua1 + termua2 - termsou

	# Output file names
    Exct = fn.File(Folder+"/Exct.pvd")
    Wave = fn.File(Folder+"/Wave.pvd")

    while True:
        # Update the time it is solving for
        print("Step: {0:1d} - Time: {1:1.4f}".format(ntimestep, t), "s")

        # Ricker source for time t
        ExcSource = RickerSource(t, tol=lmin/2)
        q.assign(fn.interpolate(ExcSource, V))

        # Time integration loop
        if ntimestep < 1:
            g = fn.interpolate(fn.Expression('0.0', degree=2), V)
            w.assign(g) # assign initial guess for solver
            w_ant1.assign(g) # assign initial guess for solver
            w_ant2.assign(g) # assign initial guess for solver
        else:
            a = aterm(w, v, dt, c, eta)
            L = lsourc(w_ant1, w_ant2, v, dt, c, q, eta)
            #solve equation
            fn.solve(a + L == 0, w, bcs=bc, solver_parameters={"newton_solver":
                {"maximum_iterations": forward_max_it, "absolute_tolerance": forward_tol,
                 "relative_tolerance": relativ_tol}})

        # Cycling the variables
        w_ant2.assign(w_ant1)
        w_ant1.assign(w)

        #Output files
        # histrec += Receiver(t, posrec, pml, w)
        Exct << (q, t)
        Wave << (w, t)

        t += dt
        ntimestep += 1
        
        if t >= T:
            break
    
    return c, eta, histrec
Пример #16
0
bcU = fn.DirichletBC(Hh.sub(0), u_g, bdry, 31)
bcP = fn.DirichletBC(Hh.sub(2), p_g, bdry, 32)
bcs = [bcU, bcP]

# ********  Weak forms ********** #

PLeft =  2*mu*fn.inner(strain(u),strain(v)) * fn.dx \
         - fn.div(v) * phi * fn.dx \
         + (c0/alpha + 1.0/lmbda)* p * q * fn.dx \
         + kappa/(alpha*nu) * fn.dot(fn.grad(p),fn.grad(q)) * fn.dx \
         - 1.0/lmbda * phi * q * fn.dx \
         - fn.div(u) * psi * fn.dx \
         + 1.0/lmbda * psi * p * fn.dx \
         - 1.0/lmbda * phi * psi * fn.dx

PRight = fn.dot(f, v) * fn.dx + fn.dot(h_g, v) * ds(32)

Sol = fn.Function(Hh)

# solve
fn.solve(PLeft == PRight, Sol, bcs)

u, phi, p = Sol.split()
u.rename("u", "u")
fileU << u
p.rename("p", "p")
fileP << p
phi.rename("phi", "phi")
filePHI << phi
Пример #17
0
	def __init__(self, state_forms, bcs_list, cost_functional_form, states, controls, adjoints, config=None,
				 riesz_scalar_products=None, control_constraints=None, initial_guess=None, ksp_options=None,
				 adjoint_ksp_options=None, desired_weights=None):
		r"""This is used to generate all classes and functionalities. First ensures
		consistent input, afterwards, the solution algorithm is initialized.

		Parameters
		----------
		state_forms : ufl.form.Form or list[ufl.form.Form]
			The weak form of the state equation (user implemented). Can be either
			a single UFL form, or a (ordered) list of UFL forms.
		bcs_list : list[dolfin.fem.dirichletbc.DirichletBC] or list[list[dolfin.fem.dirichletbc.DirichletBC]] or dolfin.fem.dirichletbc.DirichletBC or None
			The list of DirichletBC objects describing Dirichlet (essential) boundary conditions.
			If this is ``None``, then no Dirichlet boundary conditions are imposed.
		cost_functional_form : ufl.form.Form or list[ufl.form.Form]
			UFL form of the cost functional.
		states : dolfin.function.function.Function or list[dolfin.function.function.Function]
			The state variable(s), can either be a :py:class:`fenics.Function`, or a list of these.
		controls : dolfin.function.function.Function or list[dolfin.function.function.Function]
			The control variable(s), can either be a :py:class:`fenics.Function`, or a list of these.
		adjoints : dolfin.function.function.Function or list[dolfin.function.function.Function]
			The adjoint variable(s), can either be a :py:class:`fenics.Function`, or a (ordered) list of these.
		config : configparser.ConfigParser or None
			The config file for the problem, generated via :py:func:`cashocs.create_config`.
			Alternatively, this can also be ``None``, in which case the default configurations
			are used, except for the optimization algorithm. This has then to be specified
			in the :py:meth:`solve <cashocs.OptimalControlProblem.solve>` method. The
			default is ``None``.
		riesz_scalar_products : None or ufl.form.Form or list[ufl.form.Form], optional
			The scalar products of the control space. Can either be None, a single UFL form, or a
			(ordered) list of UFL forms. If ``None``, the :math:`L^2(\Omega)` product is used.
			(default is ``None``).
		control_constraints : None or list[dolfin.function.function.Function] or list[float] or list[list[dolfin.function.function.Function]] or list[list[float]], optional
			Box constraints posed on the control, ``None`` means that there are none (default is ``None``).
			The (inner) lists should contain two elements of the form ``[u_a, u_b]``, where ``u_a`` is the lower,
			and ``u_b`` the upper bound.
		initial_guess : list[dolfin.function.function.Function], optional
			List of functions that act as initial guess for the state variables, should be valid input for :py:func:`fenics.assign`.
			Defaults to ``None``, which means a zero initial guess.
		ksp_options : list[list[str]] or list[list[list[str]]] or None, optional
			A list of strings corresponding to command line options for PETSc,
			used to solve the state systems. If this is ``None``, then the direct solver
			mumps is used (default is ``None``).
		adjoint_ksp_options : list[list[str]] or list[list[list[str]]] or None
			A list of strings corresponding to command line options for PETSc,
			used to solve the adjoint systems. If this is ``None``, then the same options
			as for the state systems are used (default is ``None``).

		Examples
		--------
		Examples how to use this class can be found in the :ref:`tutorial <tutorial_index>`.
		"""

		OptimizationProblem.__init__(self, state_forms, bcs_list, cost_functional_form, states, adjoints, config, initial_guess, ksp_options, adjoint_ksp_options, desired_weights)
		### Overloading, such that we do not have to use lists for a single state and a single control
		### controls
		try:
			if type(controls) == list and len(controls) > 0:
				for i in range(len(controls)):
					if controls[i].__module__ == 'dolfin.function.function' and type(controls[i]).__name__ == 'Function':
						pass
					else:
						raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls', 'controls have to be fenics Functions.')

				self.controls = controls

			elif controls.__module__ == 'dolfin.function.function' and type(controls).__name__ == 'Function':
				self.controls = [controls]
			else:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls', 'Type of controls is wrong.')
		except:
			raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls', 'Type of controls is wrong.')

		self.control_dim = len(self.controls)

		### riesz_scalar_products
		if riesz_scalar_products is None:
			dx = fenics.Measure('dx', self.controls[0].function_space().mesh())
			self.riesz_scalar_products = [fenics.inner(fenics.TrialFunction(self.controls[i].function_space()), fenics.TestFunction(self.controls[i].function_space())) * dx
										  for i in range(len(self.controls))]
		else:
			try:
				if type(riesz_scalar_products)==list and len(riesz_scalar_products) > 0:
					for i in range(len(riesz_scalar_products)):
						if riesz_scalar_products[i].__module__== 'ufl.form' and type(riesz_scalar_products[i]).__name__== 'Form':
							pass
						else:
							raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'riesz_scalar_products have to be ufl forms')
					self.riesz_scalar_products = riesz_scalar_products
				elif riesz_scalar_products.__module__== 'ufl.form' and type(riesz_scalar_products).__name__== 'Form':
					self.riesz_scalar_products = [riesz_scalar_products]
				else:
					raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'riesz_scalar_products have to be ufl forms')
			except:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'riesz_scalar_products have to be ufl forms')

		### control_constraints
		if control_constraints is None:
			self.control_constraints = []
			for control in self.controls:
				u_a = fenics.Function(control.function_space())
				u_a.vector()[:] = float('-inf')
				u_b = fenics.Function(control.function_space())
				u_b.vector()[:] = float('inf')
				self.control_constraints.append([u_a, u_b])
		else:
			try:
				if type(control_constraints) == list and len(control_constraints) > 0:
					if type(control_constraints[0]) == list:
						for i in range(len(control_constraints)):
							if type(control_constraints[i]) == list and len(control_constraints[i]) == 2:
								for j in range(2):
									if type(control_constraints[i][j]) in [float, int]:
										pass
									elif control_constraints[i][j].__module__ == 'dolfin.function.function' and type(control_constraints[i][j]).__name__ == 'Function':
										pass
									else:
										raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')
								pass
							else:
								raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')
						self.control_constraints = control_constraints
					elif (type(control_constraints[0]) in [float, int] or (control_constraints[0].__module__ == 'dolfin.function.function' and type(control_constraints[0]).__name__=='Function')) \
						and (type(control_constraints[1]) in [float, int] or (control_constraints[1].__module__ == 'dolfin.function.function' and type(control_constraints[1]).__name__=='Function')):

						self.control_constraints = [control_constraints]
					else:
						raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')

			except:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
														 'control_constraints has to be a list containing upper and lower bounds')

		# recast floats into functions for compatibility
		temp_constraints = self.control_constraints[:]
		self.control_constraints = []
		for idx, pair in enumerate(temp_constraints):
			if type(pair[0]) in [float, int]:
				lower_bound = fenics.Function(self.controls[idx].function_space())
				lower_bound.vector()[:] = pair[0]
			elif pair[0].__module__ == 'dolfin.function.function' and type(pair[0]).__name__ == 'Function':
				lower_bound = pair[0]
			else:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints', 'Wrong type for the control constraints')

			if type(pair[1]) in [float, int]:
				upper_bound = fenics.Function(self.controls[idx].function_space())
				upper_bound.vector()[:] = pair[1]
			elif pair[1].__module__ == 'dolfin.function.function' and type(pair[1]).__name__ == 'Function':
				upper_bound = pair[1]
			else:
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints', 'Wrong type for the control constraints')

			self.control_constraints.append([lower_bound, upper_bound])

		### Check whether the control constraints are feasible, and whether they are actually present
		self.require_control_constraints = [False for i in range(self.control_dim)]
		for idx, pair in enumerate(self.control_constraints):
			if not np.alltrue(pair[0].vector()[:] < pair[1].vector()[:]):
				raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints',
								 'The lower bound must always be smaller than the upper bound for the control_constraints.')

			if np.max(pair[0].vector()[:]) == float('-inf') and np.min(pair[1].vector()[:]) == float('inf'):
				# no control constraint for this component
				pass
			else:
				self.require_control_constraints[idx] = True
				
				control_element = self.controls[idx].ufl_element()
				if control_element.family() == 'Mixed':
					for j in range(control_element.value_size()):
						sub_elem = control_element.extract_component(j)[1]
						if sub_elem.family() == 'Real' or (sub_elem.family() == 'Lagrange' and sub_elem.degree() == 1) \
								or (sub_elem.family() == 'Discontinuous Lagrange' and sub_elem.degree() == 0):
							pass
						else:
							raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls',
									 'Control constraints are only implemented for linear Lagrange, constant Discontinuous Lagrange, and Real elements.')

				else:
					if control_element.family() == 'Real' or (control_element.family() == 'Lagrange' and control_element.degree() == 1) \
							or (control_element.family() == 'Discontinuous Lagrange' and control_element.degree() == 0):
						pass
					else:
						raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'controls',
									 'Control constraints are only implemented for linear Lagrange, constant Discontinuous Lagrange, and Real elements.')

		if not len(self.riesz_scalar_products) == self.control_dim:
			raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'riesz_scalar_products', 'Length of controls does not match')
		if not len(self.control_constraints) == self.control_dim:
			raise InputError('cashocs._optimal_control.optimal_control_problem.OptimalControlProblem', 'control_constraints', 'Length of controls does not match')
		### end overloading
		
		self.form_handler = ControlFormHandler(self.lagrangian, self.bcs_list, self.states, self.controls, self.adjoints, self.config,
											   self.riesz_scalar_products, self.control_constraints, self.ksp_options, self.adjoint_ksp_options,
											   self.require_control_constraints)

		self.state_spaces = self.form_handler.state_spaces
		self.control_spaces = self.form_handler.control_spaces
		self.adjoint_spaces = self.form_handler.adjoint_spaces

		self.projected_difference = [fenics.Function(V) for V in self.control_spaces]

		self.state_problem = StateProblem(self.form_handler, self.initial_guess)
		self.adjoint_problem = AdjointProblem(self.form_handler, self.state_problem)
		self.gradient_problem = GradientProblem(self.form_handler, self.state_problem, self.adjoint_problem)

		self.algorithm = _optimization_algorithm_configuration(self.config)

		self.reduced_cost_functional = ReducedCostFunctional(self.form_handler, self.state_problem)

		self.gradients = self.gradient_problem.gradients
		self.objective_value = 1.0
Пример #18
0
    def __compute_shape_gradient_forms(self):
        """Calculates the necessary left-hand-sides for the shape gradient problem.

		Returns
		-------
		None
		"""

        self.shape_bdry_def = json.loads(
            self.config.get('ShapeGradient', 'shape_bdry_def', fallback='[]'))
        if not type(self.shape_bdry_def) == list:
            raise ConfigError('ShapeGradient', 'shape_bdry_def',
                              'The input has to be a list.')
        # if not len(self.shape_bdry_def) > 0:
        # 	raise ConfigError('ShapeGradient', 'shape_bdry_def','The input must not be empty.')

        self.shape_bdry_fix = json.loads(
            self.config.get('ShapeGradient', 'shape_bdry_fix', fallback='[]'))
        if not type(self.shape_bdry_def) == list:
            raise ConfigError('ShapeGradient', 'shape_bdry_fix',
                              'The input has to be a list.')

        self.shape_bdry_fix_x = json.loads(
            self.config.get('ShapeGradient', 'shape_bdry_fix_x',
                            fallback='[]'))
        if not type(self.shape_bdry_fix_x) == list:
            raise ConfigError('ShapeGradient', 'shape_bdry_fix_x',
                              'The input has to be a list.')

        self.shape_bdry_fix_y = json.loads(
            self.config.get('ShapeGradient', 'shape_bdry_fix_y',
                            fallback='[]'))
        if not type(self.shape_bdry_fix_y) == list:
            raise ConfigError('ShapeGradient', 'shape_bdry_fix_y',
                              'The input has to be a list.')

        self.shape_bdry_fix_z = json.loads(
            self.config.get('ShapeGradient', 'shape_bdry_fix_z',
                            fallback='[]'))
        if not type(self.shape_bdry_fix_z) == list:
            raise ConfigError('ShapeGradient', 'shape_bdry_fix_z',
                              'The input has to be a list.')

        self.bcs_shape = create_bcs_list(
            self.deformation_space,
            fenics.Constant([0] *
                            self.deformation_space.ufl_element().value_size()),
            self.boundaries, self.shape_bdry_fix)
        self.bcs_shape += create_bcs_list(self.deformation_space.sub(0),
                                          fenics.Constant(0.0),
                                          self.boundaries,
                                          self.shape_bdry_fix_x)
        self.bcs_shape += create_bcs_list(self.deformation_space.sub(1),
                                          fenics.Constant(0.0),
                                          self.boundaries,
                                          self.shape_bdry_fix_y)
        if self.deformation_space.num_sub_spaces() == 3:
            self.bcs_shape += create_bcs_list(self.deformation_space.sub(2),
                                              fenics.Constant(0.0),
                                              self.boundaries,
                                              self.shape_bdry_fix_z)

        self.CG1 = fenics.FunctionSpace(self.mesh, 'CG', 1)
        self.DG0 = fenics.FunctionSpace(self.mesh, 'DG', 0)

        if self.shape_scalar_product is None:
            # Use the default linear elasticity approach

            self.mu_lame = fenics.Function(self.CG1)
            self.lambda_lame = self.config.getfloat('ShapeGradient',
                                                    'lambda_lame',
                                                    fallback=0.0)
            self.damping_factor = self.config.getfloat('ShapeGradient',
                                                       'damping_factor',
                                                       fallback=0.0)

            if self.config.getboolean('ShapeGradient',
                                      'inhomogeneous',
                                      fallback=False):
                self.volumes = fenics.project(fenics.CellVolume(self.mesh),
                                              self.DG0)
                vol_max = np.max(np.abs(self.volumes.vector()[:]))
                self.volumes.vector()[:] /= vol_max

            else:
                self.volumes = fenics.Constant(1.0)

            def eps(u):
                return fenics.Constant(0.5) * (fenics.grad(u) +
                                               fenics.grad(u).T)

            trial = fenics.TrialFunction(self.deformation_space)
            test = fenics.TestFunction(self.deformation_space)

            self.riesz_scalar_product = fenics.Constant(2)*self.mu_lame/self.volumes*fenics.inner(eps(trial), eps(test))*self.dx \
                   + fenics.Constant(self.lambda_lame)/self.volumes*fenics.div(trial)*fenics.div(test)*self.dx \
                   + fenics.Constant(self.damping_factor)/self.volumes*fenics.inner(trial, test)*self.dx

        else:
            # Use the scalar product supplied by the user

            self.riesz_scalar_product = self.shape_scalar_product
    def __init__(self, optimization_problem):
        """Parent class for the optimization methods implemented in cashocs.optimization.methods

		Parameters
		----------
		optimization_problem : cashocs.ShapeOptimizationProblem
			the optimization problem
		"""

        self.line_search_broken = False
        self.has_curvature_info = False

        self.optimization_problem = optimization_problem
        self.form_handler = self.optimization_problem.form_handler
        self.state_problem = self.optimization_problem.state_problem
        self.config = self.state_problem.config
        self.adjoint_problem = self.optimization_problem.adjoint_problem

        self.shape_gradient_problem = self.optimization_problem.shape_gradient_problem
        self.gradient = self.shape_gradient_problem.gradient
        self.cost_functional = self.optimization_problem.reduced_cost_functional
        self.search_direction = fenics.Function(
            self.form_handler.deformation_space)

        if self.config.getboolean('Mesh', 'remesh', fallback=False):
            self.iteration = self.optimization_problem.temp_dict[
                'OptimizationRoutine'].get('iteration_counter', 0)
        else:
            self.iteration = 0
        self.objective_value = 1.0
        self.gradient_norm_initial = 1.0
        self.relative_norm = 1.0
        self.stepsize = 1.0

        self.converged = False
        self.converged_reason = 0

        self.output_dict = dict()
        try:
            self.output_dict[
                'cost_function_value'] = self.optimization_problem.temp_dict[
                    'output_dict']['cost_function_value']
            self.output_dict[
                'gradient_norm'] = self.optimization_problem.temp_dict[
                    'output_dict']['gradient_norm']
            self.output_dict['stepsize'] = self.optimization_problem.temp_dict[
                'output_dict']['stepsize']
            self.output_dict[
                'MeshQuality'] = self.optimization_problem.temp_dict[
                    'output_dict']['MeshQuality']
        except (TypeError, KeyError):
            self.output_dict['cost_function_value'] = []
            self.output_dict['gradient_norm'] = []
            self.output_dict['stepsize'] = []
            self.output_dict['MeshQuality'] = []

        self.verbose = self.config.getboolean('Output',
                                              'verbose',
                                              fallback=True)
        self.save_results = self.config.getboolean('Output',
                                                   'save_results',
                                                   fallback=True)
        self.rtol = self.config.getfloat('OptimizationRoutine',
                                         'rtol',
                                         fallback=1e-3)
        self.atol = self.config.getfloat('OptimizationRoutine',
                                         'atol',
                                         fallback=0.0)
        self.maximum_iterations = self.config.getint('OptimizationRoutine',
                                                     'maximum_iterations',
                                                     fallback=100)
        self.soft_exit = self.config.getboolean('OptimizationRoutine',
                                                'soft_exit',
                                                fallback=False)
        self.save_pvd = self.config.getboolean('Output',
                                               'save_pvd',
                                               fallback=False)
        self.result_dir = self.config.get('Output',
                                          'result_dir',
                                          fallback='./')

        if self.save_pvd:
            self.state_pvd_list = []
            for i in range(self.form_handler.state_dim):
                if self.form_handler.state_spaces[i].num_sub_spaces() > 0:
                    self.state_pvd_list.append([])
                    for j in range(self.form_handler.state_spaces[i].
                                   num_sub_spaces()):
                        if self.optimization_problem.mesh_handler.do_remesh:
                            self.state_pvd_list[i].append(
                                fenics.
                                File(self.result_dir + '/pvd/remesh_' + format(
                                    self.optimization_problem.temp_dict.get(
                                        'remesh_counter', 0), 'd') +
                                     '_state_' + str(i) + '_' + str(j) +
                                     '.pvd'))
                        else:
                            self.state_pvd_list[i].append(
                                fenics.File(self.result_dir + '/pvd/state_' +
                                            str(i) + '_' + str(j) + '.pvd'))
                else:
                    if self.optimization_problem.mesh_handler.do_remesh:
                        self.state_pvd_list.append(
                            fenics.File(self.result_dir + '/pvd/remesh_' +
                                        format(
                                            self.optimization_problem.temp_dict
                                            .get('remesh_counter', 0), 'd') +
                                        '_state_' + str(i) + '.pvd'))
                    else:
                        self.state_pvd_list.append(
                            fenics.File(self.result_dir + '/pvd/state_' +
                                        str(i) + '.pvd'))
Пример #20
0
mu = 1                  # kinematic viscosity
rho = 1                 # density

# Create mesh and define function spaces SEPARATELY for pressure and velocity spaces. 
mesh = fs.UnitSquareMesh(16, 16)
V = fs.VectorFunctionSpace(mesh, 'P', 2)    # velocity space, a vector space
Q = fs.FunctionSpace(mesh, 'P', 1)          # pressure space, a scalar space

# Define trial and test functions
u = fs.TrialFunction(V)     # in velocity space
v = fs.TestFunction(V)
p = fs.TrialFunction(Q)     # in pressure space
q = fs.TestFunction(Q)

# Define functions for solutions at previous and current time steps
u_n = fs.Function(V)    # u^(n)
u_  = fs.Function(V)    # u^(n+1)
p_n = fs.Function(Q)    # p^(n)
p_  = fs.Function(Q)    # p^(n+1)

# Define boundaries
inflow  = 'near(x[0], 0)'
outflow = 'near(x[0], 1)'
walls   = 'near(x[1], 0) || near (x[1], 1)'

# Define boundary bonditions
bcu_noslip  = fs.DirichletBC(V, fs.Constant((0,0)), walls)
bcp_inflow  = fs.DirichletBC(Q, fs.Constant(8), inflow)
bcp_outflow = fs.DirichletBC(Q, fs.Constant(0), outflow)
bcu = [bcu_noslip]
bcp = [bcp_inflow, bcp_outflow]
Пример #21
0
    def demo16(self, permeability, obs_case=1):
        """This demo program solves the mixed formulation of Poisson's
        equation:

            sigma + grad(u) = 0    in Omega
                div(sigma) = f    in Omega
                    du/dn = g    on Gamma_N
                        u = u_D  on Gamma_D
        
        The corresponding weak (variational problem)
        
            <sigma, tau> + <grad(u), tau>   = 0
                                                    for all tau
                        - <sigma, grad(v)> = <f, v> + <g, v>
                                                    for all v
        
        is solved using DRT (Discontinuous Raviart-Thomas) elements
        of degree k for (sigma, tau) and CG (Lagrange) elements
        of degree k + 1 for (u, v) for k >= 1.
        """

        mesh = UnitSquareMesh(15, 15)
        ak_values = permeability
        flux_order = 3
        s = scenarios.darcy_problem_1()
        DRT = fenics.FiniteElement("DRT", mesh.ufl_cell(), flux_order)
        # Lagrange
        CG = fenics.FiniteElement("CG", mesh.ufl_cell(), flux_order + 1)
        if s.integral_constraint:
            # From https://fenicsproject.org/qa/14184/how-to-solve-linear-system-with-constaint
            R = fenics.FiniteElement("R", mesh.ufl_cell(), 0)
            W = fenics.FunctionSpace(mesh, fenics.MixedElement([DRT, CG, R]))
            # Define trial and test functions
            (sigma, u, r) = fenics.TrialFunctions(W)
            (tau, v, r_) = fenics.TestFunctions(W)
        else:
            W = fenics.FunctionSpace(mesh, DRT * CG)
            # Define trial and test functions
            (sigma, u) = fenics.TrialFunctions(W)
            (tau, v) = fenics.TestFunctions(W)
        f = s.source_function
        g = s.g

        # Define property field function
        W_CG = fenics.FunctionSpace(mesh, "Lagrange", 1)
        if s.ak is None:
            ak = property_field.get_conductivity(W_CG, ak_values)
        else:
            ak = s.ak

        # Define variational form
        a = (fenics.dot(sigma, tau) + fenics.dot(ak * fenics.grad(u), tau) +
             fenics.dot(sigma, fenics.grad(v))) * fenics.dx
        L = -f * v * fenics.dx + g * v * fenics.ds
        # L = 0
        if s.integral_constraint:
            # Lagrange multiplier?  See above link.
            a += r_ * u * fenics.dx + v * r * fenics.dx
        # Define Dirichlet BC
        bc = fenics.DirichletBC(W.sub(1), s.dirichlet_bc, s.gamma_dirichlet)
        # Compute solution
        w = fenics.Function(W)
        fenics.solve(a == L, w, bc)
        # fenics.solve(a == L, w)
        if s.integral_constraint:
            (sigma, u, r) = w.split()
        else:
            (sigma, u) = w.split()
        x = u.compute_vertex_values(mesh)
        x2 = sigma.compute_vertex_values(mesh)
        p = x
        pre = p.reshape((16, 16))
        vx = x2[:256].reshape((16, 16))
        vy = x2[256:].reshape((16, 16))

        if obs_case == 1:
            dd = np.zeros([8, 8])
            pos = np.full((8 * 8, 2), 0)
            col = [1, 3, 5, 7, 9, 11, 13, 15]
            position = [1, 3, 5, 7, 9, 11, 13, 15]
            for i in range(8):
                for j in range(8):
                    row = position
                    pos[8 * i + j, :] = [col[i], row[j]]
                    dd[i, j] = pre[col[i], row[j]]
            like = dd.reshape(8 * 8, )
        return like, pre, vx, vy, ak_values, pos
Пример #22
0
    def solve_cell_problems(self, method='regularized', plot=False):
        """
        Solve the cell problems for the given PDE by changing the geometry to exclude the zone in the middle
        :return:
        """
        class PeriodicBoundary(fe.SubDomain):

            # Left boundary is "target domain" G
            def inside(self, x, on_boundary):
                par = MembraneSimulator.w / MembraneSimulator.length
                tol = 1E-4
                return on_boundary and x[1] >= -tol and x[1] <= tol

            # Map right boundary (H) to left boundary (G)
            def map(self, x, y):
                y[1] = x[1] + 2 * self.eta / MembraneSimulator.length
                y[0] = x[0]

        mesh_size = 50
        # Domain

        if method == 'circle':
            self.obstacle_radius = self.eta / MembraneSimulator.length / 2
            box_begin_point = fe.Point(-self.w / MembraneSimulator.length, 0)
            box_end_point = fe.Point(self.w / MembraneSimulator.length,
                                     2 * self.eta / MembraneSimulator.length)
            box = mshr.Rectangle(box_begin_point, box_end_point)
            cell = box - mshr.Circle(
                fe.Point(0, self.eta / MembraneSimulator.length),
                self.obstacle_radius, mesh_size)
            self.cell_mesh = mshr.generate_mesh(cell, mesh_size)
            diff_coef = fe.Constant(
                ((0, 0), (0, self.D[1, 1])))  # limit for regularisation below.
        # elif method == 'diff_coef':
        #     print("Haha this is going to crash. Also it is horrible in accuracy")
        #     self.cell_mesh = fe.RectangleMesh(fe.Point(-self.w / MembraneSimulator.length, 0),
        #                                       fe.Point(self.w / MembraneSimulator.length,
        #                                                2 * self.eta / MembraneSimulator.length), mesh_size, mesh_size)
        #     diff_coef = fe.Expression(
        #         (('0', '0'), ('0', 'val * ((x[0] - c_x)*(x[0] - c_x) + (x[1] - c_y)*(x[1] - c_y) > r*r)')),
        #         val=(4 * self.ref_T * MembraneSimulator.d2 / MembraneSimulator.length ** 2), c_x=0,
        #         c_y=(self.eta / MembraneSimulator.length),
        #         r=self.obstacle_radius, degree=2, domain=self.cell_mesh)
        elif method == 'regularized':
            box_begin_point = fe.Point(-self.w / MembraneSimulator.length, 0)
            box_end_point = fe.Point(self.w / MembraneSimulator.length,
                                     2 * self.eta / MembraneSimulator.length)
            box = mshr.Rectangle(box_begin_point, box_end_point)
            obstacle_begin_point = fe.Point(
                -self.w / MembraneSimulator.length * self.obs_length,
                self.eta / MembraneSimulator.length * (1 - self.obs_height))
            obstacle_end_point = fe.Point(
                self.w / MembraneSimulator.length * self.obs_length,
                self.eta / MembraneSimulator.length * (1 + self.obs_height))
            obstacle = mshr.Rectangle(obstacle_begin_point, obstacle_end_point)
            cell = box - obstacle
            self.cell_mesh = mshr.generate_mesh(cell, mesh_size)
            diff_coef = fe.Constant(((self.obs_ratio * self.D[0, 0], 0),
                                     (0, self.D[1, 1])))  # defect matrix.
        else:
            raise ValueError("%s not a valid method to solve cell problem" %
                             method)
        self.cell_fs = fe.FunctionSpace(self.cell_mesh, 'P', 2)
        self.cell_solutions = [
            fe.Function(self.cell_fs),
            fe.Function(self.cell_fs)
        ]
        w = fe.TrialFunction(self.cell_fs)
        phi = fe.TestFunction(self.cell_fs)
        scaled_unit_vectors = [
            fe.Constant((1. / np.sqrt(self.obs_ratio), 0.)),
            fe.Constant((0., 1.))
        ]
        for i in range(2):
            weak_form = fe.dot(
                diff_coef *
                (fe.grad(w) + scaled_unit_vectors[i]), fe.grad(phi)) * fe.dx
            print("Solving cell problem")
            bc = fe.DirichletBC(self.cell_fs, fe.Constant(0),
                                MembraneSimulator.cell_boundary)
            if i == 0:
                # Periodicity is applied automatically
                bc = None
            fe.solve(
                fe.lhs(weak_form) == fe.rhs(weak_form), self.cell_solutions[i],
                bc)
            if plot:
                plt.rc('text', usetex=True)
                f = fe.plot(self.cell_solutions[i])
                plt.colorbar(f)
                plt.title(r'Solution to cell problem $w_%d$' % (i + 1))
                plt.xlabel(r'$Y_1$')
                plt.ylabel(r'$Y_2$')
                print("Cell solution")
                print(np.min(self.cell_solutions[i].vector().get_local()),
                      np.max(self.cell_solutions[i].vector().get_local()))
                plt.show()
Пример #23
0
 def _load_fenics_function(path):
     V = fn.FunctionSpace(mesh, element_type, element_degree)
     return fn.Function(V, path)
Пример #24
0
MODEL = False  # flag to use SA model
b = fe.Expression(('0', '0'), degree=DEG)  # forcing
nu = fe.Constant(1e-2)
rho = fe.Constant(1)
RE = 50
lmx = 1  # mixing length :)
# Re = 10 / 1e-4 = 1e5

V = fe.VectorElement("Lagrange", mesh.ufl_cell(), 2)
P = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
NU = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
if MODEL: M = fe.MixedElement([V, P, NU])
else: M = fe.MixedElement([V, P])
W = fe.FunctionSpace(mesh, M)

W0 = fe.Function(W)

if MODEL:
    (v, q, nu_test) = fe.TestFunctions(W)
    (u, p, nu_trial) = fe.split(W0)
else:
    (
        v,
        q,
    ) = fe.TestFunctions(W)
    (
        u,
        p,
    ) = fe.split(W0)
    nu_trial = fe.Constant(5)  # artificial viscosity!!!
    fv1 = fe.Constant(1)
Пример #25
0
Mixed = fn.MixedElement(Elem)
V = fn.FunctionSpace(mesh, Mixed)

# %%
# define potentials and concentrations
u_GND = fn.Expression('0', degree=2)  #Ground
u_DD = fn.Expression('0.5', degree=2)  #pontential
c_avg = fn.Expression('0.0001', degree=2)  #average concentration

# set boundary conditions
bcs = []
bcs += [fn.DirichletBC(V.sub(0), u_DD, mf, 3)]
bcs += [fn.DirichletBC(V.sub(0), u_GND, mf, 1)]

# define problem
UC = fn.Function(V)
uc = fn.split(UC)  # trial function potential concentration lagrange multi
u, c, lam = uc[0], uc[1:M + 1], uc[M + 1:]

VW = fn.TestFunctions(
    V)  # test function potential concentration lagrange multi
v, w, mu = VW[0], VW[1:M + 1], VW[M + 1:]

#lets try rot
r = fn.Expression('x[0]', degree=0)

# changing concentrations charges
Rho = 0
for i in range(M):
    if i % 2:
        Rho += -c[i]
Пример #26
0
# Volumetric Load
q = -10.0 / t
b = fn.Constant((0.0, q))


def Left_boundary(x, on_boundary):
    return on_boundary and abs(x[0]) < fn.DOLFIN_EPS


u_L = fn.Constant((0.0, 0.0))
bcs = [fn.DirichletBC(V, u_L, Left_boundary)]


# Forward problem solution
@build_jax_solve_eval((fn.Function(C), ))
def forward(x):
    u = fn.TrialFunction(V)
    w = fn.TestFunction(V)
    sigma = lmbda * tr(sym(grad(u))) * Identity(2) + 2 * G * sym(
        grad(u))  # Stress
    R = simp(x) * inner(sigma, grad(w)) * dx - dot(b, w) * dx
    a, L = ufl.lhs(R), ufl.rhs(R)
    u = fn.Function(V)
    F = L - ufl.action(a, u)
    fn.solve(a == L, u, bcs)
    return u, F, bcs


@build_jax_assemble_eval((fn.Function(V), fn.Function(C)))
def eval_cost(u, x):
Пример #27
0
boundaries = fe.MeshFunction("size_t", mesh, "mesh/beam_facet_region.xml")

# Redefine the integration measures
dxp = fe.Measure('dx', domain=mesh, subdomain_data=subdomains)
dsp = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

##################### FINITE ELEMENT SPACES ##################################
# Finite element spaces
W = fe.FunctionSpace(mesh, 'P', 1)
V = fe.VectorFunctionSpace(mesh, 'P', 1)
Z = fe.TensorFunctionSpace(mesh, 'P', 1)

# Finite element functions
du = fe.TrialFunction(V)
v = fe.TestFunction(V)
u = fe.Function(V)

######################### PROBLEM PARAMS ######################################
# Material properties
materials = {
    1: [210e9, 0.33],
}

# Load multipliers
p = 500000.
q = p * 100.

######################## BOUNDARY CONDITIONS #################################
# Define the boundary conditions
boundary_conditions = {
    2: fe.Constant((0., 0., 0.)),
Пример #28
0
    return on_boundary and fen.near(x[1], edge, tol)


def boundary_B(x, on_boundary):
    return on_boundary and fen.near(x[1], -edge, tol)


bc_L = fen.DirichletBC(V, phi_L, boundary_L)
bc_R = fen.DirichletBC(V, phi_R, boundary_R)
bc_H = fen.DirichletBC(V, phi_H, boundary_H)
bc_B = fen.DirichletBC(V, phi_B, boundary_B)

bc = [bc_L, bc_R, bc_H, bc_B]

# -------------Define variational problem------------
phi = fen.Function(V)
v = fen.TestFunction(V)

pi = np.pi

rho_sun = fen.Expression(
    'pow(pow(x[0],2)+pow(x[1],2),0.5)<=rad_sun ? 3*m_sun/(4*pi*pow(rad_sun,3)): 0',
    degree=2,
    rad_sun=rad_sun,
    m_sun=m_sun,
    pi=pi)

J = fen.Expression('pow(x[0]*x[0] + x[1]*x[1],0.5)', degree=2)

Func = (-J * phi.dx(0) * v.dx(0) - J * phi.dx(1) * v.dx(1) -
        J * 4 * np.pi * rho_sun * v) * fen.dx
Пример #29
0
# Define Boundaries
left = fe.CompiledSubDomain("near(x[0], side) && on_boundary", side=0.0)
right = fe.CompiledSubDomain("near(x[0], side) && on_boundary", side=1.0)

# Define Dirichlet boundary (x = 0 or x = 1)
u_left = fe.Expression(("0.0", "0.0", "0.0"), element=element_3)
u_right = fe.Expression(("0.0", "0.0", "0.0"), element=element_3)
p_left = fe.Constant(0.)

# Define acting force
b = fe.Constant((0.0, 0.0, 0.0))  # Body force per unit volume
t_bar = fe.Constant((0.0, 0.0, 0.0))  # Traction force on the boundary

# Define test and trial functions
w = fe.Function(V)  # most recently computed solution
(u, p) = fe.split(w)
(v, q) = fe.TestFunctions(V)
dw = fe.TrialFunction(V)

# Kinematics
d = u.geometric_dimension()
I = fe.Identity(d)  # Identity tensor

F = fe.variable(I + grad(u))  # Deformation gradient
C = fe.variable(F.T * F)  # Right Cauchy-Green tensor
J = fe.det(C)

DE = lambda v: 0.5 * (F.T * grad(v) + grad(v).T * F)

a_0 = fe.as_vector([[1.0], [0.], [0.]])
Пример #30
0
    def __init__(self, form_handler, gradient_problem):
        """Initializes self.

		Parameters
		----------
		form_handler : cashocs._forms.ControlFormHandler
			The FormHandler object for the optimization problem.
		gradient_problem : cashocs._pde_problems.GradientProblem
			The GradientProblem object (this is needed for the computation
			of the Hessian).
		"""

        self.form_handler = form_handler
        self.gradient_problem = gradient_problem

        self.config = self.form_handler.config
        self.gradients = self.gradient_problem.gradients

        self.inner_newton = self.config.get('AlgoTNM',
                                            'inner_newton',
                                            fallback='cr')
        self.max_it_inner_newton = self.config.getint('AlgoTNM',
                                                      'max_it_inner_newton',
                                                      fallback=50)
        # TODO: Add absolute tolerance, too
        self.inner_newton_tolerance = self.config.getfloat(
            'AlgoTNM', 'inner_newton_tolerance', fallback=1e-15)

        self.test_directions = self.form_handler.test_directions
        self.residual = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.delta_control = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]

        self.state_dim = self.form_handler.state_dim
        self.control_dim = self.form_handler.control_dim

        self.temp1 = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.temp2 = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]

        self.p = [fenics.Function(V) for V in self.form_handler.control_spaces]
        self.p_prev = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.p_pprev = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.s = [fenics.Function(V) for V in self.form_handler.control_spaces]
        self.s_prev = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.s_pprev = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.q = [fenics.Function(V) for V in self.form_handler.control_spaces]
        self.q_prev = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]

        self.hessian_actions = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.inactive_part = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]
        self.active_part = [
            fenics.Function(V) for V in self.form_handler.control_spaces
        ]

        self.controls = self.form_handler.controls

        self.rtol = self.config.getfloat('StateSystem',
                                         'picard_rtol',
                                         fallback=1e-10)
        self.atol = self.config.getfloat('StateSystem',
                                         'picard_atol',
                                         fallback=1e-12)
        self.maxiter = self.config.getint('StateSystem',
                                          'picard_iter',
                                          fallback=50)
        self.picard_verbose = self.config.getboolean('StateSystem',
                                                     'picard_verbose',
                                                     fallback=False)

        self.no_sensitivity_solves = 0
        self.state_ksps = [
            PETSc.KSP().create() for i in range(self.form_handler.state_dim)
        ]
        _setup_petsc_options(self.state_ksps,
                             self.form_handler.state_ksp_options)
        self.adjoint_ksps = [
            PETSc.KSP().create() for i in range(self.form_handler.state_dim)
        ]
        _setup_petsc_options(self.adjoint_ksps,
                             self.form_handler.adjoint_ksp_options)

        # Initialize the PETSc Krylov solver for the Riesz projection problems
        self.ksps = [PETSc.KSP().create() for i in range(self.control_dim)]

        option = [['ksp_type', 'cg'], ['pc_type', 'hypre'],
                  ['pc_hypre_type', 'boomeramg'],
                  ['pc_hypre_boomeramg_strong_threshold', 0.7],
                  ['ksp_rtol', 1e-16], ['ksp_atol', 1e-50],
                  ['ksp_max_it', 100]]
        self.riesz_ksp_options = []
        for i in range(self.control_dim):
            self.riesz_ksp_options.append(option)

        _setup_petsc_options(self.ksps, self.riesz_ksp_options)
        for i, ksp in enumerate(self.ksps):
            ksp.setOperators(self.form_handler.riesz_projection_matrices[i])