Ejemplo n.º 1
0
def read_fenics_solution(filepath):
    from dolfin import (Mesh, XDMFFile, MeshValueCollection, cpp,
                        FunctionSpace, Function, HDF5File, MPI)
    mesh = Mesh()
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mesh)  # read the complete mesh

    #mvc_subdo = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 1)
    #with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
    #    infile.read(mvc_subdo, "subdomains")  # read the diferent subdomians
    #subdomains = cpp.mesh.MeshFunctionSizet(mesh, mvc_subdo)

    #mvc = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 2)
    #with XDMFFile("%s_line.xdmf" % filepath.split('.')[0]) as infile:
    #    infile.read(mvc, "boundary_conditions")  # read the boundary conditions
    #boundary = cpp.mesh.MeshFunctionSizet(mesh, mvc)

    # Define function space and basis functions
    V = FunctionSpace(mesh, "CG", 1)
    U = Function(V)
    input_file = HDF5File(MPI.comm_world,
                          filepath.split('.')[0] + "_solution_field.h5", "r")
    input_file.read(U, "solution")
    input_file.close()

    dofs = V.tabulate_dof_coordinates().reshape(
        V.dim(),
        mesh.geometry().dim())  # coordinates of nodes
    U.set_allow_extrapolation(True)
    return U, mesh, dofs.shape[0]
Ejemplo n.º 2
0
def test_fenics_vector_copy():
    mesh = UnitSquare(3, 3)
    fs = FunctionSpace(mesh, "CG", 1)
    vec1 = FEniCSVector(Function(fs))
    vec1.coeffs = np.array(range(fs.dim()))
    assert_equal(vec1.coeffs[0], 0)
    vec2 = vec1.copy()
    vec2.coeffs[0] = 5
    assert_equal(vec1.coeffs[0], 0)
Ejemplo n.º 3
0
 def create_function_space(cls, simulation):
     mesh = simulation.data['mesh']
     cd = simulation.data['constrained_domain']
     Vc_name = simulation.input.get_value(
         'multiphase_solver/function_space_colour',
         'Discontinuous Lagrange', 'string')
     Pc = simulation.input.get_value(
         'multiphase_solver/polynomial_degree_colour',
         cls.default_polynomial_degree_colour,
         'int',
     )
     Vc = FunctionSpace(mesh, Vc_name, Pc, constrained_domain=cd)
     simulation.data['Vc'] = Vc
     simulation.ndofs += Vc.dim()
Ejemplo n.º 4
0
    def _prepare_solution_fcns(self):
        # Extract parameters needed to create finite elements
        N = self.parameters["N"]
        gdim = self._mesh.geometry().dim()

        # Group elements for phi, chi, v
        elements_ch = (N - 1) * [
            self._FE["phi"],
        ] + (N - 1) * [
            self._FE["chi"],
        ]
        elements_ns = [
            VectorElement(self._FE["v"], dim=gdim),
        ]

        # Append elements for p and th
        elements_ns.append(self._FE["p"])
        if self._FE["th"] is not None:
            elements_ns.append(self._FE["th"])

        # Build function spaces
        W_ch = FunctionSpace(self._mesh,
                             MixedElement(elements_ch),
                             constrained_domain=self._constrained_domain)
        W_ns = FunctionSpace(self._mesh,
                             MixedElement(elements_ns),
                             constrained_domain=self._constrained_domain)
        self._ndofs["CH"] = W_ch.dim()
        self._ndofs["NS"] = W_ns.dim()
        self._ndofs["total"] = W_ch.dim() + W_ns.dim()
        self._subspace["phi"] = [W_ch.sub(i) for i in range(N - 1)]
        self._subspace["chi"] = [
            W_ch.sub(i) for i in range(N - 1, 2 * (N - 1))
        ]
        self._ndofs["phi"] = W_ch.sub(0).dim()
        self._ndofs["chi"] = W_ch.sub(N - 1).dim()
        if gdim == 1:
            self._subspace["v"] = [
                W_ns.sub(0),
            ]
            self._ndofs["v"] = W_ns.sub(0).dim()
        else:
            self._subspace["v"] = [W_ns.sub(0).sub(i) for i in range(gdim)]
            self._ndofs["v"] = W_ns.sub(0).sub(0).dim()
        self._subspace["p"] = W_ns.sub(1)
        self._ndofs["p"] = W_ns.sub(1).dim()
        self._ndofs["th"] = 0
        if W_ns.num_sub_spaces() == 3:
            self._subspace["th"] = W_ns.sub(2)
            self._ndofs["th"] = W_ns.sub(2).dim()
        # ndofs = (
        #       (N-1)*(self._ndofs["phi"] + self._ndofs["chi"])
        #     + gdim*self._ndofs["v"]
        #     + self._ndofs["p"]
        #     + self._ndofs["th"]
        # )
        # assert self._ndofs["total"] == ndofs

        # Create solution variables at ctl
        w_ctl = (Function(W_ch), Function(W_ns))
        w_ctl[0].rename("semi_ctl_ch", "solution_semi_ch_ctl")
        w_ctl[1].rename("semi_ctl_ns", "solution_semi_ns_ctl")

        # Create solution variables at ptl
        w_ptl = [(Function(W_ch), Function(W_ns)) \
                     for i in range(self.parameters["PTL"])]
        for i, f in enumerate(w_ptl):
            f[0].rename("semi_ptl%i_ch" % i, "solution_semi_ch_ptl%i" % i)
            f[1].rename("semi_ptl%i_ns" % i, "solution_semi_ns_ptl%i" % i)

        return (w_ctl, w_ptl)
Ejemplo n.º 5
0
    def _prepare_solution_fcns(self):
        # Extract parameters needed to create finite elements
        N = self.parameters["N"]
        gdim = self._mesh.geometry().dim()

        # Group elements for phi, chi, v
        elements_ch = (N - 1) * [
            self._FE["phi"],
        ] + (N - 1) * [
            self._FE["chi"],
        ]
        # NOTE: Elements for phi and chi are grouped together to avoid special
        #       treatment of the case with N = 2. For example, if N == 2 and
        #       phi would be represented as a vector with a single component
        #       then a special treatment is needed to plot this single
        #       component (UFL/DOLFIN ban to plot 1D function on a 2D mesh).
        elements = []
        elements.append(MixedElement(elements_ch))
        elements.append(VectorElement(self._FE["v"], dim=gdim))

        # Append elements for p and th
        elements.append(self._FE["p"])
        if self._FE["th"] is not None:
            elements.append(self._FE["th"])

        # Build function spaces
        W = FunctionSpace(self._mesh,
                          MixedElement(elements),
                          constrained_domain=self._constrained_domain)
        self._ndofs["total"] = W.dim()
        self._subspace["phi"] = [W.sub(0).sub(i) for i in range(N - 1)]
        self._subspace["chi"] = [
            W.sub(0).sub(i) for i in range(N - 1, 2 * (N - 1))
        ]
        self._ndofs["phi"] = W.sub(0).sub(0).dim()
        self._ndofs["chi"] = W.sub(0).sub(N - 1).dim()
        if gdim == 1:
            self._subspace["v"] = [
                W.sub(1),
            ]
            self._ndofs["v"] = W.sub(1).dim()
        else:
            self._subspace["v"] = [W.sub(1).sub(i) for i in range(gdim)]
            self._ndofs["v"] = W.sub(1).sub(0).dim()
        self._subspace["p"] = W.sub(2)
        self._ndofs["p"] = W.sub(2).dim()
        self._ndofs["th"] = 0
        if W.num_sub_spaces() == 4:
            self._subspace["th"] = W.sub(3)
            self._ndofs["th"] = W.sub(3).dim()
        self._ndofs["CH"] = W.sub(0).dim()
        self._ndofs["NS"] = (gdim * self._ndofs["v"] + self._ndofs["p"] +
                             self._ndofs["th"])
        assert self._ndofs["total"] == self._ndofs["CH"] + self._ndofs["NS"]

        # Create solution variable at ctl
        w_ctl = (Function(W), )
        w_ctl[0].rename("mono_ctl", "solution_mono_ctl")

        # Create solution variables at ptl
        w_ptl = [(Function(W), ) for i in range(self.parameters["PTL"])]
        for (i, f) in enumerate(w_ptl):
            f[0].rename("mono_ptl%i" % i, "solution_mono_ptl%i" % i)

        return (w_ctl, w_ptl)
