Ejemplo n.º 1
0
    def compute(self, get):
        u = get(self.valuename)

        if u is None:
            return

        if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
            rank = len(u.ufl_shape)
            shape = u.ufl_shape
            mesh = u.ufl_domain()._ufl_cargo
            dIdomain = self.dI.ufl_domain()
        else:
            rank = u.rank()
            shape = u.shape()
            mesh = u.domain().data()
            dIdomain = self.dI.domain()

        mesh_id = mesh.id()

        # Find mesh/domain
        if isinstance(self.dI.subdomain_data(), MeshFunctionSizet):
            mf = self.dI.subdomain_data()
            mf_mesh_id = mf.mesh().id()

            if mf_mesh_id != mesh_id:
                mf = duplicate_meshfunction(mf, mesh)
            mesh = mf.mesh()

            self.dI = self.dI.reconstruct(domain=mesh, subdomain_data=mf)

        if dIdomain is None:
            self.dI = self.dI.reconstruct(domain=mesh)
            if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
                dIdomain = self.dI.ufl_domain()
            else:
                dIdomain = self.dI.domain()

        assert dIdomain is not None

        # Calculate volume
        if not hasattr(self, "volume"):
            self.volume = assemble(Constant(1) * self.dI)
            assert self.volume > 0

        if rank == 0:
            value = assemble(u * self.dI) / self.volume
        elif rank == 1:
            value = [
                assemble(u[i] * self.dI) / self.volume
                for i in xrange(u.value_size())
            ]
        elif rank == 2:
            value = []
            for i in xrange(shape[0]):
                for j in xrange(shape[1]):
                    value.append(assemble(u[i, j] * self.dI) / self.volume)

        return value
Ejemplo n.º 2
0
    def compute(self, get):
        u = get(self.valuename)
        if u is None:
            return None

        if not hasattr(self, "u"):
            self.before_first_compute(get)

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

        if rank > 0:
            u = u.split()
            U = []
            for i, _u in enumerate(u):
                U.append(_interpolate(self.us[i], _u))
                #U.append(self._ft.interpolate_nonmatching_mesh(_u, self.us.function_space()))
            MPI.barrier(mpi_comm_world())

            self.assigner.assign(self.u, U)
        else:
            _interpolate(self.u, u)
            MPI.barrier(mpi_comm_world())

            # FIXME: This gives a PETSc-error (VecCopy). Unnecessary interpolation used instead.
            #self.u.assign(U)
            #self.u.assign(interpolate(U, self.u.function_space()))
        return self.u
Ejemplo n.º 3
0
    def before_first_compute(self, get):
        u = get(self.valuename)
        if u is None:
            return None

        V = u.function_space()
        element = V.ufl_element()
        #family = element.family()
        #degree = element.degree()

        spaces = SpacePool(self.mesh)
        FS = spaces.get_custom_space(element.family(), element.degree(), element.value_shape())

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

        if rank > 0:
            FS_scalar = spaces.get_custom_space(element.family(), element.degree(), ())
            self.assigner = FunctionAssigner(FS, [FS_scalar]*FS.num_sub_spaces())
            self.us = []
            for i in range(FS.num_sub_spaces()):
                self.us.append(Function(FS_scalar))

        self.u = Function(FS, name=self.name)
Ejemplo n.º 4
0
    def get_grad_space(self, V, family="auto", degree="auto", shape="auto"):
        """Get gradient space of FunctionSpace V.

        .. warning::
            This is experimental and currently only designed to work with CG-spaces.

        """
        element = V.ufl_element()

        if degree == "auto":
            degree = element.degree() - 1

        if family == "auto":
            family = "DG"

        if family in ("CG", "Lagrange") and degree == 0:
            family = "DG"

        if shape == "auto":
            if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
                shape = grad(Coefficient(element)).ufl_shape
            else:
                shape = grad(Coefficient(element)).shape()

        DV = self.get_custom_space(family, degree, shape)
        return DV
