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)
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)
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
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