예제 #1
0
def _calc_metric(name, domain, region, weights, reference_state):
    """
    Calculate metric `name` on `region` using `weights` and `reference_state`.
    """
    zone_name = region[0]
    zone = getattr(domain, zone_name)
    cls, integrate, geometry = get_metric(name)
    metric = cls(zone, zone_name, reference_state)
    weights = weights.get(zone_name)

    # Could be volume, surface, curve, or point.
    dim = _get_dimension(region)
    if dim == 3:
        if geometry not in ('volume', 'any'):
            raise RuntimeError('metric %r not applicable to volumes')
        total = _volume(metric, integrate, zone, region, weights)
    elif dim == 2:
        if geometry not in ('surface', 'any'):
            raise RuntimeError('metric %r not applicable to surfaces')
        if len(region) == 7:
            total = _surface_3d(metric, integrate, zone, region, weights)
        else:
            total = _surface_2d(metric, integrate, zone, region, weights)
    elif dim == 1:
        if geometry not in ('curve', 'any'):
            raise RuntimeError('metric %r not applicable to curves')
        if len(region) == 7:
            total = _curve_3d(metric, integrate, zone, region, weights)
        elif len(region) == 5:
            total = _curve_2d(metric, integrate, zone, region, weights)
        else:
            total = _curve_1d(metric, integrate, zone, region, weights)
    else:
        if geometry != 'any':
            raise RuntimeError('metric %r not applicable to points')
        total = _point(metric, zone, region)

    if reference_state is None:
        return total
    else:
        return metric.dimensionalize(total)
예제 #2
0
def _calc_metric(name, domain, region, weights, reference_state):
    """
    Calculate metric `name` on `region` using `weights` and `reference_state`.
    """
    zone_name = region[0]
    zone = getattr(domain, zone_name)
    cls, integrate, geometry = get_metric(name)
    metric = cls(zone, zone_name, reference_state)
    weights = weights.get(zone_name)

    # Could be volume, surface, curve, or point.
    dim = _get_dimension(region)
    if dim == 3:
        if geometry not in ('volume', 'any'):
            raise RuntimeError('metric %r not applicable to volumes')
        total = _volume(metric, integrate, zone, region, weights)
    elif dim == 2:
        if geometry not in ('surface', 'any'):
            raise RuntimeError('metric %r not applicable to surfaces')
        if len(region) == 7:
            total = _surface_3d(metric, integrate, zone, region, weights)
        else:
            total = _surface_2d(metric, integrate, zone, region, weights)
    elif dim == 1:
        if geometry not in ('curve', 'any'):
            raise RuntimeError('metric %r not applicable to curves')
        if len(region) == 7:
            total = _curve_3d(metric, integrate, zone, region, weights)
        elif len(region) == 5:
            total = _curve_2d(metric, integrate, zone, region, weights)
        else:
            total = _curve_1d(metric, integrate, zone, region, weights)
    else:
        if geometry != 'any':
            raise RuntimeError('metric %r not applicable to points')
        total = _point(metric, zone, region)

    if reference_state is None:
        return total
    else:
        return metric.dimensionalize(total)
예제 #3
0
def mesh_probe(domain, regions, variables, weighting_scheme='area'):
    """
    Calculate metrics on mesh regions.
    Currently only supports structured grids.

    domain: DomainObj
        The domain to be processed.

    regions: list
        List of ``(zone_name, imin, imax[, jmin, jmax[, kmin, kmax]])``
        mesh region specifications to be used for the calculation.
        Indices start at 0. Negative indices are relative to the end of the
        array.

    variables: list
        List of ``(metric_name, units)`` tuples. Legal pre-existing metric
        names can be obtained from :meth:`list_metrics`. If `units` is
        None then no unit conversion is attempted. `metric_name` may also
        be the name of a flow solution scalar variable, if `units` is None.
        In this case a minimal metric calculator will be auto-generated.

    weighting_scheme: string
        Specifies how individual values are weighted. Legal values are
        'area' for area averaging and 'mass' for mass averaging.

    Returns a list of metric values in the order of the `variables` list.

    .. note::

        The per-item averaging scheme is simplistic. For instance, all four
        vertices of a face get equal weight, or the two cells sharing a
        face get equal weight. This will lead to inaccuracies for highly
        irregular grids.

    """
    # Check validity of region specifications.
    _regions = _check_regions(domain, regions)

    # Check validity of variables.
    need_weights = False
    for name, units in variables:
        if name not in list_metrics():
            if units is None:
                # See if it's something we can create dynamically.
                zone_name = regions[0][0]
                zone = getattr(domain, zone_name)
                if hasattr(zone.flow_solution, name):
                    create_scalar_metric(name)
                else:
                    raise ValueError('Unknown variable %r' % name)
            else:
                raise ValueError('Unsupported variable %r' % name)
        cls, integrate, geometry = get_metric(name)
        if not integrate:
            need_weights = True

    # Check validity of weighting scheme.
    if weighting_scheme not in _SCHEMES:
        raise ValueError('Unknown/unsupported weighting scheme %r' %
                         weighting_scheme)

    # Collect weights.
    if need_weights:
        weights, weight_total = _calc_weights(weighting_scheme, domain,
                                              _regions)
    else:
        weights, weight_total = {}, 0.

    # Collect metric values.
    metrics = []
    for name, units in variables:
        # Compute total for each region.
        total = None
        for region in _regions:
            zone_name = region[0]
            zone = getattr(domain, zone_name)

            if units is None:
                ref = None
            else:  # Check for a reference_state dictionary.
                ref = zone.reference_state or domain.reference_state
                if not ref:
                    raise ValueError('No zone or domain reference_state'
                                     ' dictionary supplied for zone %s.' %
                                     zone_name)

            value = _calc_metric(name, domain, region, weights, ref)
            value *= zone.symmetry_instances  # Adjust for symmetry.
            if total is None:
                total = value  # Set initial PhysicalQuantity (or float).
            else:
                total += value

        # If not integrating adjust for overall weighting.
        cls, integrate, geometry = get_metric(name)
        if not integrate:
            total /= weight_total

        if units is None:
            metrics.append(total)
        else:
            total.convert_to_unit(units)  # Convert to requested units.
            metrics.append(total.value)

    return metrics