Ejemplo n.º 5
0
    def _update_metadata_file(self, field_name, data, t, timestep, save_as,
                              metadata):
        "Update metadata shelve file from master process."
        if on_master_process():
            if self._metadata_cache.get(field_name) is None:
                savedir = self.get_savedir(field_name)
                metadata_filename = os.path.join(savedir, 'metadata.db')
                #metadata_file = shelve.open(metadata_filename)
                metadata_file = shelve.open(metadata_filename)
                self._metadata_cache[field_name] = metadata_file

            metadata_file = self._metadata_cache[field_name]

            # Store some data the first time
            if "type" not in metadata_file and data is not None:
                # Data about type and formats
                metadata_file["type"] = type(data).__name__
                metadata_file["saveformats"] = list(
                    set(save_as + metadata_file.get("saveformats", [])))
                # Data about function space
                if isinstance(data, Function):
                    if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
                        element = data.ufl_element()
                    else:
                        element = data.element()

                    metadata_file["element"] = repr(element, )
                    metadata_file["element_degree"] = repr(element.degree(), )
                    metadata_file["element_family"] = repr(element.family(), )
                    metadata_file["element_value_shape"] = repr(
                        element.value_shape(), )
            # Store some data each timestep
            metadata_file[str(timestep)] = metadata
            metadata_file[str(timestep)]["t"] = t
    def __init__(self, mesh, facet_ids, bcs, params, ics=dict()):
        # input check: mesh
        assert isinstance(mesh, dlfn.Mesh)
        self._mesh = mesh
        self._space_dim = self._mesh.topology().dim()
        assert self._space_dim in (2, 3)
        # input check: facet_ids
        assert isinstance(facet_ids, dlfn.MeshFunctionSizet)
        self._facet_markers = facet_ids
        # input check: boundary conditions
        self._check_boundary_conditions(bcs)
        self._bcs = bcs
        # input check: parameters
        from parameters import ParameterHandler
        assert isinstance(params, ParameterHandler)
        self._parameters = params
        # input check: initial conditions
        assert isinstance(ics, dict)
        self._ics = ics
        # equation coefficients
        tmp = self._parameters.coefficients()
        self._coefficients = tuple([dlfn.Constant(t) for t in tmp])
        # imex coefficients
        self._imex = IMEXCoefficients(self._parameters.imex_type)
        # gravity field
        import gravity_field as gf
        if params.gravity_type not in (gf.GravityType.radial,
                                       gf.GravityType.radial_linear):
            self._gravity = gf.get_gravity_field(self._space_dim,
                                                 params.gravity_type)
        else:
            self._gravity = gf.get_gravity_field(self._space_dim,
                                                 params.gravity_type,
                                                 radii=params.radii)
        # initialize timestep as dolfin constant
        self._timestep = dlfn.Constant(1.0)
        self._timestep.assign(self._parameters.timestep)
        # runtime flags
        self._rebuild_matrices = True
        # helpful constants
        self._one = dlfn.Constant(1.0)
        self._omega = dlfn.Constant(1.0)
        self._rotation_vector = None
        if self._space_dim == 2:
            self._null_vector = dlfn.Constant((0.0, 0.0))
        elif self._space_dim == 3:
            self._rotation_vector = dlfn.Constant((0.0, 0.0, 1.0))
            self._null_vector = dlfn.Constant((0.0, 0.0, 0.0))
        else:
            raise ValueError()

        print "The system's version of FEniCS is", dlfn.dolfin_version(), "."