plt.ylim(0.0, 0.015)
plt.yticks([0.0, 0.005, 0.01, 0.015])
plt.colorbar(first)
plt.show()

second = plot(ca, title="Cation concentration, $c^+$")
plt.xlim(0.0, 0.015)
plt.xticks([0.0, 0.005, 0.01, 0.015])
plt.ylim(0.0, 0.015)
plt.yticks([0.0, 0.005, 0.01, 0.015])
plt.colorbar(second)
plt.show()

third = plot(psi, title="Electric potential, $\psi$")
plt.xlim(0.0, 0.015)
plt.xticks([0.0, 0.005, 0.01, 0.015])
plt.ylim(0.0, 0.015)
plt.yticks([0.0, 0.005, 0.01, 0.015])
plt.colorbar(third)
plt.show()

File('an_ES.pvd') << an
File('ca_ES.pvd') << ca
File('psi_ES.pvd') << psi

totime = aftersolveT - startime
#print("Start time is : " + str(round(startime, 2)))
#print("After solve time : " + str(round(aftersolveT, 2)))
print("Number of DOFs: {}".format(ME.dim()))
print("Total time for Simulation : " + str(round(totime)) + "s")
Ejemplo n.º 7
0
class TestLumpedMass(unittest.TestCase):

    def setUp(self):
        mesh = UnitSquareMesh(5, 5, 'crossed')
        self.V = FunctionSpace(mesh, 'Lagrange', 5)
        self.u = Function(self.V)
        self.uM = Function(self.V)
        self.uMdiag = Function(self.V)
        test = TestFunction(self.V)
        trial = TrialFunction(self.V)
        m = test*trial*dx
        self.M = assemble(m)
        self.solver = LUSolver()
        self.solver.parameters['reuse_factorization'] = True
        self.solver.parameters['symmetric'] = True
        self.solver.set_operator(self.M)
        self.ones = np.ones(self.V.dim())
        

    def test00(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolver(self.V)

    def test01_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)

    def test01_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for index, ii in enumerate(self.M.array()):
            err += abs(ii.sum() - myobj.Mdiag[index])
        self.assertTrue(err < index*1e-16)


    def test02(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1./myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii*1e-16)


    def test03_basic(self):
        """ solve """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = (myobj.one - self.uMdiag.vector()).array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.one.array()) < 1e-14)


    def test04_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj*myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.Mdiag.array()) < 1e-14)


    def test10(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolverS(self.V)

    def test11_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)

    def test11_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        Msum = np.dot(self.ones, self.M.array().dot(self.ones))
        err = abs(myobj.Mdiag.array().dot(self.ones) - \
        Msum) / Msum
        self.assertTrue(err < 1e-14, err)


    def test12(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1./myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii*1e-16)


    def test13_basic(self):
        """ solve """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = myobj.one.array() - self.uMdiag.vector().array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.one.array()) < 1e-14)


    def test14_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj*myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(np.linalg.norm(diff)/np.linalg.norm(myobj.Mdiag.array()) < 1e-14)
Ejemplo n.º 8
0
def test_fenics_vector_inner():
    mesh = UnitSquare(3, 3)
    fs = FunctionSpace(mesh, "CG", 1)
    vec = FEniCSVector(Function(fs))
    vec.coeffs = np.array(range(fs.dim()))
    assert_equal(vec.__inner__(vec), 1240)
Ejemplo n.º 9
0
def run_simulation(
        filepath,
        topology_info: int = None,
        top_bc: int = None,
        bot_bc: int = None,
        left_bc: int = None,
        right_bc: int = None,
        geometry: dict = None,
        kappa=3,  #only if geometry is None
        show=True,
        save_solution=False):

    from dolfin import (Mesh, XDMFFile, MeshValueCollection, cpp,
                        FunctionSpace, TrialFunction, TestFunction,
                        DirichletBC, Constant, Measure, inner, nabla_grad,
                        Function, solve, plot, File)
    mesh = Mesh()
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mesh)  # read the complete mesh

    mvc_subdo = MeshValueCollection("size_t", mesh,
                                    mesh.geometric_dimension() - 1)
    with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mvc_subdo, "subdomains")  # read the diferent subdomians
    subdomains = cpp.mesh.MeshFunctionSizet(mesh, mvc_subdo)

    mvc = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 2)
    with XDMFFile("%s_line.xdmf" % filepath.split('.')[0]) as infile:
        infile.read(mvc, "boundary_conditions")  #read the boundary conditions
    boundary = cpp.mesh.MeshFunctionSizet(mesh, mvc)

    # Define function space and basis functions
    V = FunctionSpace(mesh, "CG", 1)
    u = TrialFunction(V)
    v = TestFunction(V)
    # Boundary conditions
    bcs = []
    for bc_id in topology_info.keys():
        if bc_id[-2:] == "bc":
            if bot_bc is not None and bc_id[:3] == "bot":
                bcs.append(
                    DirichletBC(V, Constant(bot_bc), boundary,
                                topology_info[bc_id]))
            elif left_bc is not None and bc_id[:4] == "left":
                bcs.append(
                    DirichletBC(V, Constant(left_bc), boundary,
                                topology_info[bc_id]))
            elif top_bc is not None and bc_id[:3] == "top":
                bcs.append(
                    DirichletBC(V, Constant(top_bc), boundary,
                                topology_info[bc_id]))
            elif right_bc is not None and bc_id[:5] == "right":
                bcs.append(
                    DirichletBC(V, Constant(right_bc), boundary,
                                topology_info[bc_id]))
            else:
                print(bc_id + " Not assigned as boundary condition ")
            #    raise NotImplementedError

    # Define new measures associated with the interior domains and
    # exterior boundaries
    dx = Measure("dx", subdomain_data=subdomains)
    ds = Measure("ds", subdomain_data=boundary)

    f = Constant(0)
    g = Constant(0)
    if geometry is not None:  # run multipatch implementation (Multiple domains)
        a = []
        L = []
        for patch_id in geometry.keys():
            kappa = geometry[patch_id].get("kappa")
            a.append(
                inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) *
                dx(topology_info[patch_id]))
            L.append(f * v * dx(topology_info[patch_id]))
        a = sum(a)
        L = sum(L)
    else:
        a = inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) * dx
        L = f * v * dx

    ## Redefine u as a function in function space V for the solution
    u = Function(V)
    # Solve
    solve(a == L, u, bcs)
    u.rename('u', 'Temperature')
    # Save solution to file in VTK format
    print('  [+] Output to %s_solution.pvd' % filepath.split('.')[0])
    vtkfile = File('%s_solution.pvd' % filepath.split('.')[0])
    vtkfile << u

    if show:
        import matplotlib
        matplotlib.use("Qt5Agg")
        # Plot solution and gradient
        plot(u, title="Temperature")
        plt.gca().view_init(azim=-90, elev=90)
        plt.show()

    dofs = V.tabulate_dof_coordinates().reshape(
        V.dim(),
        mesh.geometry().dim())  #coordinates of nodes
    vals = u.vector().get_local()  #temperature at nodes

    if save_solution:
        from dolfin import HDF5File, MPI
        output_file = HDF5File(MPI.comm_world,
                               filepath.split('.')[0] + "_solution_field.h5",
                               "w")
        output_file.write(u, "solution")
        output_file.close()
    u.set_allow_extrapolation(True)
    return dofs, vals, mesh, u
