示例#1
0
def test_local_assembler_on_facet_integrals():
    mesh = UnitSquareMesh(MPI.comm_world, 4, 4, 'right')
    Vdgt = FunctionSpace(mesh, 'DGT', 1)

    v = TestFunction(Vdgt)
    x = SpatialCoordinate(mesh)

    w = (1.0 + x[0] ** 2.2 + 1. / (0.1 + x[1] ** 3)) * 300

    # Define form that tests that the correct + and - values are used
    L = w('-') * v('+') * dS

    # Compile form. This is collective
    L = Form(L)

    # Get global cell 10. This will return a cell only on one of the
    # processes
    c = get_cell_at(mesh, 5 / 12, 1 / 3, 0)

    if c:
        # Assemble locally on the selected cell
        b_e = assemble_local(L, c)

        # Compare to values from phonyx (fully independent
        # implementation)
        b_phonyx = numpy.array([266.55210302, 266.55210302, 365.49000122, 365.49000122, 0.0, 0.0])
        error = sum((b_e - b_phonyx)**2)**0.5
        error = float(error)  # MPI.max does strange things to numpy.float64

    else:
        error = 0.0

    error = MPI.max(MPI.comm_world, float(error))
    assert error < 1e-8
def _adaptive_mesh_refinement(dx, phi, mu, sigma, omega, conv, voltages):
    from dolfin import cells, refine
    eta = _error_estimator(dx, phi, mu, sigma, omega, conv, voltages)
    mesh = phi.function_space().mesh()
    level = 0
    TOL = 1.0e-4
    E = sum([e * e for e in eta])
    E = sqrt(MPI.sum(E))
    info('Level %d: E = %g (TOL = %g)' % (level, E, TOL))
    # Mark cells for refinement
    REFINE_RATIO = 0.5
    cell_markers = MeshFunction('bool', mesh, mesh.topology().dim())
    eta_0 = sorted(eta, reverse=True)[int(len(eta) * REFINE_RATIO)]
    eta_0 = MPI.max(eta_0)
    for c in cells(mesh):
        cell_markers[c] = eta[c.index()] > eta_0
    # Refine mesh
    mesh = refine(mesh, cell_markers)
    # Plot mesh
    plot(mesh)
    interactive()
    exit()
    ## Compute error indicators
    #K = array([c.volume() for c in cells(mesh)])
    #R = array([abs(source([c.midpoint().x(), c.midpoint().y()])) for c in cells(mesh)])
    #gam = h*R*sqrt(K)
    return
示例#3
0
文件: inputoutput.py 项目: pf4d/cslvr
def print_min_max(u, title, color='97', cls=None):
	"""
	Print the minimum and maximum values of ``u``, a Vector, Function, or array.

	:param u: the variable to print the min and max of
	:param title: the name of the function to print
	:param color: the color of printed text
	:type u: :class:`~dolfin.GenericVector`, :class:`~numpy.ndarray`, :class:`~dolfin.Function`, int, float, :class:`~dolfin.Constant`
	:type title: string
	:type color: string
	"""
	if isinstance(u, GenericVector):
		uMin = MPI.min(mpi_comm_world(), u.min())
		uMax = MPI.max(mpi_comm_world(), u.max())
		s    = title + ' <min, max> : <%.3e, %.3e>' % (uMin, uMax)
		print_text(s, color, cls=cls)
	elif isinstance(u, indexed.Indexed):
		dim = u.value_rank() + 1
		for i in range(u.value_rank()):
			uMin = u.vector().array()[i : u.vector().size() : dim].min()
			uMax = u.vector().array()[i : u.vector().size() : dim].max()
			s    = title + '_%i <min, max> : <%.3e, %.3e>' % (i, uMin, uMax)
			print_text(s, color, cls=cls)
	elif isinstance(u, ndarray):
		if u.dtype != float64:
			u = u.astype(float64)
		uMin = MPI.min(mpi_comm_world(), u.min())
		uMax = MPI.max(mpi_comm_world(), u.max())
		s    = title + ' <min, max> : <%.3e, %.3e>' % (uMin, uMax)
		print_text(s, color, cls=cls)
	elif isinstance(u, Function):# \
		#   or isinstance(u, dolfin.functions.function.Function):
		uMin = MPI.min(mpi_comm_world(), u.vector().min())
		uMax = MPI.max(mpi_comm_world(), u.vector().max())
		s    = title + ' <min, max> : <%.3e, %.3e>' % (uMin, uMax)
		print_text(s, color, cls=cls)
	elif isinstance(u, int) or isinstance(u, float):
		s    = title + ' : %.3e' % u
		print_text(s, color, cls=cls)
	elif isinstance(u, Constant):
		s    = title + ' : %.3e' % u(0)
		print_text(s, color, cls=cls)
	else:
		er = title + ": print_min_max function requires a Vector, Function" \
		     + ", array, int or float, not %s." % type(u)
		print_text(er, 'red', 1)
示例#4
0
 def error(self, ys1, ys2) :
   errors = []
   
   for i in range(self.num_unknowns):
     err = MPI.max(mpi_comm_world(), (abs(ys2[i] - ys1[i])).max())
     errors.append(err)
   
   return errors