Ejemplo n.º 7
0
def _init_measure(measure="default",
                  cell_domains=None,
                  facet_domains=None,
                  indicator=None):
    assert cell_domains is None or facet_domains is None, "You can't specify both cell_domains or facet_domains"

    if cell_domains is not None:
        assert isinstance(cell_domains, (MeshFunctionSizet, MeshFunctionInt))

    if facet_domains is not None:
        assert isinstance(facet_domains, (MeshFunctionSizet, MeshFunctionInt))

    if (cell_domains and indicator is not None):
        if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
            dI = Measure("cell")(subdomain_data=cell_domains)(indicator)
        else:
            dI = Measure("cell")[cell_domains](indicator)
    elif (facet_domains and indicator is not None):
        if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
            dI = Measure("exterior_facet")(
                subdomain_data=facet_domains)(indicator)
        else:
            dI = Measure("exterior_facet")[facet_domains](indicator)
    elif measure == "default":
        if indicator is not None:
            cbc_warning(
                "Indicator specified, but no domains. Will dompute average over entire domain."
            )
        dI = dx()
    elif isinstance(measure, Measure):
        dI = measure
    else:
        raise TypeError(
            "Unable to create a domain measure from provided domains or measure."
        )

    return dI
Ejemplo n.º 8
0
    def compute(self, get):
        u = get(self.valuename)

        if isinstance(u, Function):
            if not hasattr(self, "use_project"):
                self.before_first_compute(get)

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

            if rank == 0:
                self.f.vector().zero()
                self.f.vector().axpy(1.0, u.vector())
                self.f.vector().abs()
                return self.f
            elif rank >= 1:
                if self.use_project:
                    b = assemble(sqrt(inner(u, u)) * self.v * dx(None))
                    self.projection.solve(self.f.vector(), b)
                else:
                    self.assigner.assign(self.subfuncs, u)
                    self.f.vector().zero()
                    for i in xrange(u.function_space().num_sub_spaces()):
                        vec = self.subfuncs[i].vector()
                        vec.apply('')
                        self.f.vector().axpy(1.0, vec * vec)

                    try:
                        sqrt_in_place(self.f.vector())
                    except:
                        r = self.f.vector().local_range()
                        self.f.vector()[r[0]:r[1]] = np.sqrt(
                            self.f.vector()[r[0]:r[1]])
                    self.f.vector().apply('')

                return self.f
        elif isinstance(u, Iterable) and all(
                isinstance(_u, Number) for _u in u):
            return np.sqrt(sum(_u**2 for _u in u))
        elif isinstance(u, Number):
            return abs(u)
        else:
            # Don't know how to handle object
            cbc_warning(
                "Don't know how to calculate magnitude of object of type %s. Returning object."
                % type(u))
            return u
Ejemplo n.º 9
0
    def compute(self, get):
        u = get(self.valuename)

        if u is None:
            return None

        if not isinstance(u, Function):
            cbc_warning("Do not understand how to handle datatype %s" %
                        str(type(u)))
            return None

        #if not hasattr(self, "restriction_map"):
        if not hasattr(self, "keys"):
            V = u.function_space()
            element = V.ufl_element()
            family = element.family()
            degree = element.degree()

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

            if rank == 0:
                FS = FunctionSpace(self.submesh, family, degree)
            elif rank == 1:
                FS = VectorFunctionSpace(self.submesh, family, degree)
            elif rank == 2:
                FS = TensorFunctionSpace(self.submesh,
                                         family,
                                         degree,
                                         symmetry={})

            self.u = Function(FS)

            #self.restriction_map = restriction_map(V, FS)
            rmap = restriction_map(V, FS)
            self.keys = np.array(rmap.keys(), dtype=np.intc)
            self.values = np.array(rmap.values(), dtype=np.intc)
            self.temp_array = np.zeros(len(self.keys), dtype=np.float_)

        # The simple __getitem__, __setitem__ has been removed in dolfin 1.5.0.
        # The new cbcpost-method get_set_vector should be compatible with 1.4.0 and 1.5.0.
        #self.u.vector()[self.keys] = u.vector()[self.values]

        get_set_vector(self.u.vector(), self.keys, u.vector(), self.values,
                       self.temp_array)
        return self.u