Ejemplo n.º 10
0
class TestLumpedMass(unittest.TestCase):
    def setUp(self):
        mesh = UnitSquareMesh(5, 5, 'crossed')
        self.V = FunctionSpace(mesh, 'Lagrange', 5)
        self.u = Function(self.V)
        self.uM = Function(self.V)
        self.uMdiag = Function(self.V)
        test = TestFunction(self.V)
        trial = TrialFunction(self.V)
        m = test * trial * dx
        self.M = assemble(m)
        self.solver = LUSolver()
        self.solver.parameters['reuse_factorization'] = True
        self.solver.parameters['symmetric'] = True
        self.solver.set_operator(self.M)
        self.ones = np.ones(self.V.dim())

    def test00(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolver(self.V)

    def test01_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)

    def test01_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for index, ii in enumerate(self.M.array()):
            err += abs(ii.sum() - myobj.Mdiag[index])
        self.assertTrue(err < index * 1e-16)

    def test02(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1. / myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii * 1e-16)

    def test03_basic(self):
        """ solve """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = (myobj.one - self.uMdiag.vector()).array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.one.array()) < 1e-14)

    def test04_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolver(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj * myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.Mdiag.array()) < 1e-14)

    def test10(self):
        """ Create a lumped solver """
        myobj = LumpedMatrixSolverS(self.V)

    def test11_set(self):
        """ Set operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)

    def test11_entries(self):
        """ Lump matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        Msum = np.dot(self.ones, self.M.array().dot(self.ones))
        err = abs(myobj.Mdiag.array().dot(self.ones) - \
        Msum) / Msum
        self.assertTrue(err < 1e-14, err)

    def test12(self):
        """ Invert lumped matrix """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        err = 0.0
        for ii in range(len(myobj.Mdiag.array())):
            err += abs(1. / myobj.Mdiag[ii] - myobj.invMdiag[ii])
        self.assertTrue(err < ii * 1e-16)

    def test13_basic(self):
        """ solve """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        myobj.solve(self.uMdiag.vector(), myobj.Mdiag)
        diff = myobj.one.array() - self.uMdiag.vector().array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.one.array()) < 1e-14)

    def test14_mult(self):
        """ overloaded * operator """
        myobj = LumpedMatrixSolverS(self.V)
        myobj.set_operator(self.M)
        self.uMdiag.vector().axpy(1.0, myobj * myobj.one)
        diff = (myobj.Mdiag - self.uMdiag.vector()).array()
        self.assertTrue(
            np.linalg.norm(diff) / np.linalg.norm(myobj.Mdiag.array()) < 1e-14)