def _check_space_order(problem, method):
    mesh_generator, solution, weak_F = problem()

    # Translate data into FEniCS expressions.
    fenics_sol = Expression(smp.prining.ccode(solution['value']),
                            degree=solution['degree'],
                            t=0.0
                            )

    # Create initial solution.
    theta0 = Expression(fenics_sol.cppcode,
                        degree=solution['degree'],
                        t=0.0,
                        cell=triangle
                        )

    # Estimate the error component in space.
    # Leave out too rough discretizations to avoid showing spurious errors.
    N = [2 ** k for k in range(2, 8)]
    dt = 1.0e-8
    Err = []
    H = []
    for n in N:
        mesh = mesh_generator(n)
        H.append(MPI.max(mesh.hmax()))
        V = FunctionSpace(mesh, 'CG', 3)
        # Create boundary conditions.
        fenics_sol.t = dt
        #bcs = DirichletBC(V, fenics_sol, 'on_boundary')
        # Create initial state.
        theta_approx = method(V,
                              weak_F,
                              theta0,
                              0.0, dt,
                              bcs=[solution],
                              tol=1.0e-12,
                              verbose=True
                              )
        # Compute the error.
        fenics_sol.t = dt
        Err.append(errornorm(fenics_sol, theta_approx)
                   / norm(fenics_sol, mesh=mesh)
                   )
        print('n: %d    error: %e' % (n, Err[-1]))

    from matplotlib import pyplot as pp
    # Compare with order 1, 2, 3 curves.
    for o in [2, 3, 4]:
        pp.loglog([H[0], H[-1]],
                  [Err[0], Err[0] * (H[-1] / H[0]) ** o],
                  color='0.5'
                  )
    # Finally, the actual data.
    pp.loglog(H, Err, '-o')
    pp.xlabel('h_max')
    pp.ylabel('||u-u_h|| / ||u||')
    pp.show()
    return
示例#6
0
    def compute(self, get):
        u = get(self.valuename)

        if u is None:
            return None

        if isinstance(u, Function):
            if len(u.vector().array()) > 0:
                maximum = numpy.max(u.vector().array())
            else:
                maximum = -1e16
            return MPI.max(mpi_comm_world(), maximum)
            #return MPI.max(mpi_comm_world(), numpy.max(u.vector().array()))
        elif hasattr(u, "__len__"):
            return MPI.max(mpi_comm_world(), max(u))
        elif isinstance(u, (float,int,long)):
            return MPI.max(mpi_comm_world(), u)
        else:
            raise Exception("Unable to take max of %s" %str(u))
示例#7
0
def test_interpolation_rank0(V):
    @function.expression.numba_eval
    def expr_eval(values, x, cell_idx):
        values[:, 0] = 1.0

    f = Expression(expr_eval, shape=())
    w = interpolate(f, V)
    x = w.vector()
    assert MPI.max(MPI.comm_world, abs(x.get_local()).max()) == 1
    assert MPI.min(MPI.comm_world, abs(x.get_local()).min()) == 1
示例#8
0
    def _x_cell_id(self):
        x = self.x
        mesh = self.probes._mesh

        val = -1
        index = mesh.bounding_box_tree().compute_first_entity_collision(x)
        if (0 <= index < mesh.num_cells()):
            val = index

        return MPI.max(dolfin.mpi_comm_world(), val)
示例#9
0
def _compute_errors(problem, mesh_sizes):
    mesh_generator, solution, f, cell_type = problem()

    max_degree = 20

    if solution['degree'] > max_degree:
        warnings.warn(('Expression degree (%r) > maximum degree (%d). '
                       'Truncating.')
                      % (solution['degree'], max_degree)
                      )
        degree = 20
    else:
        degree = solution['degree']

    sol = Expression((smp.printing.ccode(solution['value'][0]),
                      smp.printing.ccode(solution['value'][1])),
                     t=0.0,
                     degree=degree,
                     cell=cell_type
                     )

    errors = numpy.empty(len(mesh_sizes))
    hmax = numpy.empty(len(mesh_sizes))
    for k, mesh_size in enumerate(mesh_sizes):
        mesh, dx, ds = mesh_generator(mesh_size)
        hmax[k] = MPI.max(mpi_comm_world(), mesh.hmax())
        V = FunctionSpace(mesh, 'CG', 1)
        # TODO don't hardcode Mu, Sigma, ...
        phi_approx = mcyl.solve_maxwell(V, dx,
                                        Mu={0: 1.0},
                                        Sigma={0: 1.0},
                                        omega=1.0,
                                        f_list=[{0: f['value']}],
                                        convections={},
                                        tol=1.0e-12,
                                        bcs=None,
                                        compute_residuals=False,
                                        verbose=False
                                        )
        #plot(sol0, mesh=mesh, title='sol')
        #plot(phi_approx[0][0], title='approx')
        ##plot(fenics_sol - theta_approx, title='diff')
        #interactive()
        #exit()
        #
        errors[k] = errornorm(sol, phi_approx[0])

    # Compute the numerical order of convergence.
    order = numpy.empty(len(errors) - 1)
    for i in range(len(errors) - 1):
        order[i] = numpy.log(errors[i + 1] / errors[i]) \
            / numpy.log(hmax[i + 1] / hmax[i])

    return errors, order, hmax
示例#10
0
def _check_spatial_order(problem, method):
    mesh_generator, solution, weak_F = problem()

    # Translate data into FEniCS expressions.
    fenics_sol = Expression(sympy.printing.ccode(solution['value']),
                            degree=solution['degree'],
                            t=0.0)

    # Create initial solution.
    theta0 = Expression(fenics_sol.cppcode,
                        degree=solution['degree'],
                        t=0.0,
                        cell=triangle)

    # Estimate the error component in space.
    # Leave out too rough discretizations to avoid showing spurious errors.
    N = [2**k for k in range(2, 8)]
    dt = 1.0e-8
    Err = []
    H = []
    for n in N:
        mesh = mesh_generator(n)
        H.append(MPI.max(mesh.hmax()))
        V = FunctionSpace(mesh, 'CG', 5)
        # Create boundary conditions.
        fenics_sol.t = dt
        # bcs = DirichletBC(V, fenics_sol, 'on_boundary')
        # Create initial state.
        theta_approx = method(V,
                              weak_F,
                              theta0,
                              0.0,
                              dt,
                              bcs=[solution],
                              tol=1.0e-12,
                              verbose=True)
        # Compute the error.
        fenics_sol.t = dt
        Err.append(
            errornorm(fenics_sol, theta_approx) / norm(fenics_sol, mesh=mesh))
        print('n: %d    error: %e' % (n, Err[-1]))

    # Plot order curves for comparison.
    for order in [2, 3, 4]:
        plt.loglog([H[0], H[-1]], [Err[0], Err[0] * (H[-1] / H[0])**order],
                   color='0.5')
    # Finally, the actual data.
    plt.loglog(H, Err, '-o')
    plt.xlabel('h_max')
    plt.ylabel('||u-u_h|| / ||u||')
    plt.show()
    return