Ejemplo n.º 10
0
def get_set_vector(setvector, set_indices, getvector, get_indices, temp_array=None):
    """Equivalent of setvector[set_indices] = getvector[get_indices] for global indices (MPI-blocking).
    Pass temp_array to avoid initiation of array on call.
    """
    #if dolfin_version() == "1.4.0":
    #    setvector[set_indices] = getvector[get_indices]
    #    return
    if not hasattr(get_set_vector, "cppmodule"):
        code = """
        void get_set_vector(std::shared_ptr<GenericVector> set_vector,
                            const Array<dolfin::la_index> & set_indices,
                            std::shared_ptr<const GenericVector> get_vector,
                            const Array<dolfin::la_index> & get_indices,
                            const Array<double> & temp_array)
        {
            std::size_t N = set_indices.size();

            // Perform a const_cast (unable to pass non-const Array through from python layer)
            Array<double> & temp_array2 = const_cast<Array<double> &>(temp_array);

            // Get and set using the non-const temp_array2
            get_vector->get(temp_array2.data(), N, get_indices.data());
            set_vector->set(temp_array2.data(), N, set_indices.data());

            // Apply vector (MPI-part)
            set_vector->apply("insert");
        }
        """

        # Very minor change required for dolfin 1.4.0
        #if dolfin_version() == "1.4.0":
        if LooseVersion(dolfin_version()) <= LooseVersion("1.4.0"):
            code = code.replace("get_vector->get", "get_vector->get_local")

        cbc_log(20, "Compiling get_set_vector.cppmodule")
        get_set_vector.cppmodule = compile_extension_module(code)

    assert len(set_indices) == len(get_indices)

    if temp_array is None:
        temp_array = zeros(len(set_indices), dtype=float_)

    assert len(temp_array) == len(set_indices)
    get_set_vector.cppmodule.get_set_vector(setvector,
                                            set_indices,
                                            getvector,
                                            get_indices,
                                            temp_array)
Ejemplo n.º 11
0
 def _set_solver(self, operator, op_name=None):
     """
     Set the solver of an operator
     """
     if type(operator) is df.PETScMatrix:
         if df.dolfin_version() <= '1.6.0':
             solver = df.PETScLUSolver(
                 'mumps' if df.has_lu_solver_method('mumps') else 'default')
         else:
             solver = df.PETScLUSolver(
                 self.mpi_comm,
                 'mumps' if df.has_lu_solver_method('mumps') else 'default')
         solver.set_operator(operator)
         solver.parameters['reuse_factorization'] = True
         if op_name == 'K':
             solver.parameters['symmetric'] = True
     else:
         import scipy.sparse.linalg as spsla
         solver = spsla.splu(operator.tocsc(copy=True))
     return solver