Ejemplo n.º 11
0
class PiecewiseEllipse:
    def __init__(self, centers, J, n):
        self.centers = centers
        self.J = J

        self.target = 0.002
        self.J /= self.target

        # dir_path = os.path.dirname(os.path.realpath(__file__))
        # with open(os.path.join(dir_path, '../colorio/data/gamut_triangulation.yaml')) as f:
        #     data = yaml.safe_load(f)

        # self.points = numpy.column_stack([
        #     data['points'], numpy.zeros(len(data['points']))
        #     ])
        # self.cells = numpy.array(data['cells'])

        # self.points, self.cells = colorio.xy_gamut_mesh(0.15)

        self.points, self.cells = meshzoo.triangle(n,
                                                   corners=numpy.array(
                                                       [[0.0, 0.0], [1.0, 0.0],
                                                        [0.0, 1.0]]))

        # https://bitbucket.org/fenics-project/dolfin/issues/845/initialize-mesh-from-vertices
        editor = MeshEditor()
        mesh = Mesh()
        editor.open(mesh, "triangle", 2, 2)
        editor.init_vertices(self.points.shape[0])
        editor.init_cells(self.cells.shape[0])
        for k, point in enumerate(self.points):
            editor.add_vertex(k, point)
        for k, cell in enumerate(self.cells):
            editor.add_cell(k, cell)
        editor.close()

        self.V = FunctionSpace(mesh, "CG", 1)
        self.Vgrad = VectorFunctionSpace(mesh, "DG", 0)

        # self.ux0 = Function(self.V)
        # self.uy0 = Function(self.V)

        # 0 starting guess
        # ax = numpy.zeros(self.V.dim())
        # ay = numpy.zeros(self.V.dim())

        # Use F(x, y) = (x, y) as starting guess
        self.ux0 = project(Expression("x[0]", degree=1), self.V)
        self.uy0 = project(Expression("x[1]", degree=1), self.V)
        ax = self.ux0.vector().get_local()
        ay = self.uy0.vector().get_local()
        # Note that alpha doesn't contain the values in the order that one might expect,
        # see
        # <https://www.allanswered.com/post/awevg/projectexpressionx0-v-vector-get_local-not-in-order/>.
        self.alpha = numpy.concatenate([ax, ay])

        self.num_f_eval = 0

        # Build L as scipy.csr_matrix
        u = TrialFunction(self.V)
        v = TestFunction(self.V)
        L = assemble(dot(grad(u), grad(v)) * dx)
        Lmat = as_backend_type(L).mat()
        indptr, indices, data = Lmat.getValuesCSR()

        size = Lmat.getSize()
        self.L = sparse.csr_matrix((data, indices, indptr), shape=size)
        self.LT = self.L.getH()

        self.dx, self.dy = build_grad_matrices(self.V, centers)
        self.dxT = self.dx.getH()
        self.dyT = self.dy.getH()
        return

    def apply_M(self, ax, ay):
        """Linear operator that converts ax, ay to abcd."""
        jac = numpy.array([[self.dx.dot(ax), self.dy.dot(ax)],
                           [self.dx.dot(ay), self.dy.dot(ay)]])

        # jacs and J are of shape (2, 2, k). M must be of the same shape and
        # contain the result of the k 2x2 dot products. Perhaps there's a
        # dot() for this.
        M = numpy.einsum("ijl,jkl->ikl", jac, self.J)
        # M = numpy.array([
        #     [
        #         jac[0][0]*self.J[0][0] + jac[0][1]*self.J[1][0],
        #         jac[0][0]*self.J[0][1] + jac[0][1]*self.J[1][1],
        #     ],
        #     [
        #         jac[1][0]*self.J[0][0] + jac[1][1]*self.J[1][0],
        #         jac[1][0]*self.J[0][1] + jac[1][1]*self.J[1][1],
        #     ],
        #     ])

        # One could use
        #
        #     M = numpy.moveaxis(M, -1, 0)
        #     _, sigma, _ = numpy.linalg.svd(M)
        #
        # but computing the singular values explicitly via
        # <https://scicomp.stackexchange.com/a/14103/3980> is faster and more
        # explicit.
        a = (M[0, 0] + M[1, 1]) / 2
        b = (M[0, 0] - M[1, 1]) / 2
        c = (M[1, 0] + M[0, 1]) / 2
        d = (M[1, 0] - M[0, 1]) / 2

        return a, b, c, d

    def apply_M_alt(self, ax, ay):
        X = numpy.array([
            self.dx.dot(ax),
            self.dy.dot(ax),
            self.dx.dot(ay),
            self.dy.dot(ay)
        ])

        Y = numpy.array([
            X[0] * self.J[0][0] + X[1] * self.J[1][0],
            X[0] * self.J[0][1] + X[1] * self.J[1][1],
            X[2] * self.J[0][0] + X[3] * self.J[1][0],
            X[2] * self.J[0][1] + X[3] * self.J[1][1],
        ])

        Z = 0.5 * numpy.array(
            [Y[0] + Y[3], Y[0] - Y[3], Y[2] + Y[1], Y[2] - Y[1]])
        return Z

    def apply_MT(self, abcd):
        a, b, c, d = abcd
        X = 0.5 * numpy.array([a + b, c - d, c + d, a - b])

        Y = numpy.array([
            X[0] * self.J[0][0] + X[1] * self.J[0][1],
            X[0] * self.J[1][0] + X[1] * self.J[1][1],
            X[2] * self.J[0][0] + X[3] * self.J[0][1],
            X[2] * self.J[1][0] + X[3] * self.J[1][1],
        ])

        Z = numpy.array([
            self.dxT.dot(Y[0]) + self.dyT.dot(Y[1]),
            self.dxT.dot(Y[2]) + self.dyT.dot(Y[3]),
        ])
        return Z

    def get_q2_r2(self, ax, ay):
        a, b, c, d = self.apply_M(ax, ay)
        # From the square roots of q2 and r2, the ellipse axes can be computed,
        # namely
        #
        #   s1 = q + r
        #   s2 = q - r
        #
        q2 = a**2 + d**2
        r2 = b**2 + c**2
        return q2, r2

    def jac_q2_r2(self, ax, ay, bx, by):
        a, b, c, d = self.apply_M(ax, ay)
        #
        e, f, g, h = self.apply_M(bx, by)
        out1 = 2 * (a * e + d * h)
        out2 = 2 * (b * f + c * g)
        return out1, out2

    def jacT_q2_r2(self, ax, ay, out1, out2):
        a, b, c, d = self.apply_M(ax, ay)
        #
        X = 2 * numpy.array([a * out1, b * out2, c * out2, d * out1])
        Y = self.apply_MT(X)
        return Y

    def get_ellipse_axes(self, alpha):
        ax, ay = numpy.split(alpha, 2)
        q, r = numpy.sqrt(self.get_q2_r2(ax, ay))
        sigma = numpy.array([q + r, q - r]) * self.target
        return sigma

    def cost_ls(self, alpha):
        n = self.V.dim()
        ax = alpha[:n]
        ay = alpha[n:]

        # res_x, res_y = self.L.dot(numpy.column_stack([ax, ay])).T
        res_x = self.L.dot(ax)
        res_y = self.L.dot(ay)

        q2, r2 = self.get_q2_r2(ax, ay)

        # Some word on the (absence of) weights here.
        # Weights on the residuals are not required: The residual entries are integrals
        # with the test functions, so they'll naturally decrease in absolute value as
        # the cell size decreases.
        # One idea for scaling q2 and r2 would be to divide by the number of measurement
        # points (or rather the sqrt thereof). This would ensure that, if more measure
        # points are added, they as a set aren't weighted more than the other quality
        # indicators, e.g., the smoothness in x and y.  On the other hand, by omitting
        # an explicit weight that depends on the number of data points, one asserts that
        # additional measurements do not decrease the weights on the other measurements.
        # As consequence, more measurements as a set take a higher relative weight in
        # the cost function. This is what we want.
        out = numpy.array([res_x, res_y, q2 - 1.0, r2])

        self.num_f_eval += 1
        if self.num_f_eval % 100 == 0:
            cost = numpy.array([numpy.dot(ot, ot) for ot in out])
            print("{:7d}     {:e} {:e} {:e} {:e}".format(
                self.num_f_eval, *cost))

        return numpy.concatenate(out)

    def jac_ls(self, alpha):
        m = 2 * self.V.dim() + 2 * self.centers.shape[0]
        n = alpha.shape[0]

        d = self.V.dim()
        c = self.centers.shape[0]
        assert 2 * d == n

        ax = alpha[:d]
        ay = alpha[d:]
        jac_alpha = numpy.array([[self.dx.dot(ax),
                                  self.dy.dot(ax)],
                                 [self.dx.dot(ay),
                                  self.dy.dot(ay)]])
        M_alpha = numpy.einsum("ijl,jkl->ikl", jac_alpha, self.J)
        a_alpha = (M_alpha[0, 0] + M_alpha[1, 1]) / 2
        b_alpha = (M_alpha[0, 0] - M_alpha[1, 1]) / 2
        c_alpha = (M_alpha[1, 0] + M_alpha[0, 1]) / 2
        d_alpha = (M_alpha[1, 0] - M_alpha[0, 1]) / 2

        def matvec(phi):
            if len(phi.shape) > 1:
                assert len(phi.shape) == 2
                assert phi.shape[1] == 1
                phi = phi[:, 0]

            # Laplace part (it's linear, so this is easy)
            ax = phi[:d]
            ay = phi[d:]
            res_x = self.L.dot(ax)
            res_y = self.L.dot(ay)

            # q2, r2 part
            jac_phi = numpy.array([[self.dx.dot(ax),
                                    self.dy.dot(ax)],
                                   [self.dx.dot(ay),
                                    self.dy.dot(ay)]])
            M_phi = numpy.einsum("ijl,jkl->ikl", jac_phi, self.J)
            a_phi = M_phi[0, 0] + M_phi[1, 1]
            b_phi = M_phi[0, 0] - M_phi[1, 1]
            c_phi = M_phi[1, 0] + M_phi[0, 1]
            d_phi = M_phi[1, 0] - M_phi[0, 1]
            dq2_phi = a_alpha * a_phi + d_alpha * d_phi
            dr2_phi = b_alpha * b_phi + c_alpha * c_phi

            return numpy.concatenate([res_x, res_y, dq2_phi, dr2_phi])

        def rmatvec(vec):
            res_x = vec[:d]
            res_y = vec[d:2 * d]
            dq2_phi = vec[2 * d:2 * d + c]
            dr2_phi = vec[2 * d + c:]

            X = numpy.array([
                a_alpha * dq2_phi,
                b_alpha * dr2_phi,
                c_alpha * dr2_phi,
                d_alpha * dq2_phi,
            ])
            Y = numpy.array(
                [X[0] + X[1], X[2] - X[3], X[2] + X[3], X[0] - X[1]])
            Z = numpy.array([
                self.J[0][0] * Y[0] + self.J[0][1] * Y[1],
                self.J[1][0] * Y[0] + self.J[1][1] * Y[1],
                self.J[0][0] * Y[2] + self.J[0][1] * Y[3],
                self.J[1][0] * Y[2] + self.J[1][1] * Y[3],
            ])

            return numpy.concatenate([
                self.LT.dot(res_x) + self.dxT.dot(Z[0]) + self.dyT.dot(Z[1]),
                self.LT.dot(res_y) + self.dxT.dot(Z[2]) + self.dyT.dot(Z[3]),
            ])

        # # test matvec
        # u = alpha
        # numpy.random.seed(0)
        # du = numpy.random.rand(n)
        # # du = numpy.zeros(n)
        # # du[0] = 1.0
        # eps = 1.0e-10
        # fupdu = self.cost(u + eps*du)
        # fumdu = self.cost(u - eps*du)
        # fu = self.cost(u)
        # ndiff1 = (fupdu - fu) / eps
        # ndiff2 = (fu - fumdu) / eps
        # ndiff3 = (fupdu - fumdu) / (2*eps)
        # jdiff1 = matvec(du)
        # jdiff2 = numpy.dot(matrix, du)
        # print()
        # d = self.V.dim()
        # print(ndiff1[-4:])
        # print(ndiff2[-4:])
        # print(ndiff3[-4:])
        # print(jdiff1[-4:])
        # print(jdiff2[-4:])
        # print()

        return LinearOperator([m, n], matvec=matvec, rmatvec=rmatvec)

    def cost_min(self, alpha):
        n = self.V.dim()
        ax = alpha[:n]
        ay = alpha[n:]

        Lax = self.L * ax
        Lay = self.L * ay

        q2, r2 = self.get_q2_r2(ax, ay)

        out = [
            0.5 * numpy.dot(Lax, Lax),
            0.5 * numpy.dot(Lay, Lay),
            0.5 * numpy.dot(q2 - 1, q2 - 1),
            0.5 * numpy.dot(r2, r2),
        ]

        if self.num_f_eval % 10000 == 0:
            print("{:7d}     {:e} {:e} {:e} {:e}".format(
                self.num_f_eval, *out))

        self.num_f_eval += 1
        return numpy.sum(out)

    def grad_min(self, alpha, assert_equality=False):
        n = self.V.dim()

        if assert_equality:
            M = []
            for k in range(30):
                e = numpy.zeros(30)
                e[k] = 1.0
                ax = e[:n]
                ay = e[n:]
                M.append(numpy.concatenate(self.apply_M_alt(ax, ay)))
            M = numpy.column_stack(M)

            MT = []
            for k in range(100):
                e = numpy.zeros(100)
                e[k] = 1.0
                abcd = numpy.array([e[:25], e[25:50], e[50:75], e[75:]])
                MT.append(numpy.concatenate(self.apply_MT(abcd)))
            MT = numpy.column_stack(MT)
            assert numpy.all(abs(M.T - MT) < 1.0e-13)

        if assert_equality:
            M = []
            for k in range(30):
                e = numpy.zeros(30)
                e[k] = 1.0
                bx = e[:n]
                by = e[n:]
                M.append(numpy.concatenate(self.jac_q2_r2(ax, ay, bx, by)))
            M = numpy.column_stack(M)

            MT = []
            for k in range(50):
                e = numpy.zeros(50)
                e[k] = 1.0
                out1 = e[:25]
                out2 = e[25:]
                MT.append(
                    numpy.concatenate(self.jacT_q2_r2(ax, ay, out1, out2)))
            MT = numpy.column_stack(MT)
            assert numpy.all(abs(M.T - MT) < 1.0e-13)

        ax = alpha[:n]
        ay = alpha[n:]

        q2, r2 = self.get_q2_r2(ax, ay)
        j = self.jacT_q2_r2(ax, ay, q2 - 1, r2)

        out = [
            self.LT.dot(self.L.dot(ax)) + j[0],
            self.LT.dot(self.L.dot(ay)) + j[1]
        ]

        if assert_equality:
            n = len(alpha)
            g = []
            for k in range(n):
                e = numpy.zeros(n)
                e[k] = 1.0
                eps = 1.0e-5
                f0 = self.cost_min(alpha - eps * e)
                f1 = self.cost_min(alpha + eps * e)
                g.append((f1 - f0) / (2 * eps))

            # print(numpy.array(g))
            # print(numpy.concatenate(out))
            assert numpy.all(
                abs(numpy.array(g) - numpy.concatenate(out)) < 1.0e-5)

        return numpy.concatenate(out)

    def cost_min2(self, alpha):
        """Residual formulation, Hessian is a low-rank update of the identity."""
        n = self.V.dim()
        ax = alpha[:n]
        ay = alpha[n:]

        # ml = pyamg.ruge_stuben_solver(self.L)
        # # ml = pyamg.smoothed_aggregation_solver(self.L)
        # print(ml)
        # print()
        # print(self.L)
        # print()
        # x = ml.solve(ax, tol=1e-10)
        # print('residual: {}'.format(numpy.linalg.norm(ax - self.L*x)))
        # print()
        # print(ax)
        # print()
        # print(x)
        # exit(1)

        # x = sparse.linalg.spsolve(self.L, ax)
        # print('residual: {}'.format(numpy.linalg.norm(ax - self.L*x)))
        # exit(1)

        q2, r2 = self.get_q2_r2(ax, ay)

        Lax = self.L * ax
        Lay = self.L * ay

        out = [
            0.5 * numpy.dot(Lax, Lax),
            0.5 * numpy.dot(Lay, Lay),
            0.5 * numpy.dot(q2 - 1, q2 - 1),
            0.5 * numpy.dot(r2, r2),
        ]

        if self.num_f_eval % 10000 == 0:
            print("{:7d}     {:e} {:e} {:e} {:e}".format(
                self.num_f_eval, *out))

        self.num_f_eval += 1
        return numpy.sum(out)

    def get_u(self, alpha):
        n = self.V.dim()
        ax = alpha[:n]
        ay = alpha[n:]

        ux = Function(self.V)
        ux.vector().set_local(ax)
        ux.vector().apply("")

        uy = Function(self.V)
        uy.vector().set_local(ay)
        uy.vector().apply("")
        return ux, uy