示例#11
0
文件: helper.py 项目: pf4d/fenics_mpm
def print_min_max(u, title, color='97'):
    r"""
	Print the minimum and maximum values of ``u``, a Vector, Function, or array.

	:param u: the variable to print the min and max of
	:param title: the name of the function to print
	:param color: the color of printed text
	:type u: :class:`~fenics.GenericVector`, :class:`~numpy.ndarray`, :class:`~fenics.Function`, int, float, :class:`~fenics.Constant`
	:type title: string
	:type color: string
	"""
    if isinstance(u, GenericVector):
        uMin = MPI.min(MPI.comm_world, u.min())
        uMax = MPI.max(MPI.comm_world, u.max())
        s = title + ' <min, max> : <%.3e, %.3e>' % (uMin, uMax)
        print_text(s, color)
    elif isinstance(u, np.ndarray):
        if u.dtype != np.float64:
            u = u.astype(float64)
        uMin = MPI.min(MPI.comm_world, u.min())
        uMax = MPI.max(MPI.comm_world, u.max())
        s = title + ' <min, max> : <%.3e, %.3e>' % (uMin, uMax)
        print_text(s, color)
    elif isinstance(u, Function):  # \
        #   or isinstance(u, dolfin.functions.function.Function):
        uMin = MPI.min(MPI.comm_world, u.vector().min())
        uMax = MPI.max(MPI.comm_world, u.vector().max())
        s = title + ' <min, max> : <%.3e, %.3e>' % (uMin, uMax)
        print_text(s, color)
    elif isinstance(u, int) or isinstance(u, float):
        s = title + ' : %.3e' % u
        print_text(s, color)
    elif isinstance(u, Constant):
        s = title + ' : %.3e' % u(0)
        print_text(s, color)
    else:
        er = title + ": print_min_max function requires a Vector, Function" \
             + ", array, int or float, not %s." % type(u)
        print_text(er, 'red', 1)
示例#12
0
def _compute_errors(problem, mesh_sizes):
    mesh_generator, solution, f, cell_type = problem()

    if solution["degree"] > MAX_DEGREE:
        warnings.warn(
            "Expression degree ({}) > maximum degree ({}). Truncating.".format(
                solution["degree"], MAX_DEGREE))
        degree = MAX_DEGREE
    else:
        degree = solution["degree"]

    sol = Expression(
        (helpers.ccode(
            solution["value"][0]), helpers.ccode(solution["value"][1])),
        t=0.0,
        degree=degree,
        cell=cell_type,
    )

    errors = numpy.empty(len(mesh_sizes))
    hmax = numpy.empty(len(mesh_sizes))
    for k, mesh_size in enumerate(mesh_sizes):
        mesh, dx, _ = mesh_generator(mesh_size)
        hmax[k] = MPI.max(mpi_comm_world(), mesh.hmax())
        V = FunctionSpace(mesh, "CG", 1)
        # TODO don't hardcode Mu, Sigma, ...
        phi_approx = maxwell.solve(
            V,
            dx,
            Mu={0: 1.0},
            Sigma={0: 1.0},
            omega=1.0,
            f_list=[{
                0: f["value"]
            }],
            f_degree=f["degree"],
            convections={},
            tol=1.0e-12,
            bcs=None,
            verbose=False,
        )
        # plot(sol0, mesh=mesh, title='sol')
        # plot(phi_approx[0][0], title='approx')
        # #plot(fenics_sol - theta_approx, title='diff')
        # interactive()
        # exit()
        #
        errors[k] = errornorm(sol, phi_approx[0])

    return errors, hmax
示例#13
0
def get_cell_at(mesh, x, y, z, eps=1e-3):
    """Return the cell with the given midpoint or None if not found. The
    function also checks that the cell is found on one of the
    processes when running in parallel to avoid that the above tests
    always suceed if the cell is not found on any of the processes.

    """
    found = None
    for cell in Cells(mesh):
        mp = cell.midpoint().array()
        if abs(mp[0] - x) + abs(mp[1] - y) + abs(mp[2] - z) < eps:
            found = cell
            break

    # Make sure this cell is on at least one of the parallel processes
    marker = 1 if found is not None else 0
    assert MPI.max(MPI.comm_world, marker) == 1

    return found