Ejemplo n.º 12
0
def mesh_to_boundarymesh_dofmap(boundary, V, Vb, _should_own="cdof"):
    "Find the mapping from dofs on full mesh FS to dofs on boundarymesh FS"
    from dolfin import dolfin_version, MPI, mpi_comm_world
    #if dolfin_version() != '1.4.0' and MPI.size(mpi_comm_world()) > 1:
    #    raise RuntimeError("mesh_to_boundarymesh_dofmap is currently not supported in parallel in version %s" %(dolfin_version()))

    assert V.ufl_element().family() == Vb.ufl_element().family()
    assert V.ufl_element().degree() == Vb.ufl_element().degree()
    assert _should_own in ["cdof", "bdof"]

    # Currently only CG1 and DG0 spaces are supported
    assert V.ufl_element().family() in ["Lagrange", "Discontinuous Lagrange"]
    if V.ufl_element().family() == "Discontinuous Lagrange":
        assert V.ufl_element().degree() == 0
    else:
        assert V.ufl_element().degree() == 1

    D = boundary.topology().dim()
    mesh = V.mesh()

    V_dm = V.dofmap()
    Vb_dm = Vb.dofmap()

    dofmap_to_boundary = {}

    # Extract maps from boundary to mesh
    vertex_map = boundary.entity_map(0)
    cell_map = boundary.entity_map(D)

    for i in xrange(len(cell_map)):
        boundary_cell = Cell(boundary, i)
        mesh_facet = Facet(mesh, cell_map[i])
        mesh_cell_index = mesh_facet.entities(D + 1)[0]
        mesh_cell = Cell(mesh, mesh_cell_index)

        cell_dofs = V_dm.cell_dofs(mesh_cell_index)
        boundary_dofs = Vb_dm.cell_dofs(i)

        if V_dm.num_entity_dofs(0) > 0:
            for v_idx in boundary_cell.entities(0):

                mesh_v_idx = vertex_map[int(v_idx)]
                mesh_list_idx = where(
                    mesh_cell.entities(0) == mesh_v_idx)[0][0]
                boundary_list_idx = where(
                    boundary_cell.entities(0) == v_idx)[0][0]

                bdofs = boundary_dofs[Vb_dm.tabulate_entity_dofs(
                    0, boundary_list_idx)]
                cdofs = cell_dofs[V_dm.tabulate_entity_dofs(0, mesh_list_idx)]

                for bdof, cdof in zip(bdofs, cdofs):
                    #if dolfin_version() in ["1.4.0+", "1.5.0", "1.6.0"]:
                    if LooseVersion(dolfin_version()) > LooseVersion("1.4.0"):
                        bdof = Vb_dm.local_to_global_index(bdof)
                        cdof = V_dm.local_to_global_index(cdof)

                    if _should_own == "cdof" and not (V_dm.ownership_range(
                    )[0] <= cdof < V_dm.ownership_range()[1]):
                        continue
                    elif _should_own == "bdof" and not (Vb_dm.ownership_range(
                    )[0] <= bdof < Vb_dm.ownership_range()[1]):
                        continue
                    else:
                        dofmap_to_boundary[bdof] = cdof

        if V_dm.num_entity_dofs(D + 1) > 0 and V_dm.num_entity_dofs(0) == 0:
            bdofs = boundary_dofs[Vb_dm.tabulate_entity_dofs(D, 0)]
            cdofs = cell_dofs[V_dm.tabulate_entity_dofs(D + 1, 0)]
            for bdof, cdof in zip(bdofs, cdofs):
                #if dolfin_version() in ["1.4.0+", "1.5.0"]:
                if LooseVersion(dolfin_version()) > LooseVersion("1.4.0"):
                    bdof = Vb_dm.local_to_global_index(bdof)
                    cdof = V_dm.local_to_global_index(cdof)

                dofmap_to_boundary[bdof] = cdof

    return dofmap_to_boundary