Ejemplo n.º 12
0
class Problem(object):
  def __init__(self, coarse_mesh, nref, p_coarse, p_fine, sym=False):
    """

    :param dolfin.cpp.mesh.Mesh coarse_mesh:
    :param int nref:
    :param int p_coarse:
    :param int p_fine:
    :param bool sym:
    :return:
    """

    print0("Creating approximation spaces")

    self.V_coarse = FunctionSpace(coarse_mesh, "CG", p_coarse)
    self.ndof_coarse = self.V_coarse.dim()

    refined_mesh = coarse_mesh
    for ref in xrange(nref):
      refined_mesh = refine(refined_mesh)   # creates a new Mesh, initial coarse mesh is unchanged

    self.V_fine = FunctionSpace(refined_mesh, "CG", p_fine)
    self.ndof_fine = self.V_fine.dim()

    H = coarse_mesh.hmax()
    h = refined_mesh.hmax()
    self.alpha = log(H)/log(h)
    self.beta = p_fine + 1

    if comm.rank == 0:
      prop = Table("Approximation properties")
      prop.set("ndof", "coarse", self.ndof_coarse)
      prop.set("ndof", "fine", self.ndof_fine)
      prop.set("h", "coarse", H)
      prop.set("h", "fine", h)

      info(prop)

      print "alpha = {}, beta = {}".format(self.alpha, self.beta)

    self.bc_coarse = None

    self.A_fine = PETScMatrix()
    self.B_fine = PETScMatrix()
    self.A_coarse = PETScMatrix()
    self.B_coarse = PETScMatrix()

    self.sym = sym
    self.switch_gep_matrices = False

  def identity_at_coarse_level(self):
    I = PETScMatrix()
    u = TrialFunction(self.V_coarse)
    v = TestFunction(self.V_coarse)
    assemble(Constant(0)*u*v*dx, tensor=I)
    I.ident_zeros()
    return I

  def residual_norm(self, vec, lam, norm_type='l2', A=None, B=None):
    if A is None:
      A = self.A_fine
      B = self.B_fine

    r = PETScVector()
    A.mult(vec, r)

    if B.size(0) > 0:
      y = PETScVector()
      B.mult(vec, y)
    else:
      y = 1

    r -= lam*y

    return norm(r,norm_type)

  def rayleigh_quotient(self, vec, A=None, B=None):
    if A is None:
      A = self.A_fine
      B = self.B_fine

    r = PETScVector()
    A.mult(vec, r)
    nom = MPI_sum( numpy.dot(r, vec) )

    if B.size(0) > 0:
      B.mult(vec, r)
      denom = MPI_sum( numpy.dot(r, vec) )
    else:
      denom = sqr(norm(r, norm_type='l2'))

    return nom/denom