示例#14
0
def _compute_errors(problem, mesh_sizes, stabilization):
    mesh_generator, solution, f, cell_type, kappa, rho, cp, conv = problem()

    if solution["degree"] > MAX_DEGREE:
        warnings.warn(
            "Expression degree ({}) > maximum degree ({}). Truncating.".format(
                solution["degree"], MAX_DEGREE
            )
        )
        degree = MAX_DEGREE
    else:
        degree = solution["degree"]

    sol = Expression(
        helpers.ccode(solution["value"]), t=0.0, degree=degree, cell=cell_type
    )

    errors = numpy.empty(len(mesh_sizes))
    hmax = numpy.empty(len(mesh_sizes))
    for k, mesh_size in enumerate(mesh_sizes):
        mesh = mesh_generator(mesh_size)
        hmax[k] = MPI.max(mpi_comm_world(), mesh.hmax())
        Q = FunctionSpace(mesh, "CG", 1)
        prob = heat.Heat(
            Q,
            kappa=kappa,
            rho=rho,
            cp=cp,
            convection=conv,
            source=f["value"],
            dirichlet_bcs=[DirichletBC(Q, 0.0, "on_boundary")],
            stabilization=stabilization,
        )
        phi_approx = prob.solve_stationary()
        errors[k] = errornorm(sol, phi_approx)

    return errors, hmax
示例#15
0
def _compute_errors(problem, mesh_sizes, stabilization):
    mesh_generator, solution, f, cell_type, kappa, rho, cp, conv = problem()

    if solution["degree"] > MAX_DEGREE:
        warnings.warn(
            "Expression degree ({}) > maximum degree ({}). Truncating.".format(
                solution["degree"], MAX_DEGREE))
        degree = MAX_DEGREE
    else:
        degree = solution["degree"]

    sol = Expression(helpers.ccode(solution["value"]),
                     t=0.0,
                     degree=degree,
                     cell=cell_type)

    errors = numpy.empty(len(mesh_sizes))
    hmax = numpy.empty(len(mesh_sizes))
    for k, mesh_size in enumerate(mesh_sizes):
        mesh = mesh_generator(mesh_size)
        hmax[k] = MPI.max(mpi_comm_world(), mesh.hmax())
        Q = FunctionSpace(mesh, "CG", 1)
        prob = heat.Heat(
            Q,
            kappa=kappa,
            rho=rho,
            cp=cp,
            convection=conv,
            source=f["value"],
            dirichlet_bcs=[DirichletBC(Q, 0.0, "on_boundary")],
            stabilization=stabilization,
        )
        phi_approx = prob.solve_stationary()
        errors[k] = errornorm(sol, phi_approx)

    return errors, hmax
示例#16
0
def test_local_assembler_on_facet_integrals2():
    mesh = UnitSquareMesh(MPI.comm_world, 4, 4)
    Vu = VectorFunctionSpace(mesh, 'DG', 1)
    Vv = FunctionSpace(mesh, 'DGT', 1)
    u = TrialFunction(Vu)
    v = TestFunction(Vv)
    n = FacetNormal(mesh)

    # Define form
    a = dot(u, n) * v * ds
    for R in '+-':
        a += dot(u(R), n(R)) * v(R) * dS

    # Compile form. This is collective
    a = Form(a)

    # Get global cell 0. This will return a cell only on one of the
    # processes
    c = get_cell_at(mesh, 1 / 6, 1 / 12, 0)

    if c:
        A_e = assemble_local(a, c)
        A_correct = numpy.array([[0, 1 / 12, 1 / 24, 0, 0, 0],
                                 [0, 1 / 24, 1 / 12, 0, 0, 0],
                                 [-1 / 12, 0, -1 / 24, 1 / 12, 0, 1 / 24],
                                 [-1 / 24, 0, -1 / 12, 1 / 24, 0, 1 / 12],
                                 [0, 0, 0, -1 / 12, -1 / 24, 0],
                                 [0, 0, 0, -1 / 24, -1 / 12, 0]])
        error = ((A_e - A_correct)**2).sum()**0.5
        error = float(error)  # MPI.max does strange things to numpy.float64

    else:
        error = 0.0

    error = MPI.max(MPI.comm_world, float(error))
    assert error < 1e-16
示例#17
0
def test_interpolation_jit_rank0(V):
    f = Expression("1.0", degree=0)
    w = interpolate(f, V)
    x = w.vector()
    assert MPI.max(MPI.comm_world, abs(x.get_local()).max()) == 1
    assert MPI.min(MPI.comm_world, abs(x.get_local()).min()) == 1
示例#18
0
    def before_first_compute(self, get):
        u = get(self.valuename)

        if isinstance(u, Function):

            if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
                rank = len(u.ufl_shape)
            else:
                rank = u.rank()

            if rank == 0:
                self.f = Function(u.function_space())
            elif rank >= 1:
                # Assume all subpaces are equal
                V = u.function_space().extract_sub_space([0]).collapse()
                mesh = V.mesh()
                el = V.ufl_element()
                self.f = Function(V)

                # Find out if we can operate directly on vectors, or if we have to use a projection
                # We can operate on vectors if all sub-dofmaps are ordered the same way
                # For simplicity, this is only tested for CG- or DG0-spaces
                # (this might always be true for these spaces, but better to be safe than sorry )
                self.use_project = True
                if el.family() == "Lagrange" or (el.family()
                                                 == "Discontinuous Lagrange"
                                                 and el.degree() == 0):
                    #dm = u.function_space().dofmap()
                    dm0 = V.dofmap()
                    self.use_project = False
                    for i in xrange(u.function_space().num_sub_spaces()):
                        Vi = u.function_space().extract_sub_space(
                            [i]).collapse()
                        dmi = Vi.dofmap()
                        try:
                            # For 1.6.0+ and newer
                            diff = Vi.tabulate_dof_coordinates(
                            ) - V.tabulate_dof_coordinates()
                        except:
                            # For 1.6.0 and older
                            diff = dmi.tabulate_all_coordinates(
                                mesh) - dm0.tabulate_all_coordinates(mesh)
                        if len(diff) > 0:
                            max_diff = max(abs(diff))
                        else:
                            max_diff = 0.0
                        max_diff = MPI.max(mpi_comm_world(), max_diff)
                        if max_diff > 1e-12:
                            self.use_project = True
                            break
                        self.assigner = FunctionAssigner(
                            [V] * u.function_space().num_sub_spaces(),
                            u.function_space())
                        self.subfuncs = [
                            Function(V)
                            for _ in range(u.function_space().num_sub_spaces())
                        ]

                # IF we have to use a projection, build projection matrix only once
                if self.use_project:
                    self.v = TestFunction(V)
                    M = assemble(inner(self.v, TrialFunction(V)) * dx)
                    self.projection = KrylovSolver("cg", "default")
                    self.projection.set_operator(M)
        elif isinstance(u, Iterable) and all(
                isinstance(_u, Number) for _u in u):
            pass
        elif isinstance(u, Number):
            pass
        else:
            # Don't know how to handle object
            cbc_warning(
                "Don't know how to calculate magnitude of object of type %s." %
                type(u))
