Ejemplo n.º 1
0
def load_gnome_tri(filename):
    """
    load an fvcom/gnome netcdf file

    :param filename: the path to the file to load

    :returns: an UGRID object with the data from the file
    """
    nc = netCDF4.Dataset(filename)

    # check if it's the file type we are looking for
    if nc.getncattr('grid_type').lower() != 'triangular':
        raise ValueError(
            'This does not appear to be a valid triangular grid file:\nIt does not have the "grid_type"="Triangular" global attribute'
        )

    # create an empty UGrid:
    ug = pyugrid.UGrid()
    # load the nodes
    lon = nc.variables['lon']
    lat = nc.variables['lat']

    num_nodes = lon.shape[0]
    ug.nodes = np.zeros((num_nodes, 2), dtype=lon.dtype)
    ug.nodes[:, 0] = lon[:]
    ug.nodes[:, 1] = lat[:]

    # load the faces
    ug.faces = nc.variables['nv'][:].T

    # load the connectivity array
    ug.face_face_connectivity = nc.variables['nbe'][:].T

    # load the center points of the faces
    ug.face_coordinates = np.zeros((len(ug.faces), 2), dtype=lon.dtype)
    ug.face_coordinates[:, 0] = nc.variables['lonc'][:]
    ug.face_coordinates[:, 1] = nc.variables['latc'][:]

    bounds = nc.variables['bnd']
    ug.boundaries = bounds[:, :
                           2]  # ignoring the second two fields -- what are they???

    return ug
Ejemplo n.º 2
0
def tri_vector_field(filename=None, dataset=None):
    if dataset is None:
        dataset = nc4.Dataset(filename)

    nodes = np.ascontiguousarray(
        np.column_stack((dataset['lon'], dataset['lat']))).astype(np.double)
    faces = np.ascontiguousarray(np.array(dataset['nv']).T - 1)
    boundaries = np.ascontiguousarray(np.array(dataset['bnd'])[:, 0:2] - 1)
    neighbors = np.ascontiguousarray(np.array(dataset['nbe']).T - 1)
    edges = None
    grid = pyugrid.UGrid(nodes,
                         faces,
                         edges,
                         boundaries,
                         neighbors)
    grid.build_edges()
    u = pyugrid.UVar('u', 'node', dataset['u'])
    v = pyugrid.UVar('v', 'node', dataset['v'])
    time = Time(dataset['time'])
    variables = {'u':u, 'v':v}
    type = dataset.grid_type
    return VectorField(grid, time=time, variables=variables, type=type)
Ejemplo n.º 3
0
def init_grid(filename,
              grid_topology=None,
              dataset=None,):
    gt = grid_topology
    gf = dataset
    if gf is None:
        gf = _get_dataset(filename)
    grid = None
    if gt is None:
        try:
            grid = pyugrid.UGrid.from_nc_dataset(gf)
        except (ValueError, NameError):
            pass
        try:
            grid = pysgrid.SGrid.load_grid(gf)
        except (ValueError, NameError):
            gt = _gen_topology(filename)
    if grid is None:
        nodes = node_lon = node_lat = None
        if 'nodes' not in gt:
            if 'node_lon' not in gt and 'node_lat' not in gt:
                raise ValueError('Nodes must be specified with either the "nodes" or "node_lon" and "node_lat" keys')
            node_lon = gf[gt['node_lon']]
            node_lat = gf[gt['node_lat']]
        else:
            nodes = gf[gt['nodes']]
        if 'faces' in gt and gf[gt['faces']]:
            # UGrid
            faces = gf[gt['faces']]
            if faces.shape[0] == 3:
                faces = np.ascontiguousarray(np.array(faces).T - 1)
            if nodes is None:
                nodes = np.column_stack((node_lon, node_lat))
            grid = pyugrid.UGrid(nodes=nodes, faces=faces)
        else:
            # SGrid
            center_lon = center_lat = edge1_lon = edge1_lat = edge2_lon = edge2_lat = None
            if node_lon is None:
                node_lon = nodes[:, 0]
            if node_lat is None:
                node_lat = nodes[:, 1]
            if 'center_lon' in gt:
                center_lon = gf[gt['center_lon']]
            if 'center_lat' in gt:
                center_lat = gf[gt['center_lat']]
            if 'edge1_lon' in gt:
                edge1_lon = gf[gt['edge1_lon']]
            if 'edge1_lat' in gt:
                edge1_lat = gf[gt['edge1_lat']]
            if 'edge2_lon' in gt:
                edge2_lon = gf[gt['edge2_lon']]
            if 'edge2_lat' in gt:
                edge2_lat = gf[gt['edge2_lat']]
            grid = pysgrid.SGrid(node_lon=node_lon,
                                 node_lat=node_lat,
                                 center_lon=center_lon,
                                 center_lat=center_lat,
                                 edge1_lon=edge1_lon,
                                 edge1_lat=edge1_lat,
                                 edge2_lon=edge2_lon,
                                 edge2_lat=edge2_lat)
    return grid