Ejemplo n.º 13
0
class Discretization(object):
  def __init__(self, problem, verbosity=0):
    """

    :param ProblemData problem:
    :param int verbosity:
    :return:
    """
    self.parameters = parameters["discretization"]

    self.verb = verbosity
    self.vis_folder = os.path.join(problem.out_folder, "MESH")
    self.core = problem.core
    self.G = problem.G

    if self.verb > 1: print pid+"Loading mesh"
        
    t_load = Timer("DD: Data loading")

    if not problem.mesh_module:
      if self.verb > 1: print pid + "  mesh data"
      self.mesh = Mesh(problem.mesh_files.mesh)

      if self.verb > 1: print pid + "  physical data"
      self.cell_regions_fun = MeshFunction("size_t", self.mesh, problem.mesh_files.physical_regions)

      if self.verb > 1: print pid + "  boundary data"
      self.boundaries = MeshFunction("size_t", self.mesh, problem.mesh_files.facet_regions)
    else:
      self.mesh = problem.mesh_module.mesh
      self.cell_regions_fun = problem.mesh_module.regions

      try:
        self.boundaries = problem.mesh_module.boundaries
      except AttributeError:
        self.boundaries = None

    assert self.mesh
    assert self.boundaries is None or self.boundaries.array().size > 0

    if self.verb > 2:
      print pid+"  mesh info: " + str(self.mesh)

    if self.verb > 1: print0("Defining function spaces" )

    self.t_spaces = Timer("DD: Function spaces construction")

    # Spaces that must be specified by the respective subclasses
    self.V = None     # solution space
    self.Vphi1 = None # 1-g scalar flux space
    
    # XS / TH space
    self.V0 = FunctionSpace(self.mesh, "DG", 0)
    self.ndof0 = self.V0.dim()

    dofmap = self.V0.dofmap()
    self.local_ndof0 = dofmap.local_dimension("owned")

    self.cell_regions = self.cell_regions_fun.array()
    assert self.cell_regions.size == self.local_ndof0

  def __create_cell_dof_mapping(self, dofmap):
    """
    Generate cell -> dof mapping for all cells of current partition.
    Note: in DG(0) space, there is one dof per element and no ghost cells.

    :param GenericDofMap dofmap: DG(0) dofmap
    """

    if self.verb > 2: print0("Constructing cell -> dof mapping")
    timer = Timer("DD: Cell->dof construction")

    code = \
    '''
      #include <dolfin/mesh/Cell.h>

      namespace dolfin
      {
        void fill_in(Array<int>& local_cell_dof_map, const Mesh& mesh, const GenericDofMap& dofmap)
        {
          std::size_t local_dof_range_start = dofmap.ownership_range().first;
          int* cell_dof_data = local_cell_dof_map.data();

          for (CellIterator c(mesh); !c.end(); ++c)
            *cell_dof_data++ = dofmap.cell_dofs(c->index())[0] - local_dof_range_start;
        }
      }
    '''

    cell_mapping_module = compile_extension_module(code)
    cell_dof_array = IntArray(self.local_ndof0)
    cell_mapping_module.fill_in(cell_dof_array, self.mesh, dofmap)
    self._local_cell_dof_map = cell_dof_array.array()

    timer.stop()

  def __create_cell_layers_mapping(self):
    """
    Generate a cell -> axial layer mapping for all cells of current partition. Note that keys are ordered by the
    associated DG(0) dof, not by the cell index in the mesh.
    """

    if self.verb > 2: print0("Constructing cell -> layer mapping")
    timer = Timer("DD: Cell->layer construction")

    code = \
    '''
      #include <dolfin/mesh/Cell.h>

      namespace dolfin
      {
        void fill_in(Array<int>& local_cell_layers,
                     const Mesh& mesh, const Array<int>& cell_dofs, const Array<double>& layer_boundaries)
        {
          std::size_t num_layers = layer_boundaries.size() - 1;
          unsigned int layer;

          for (CellIterator c(mesh); !c.end(); ++c)
          {
            double midz = c->midpoint().z();
            for (layer = 0; layer < num_layers; layer++)
              if (layer_boundaries[layer] <= midz && midz <= layer_boundaries[layer+1])
                break;

            int dof = cell_dofs[c->index()];
            local_cell_layers[dof] = layer;
          }
        }
      }
    '''

    cell_mapping_module = compile_extension_module(code)

    cell_layers_array =  IntArray(self.local_ndof0)
    cell_mapping_module.fill_in(cell_layers_array, self.mesh, self.local_cell_dof_map, self.core.layer_boundaries)
    self._local_cell_layers = cell_layers_array.array()

    timer.stop()

  def __create_cell_vol_mapping(self):
    """
    Generate cell -> volume mapping for all cells of current partition. Note that keys are ordered by the
    associated DG(0) dof, not by the cell index in the mesh.

    This map is required for calculating various densities from total region integrals (like cell power densities from
    cell-integrated powers).
    """

    if self.verb > 2: print0("Constructing cell -> volume mapping")
    timer = Timer("DD: Cell->vol construction")

    code = \
    '''
      #include <dolfin/mesh/Cell.h>

      namespace dolfin
      {
        void fill_in(Array<double>& cell_vols, const Mesh& mesh, const Array<int>& cell_dofs)
        {
          for (CellIterator c(mesh); !c.end(); ++c)
            cell_vols[cell_dofs[c->index()]] = c->volume();
        }
      }
    '''

    cell_mapping_module = compile_extension_module(code)
    cell_vol_array = DoubleArray(self.local_ndof0)
    cell_mapping_module.fill_in(cell_vol_array, self.mesh, self.local_cell_dof_map)
    self._local_cell_volumes = cell_vol_array.array()

    timer.stop()

  @property
  def local_cell_dof_map(self):
    try:
      self._local_cell_dof_map
    except AttributeError:
      self.__create_cell_dof_mapping(self.V0.dofmap())
    return self._local_cell_dof_map

  @property
  def local_cell_volumes(self):
    try:
      self._local_cell_volumes
    except AttributeError:
      self.__create_cell_vol_mapping()
    return self._local_cell_volumes

  @property
  def local_cell_layers(self):
    try:
      self._local_cell_layers
    except AttributeError:
      self.__create_cell_layers_mapping()
    return self._local_cell_layers

  def visualize_mesh_data(self):
    timer = Timer("DD: Mesh data visualization")
    if self.verb > 2: print0("Visualizing mesh data")

    File(os.path.join(self.vis_folder, "mesh.pvd"), "compressed") << self.mesh
    if self.boundaries:
      File(os.path.join(self.vis_folder, "boundaries.pvd"), "compressed") << self.boundaries
    File(os.path.join(self.vis_folder, "mesh_regions.pvd"), "compressed") << self.cell_regions_fun

    # Create MeshFunction to hold cell process rank
    processes = CellFunction('size_t', self.mesh, MPI.rank(comm))
    File(os.path.join(self.vis_folder, "mesh_partitioning.pvd"), "compressed") << processes

  def print_diagnostics(self):
    print "\nDiscretization diagnostics"

    print MPI.rank(comm), self.mesh.num_entities(self.mesh.topology().dim())

    dofmap = self.V0.dofmap()

    print MPI.rank(comm), dofmap.ownership_range()
    print MPI.rank(comm), numpy.min(dofmap.collapse(self.mesh)[1].values()), \
          numpy.max(dofmap.collapse(self.mesh)[1].values())

    print "#Owned by {}: {}".format(MPI.rank(comm), dofmap.local_dimension("owned"))
    print "#Unowned by {}: {}".format(MPI.rank(comm), dofmap.local_dimension("unowned"))