示例#19
0
 def default_error(self, x1, x2) :
   dif_max = MPI.max(mpi_comm_world(), abs(x1 - x2).max())
   return dif_max
示例#20
0
def create_submesh(mesh, markers, marker):
    "This function allows for a SubMesh-equivalent to be created in parallel"
    # Build mesh
    submesh = Mesh()
    mesh_editor = MeshEditor()
    mesh_editor.open(submesh,
                     mesh.ufl_cell().cellname(),
                     mesh.ufl_cell().topological_dimension(),
                     mesh.ufl_cell().geometric_dimension())

    # Return empty mesh if no matching markers
    if MPI.sum(mpi_comm_world(), int(marker in markers.array())) == 0:
        cbc_warning(
            "Unable to find matching markers in meshfunction. Submesh is empty."
        )
        mesh_editor.close()
        return submesh

    base_cell_indices = np.where(markers.array() == marker)[0]
    base_cells = mesh.cells()[base_cell_indices]
    base_vertex_indices = np.unique(base_cells.flatten())

    base_global_vertex_indices = sorted(
        [mesh.topology().global_indices(0)[vi] for vi in base_vertex_indices])

    gi = mesh.topology().global_indices(0)
    shared_local_indices = set(base_vertex_indices).intersection(
        set(mesh.topology().shared_entities(0).keys()))
    shared_global_indices = [gi[vi] for vi in shared_local_indices]

    unshared_global_indices = list(
        set(base_global_vertex_indices) - set(shared_global_indices))
    unshared_vertices_dist = distribution(len(unshared_global_indices))

    # Number unshared vertices on separate process
    idx = sum(unshared_vertices_dist[:MPI.rank(mpi_comm_world())])
    base_to_sub_global_indices = {}
    for gi in unshared_global_indices:
        base_to_sub_global_indices[gi] = idx
        idx += 1

    # Gather all shared process on process 0 and assign global index
    all_shared_global_indices = gather(shared_global_indices,
                                       on_process=0,
                                       flatten=True)
    all_shared_global_indices = np.unique(all_shared_global_indices)

    shared_base_to_sub_global_indices = {}
    idx = int(
        MPI.max(mpi_comm_world(),
                float(max(base_to_sub_global_indices.values() + [-1e16]))) + 1)
    if MPI.rank(mpi_comm_world()) == 0:
        for gi in all_shared_global_indices:
            shared_base_to_sub_global_indices[int(gi)] = idx
            idx += 1

    # Broadcast global numbering of all shared vertices
    shared_base_to_sub_global_indices = dict(
        zip(broadcast(shared_base_to_sub_global_indices.keys(), 0),
            broadcast(shared_base_to_sub_global_indices.values(), 0)))

    # Join shared and unshared numbering in one dict
    base_to_sub_global_indices = dict(
        base_to_sub_global_indices.items() +
        shared_base_to_sub_global_indices.items())

    # Create mapping of local indices
    base_to_sub_local_indices = dict(
        zip(base_vertex_indices, range(len(base_vertex_indices))))

    # Define sub-cells
    sub_cells = [None] * len(base_cells)
    for i, c in enumerate(base_cells):
        sub_cells[i] = [base_to_sub_local_indices[j] for j in c]

    # Store vertices as sub_vertices[local_index] = (global_index, coordinates)
    sub_vertices = {}
    for base_local, sub_local in base_to_sub_local_indices.items():
        sub_vertices[sub_local] = (base_to_sub_global_indices[
            mesh.topology().global_indices(0)[base_local]],
                                   mesh.coordinates()[base_local])

    ## Done with base mesh

    # Distribute meshdata on (if any) empty processes
    sub_cells, sub_vertices = distribute_meshdata(sub_cells, sub_vertices)
    global_cell_distribution = distribution(len(sub_cells))
    #global_vertex_distribution = distribution(len(sub_vertices))

    global_num_cells = MPI.sum(mpi_comm_world(), len(sub_cells))
    global_num_vertices = sum(unshared_vertices_dist) + MPI.sum(
        mpi_comm_world(), len(all_shared_global_indices))

    mesh_editor.init_vertices(len(sub_vertices))
    #mesh_editor.init_cells(len(sub_cells))
    mesh_editor.init_cells_global(len(sub_cells), global_num_cells)
    global_index_start = sum(
        global_cell_distribution[:MPI.rank(mesh.mpi_comm())])

    for index, cell in enumerate(sub_cells):
        if LooseVersion(dolfin_version()) >= LooseVersion("1.6.0"):
            mesh_editor.add_cell(index, *cell)
        else:
            mesh_editor.add_cell(int(index), global_index_start + index,
                                 np.array(cell, dtype=np.uintp))

    for local_index, (global_index, coordinates) in sub_vertices.items():
        #print coordinates
        mesh_editor.add_vertex_global(int(local_index), int(global_index),
                                      coordinates)

    mesh_editor.close()

    submesh.topology().init(0, len(sub_vertices), global_num_vertices)
    submesh.topology().init(mesh.ufl_cell().topological_dimension(),
                            len(sub_cells), global_num_cells)

    # FIXME: Set up shared entities
    # What damage does this do?
    submesh.topology().shared_entities(0)[0] = []
    # The code below sets up shared vertices, but lacks shared facets.
    # It is considered incomplete, and therefore commented out
    '''
    #submesh.topology().shared_entities(0)[0] = []
    from dolfin import compile_extension_module
    cpp_code = """
    void set_shared_entities(Mesh& mesh, std::size_t idx, const Array<std::size_t>& other_processes)
    {
        std::set<unsigned int> set_other_processes;
        for (std::size_t i=0; i<other_processes.size(); i++)
        {
            set_other_processes.insert(other_processes[i]);
            //std::cout << idx << " --> " << other_processes[i] << std::endl;
        }
        //std::cout << idx << " --> " << set_other_processes[0] << std::endl;
        mesh.topology().shared_entities(0)[idx] = set_other_processes;
    }
    """

    set_shared_entities = compile_extension_module(cpp_code).set_shared_entities
    base_se = mesh.topology().shared_entities(0)
    se = submesh.topology().shared_entities(0)

    for li in shared_local_indices:
        arr = np.array(base_se[li], dtype=np.uintp)
        sub_li = base_to_sub_local_indices[li]
        set_shared_entities(submesh, base_to_sub_local_indices[li], arr)
    '''
    return submesh
