Пример #1
0
def gaussian_mesh_randomizer(mesh, percentage, preserve_boundary=True):
    """
    Randomly perturb a given mesh.

    Args:
        mesh: Input mesh.
        percentage: Maximum perturbation in percentage of mesh.hmin().
        preserve_boundary: Whether to move the vertices on the boundary.
    Returns:
        rmesh: The perturbed mesh.
    """
    rmesh = Mesh(mesh)
    deltax = (np.random.randn(rmesh.num_vertices(),
                              rmesh.geometry().dim()) * percentage *
              rmesh.hmin())
    if preserve_boundary:
        boundary_mesh = BoundaryMesh(rmesh, "exterior")
        boundary_vertices = boundary_mesh.entity_map(0).array()
        deltax[boundary_vertices] = 0.0
    rmesh.coordinates()[:] = rmesh.coordinates() + deltax
    return rmesh
Пример #2
0
def remap_from_files(prefix, ksdg=None):
    """remap dofs from multiprocess FunctionSpace to single process

    Required parameter:
    prefix -- the filename prefix for the fsinfo files

    Optional parameter:
    ksdg -- the KSDGSolver that defines the single process
            FunctionsSpace

    Returns a vector of integers that can be used to remap degrees of
    freedom on a distributed mesh to those on the local mesh, using
    numpy indirection, i.e.

    remap = remap_from_files(ksdg, local_mesh=lmesh)
    local_function.vector()[:] = global_function.vector()[:][remap]
    
    This function does the same thing as dofremap, but at a different
    time and a different way. Unlike dofremap, remap_from_files is
    called after a solution is finished, not while it is in
    progress. The information about the degrees of freedom is
    retrieved from h5 files created at the time of solution. If the
    solution was run as an MPI group on S processes, there
    remap_from_files consults S+1 files:

    prefix_mesh.xml.gz
    prefixrank0_fsinfo.h5
    prefixrank1_fsinfo.h5
    ...
    prefixrank<S-1>_fsinfo.h5

    The mesh file contains the total mesh for the problem, as
    assembled by gather_mesh. Of the fsinfo files (which contain
    information about the function space local to each MPI process),
    at least the rank0 file must exist. Its 'size' entry is read to
    determine the number of fsinfo files, and its degree and dim
    entries are used to create a FunctionSpace on this mesh (by
    creating a KSDGSolver with those arguments). It then goes through
    the fsinfo files sequentially, determining the mapping from each
    one's DOFs to the DOFs pof the global FunctionSpace. 

    Note: this works only for solutions with a single rho and a single
    U.
    """
    if (ksdg):
        mesh = ksdg.mesh
    else:
        meshfile = prefix + '_mesh.xml.gz'
        mesh = Mesh(meshfile)
    dim = mesh.geometry().dim()
    r0name = fsinfo_filename(prefix, 0)
    with h5py.File(r0name, 'r') as fsf:
        size = fsf['/mpi/size'].value
        if (dim != fsf['dim'].value):
            raise KSDGException("mesh dimension = " + dim +
                                ", FunctionSpace dim = " + fsf['dim'])
        try:
            degree = fsf['degree'].value
        except KeyError:
            degree = 3
            try:
                periodic = fsf['periodic'].value
            except KeyError:
                periodic = False
    if not ksdg:
        from .ksdgmakesolver import makeKSDGSolver  # circular import
        ksdg = makeKSDGSolver(mesh=mesh,
                              degree=degree,
                              project_initial_condition=False,
                              periodic=periodic)
    owneddofs = []
    ltg = []
    dofcoords = []
    dofs = []
    rho_dofs = []
    U_dofs = []
    cell_dofs = []
    cell_indices = []
    #
    # collect info about each processes dofs from files
    #
    for rank in range(size):
        rname = fsinfo_filename(prefix, rank)
        with h5py.File(rname, 'r') as fsf:
            owneddofs.append(fsf['ownership_range'].value.copy())
            ltg.append(fsf['tabulate_local_to_global_dofs'].value.copy())
            dofcoords.append(fsf['dofcoords'].value[0].copy())
            dofs.append(fsf['dofs'].value.copy())
            U_dofs.append(fsf['U_dofs'].value.copy())
            rho_dofs.append(fsf['rho_dofs'].value.copy())
            cell_dofs.append(fsf['cell_dofs'].value.copy())
            cell_indices.append(fsf['/mesh/cell_indices'].value.copy())
    transform = integerify_transform(dofcoords)
    spacing = transform[0]
    base = transform[1]
    #
    # check against global info
    #
    owneddofs = np.array(owneddofs)
    gdofmap = ksdg.VS.dofmap()
    gdofrange = gdofmap.ownership_range()
    if gdofrange[0] != 0:
        raise KSDGException("First dof %d, expected 0", gdofrange[0])
    fdofmin = owneddofs[:, 0].min()
    fdofmax = owneddofs[:, 1].max()
    if (fdofmin != gdofrange[0] or fdofmax != gdofrange[1]):
        raise KSDGException("dof mismatch: global %d - %d, files %d - %d" %
                            (gdofrange[0], gdofrange[1], fdofmin, fdofmax))
    fdofs = np.zeros((gdofrange[1], dim + 2))
    #
    # combine file info into one list of file dofs
    #
    for rank in range(size):
        fdofs[rho_dofs[rank], 1] = 0.0
        fdofs[U_dofs[rank], 1] = 1.0
        ncells = cell_indices[rank].shape[0]
        dofspercell = cell_dofs[rank].shape[1]
        for cell in range(ncells):
            fdofs[ltg[rank][cell_dofs[rank][cell]],
                  0] = cell_indices[rank][cell]
        nlocal = owneddofs[rank, 1] - owneddofs[rank, 0]
        fdofs[ltg[rank][:nlocal], 2:] = dofcoords[rank]
    #
    # assemble global dof list
    #
    ifdofs = np.empty_like(fdofs, dtype=int)
    np.rint(fdofs[:, :2], out=ifdofs[:, :2], casting='unsafe')
    np.rint(fdofs[:, 2:] / spacing - base, out=ifdofs[:, 2:], casting='unsafe')
    gdofs = local_dofs(ksdg)
    gdofs = gdofs[:, :-1]
    igdofs = np.empty_like(gdofs, dtype=int)
    np.rint(gdofs[:, :2], out=igdofs[:, :2], casting='unsafe')
    np.rint(gdofs[:, 2:] / spacing - base, out=igdofs[:, 2:], casting='unsafe')
    #
    # DOFs belonging to R subspaces don't have cells or coordinates
    #
    Rdofs = np.array([], dtype=int)
    for ss in subspaces(fs):
        if isRsubspace(ss):
            Rdofs = np.append(Rdofs, ss.dofmap().dofs())
    logGATHER('Rdofs', Rdofs)
    try:
        doflist[Rdofs - owneddofs[0], 1] = -2.0
        doflist[Rdofs - owneddofs[0], 2:-1] = -float('inf')
    except IndexError:
        logGATHER('IndexError: Rdofs-owneddofs[0]', Rdofs - owneddofs[0])
    return (remap_list(ifdofs, igdofs, fdofs, gdofs))