Ejemplo n.º 4
0
def load_from_varnames(filename, names_mapping):
    """
    load a UGrid from a netcdf file where the roles are defined by the names of the variables

    :param filename: the names of the file to load (or opendap url)

    :param names_mapping: dict that maps the variable names to the UGRid components

    """

    nc = netCDF4.Dataset("small_trigrid_example.nc")

    # check if it's the file type we are looking for
    try:
        name, value = names_mapping['attribute_check']
        if nc.getncattr(name).lower() != value:
            raise ValueError(
                'This does not appear to be a valid triangular grid file:\nIt does not have the "grid_type"="Triangular" global attribute'
            )
    except KeyError:
        pass

    # create an empty UGrid:
    ug = pyugrid.UGrid()

    # load the nodes -- this is required
    # nodes are usually stored in two different arrays
    lon = nc.variables[names_mapping['nodes_lon']]
    lat = nc.variables[names_mapping['nodes_lat']]

    num_nodes = lon.shape[0]
    ug.nodes = np.zeros((num_nodes, 2), dtype=lon.dtype)
    ug.nodes[:, 0] = lon[:]
    ug.nodes[:, 1] = lat[:]

    # load the faces
    faces = nc.variables[names_mapping['faces']]
    # does it need to be transposed?
    if faces.shape[0] <= faces.shape[
            1]:  # assume there are more than three triangles...
        # fortran order -- needs to be transposed
        faces = faces[:].T
    else:
        faces = faces[:]
    # is it one-indexed?
    if faces.min() == 1:
        one_indexed = True
        faces -= 1
        ug.faces = faces
    else:
        one_indexed = False

    # load the connectivity array: optional
    if 'face_face_connectivity' in names_mapping:
        face_face_connectivity = nc.variables[
            names_mapping['face_face_connectivity']]
        # does it need to be transposed?
        if face_face_connectivity.shape[0] <= face_face_connectivity.shape[
                1]:  # assume there are more than three triangles...
            # fortran order -- needs to be transposed
            face_face_connectivity = face_face_connectivity[:].T
        else:
            face_face_connectivity = face_face_connectivity[:]
        if one_indexed:
            face_face_connectivity -= 1
        ug.face_face_connectivity = face_face_connectivity[:]

    # load the center points of the faces: optional
    if 'face_coordinates_lon' in names_mapping and 'face_coordinates_lon' in names_mapping:
        ug.face_coordinates = np.zeros((len(ug.faces), 2), dtype=lon.dtype)
        ug.face_coordinates[:, 0] = nc.variables[
            names_mapping['face_coordinates_lon']][:]
        ug.face_coordinates[:, 1] = nc.variables[
            names_mapping['face_coordinates_lat']][:]

    print "checking bounds"
    if 'boundaries' in names_mapping:  # optional
        print "loading boundaries"
        ## fixme --  this one is weird and non-conforming....
        boundaries = nc.variables[names_mapping['boundaries']][:]
        if one_indexed:
            boundaries[:, :2] -= 1
        ug.boundaries = boundaries[:, :
                                   2]  # ignoring the rest of the fields -- they are boundary data -- see below
        # kludge to handle the gnome tri format's putting boundary data in with the boundary indexes..
        if boundaries.shape[
                1] == 4:  #this looks like GNOME-style boundary data
            ## add the boudnary data as uvars
            pass

    return ug