示例#21
0
def distribute_meshdata(cells, vertices):
    """Because dolfin does not support a distributed mesh that is empty on some processes,
    we move a single cell from the process with the largest mesh to all processes with
    empty meshes."""
    global_cell_distribution = distribution(len(cells))

    x_per_v = 0
    v_per_cell = 0
    if len(vertices.values()) > 0:
        x_per_v = len(vertices.values()[0][1])
        v_per_cell = len(cells[0])

    x_per_v = int(MPI.max(mpi_comm_world(), x_per_v))
    v_per_cell = int(MPI.max(mpi_comm_world(), v_per_cell))

    # Move a single cell to process with no cells
    while 0 in global_cell_distribution:
        to_process = list(global_cell_distribution).index(0)
        from_process = list(global_cell_distribution).index(
            max(global_cell_distribution))

        # Extract vertices and remove cells[0] on from_process
        v_out = np.zeros((1 + x_per_v) * v_per_cell)
        if MPI.rank(mpi_comm_world()) == from_process:
            # Structure v_out as (ind0, x0, y0, .., ind1, x1, .., )
            for i, v in enumerate(cells[0]):
                v_out[i * (x_per_v + 1)] = vertices[v][0]
                v_out[i * (x_per_v + 1) + 1:(i + 1) *
                      (x_per_v + 1)] = vertices[v][1]

            # Remove vertices no longer used in remaining cells.
            for i, v in enumerate(cells[0]):
                if not any([v in c for c in cells[1:]]):
                    for j in xrange(len(cells)):
                        cells[j] = [
                            vi - 1 if vi > v else vi for vi in cells[j]
                        ]

                    for vi in range(v, max(vertices)):
                        vertices[vi] = vertices[vi + 1]
                    vertices.pop(max(vertices))

            cells.pop(0)
        MPI.barrier(mpi_comm_world())
        # Broadcast vertices in cell[0] on from_process
        v_in = broadcast(v_out, from_process)
        MPI.barrier(mpi_comm_world())
        # Create cell and vertices on to_process
        if MPI.rank(mpi_comm_world()) == to_process:
            for i in xrange(v_per_cell):
                vertices[i] = (int(v_in[i * (x_per_v + 1)]),
                               v_in[i * (x_per_v + 1) + 1:(i + 1) *
                                    (x_per_v + 1)])

            assert len(cells) == 0
            cells = [range(v_per_cell)]

        MPI.barrier(mpi_comm_world())

        # Update distribution
        global_cell_distribution = distribution(len(cells))

    return cells, vertices
示例#22
0
    rndnoise = np.random.randn(nbobspt*dimsol).reshape((nbobspt, dimsol))
    DD[ii] = dd + sigmas.reshape((len(sigmas),1))*rndnoise
waveobj.dd = DD
waveobj.solvefwd_cost()
if mpirank == 0:
    print 'noise misfit={}, regul cost={}, ratio={}'.format(waveobj.cost_misfit, \
    waveobj.cost_reg, waveobj.cost_misfit/waveobj.cost_reg)
#myplot.plot_timeseries(waveobj.solfwd[2], 'pd', 0, skip, dl.Function(V))


# Matvec for Hessian
if mpirank == 0:    print 'Compute gradient'
waveobj.update_PDE({'b':b_target_fn})
waveobj.solvefwd_cost()
waveobj.solveadj_constructgrad()
x, y = dl.Function(Vm), dl.Function(Vm)
setfct(x, 1.0)
if mpirank == 0:    print 'Time Hessian matvec'
for ii in range(10):
    MPI.barrier(mpicomm)
    t0 = Wtime()
    waveobj.mult(x.vector(), y.vector())
    t1 = Wtime()
    dt = t1-t0
    mindt = MPI.min(mpicomm, t1-t0)
    maxdt = MPI.max(mpicomm, t1-t0)
    avgdt = MPI.sum(mpicomm, t1-t0) / float(mpisize)
    if mpirank == 0:
        print 'min={}, max={}, avg={}'.format(mindt, maxdt, avgdt)