Ejemplo n.º 14
0
        print('-- p = {0}, N = {1} --------'.format(p, Ne))
        filen_data = 'data/t%d_d%d_Nm%d_p%.2d_Ne%.3d' % (problem, dim, Ne_max,
                                                         p, Ne)

        if dim == 2:
            mesh = UnitSquareMesh(Ne, Ne)
            Amat = Expression("1+10*exp(x[0])*exp(x[1])", degree=2)
        elif dim == 3:
            mesh = UnitCubeMesh(Ne, Ne, Ne)
            Amat = Expression("1+100*exp(x[0])*exp(x[1])*x[2]*x[1]", degree=3)

        mesh.coordinates()[:] += 0.1 * np.random.random(
            mesh.coordinates().shape)  # mesh perturbation

        V = FunctionSpace(mesh, 'CG', p)
        print('V.dim = {0}'.format(V.dim()))

        if calculate in [1, -1]:
            ut, vt = TrialFunction(V), TestFunction(V)
            print('generating matrices A, Ad, A_T')
            if problem == 0:
                AG = assemble(Amat * ut * vt * dx, tensor=EigenMatrix())
                A_T = get_A_T_empty(V, problem=problem, full=False)
            else:
                AG = assemble(inner(Amat * grad(ut), grad(vt)) * dx,
                              tensor=EigenMatrix())
                A_T = get_A_T_empty(V, problem=problem, full=False)

            print('generating matrices B, B0...')
            B0 = get_Bhat(dim=dim, pol_order=p, problem=problem)
Ejemplo n.º 15
0
    from dolfin import XDMFFile, inner, grad, dx, assemble
    from interpreter import Eval
    # Build a monomial basis for x, y, x**2, xy, y**2, ...

    try:
        from pydmd import DMD
        # https://github.com/mathLab/PyDMD
    except ImportError:
        from xcalc.dmdbase import DMD

    deg = 4

    mesh = UnitSquareMesh(3, 3)
    V = FunctionSpace(mesh, 'CG', 1)
    f = interpolate(Expression('x[0]+x[1]', degree=1), V).vector().get_local()
    A = np.diag(np.random.rand(V.dim()))

    basis = []
    for i in range(deg):
        for j in range(deg):
            f = A.dot(f)
            Af = Function(V); Af.vector().set_local(f)
            basis.append(Af)
            
    # NOTE: skipping 1 bacause Eval of it is not a Function
    dmd_ = DMD(svd_rank=-1, exact=False)
    energy, pod_basis = dmd(basis[1:], dmd_)

    print np.linalg.norm(dmd_.snapshots - dmd_.reconstructed_data.real)
    print len(pod_basis), len(basis[1:])
