def __init__(self, value, domain=None): # Init also called in mesh constructor, but constant can be built without mesh utils._init() data = np.array(value, dtype=np.float64) shape = data.shape rank = len(shape) if rank == 0: self.dat = op2.Global(1, data) else: self.dat = op2.Global(shape, data) self._ufl_element = self.element() self._repr = 'Constant(%r)' % self._ufl_element
def __init__(self, filename, dim=None, periodic_coords=None, plex=None, reorder=None): """ :param filename: the mesh file to read. Supported mesh formats are Gmsh (extension ``msh``) and triangle (extension ``node``). :param dim: optional dimension of the coordinates in the supplied mesh. If not supplied, the coordinate dimension is determined from the type of topological entities in the mesh file. In particular, you will need to supply a value for ``dim`` if the mesh is an immersed manifold (where the geometric and topological dimensions of entities are not the same). :param periodic_coords: optional numpy array of coordinates used to replace those read from the mesh file. These are only supported in 1D and must have enough entries to be used as a DG1 field on the mesh. :param reorder: optional flag indicating whether to reorder meshes for better cache locality. If not supplied the default value in :py:data:`parameters["reorder_meshes"]` is used. """ utils._init() # A cache of function spaces that have been built on this mesh self._cache = {} self.parent = None if dim is None: # Mesh reading in Fluidity level considers 0 to be None. dim = 0 if reorder is None: reorder = parameters["reorder_meshes"] if plex is not None: self._from_dmplex(plex, geometric_dim=dim, periodic_coords=periodic_coords, reorder=reorder) self.name = filename else: basename, ext = os.path.splitext(filename) if ext in ['.e', '.exo', '.E', '.EXO']: self._from_exodus(filename, dim, reorder=reorder) elif ext in ['.cgns', '.CGNS']: self._from_cgns(filename, dim) elif ext in ['.msh']: self._from_gmsh(filename, dim, periodic_coords, reorder=reorder) elif ext in ['.node']: self._from_triangle(filename, dim, periodic_coords, reorder=reorder) else: raise RuntimeError("Unknown mesh file format.")
def apply_file(self, args): utils._init() logger = log.Log() utils.set_logger(logger) config = utils.ConfFile(args.file) test_mode = config.get_test_mode() if test_mode == 'quorum': test_quorum = control.QuorumAutoTest(config) # test_quorum.ssh_conn_build() test_quorum.test_drbd_quorum() if test_mode == 'drbd_in_used': test_iscsi = control.IscsiTest(config) test_iscsi.test_drbd_in_used()
def __init__(self, value, domain=None): # Init also called in mesh constructor, but constant can be built without mesh utils._init() try: domain.init() except AttributeError: pass self.dat, rank, shape = _globalify(value) if rank == 0: e = ufl.FiniteElement("Real", domain, 0) elif rank == 1: e = ufl.VectorElement("Real", domain, 0, shape[0]) elif rank == 2: e = ufl.TensorElement("Real", domain, 0, shape=shape) super(Constant, self).__init__(e) self._ufl_element = self.element() self._repr = 'Constant(%r, %r)' % (self._ufl_element, self.count())
def __init__(self, value, domain=None): # Init also called in mesh constructor, but constant can be built without mesh utils._init() data = np.array(value, dtype=np.float64) shape = data.shape rank = len(shape) if rank == 0: e = ufl.FiniteElement("Real", domain, 0) self.dat = op2.Global(1, data) elif rank == 1: e = ufl.VectorElement("Real", domain, 0, shape[0]) self.dat = op2.Global(shape, data) elif rank == 2: e = ufl.TensorElement("Real", domain, 0, shape=shape) self.dat = op2.Global(shape, data) else: raise RuntimeError("Don't know how to make Constant from data with rank %d" % rank) super(Constant, self).__init__(e) self._ufl_element = self.element() self._repr = 'Constant(%r)' % self._ufl_element
def __init__(self, meshfile, **kwargs): """Construct a mesh object. Meshes may either be created by reading from a mesh file, or by providing a PETSc DMPlex object defining the mesh topology. :param meshfile: Mesh file name (or DMPlex object) defining mesh topology. See below for details on supported mesh formats. :param dim: optional specification of the geometric dimension of the mesh (ignored if not reading from mesh file). If not supplied the geometric dimension is deduced from the topological dimension of entities in the mesh. :param reorder: optional flag indicating whether to reorder meshes for better cache locality. If not supplied the default value in :data:`parameters["reorder_meshes"]` is used. :param periodic_coords: optional numpy array of coordinates used to replace those in the mesh object. These are only supported in 1D and must have enough entries to be used as a DG1 field on the mesh. Not supported when reading from file. When the mesh is read from a file the following mesh formats are supported (determined, case insensitively, from the filename extension): * GMSH: with extension `.msh` * Exodus: with extension `.e`, `.exo` * CGNS: with extension `.cgns` * Triangle: with extension `.node` .. note:: When the mesh is created directly from a DMPlex object, the :data:`dim` parameter is ignored (the DMPlex already knows its geometric and topological dimensions). """ utils._init() geometric_dim = kwargs.get("dim", None) reorder = kwargs.get("reorder", parameters["reorder_meshes"]) periodic_coords = kwargs.get("periodic_coords", None) distribute = kwargs.get("distribute", True) if isinstance(meshfile, PETSc.DMPlex): name = "plexmesh" plex = meshfile else: name = meshfile basename, ext = os.path.splitext(meshfile) if periodic_coords is not None: raise RuntimeError("Periodic coordinates are unsupported when reading from file") if ext.lower() in ['.e', '.exo']: plex = _from_exodus(meshfile) elif ext.lower() == '.cgns': plex = _from_cgns(meshfile) elif ext.lower() == '.msh': plex = _from_gmsh(meshfile) elif ext.lower() == '.node': plex = _from_triangle(meshfile, geometric_dim) else: raise RuntimeError("Mesh file %s has unknown format '%s'." % (meshfile, ext[1:])) # Mark exterior and interior facets # Note. This must come before distribution, because otherwise # DMPlex will consider facets on the domain boundary to be # exterior, which is wrong. with timed_region("Mesh: label facets"): label_boundary = op2.MPI.comm.size == 1 or distribute dmplex.label_facets(plex, label_boundary=label_boundary) # Distribute the dm to all ranks if op2.MPI.comm.size > 1 and distribute: # We distribute with overlap zero, in case we're going to # refine this mesh in parallel. Later, when we actually use # it, we grow the halo. plex.distribute(overlap=0) # A cache of function spaces that have been built on this mesh self._cache = {} self.parent = None self.name = name self._plex = plex self.uid = utils._new_uid() topological_dim = self._plex.getDimension() if geometric_dim is None: geometric_dim = topological_dim cStart, cEnd = self._plex.getHeightStratum(0) # cells cell_facets = self._plex.getConeSize(cStart) self._ufl_cell = ufl.Cell(fiat_utils._cells[topological_dim][cell_facets], geometric_dimension=geometric_dim) self._ufl_domain = ufl.Domain(self.ufl_cell(), data=self) self._grown_halos = False def callback(self): del self._callback if op2.MPI.comm.size > 1: self._plex.distributeOverlap(1) self._grown_halos = True if reorder: with timed_region("Mesh: reorder"): old_to_new = self._plex.getOrdering(PETSc.Mat.OrderingType.RCM).indices reordering = np.empty_like(old_to_new) reordering[old_to_new] = np.arange(old_to_new.size, dtype=old_to_new.dtype) else: # No reordering reordering = None # Mark OP2 entities and derive the resulting Plex renumbering with timed_region("Mesh: renumbering"): dmplex.mark_entity_classes(self._plex) self._entity_classes = dmplex.get_entity_classes(self._plex) self._plex_renumbering = dmplex.plex_renumbering(self._plex, self._entity_classes, reordering) with timed_region("Mesh: cell numbering"): # Derive a cell numbering from the Plex renumbering entity_dofs = np.zeros(topological_dim+1, dtype=np.int32) entity_dofs[-1] = 1 self._cell_numbering = self._plex.createSection([1], entity_dofs, perm=self._plex_renumbering) entity_dofs[:] = 0 entity_dofs[0] = 1 self._vertex_numbering = self._plex.createSection([1], entity_dofs, perm=self._plex_renumbering) # Note that for bendy elements, this needs to change. with timed_region("Mesh: coordinate field"): if periodic_coords is not None: if self.ufl_cell().geometric_dimension() != 1: raise NotImplementedError("Periodic coordinates in more than 1D are unsupported") # We've been passed a periodic coordinate field, so use that. self._coordinate_fs = functionspace.VectorFunctionSpace(self, "DG", 1) self.coordinates = function.Function(self._coordinate_fs, val=periodic_coords, name="Coordinates") else: self._coordinate_fs = functionspace.VectorFunctionSpace(self, "Lagrange", 1) coordinates = dmplex.reordered_coords(self._plex, self._coordinate_fs._global_numbering, (self.num_vertices(), geometric_dim)) self.coordinates = function.Function(self._coordinate_fs, val=coordinates, name="Coordinates") self._ufl_domain = ufl.Domain(self.coordinates) # Build a new ufl element for this function space with the # correct domain. This is necessary since this function space # is in the cache and will be picked up by later # VectorFunctionSpace construction. self._coordinate_fs._ufl_element = self._coordinate_fs.ufl_element().reconstruct(domain=self.ufl_domain()) # HACK alert! # Replace coordinate Function by one that has a real domain on it (but don't copy values) self.coordinates = function.Function(self._coordinate_fs, val=self.coordinates.dat) # Add subdomain_data to the measure objects we store with # the mesh. These are weakrefs for consistency with the # "global" measure objects self._dx = ufl.Measure('cell', subdomain_data=weakref.ref(self.coordinates)) self._ds = ufl.Measure('exterior_facet', subdomain_data=weakref.ref(self.coordinates)) self._dS = ufl.Measure('interior_facet', subdomain_data=weakref.ref(self.coordinates)) # Set the subdomain_data on all the default measures to this # coordinate field. # We don't set the domain on the measure since this causes # an uncollectable reference in the global space (dx is # global). Furthermore, it's never used anyway. for measure in [ufl.dx, ufl.ds, ufl.dS]: measure._subdomain_data = weakref.ref(self.coordinates) self._callback = callback
def __init__(self, code=None, element=None, cell=None, degree=None, **kwargs): """ :param code: a string C statement, or list of statements. :param element: a :class:`~ufl.finiteelement.finiteelement.FiniteElement`, optional (currently ignored) :param cell: a :class:`~ufl.geometry.Cell`, optional (currently ignored) :param degree: the degree of quadrature to use for evaluation (currently ignored) :param kwargs: user-defined values that are accessible in the Expression code. These values maybe updated by accessing the property of the same name. This can be used, for example, to pass in the current timestep to an Expression without necessitating recompilation. For example: .. code-block:: python f = Function(V) e = Expression('sin(x[0]*t)', t=t) while t < T: f.interpolate(e) ... t += dt e.t = t The currently ignored parameters are retained for API compatibility with Dolfin. """ # Init also called in mesh constructor, but expression can be built without mesh utils._init() self.code = code self._shape = () if code is not None: shape = np.array(code).shape self._shape = shape if self.rank() == 0: # Make code slot iterable even for scalar expressions self.code = [code] self.cell = cell self.degree = degree # These attributes are required by ufl.Coefficient to render the repr # of an Expression. Since we don't call the ufl.Coefficient constructor # (since we don't yet know the element) we need to set them ourselves self._element = element self._repr = None self._count = 0 self._user_args = [] # Changing counter used to record when user changes values self._state = 0 # Save the kwargs so that when we rebuild an expression we can # reconstruct the user arguments. self._kwargs = {} if len(kwargs) == 0: # No need for magic, since there are no user arguments. return # We have to build a new class to add these properties to # since properties work on classes not instances and we don't # want every Expression to have all the properties of all # Expressions. cls = type(self.__class__.__name__, (self.__class__, ), {}) for slot, val in kwargs.iteritems(): # Save the argument for later reconstruction self._kwargs[slot] = val # Scalar arguments have to be treated specially val = np.array(val, dtype=np.float64) shape = val.shape rank = len(shape) if rank == 0: shape = 1 val = op2.Global(shape, val, dtype=np.float64, name=slot) # Record the Globals in a known order (for later passing # to a par_loop). Remember their "name" too, so we can # construct a kwarg dict when applying python expressions. self._user_args.append((slot, val)) # And save them as an attribute setattr(self, '_%s' % slot, val) # We have to do this because of the worthlessness of # Python's support for closing over variables. def make_getx(slot): def getx(self): glob = getattr(self, '_%s' % slot) return glob.data_ro return getx def make_setx(slot): def setx(self, value): glob = getattr(self, '_%s' % slot) glob.data = value self._kwargs[slot] = value # Bump state self._state += 1 return setx # Add public properties for the user-defined variables prop = property(make_getx(slot), make_setx(slot)) setattr(cls, slot, prop) # Set the class on this instance to the newly built class with # properties attached. self.__class__ = cls
def Mesh(meshfile, **kwargs): """Construct a mesh object. Meshes may either be created by reading from a mesh file, or by providing a PETSc DMPlex object defining the mesh topology. :param meshfile: Mesh file name (or DMPlex object) defining mesh topology. See below for details on supported mesh formats. :param dim: optional specification of the geometric dimension of the mesh (ignored if not reading from mesh file). If not supplied the geometric dimension is deduced from the topological dimension of entities in the mesh. :param reorder: optional flag indicating whether to reorder meshes for better cache locality. If not supplied the default value in :data:`parameters["reorder_meshes"]` is used. :param periodic_coords: optional numpy array of coordinates used to replace those in the mesh object. These are only supported in 1D and must have enough entries to be used as a DG1 field on the mesh. Not supported when reading from file. When the mesh is read from a file the following mesh formats are supported (determined, case insensitively, from the filename extension): * GMSH: with extension `.msh` * Exodus: with extension `.e`, `.exo` * CGNS: with extension `.cgns` * Triangle: with extension `.node` .. note:: When the mesh is created directly from a DMPlex object, the :data:`dim` parameter is ignored (the DMPlex already knows its geometric and topological dimensions). """ utils._init() dim = kwargs.get("dim", None) reorder = kwargs.get("reorder", parameters["reorder_meshes"]) periodic_coords = kwargs.get("periodic_coords", None) if isinstance(meshfile, PETSc.DMPlex): name = "plexmesh" plex = meshfile else: name = meshfile basename, ext = os.path.splitext(meshfile) if periodic_coords is not None: raise RuntimeError("Periodic coordinates are unsupported when reading from file") if ext.lower() in ['.e', '.exo']: plex = _from_exodus(meshfile) elif ext.lower() == '.cgns': plex = _from_cgns(meshfile) elif ext.lower() == '.msh': plex = _from_gmsh(meshfile) elif ext.lower() == '.node': plex = _from_triangle(meshfile, dim) else: raise RuntimeError("Mesh file %s has unknown format '%s'." % (meshfile, ext[1:])) # Distribute the dm to all ranks if op2.MPI.comm.size > 1: plex.distribute(overlap=1) topological_dim = plex.getDimension() cStart, cEnd = plex.getHeightStratum(0) # cells cell_facets = plex.getConeSize(cStart) if topological_dim + 1 == cell_facets: MeshClass = SimplexMesh elif topological_dim == 2 and cell_facets == 4: MeshClass = QuadrilateralMesh else: raise RuntimeError("Unsupported mesh type.") return MeshClass(name, plex, dim, reorder, periodic_coords=periodic_coords)