示例#23
0
def create_slice(basemesh, point, normal, closest_region=False, crinkle_clip=False):
    """Create a slicemesh from a basemesh.

    :param basemesh: Mesh to slice
    :param point: Point in slicing plane
    :param normal: Normal to slicing plane
    :param closest_region: Set to True to extract disjoint region closest to specified point
    :param crinkle_clip: Set to True to return mesh of same topological dimension as basemesh

    .. note::

        Only 3D-meshes currently supported for slicing.

    .. warning::

        Slice-instances are intended for visualization only, and may produce erronous
        results if used for computations.

    """
    assert basemesh.geometry().dim() == 3, "Can only slice 3D-meshes."

    P = np.array([point[0], point[1], point[2]], dtype=np.double)

    # Create unit normal
    n = np.array([normal[0],normal[1], normal[2]])
    n = n/np.linalg.norm(n)
    #self.n = Constant((n[0], n[1], n[2]))

    # Calculate the distribution of vertices around the plane
    # (sign of np.dot(p-P, n) determines which side of the plane p is on)
    vsplit = np.dot(basemesh.coordinates()-P, n)

    # Count each cells number of vertices on the "positive" side of the plane
    # Only cells with vertices on both sides of the plane intersect the plane
    operator = np.less
    npos = np.sum(vsplit[basemesh.cells()] < 0, 1)

    intersection_cells = basemesh.cells()[(npos > 0) & (npos < 4)]

    if len(intersection_cells) == 0:
        # Try to put "zeros" on other side of plane
        # FIXME: handle cells with vertices exactly intersecting the plane in a more robust manner.
        operator = np.greater
        npos = np.sum(vsplit[basemesh.cells()] > 0, 1)
        #cell_indices = (npos > 0) & (npos < 4)
        intersection_cells = basemesh.cells()[(npos > 0) & (npos < 4)]

    if crinkle_clip:
        cf = CellFunction("size_t", basemesh)
        cf.set_all(0)
        cf.array()[(npos>0) & (npos<4)] = 1
        mesh = create_submesh(basemesh, cf, 1)
    else:
        def add_cell(cells, cell):
            # Split cell into triangles
            for i in xrange(len(cell)-2):
                cells.append(cell[i:i+3])

        cells = []
        index = 0
        indexes = {}
        for c in intersection_cells:
            a = operator(vsplit[c], 0)
            positives = c[np.where(a==True)[0]]
            negatives = c[np.where(a==False)[0]]

            cell = []
            for pp_ind in positives:
                pp = basemesh.coordinates()[pp_ind]

                for pn_ind in negatives:
                    pn = basemesh.coordinates()[pn_ind]
                    if (pp_ind, pn_ind) not in indexes:
                        # Calculate intersection point with the plane
                        d = np.dot(P-pp, n)/np.dot(pp-pn, n)
                        ip = pp+(pp-pn)*d

                        indexes[(pp_ind, pn_ind)] = (index, ip)
                        index += 1

                    cell.append(indexes[(pp_ind, pn_ind)][0])


            add_cell(cells, cell)
        MPI.barrier(mpi_comm_world())

        # Assign global indices
        # TODO: Assign global indices properly
        dist = distribution(index)
        global_idx = sum(dist[:MPI.rank(mpi_comm_world())])
        vertices = {}
        for idx, p in indexes.values():
            vertices[idx] = (global_idx, p)
            global_idx += 1


        global_num_cells = MPI.sum(mpi_comm_world(), len(cells))
        global_num_vertices = MPI.sum(mpi_comm_world(), len(vertices))

        mesh = Mesh()

        # Return empty mesh if no intersections were found
        if global_num_cells == 0:
            mesh_editor = MeshEditor()
            mesh_editor.open(mesh, "triangle", 2, 3)

            mesh_editor.init_vertices(0)
            mesh_editor.init_cells(0)

            mesh_editor.close()
        else:

            # Distribute mesh if empty on any processors
            cells, vertices = distribute_meshdata(cells, vertices)

            # Build mesh
            mesh_editor = MeshEditor()
            mesh_editor.open(mesh, "triangle", 2, 3)

            mesh_editor.init_vertices(len(vertices))
            mesh_editor.init_cells(len(cells))

            for index, cell in enumerate(cells):
                mesh_editor.add_cell(index, cell[0], cell[1], cell[2])

            for local_index, (global_index, coordinates) in vertices.items():
                mesh_editor.add_vertex_global(int(local_index), int(global_index), coordinates)

            mesh_editor.close()
            mesh.topology().init(0, len(vertices), global_num_vertices)
            mesh.topology().init(2, len(cells), global_num_cells)


    if closest_region and mesh.size_global(0) > 0:
        assert MPI.size(mpi_comm_world())==1, "Extract closest region does not work in parallel"
        regions = compute_connectivity(mesh)
        i,d = mesh.bounding_box_tree().compute_closest_entity(Point(P))

        if d == MPI.min(mesh.mpi_comm(), d):
            v = regions[int(i)]
        else:
            v = 0

        v = MPI.max(mesh.mpi_comm(), v)
        mesh = create_submesh(mesh, regions, v)

    return mesh