예제 #4
0
def mesh_probe(domain, regions, variables, weighting_scheme='area'):
    """
    Calculate metrics on mesh regions.
    Currently only supports structured grids.

    domain: DomainObj
        The domain to be processed.

    regions: list
        List of ``(zone_name, imin, imax[, jmin, jmax[, kmin, kmax]])``
        mesh region specifications to be used for the calculation.
        Indices start at 0. Negative indices are relative to the end of the
        array.

    variables: list
        List of ``(metric_name, units)`` tuples. Legal pre-existing metric
        names can be obtained from :meth:`list_metrics`. If `units` is
        None, then no unit conversion is attempted. `metric_name` may also
        be the name of a flow solution scalar variable if `units` is None.
        In this case a minimal metric calculator will be auto-generated.

    weighting_scheme: string
        Specifies how individual values are weighted. Legal values are
        'area' for area averaging and 'mass' for mass averaging.

    Returns a list of metric values in the order of the `variables` list.

    .. note::

        The per-item averaging scheme is simplistic. For instance, all four
        vertices of a face get equal weight, or the two cells sharing a
        face get equal weight. This will lead to inaccuracies for highly
        irregular grids.

    """
    # Check validity of region specifications.
    _regions = _check_regions(domain, regions)

    # Check validity of variables.
    need_weights = False
    for name, units in variables:
        if name not in list_metrics():
            if units is None:
                # See if it's something we can create dynamically.
                zone_name = regions[0][0]
                zone = getattr(domain, zone_name)
                if hasattr(zone.flow_solution, name):
                    create_scalar_metric(name)
                else:
                    raise ValueError('Unknown variable %r' % name)
            else:
                raise ValueError('Unsupported variable %r' % name)
        cls, integrate, geometry = get_metric(name)
        if not integrate:
            need_weights = True

    # Check validity of weighting scheme.
    if weighting_scheme not in _SCHEMES:
        raise ValueError('Unknown/unsupported weighting scheme %r'
                         % weighting_scheme)

    # Collect weights.
    if need_weights:
        weights, weight_total = _calc_weights(weighting_scheme, domain, _regions)
    else:
        weights, weight_total = {}, 0.

    # Collect metric values.
    metrics = []
    for name, units in variables:
        # Compute total for each region.
        total = None
        for region in _regions:
            zone_name = region[0]
            zone = getattr(domain, zone_name)

            if units is None:
                ref = None
            else:  # Check for a reference_state dictionary.
                ref = zone.reference_state or domain.reference_state
                if not ref:
                    raise ValueError('No zone or domain reference_state'
                                     ' dictionary supplied for zone %s.'
                                     % zone_name)

            value = _calc_metric(name, domain, region, weights, ref)
            value *= zone.symmetry_instances  # Adjust for symmetry.
            if total is None:
                total = value  # Set initial PhysicalQuantity (or float).
            else:
                total += value

        # If not integrating adjust for overall weighting.
        cls, integrate, geometry = get_metric(name)
        if not integrate:
            total /= weight_total

        if units is None:
            metrics.append(total)
        else:
            total.convert_to_unit(units)  # Convert to requested units.
            metrics.append(total.value)

    return metrics