Ejemplo n.º 13
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))
Ejemplo n.º 14
0
def restriction_map(V, Vb, _all_coords=None, _all_coordsb=None):
    "Return a map between dofs in Vb to dofs in V. Vb's mesh should be a submesh of V's Mesh."
    if V.ufl_element().family(
    ) == "Discontinuous Lagrange" and V.ufl_element().degree() > 0:
        raise RuntimeError(
            "This function does not work for DG-spaces of degree >0 \
                           (several dofs associated with same point in same subspace)."
        )

    if V.ufl_element().family() != "Lagrange":
        cbc_warning("This function is only tested for CG-spaces.")
    assert V.ufl_element().family() == Vb.ufl_element().family(
    ), "ufl elements differ in the two spaces"
    assert V.ufl_element().degree() == Vb.ufl_element().degree(
    ), "ufl elements differ in the two spaces"
    assert V.ufl_element().cell() == Vb.ufl_element().cell(
    ), "ufl elements differ in the two spaces"

    D = V.mesh().geometry().dim()

    # Recursively call this function if V has sub-spaces
    if V.num_sub_spaces() > 0:
        mapping = {}
        if MPI.size(mpi_comm_world()) == 1:
            if _all_coords is None:
                try:
                    # For 1.6.0+ and newer
                    all_coords = V.tabulate_dof_coordinates().reshape(
                        V.dim(), D)
                    all_coordsb = Vb.tabulate_dof_coordinates().reshape(
                        Vb.dim(), D)
                except:
                    # For 1.6.0 and older
                    all_coords = V.dofmap().tabulate_all_coordinates(
                        V.mesh()).reshape(V.dim(), D)
                    all_coordsb = Vb.dofmap().tabulate_all_coordinates(
                        Vb.mesh()).reshape(Vb.dim(), D)
            else:
                all_coords = _all_coords
                all_coordsb = _all_coordsb
        else:
            all_coords = None
            all_coordsb = None
        for i in range(V.num_sub_spaces()):
            mapping.update(
                restriction_map(V.sub(i), Vb.sub(i), all_coords, all_coordsb))

        return mapping

    dm = V.dofmap()
    dmb = Vb.dofmap()

    N = len(dm.dofs())
    Nb = len(dmb.dofs())

    dofs = dm.dofs()

    # Extract coordinates of dofs
    if dm.is_view():
        if _all_coords is not None:
            coords = _all_coords[V.dofmap().dofs()]
        else:
            try:
                # For 1.6.0+ and newer
                coords = V.collapse().tabulate_dof_coordinates().reshape(N, D)
            except:
                # For 1.6.0 and older
                coords = V.collapse().dofmap().tabulate_all_coordinates(
                    V.mesh()).reshape(N, D)

        if _all_coordsb is not None:
            coordsb = _all_coordsb[Vb.dofmap().dofs()]
        else:
            try:
                # For 1.6.0+ and newer
                coordsb = Vb.collapse().tabulate_dof_coordinates().reshape(
                    Nb, D)
            except:
                # For 1.6.0 and older
                coordsb = Vb.collapse().dofmap().tabulate_all_coordinates(
                    Vb.mesh()).reshape(Nb, D)
    else:
        if LooseVersion(dolfin_version()) > LooseVersion("1.6.0"):
            # For 1.6.0+ and newer
            coords = V.tabulate_dof_coordinates().reshape(N, D)
            coordsb = Vb.tabulate_dof_coordinates().reshape(Nb, D)
        else:
            # For 1.6.0 and older
            coords = V.dofmap().tabulate_all_coordinates(V.mesh()).reshape(
                N, D)
            coordsb = Vb.dofmap().tabulate_all_coordinates(Vb.mesh()).reshape(
                Nb, D)

    # Build KDTree to compute distances from coordinates in base
    kdtree = KDTree(coords)
    eps = 1e-12

    mapping = {}
    request_dofs = np.array([])

    distances, indices = kdtree.query(coordsb)

    for i, subdof in enumerate(dmb.dofs()):
        # Find closest dof in base
        #d, idx = kdtree.query(coordsb[i])
        d, idx = distances[i], indices[i]
        if d < eps:
            # Dof found on this process, add to map
            dof = dofs[idx]
            assert subdof not in mapping
            mapping[subdof] = dof
        else:
            # Search for this dof on other processes
            add_dofs = np.hstack(([subdof], coordsb[i]))
            request_dofs = np.append(request_dofs, add_dofs)

    del distances
    del indices

    # Scatter all dofs not found on current process to all processes
    all_request_dofs = [None] * MPI.size(mpi_comm_world())
    for j in xrange(MPI.size(mpi_comm_world())):
        all_request_dofs[j] = broadcast(request_dofs, j)

    # Re-order all requested dofs
    # Remove items coming from this process
    all_request_dofs[MPI.rank(mpi_comm_world())] = []
    all_request_dofs = np.hstack(all_request_dofs)

    all_request_dofs = all_request_dofs.reshape(
        len(all_request_dofs) / (D + 1), D + 1)
    all_request_dofs = dict(
        zip(all_request_dofs[:, 0], all_request_dofs[:, 1:]))

    # Search this process for all dofs not found on same process as subdof
    for subdof, coordsbi in all_request_dofs.items():
        subdof = int(subdof)

        # Find closest dof in base
        d, idx = kdtree.query(coordsbi)
        if d < eps:
            # Dof found on this process, add to map
            dof = dofs[idx]
            assert subdof not in mapping
            mapping[subdof] = dof
    return mapping