示例#24
0
def _compute_boussinesq(
    problem, u0, p0, theta0, lorentz, joule, target_time=0.1, show=False
):
    # Define a facet measure on the boundaries. See discussion on
    # <https://bitbucket.org/fenics-project/dolfin/issue/249/facet-specification-doesnt-work-on-ds>.
    ds_workpiece = Measure("ds", subdomain_data=problem.wp_boundaries)

    submesh_workpiece = problem.W.mesh()

    # Start time, time step.
    t = 0.0
    dt = 1.0e-3
    dt_max = 1.0e-1

    # Standard gravity, <https://en.wikipedia.org/wiki/Standard_gravity>.
    grav = 9.80665
    assert problem.W.num_sub_spaces() == 3
    g = Constant((0.0, -grav, 0.0))

    # Compute a few mesh characteristics.
    wpi_area = assemble(1.0 * dx(submesh_workpiece))
    # mesh.hmax() is a local function; get the global hmax.
    hmax_workpiece = MPI.max(submesh_workpiece.mpi_comm(), submesh_workpiece.hmax())

    # Take the maximum length in x-direction as characteristic length of the
    # domain.
    coords = submesh_workpiece.coordinates()
    char_length = max(coords[:, 0]) - min(coords[:, 0])

    # Prepare some parameters for the Navier-Stokes simulation in the workpiece
    m = problem.subdomain_materials[problem.wpi]
    k_wpi = m.thermal_conductivity
    cp_wpi = m.specific_heat_capacity
    rho_wpi = m.density
    mu_wpi = m.dynamic_viscosity

    theta_average = average(theta0)

    # show_total_force = True
    # if show_total_force:
    #     f = rho_wpi(theta0) * g
    #     if lorentz:
    #         f += as_vector((lorentz[0], lorentz[1], 0.0))
    #     tri = plot(f, mesh=submesh_workpiece, title='Total external force')
    #     plt.colorbar(tri)
    #     plt.show()

    with XDMFFile(submesh_workpiece.mpi_comm(), "all.xdmf") as outfile:
        outfile.parameters["flush_output"] = True
        outfile.parameters["rewrite_function_mesh"] = False

        _store(outfile, u0, p0, theta0, t)
        if show:
            _plot(p0, theta0)
            plt.show()

        successful_steps = 0
        failed_steps = 0
        while t < target_time + DOLFIN_EPS:
            info(
                "Successful steps: {}    (failed: {}, total: {})".format(
                    successful_steps, failed_steps, successful_steps + failed_steps
                )
            )
            with Message("Time step {:e} -> {:e}...".format(t, t + dt)):
                # Do one heat time step.
                with Message("Computing heat..."):
                    # Redefine the heat problem with the new u0.
                    heat_problem = cyl_heat.Heat(
                        problem.Q,
                        kappa=k_wpi,
                        rho=rho_wpi(theta_average),
                        cp=cp_wpi,
                        convection=u0,
                        source=joule,
                        dirichlet_bcs=problem.theta_bcs_d,
                        neumann_bcs=problem.theta_bcs_n,
                        my_dx=dx(submesh_workpiece),
                        my_ds=ds_workpiece,
                    )

                    # For time-stepping in buoyancy-driven flows, see
                    #
                    # Numerical solution of buoyancy-driven flows;
                    # Einar Rossebø Christensen;
                    # Master's thesis;
                    # <http://www.diva-portal.org/smash/get/diva2:348831/FULLTEXT01.pdf>.
                    #
                    # Similar to the present approach, one first solves for
                    # velocity and pressure, then for temperature.
                    #
                    heat_stepper = parabolic.ImplicitEuler(heat_problem)

                    ns_stepper = cyl_ns.IPCS(time_step_method="backward euler")
                    theta1 = heat_stepper.step(theta0, t, dt)

                theta0_average = average(theta0)
                try:
                    # Do one Navier-Stokes time step.
                    with Message("Computing flux and pressure..."):
                        # Include proper temperature-dependence here to account
                        # for the Boussinesq effect.
                        f0 = rho_wpi(theta0) * g
                        f1 = rho_wpi(theta1) * g
                        if lorentz is not None:
                            f = as_vector((lorentz[0], lorentz[1], 0.0))
                            f0 += f
                            f1 += f
                        u1, p1 = ns_stepper.step(
                            Constant(dt),
                            {0: u0},
                            p0,
                            problem.W,
                            problem.P,
                            problem.u_bcs,
                            problem.p_bcs,
                            # Make constant TODO
                            Constant(rho_wpi(theta0_average)),
                            Constant(mu_wpi(theta0_average)),
                            f={0: f0, 1: f1},
                            tol=1.0e-10,
                            my_dx=dx(submesh_workpiece),
                        )
                except RuntimeError as e:
                    info(e.args[0])
                    info(
                        "Navier--Stokes solver failed to converge. "
                        "Decrease time step from {:e} to {:e} and try again.".format(
                            dt, 0.5 * dt
                        )
                    )
                    dt *= 0.5
                    failed_steps += 1
                    continue
                successful_steps += 1

                # Assignments and plotting.
                theta0.assign(theta1)
                u0.assign(u1)
                p0.assign(p1)

                _store(outfile, u0, p0, theta0, t + dt)
                if show:
                    _plot(p0, theta0)
                    plt.show()

                t += dt
                with Message("Diagnostics..."):
                    # Print some general info on the flow in the crucible.
                    umax = get_umax(u0)
                    _print_diagnostics(
                        theta0,
                        umax,
                        submesh_workpiece,
                        wpi_area,
                        problem.subdomain_materials,
                        problem.wpi,
                        rho_wpi,
                        mu_wpi,
                        char_length,
                        grav,
                    )
                    info("")
                with Message("Step size adaptation..."):
                    # Some smooth step-size adaption.
                    target_dt = 0.2 * hmax_workpiece / umax
                    info("previous dt: {:e}".format(dt))
                    info("target dt: {:e}".format(target_dt))
                    # agg is the aggressiveness factor. The distance between
                    # the current step size and the target step size is reduced
                    # by |1-agg|. Hence, if agg==1 then dt_next==target_dt.
                    # Otherwise target_dt is approached more slowly.
                    agg = 0.5
                    dt = min(
                        dt_max,
                        # At most double the step size from step to step.
                        dt * min(2.0, 1.0 + agg * (target_dt - dt) / dt),
                    )
                    info("new dt:    {:e}".format(dt))
                    info("")
                info("")
    return u0, p0, theta0