Ejemplo n.º 16
0
    def _evaluateLocalEstimator(cls, mu, w, coeff_field, pde, f, quadrature_degree, epsilon=1e-5):
        """Evaluation of patch local equilibrated estimator."""

        # prepare numerical flux and f
        sigma_mu, f_mu = evaluate_numerical_flux(w, mu, coeff_field, f)

        # ###################
        # ## MIXED PROBLEM ##
        # ###################

        # get setup data for mixed problem
        V = w[mu]._fefunc.function_space()
        mesh = V.mesh()
        mesh.init()
        degree = element_degree(w[mu]._fefunc)

        # data for nodal bases
        V_dm = V.dofmap()
        V_dofs = dict([(i, V_dm.cell_dofs(i)) for i in range(mesh.num_cells())])
        V1 = FunctionSpace(mesh, 'CG', 1)   # V1 is to define nodal base functions
        phi_z = Function(V1)
        phi_coeffs = np.ndarray(V1.dim())
        vertex_dof_map = V1.dofmap().vertex_to_dof_map(mesh)
        # vertex_dof_map = vertex_to_dof_map(V1)
        dof_list = vertex_dof_map.tolist()
        # DG0 localisation
        DG0 = FunctionSpace(mesh, 'DG', 0)
        DG0_dofs = dict([(c.index(),DG0.dofmap().cell_dofs(c.index())[0]) for c in cells(mesh)])
        dg0 = TestFunction(DG0)
        # characteristic function of patch
        xi_z = Function(DG0)
        xi_coeffs = np.ndarray(DG0.dim())
        # mesh data
        h = CellSize(mesh)
        n = FacetNormal(mesh)
        cf = CellFunction('size_t', mesh)
        # setup error estimator vector
        eq_est = np.zeros(DG0.dim())

        # setup global equilibrated flux vector
        DG = VectorFunctionSpace(mesh, "DG", degree)
        DG_dofmap = DG.dofmap()

        # define form functions
        tau = TrialFunction(DG)
        v = TestFunction(DG)

        # define global tau
        tau_global = Function(DG)
        tau_global.vector()[:] = 0.0

        # iterate vertices
        for vertex in vertices(mesh):
            # get patch cell indices
            vid = vertex.index()
            patch_cid, FF_inner, FF_boundary = get_vertex_patch(vid, mesh, layers=1)

            # set nodal base function
            phi_coeffs[:] = 0
            phi_coeffs[dof_list.index(vid)] = 1
            phi_z.vector()[:] = phi_coeffs

            # set characteristic function and mark patch
            cf.set_all(0)
            xi_coeffs[:] = 0
            for cid in patch_cid:
                xi_coeffs[DG0_dofs[int(cid)]] = 1
                cf[int(cid)] = 1
            xi_z.vector()[:] = xi_coeffs

            # determine local dofs
            lDG_cell_dofs = dict([(cid, DG_dofmap.cell_dofs(cid)) for cid in patch_cid])
            lDG_dofs = [cd.tolist() for cd in lDG_cell_dofs.values()]
            lDG_dofs = list(iter.chain(*lDG_dofs))

            # print "\nlocal DG subspace has dimension", len(lDG_dofs), "degree", degree, "cells", len(patch_cid), patch_cid
            # print "local DG_cell_dofs", lDG_cell_dofs
            # print "local DG_dofs", lDG_dofs

            # create patch measures
            dx = Measure('dx')[cf]
            dS = Measure('dS')[FF_inner]

            # define forms
            alpha = Constant(1 / epsilon) / h
            a = inner(tau,v) * phi_z * dx(1) + alpha * div(tau) * div(v) * dx(1) + avg(alpha) * jump(tau,n) * jump(v,n) * dS(1)\
                + avg(alpha) * jump(xi_z * tau,n) * jump(v,n) * dS(2)
            L = -alpha * (div(sigma_mu) + f) * div(v) * phi_z * dx(1)\
                - avg(alpha) * jump(sigma_mu,n) * jump(v,n) * avg(phi_z)*dS(1)

    #        print "L2 f + div(sigma)", assemble((f + div(sigma)) * (f + div(sigma)) * dx(0))

            # assemble forms
            lhs = assemble(a, form_compiler_parameters={'quadrature_degree': quadrature_degree})
            rhs = assemble(L, form_compiler_parameters={'quadrature_degree': quadrature_degree})

            # convert DOLFIN representation to scipy sparse arrays
            rows, cols, values = lhs.data()
            lhsA = sps.csr_matrix((values, cols, rows)).tocoo()

            # slice sparse matrix and solve linear problem
            lhsA = coo_submatrix_pull(lhsA, lDG_dofs, lDG_dofs)
            lx = spsolve(lhsA, rhs.array()[lDG_dofs])
            # print ">>> local solution lx", type(lx), lx
            local_tau = Function(DG)
            local_tau.vector()[lDG_dofs] = lx
            # print "div(tau)", assemble(inner(div(local_tau),div(local_tau))*dx(1))

            # add up local fluxes
            tau_global.vector()[lDG_dofs] += lx

        # evaluate estimator
        # maybe TODO: re-define measure dx
        eq_est = assemble( inner(tau_global, tau_global) * dg0 * (dx(0)+dx(1)),\
                           form_compiler_parameters={'quadrature_degree': quadrature_degree})

        # reorder according to cell ids
        eq_est = eq_est[DG0_dofs.values()].array()
        global_est = np.sqrt(np.sum(eq_est))
        # eq_est_global = assemble( inner(tau_global, tau_global) * (dx(0)+dx(1)), form_compiler_parameters={'quadrature_degree': quadrature_degree} )
        # global_est2 = np.sqrt(np.sum(eq_est_global))
        return global_est, FlatVector(np.sqrt(eq_est))#, tau_global
Ejemplo n.º 17
0
    def test_multiplication(self):
        print(
            '== testing multiplication of system matrix for problem of weighted projection ===='
        )

        for dim, pol_order in itertools.product([2, 3], [1, 2]):
            N = 2  # no. of elements
            print('dim={0}, pol_order={1}, N={2}'.format(dim, pol_order, N))

            # creating MESH and defining MATERIAL
            if dim == 2:
                mesh = UnitSquareMesh(N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*x[1]*(1-x[1])",
                               degree=4)  # material coefficients
            elif dim == 3:
                mesh = UnitCubeMesh(N, N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*(1-x[1])*x[2]",
                               degree=1)  # material coefficients

            mesh.coordinates()[:] += 0.1 * np.random.random(
                mesh.coordinates().shape)  # mesh perturbation

            V = FunctionSpace(mesh, "CG", pol_order)  # original FEM space
            W = FunctionSpace(mesh, "DG",
                              2 * (pol_order - 1))  # double-grid space

            print('assembling local matrices for DoGIP...')
            Bhat = get_Bhat(
                dim, pol_order, problem=1
            )  # interpolation between V on W on a reference element
            AT_dogip = get_A_T(m, V, W, problem=1)

            dofmapV = V.dofmap()

            def system_multiplication_DoGIP(AT_dogip, Bhat, u_vec):
                # matrix-vector mutliplication in DoGIP
                Au = np.zeros_like(u_vec)
                for ii, cell in enumerate(cells(mesh)):
                    ind = dofmapV.cell_dofs(ii)  # local to global map
                    Bu = Bhat.dot(u_vec[ind])
                    ABu = np.einsum('rsj,sj->rj', AT_dogip[ii], Bu)
                    Au[ind] += np.einsum('rjl,rj->l', Bhat, ABu)
                return Au

            print('assembling system matrix for FEM')
            u, v = TrialFunction(V), TestFunction(V)
            Asp = assemble(m * inner(grad(u), grad(v)) * dx,
                           tensor=EigenMatrix())
            Asp = Asp.sparray()  # sparse FEM matrix

            print('multiplication...')
            ur = Function(V)  # creating random vector
            ur_vec = 10 * np.random.random(V.dim())
            ur.vector().set_local(ur_vec)

            Au_DoGIP = system_multiplication_DoGIP(
                AT_dogip, Bhat, ur_vec)  # DoGIP multiplication
            Auex = Asp.dot(ur_vec)  # FEM multiplication with sparse matrix

            # testing the difference between DoGIP and FEniCS
            self.assertAlmostEqual(0, np.linalg.norm(Auex - Au_DoGIP))
            print('...ok')