Ejemplo n.º 5
0
def getcommonmesh_remesh(ugrid0, ugrid1, varkws):
    """
  interpolate two UGRID meshes (create with IO_netcdfplot_dg_remesh) and the
  given variables to common fine "base" mesh. Locally one mesh must
  be a submesh in the other.
  """

    # compute triangle midpoints on both grids
    midpointsf0 = np.mean(ugrid0.nodes[ugrid0.faces], axis=1)
    midpointsf1 = np.mean(ugrid1.nodes[ugrid1.faces], axis=1)

    # locate which triangles from on grid are in which triangles from the other
    f1mf0 = ugrid1.locate_faces(midpointsf0)
    f0mf1 = ugrid0.locate_faces(midpointsf1)

    # compute areas of triangles to decide, which triangles are common, and which are
    # sub-triangles in the other grid
    nodesf0 = ugrid0.nodes[ugrid0.faces]
    areaf0 = 0.5 * np.abs((nodesf0[:, 0, 0] - nodesf0[:, 2, 0]) *
                          (nodesf0[:, 1, 1] - nodesf0[:, 0, 1]) -
                          (nodesf0[:, 0, 0] - nodesf0[:, 1, 0]) *
                          (nodesf0[:, 2, 1] - nodesf0[:, 0, 1]))
    nodesf1 = ugrid1.nodes[ugrid1.faces]
    areaf1 = 0.5 * np.abs((nodesf1[:, 0, 0] - nodesf1[:, 2, 0]) *
                          (nodesf1[:, 1, 1] - nodesf1[:, 0, 1]) -
                          (nodesf1[:, 0, 0] - nodesf1[:, 1, 0]) *
                          (nodesf1[:, 2, 1] - nodesf1[:, 0, 1]))

    # compute common nodes
    idxf0same = np.isclose(areaf0, areaf1[f1mf0])
    idxn0same = ugrid0.faces[idxf0same].ravel()
    idxn1same = ugrid1.faces[idxf0same[f0mf1]].ravel()
    newnodes = ugrid0.nodes[idxn0same]

    # setup variables
    vars0 = {}
    vars1 = {}
    vars0new = {}
    vars1new = {}

    for kw in varkws:
        vars0[kw] = ugrid0.data[kw].data[0, :]
        vars1[kw] = ugrid1.data[kw].data[0, :]
        vars0new[kw] = vars0[kw][idxn0same]
        vars1new[kw] = vars1[kw][idxn1same]

    # walk through all triangle in first mesh, which are not other mesh
    for f0i in np.where(~idxf0same)[0]:
        face0i = ugrid0.faces[f0i]
        nodesf0i = ugrid0.nodes[face0i]
        areaf0i = areaf0[f0i]

        # find corresponding triangle other mesh and compare areas
        f1i = f1mf0[f0i]
        face1i = ugrid1.faces[f1i]
        areaf1i = areaf1[f1i]
        if (areaf0i < areaf1i):
            # if area is smaller, add nodes to new mesh and linearly
            # interpolate variables to finer mesh
            nodesf1i = ugrid1.nodes[face1i]
            newnodes = np.vstack([newnodes, ugrid0.nodes[face0i]])
            nodesf0b = xytobary(nodesf0i[:, 0], nodesf0i[:, 1], nodesf1i[:, 0],
                                nodesf1i[:, 1])
            for kw in varkws:
                vars0new[kw] = np.append(vars0new[kw], vars0[kw][face0i])
                vars1new[kw] = np.append(vars1new[kw],
                                         np.dot(nodesf0b, vars1[kw][face1i]))
        else:
            # if are is larger, add nodes from other mesh to new mesh and interpolate
            # variables from first mesh
            f1add = np.where(f0mf1 == f0i)[0]
            nodesf1 = ugrid1.nodes[ugrid1.faces[f1add]]
            n1add = ugrid1.faces[f1add].ravel()
            newnodes = np.vstack([newnodes, ugrid1.nodes[n1add]])
            nodesf1b = np.swapaxes(
                xytobary(nodesf1[:, :, 0], nodesf1[:, :, 1], nodesf0i[:, 0],
                         nodesf0i[:, 1]), 0, 1)
            for kw in varkws:
                vars0new[kw] = np.append(vars0new[kw],
                                         np.dot(nodesf1b, vars0[kw][face0i]))
                vars1new[kw] = np.append(vars1new[kw],
                                         vars1[kw][ugrid1.faces[f1add]])

    # create new fine common mesh
    newfaces = np.reshape(np.arange(newnodes.shape[0]),
                          (newnodes.shape[0] / 3, 3))
    ugridnew = pyugrid.UGrid(nodes=newnodes,
                             faces=newfaces,
                             mesh_name=ugrid0.mesh_name)

    # copy variables to new fine mesh
    for kw in varkws:
        uvar0new = copy.deepcopy(ugrid0.data[kw])
        uvar0new.data = np.array([vars0new[kw]])
        uvar0new.name = kw + '_0'
        ugridnew.add_data(uvar0new)

        uvar1new = copy.deepcopy(ugrid1.data[kw])
        uvar1new.data = np.array([vars1new[kw]])
        uvar1new.name = kw + '_1'
        ugridnew.add_data(uvar1new)

    return ugridnew