Ejemplo n.º 15
0
import dolfin as dlfn
import mshr
from dolfin import inner, grad, div, dot
import numpy as np
#==============================================================================
# TODO: try to use MUMPS or UMFPACK instead of LUSolver
# TODO: more diagnostic values
# TODO: write output of sol00 sol0 for restart
# TODO: implement restart
#==============================================================================
#dlfn.parameters["form_compiler"]["cpp_optimize"] = True
#comm = dlfn.mpi_comm_world()
#mpi_comm = dlfn.mpi_comm_world()
#mpi_rank = dlfn.MPI.rank(mpi_comm)
#print mpi_rank
print "The system's version of FEniCS is ", dlfn.dolfin_version(), "."
#==============================================================================
# run time parameters
t_end = 150.
n_steps = 50000
output_frequency = 50
checkpoint_frequency = 1000
rms_frequency = 5
aspect_ratio = 0.35
print_time_stepping_coefficients = False
use_assembler_method = True
non_zero_initial_temperature = True
#==============================================================================
# refinements
n_initial_refinements = 0
#==============================================================================
Ejemplo n.º 16
0
    def _update_hdf5_file(self, field_name, saveformat, data, timestep, t):
        """Update hdf5 file with new data.

        This creates a hashed dataset within the dataset to save FunctionSpace
        information only once, and for all subsequent savings only the vector
        is saved and links are created to the FunctionSpace information.

        This ensures that the saving is fully compatible with restart and
        replay on an arbitrary number of processes.
        """
        assert saveformat == "hdf5"
        fullname, metadata = self._get_datafile_name(field_name, saveformat,
                                                     timestep)

        # Create "good enough" hash. This is done to avoid data corruption when restarted from
        # different number of processes, different distribution or different function space
        local_hash = sha1()
        local_hash.update(
            str(data.function_space().mesh().num_cells()).encode())
        local_hash.update(str(data.function_space().ufl_element()).encode())
        local_hash.update(str(data.function_space().dim()).encode())
        local_hash.update(str(MPI.size(mpi_comm_world())).encode())

        # Global hash (same on all processes), 10 digits long
        global_hash = MPI.sum(mpi_comm_world(), int(local_hash.hexdigest(),
                                                    16))
        global_hash = str(int(global_hash % 1e10)).zfill(10)

        #key = (field_name, saveformat)
        #datafile = self._datafile_cache.get(key)
        #if datafile is None:
        #    datafile = HDF5File(mpi_comm_world(), fullname, 'w')
        #    self._datafile_cache[key] = datafile

        # Open HDF5File
        if not os.path.isfile(fullname):
            datafile = HDF5File(mpi_comm_world(), fullname, 'w')
        else:
            datafile = HDF5File(mpi_comm_world(), fullname, 'a')

        # Write to hash-dataset if not yet done
        if not datafile.has_dataset(global_hash) or not datafile.has_dataset(
                global_hash + "/" + field_name):
            datafile.write(data, str(global_hash) + "/" + field_name)

        if not datafile.has_dataset("Mesh"):
            datafile.write(data.function_space().mesh(), "Mesh")

        # Write vector to file
        # TODO: Link vector when function has been written to hash
        datafile.write(data.vector(), field_name + str(timestep) + "/vector")

        # HDF5File.close is broken in 1.4
        if dolfin_version() == "1.4.0+":
            datafile.close()
        del datafile
        # Link information about function space from hash-dataset
        hdf5_link(fullname,
                  str(global_hash) + "/" + field_name + "/x_cell_dofs",
                  field_name + str(timestep) + "/x_cell_dofs")
        hdf5_link(fullname,
                  str(global_hash) + "/" + field_name + "/cell_dofs",
                  field_name + str(timestep) + "/cell_dofs")
        hdf5_link(fullname,
                  str(global_hash) + "/" + field_name + "/cells",
                  field_name + str(timestep) + "/cells")

        return metadata
Ejemplo n.º 17
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