def test_quantity_1arg(self): q = Quantity("123 kg") self.assertEqual(str(q.units), "kilogram") self.assertEqual(q.to("t").magnitude, 0.123) q = pickle.loads(pickle.dumps(q)) self.assertEqual(str(q.units), "kilogram") self.assertEqual(q.to("t").magnitude, 0.123)
def test_quantity_2args(self, protocol): q = Quantity(123, "foo") self.assertEqual(str(q.units), "foo") self.assertEqual(q.to("bar").magnitude, 246) q = pickle.loads(pickle.dumps(q, protocol)) self.assertEqual(str(q.units), "foo") self.assertEqual(q.to("bar").magnitude, 246)
def test_quantity_1arg(self): q = Quantity("123 foo") self.assertEqual(str(q.units), "foo") self.assertEqual(q.to("bar").magnitude, 246) q = pickle.loads(pickle.dumps(q)) self.assertEqual(str(q.units), "foo") self.assertEqual(q.to("bar").magnitude, 246)
def test_quantity_2args(self, protocol): q = Quantity(123, "foo") assert str(q.units) == "foo" assert q.to("bar").magnitude == 246 q = pickle.loads(pickle.dumps(q, protocol)) assert str(q.units) == "foo" assert q.to("bar").magnitude == 246
def test_quantity_2args(self, protocol): q = Quantity(123, "kg") self.assertEqual(str(q.units), "kilogram") self.assertEqual(q.to("t").magnitude, 0.123) q = pickle.loads(pickle.dumps(q, protocol)) self.assertEqual(str(q.units), "kilogram") self.assertEqual(q.to("t").magnitude, 0.123)
def test_quantity_2args(self, protocol): q = Quantity(123, "kg") assert str(q.units) == "kilogram" assert q.to("t").magnitude == 0.123 q = pickle.loads(pickle.dumps(q, protocol)) assert str(q.units) == "kilogram" assert q.to("t").magnitude == 0.123
def test_quantity_2args(self, protocol): set_application_registry(self.ureg1) q1 = Quantity(1, "foo") set_application_registry(self.ureg2) q2 = Quantity(1, "foo") q3 = pickle.loads(pickle.dumps(q1, protocol)) assert q1.dimensionality == {"[dim1]": 1} assert q2.dimensionality == {"[dim2]": 1} assert q3.dimensionality == {"[dim2]": 1} assert q1.to("bar").magnitude == 2 assert q2.to("bar").magnitude == 3 assert q3.to("bar").magnitude == 3
def add_opaque_material(idf: IDF, idf_obj_name: str, mat_def: OpaqueMaterial, thickness: pint.Quantity, ureg: pint.UnitRegistry) -> None: """ For materials without mass specified (e.g. vapour barriers) thickness is not :param idf: :param idf_obj_name: :param mat_def: :param thickness: :param ureg: :return: """ if not idf_writing_helpers.exists_in_idf( idf, idf_strings.IDFObjects.material, idf_obj_name): assert mat_def.is_mass_fully_specified( ), f"trying to add opaque material {mat_def.name}, but no mass properties specified" idf_mat = idf.newidfobject(idf_strings.IDFObjects.material) idf_mat.Name = idf_obj_name idf_mat.Roughness = get_idf_roughness_string_for(mat_def.roughness) idf_mat.Thickness = thickness.to(ureg.m).m idf_mat.Conductivity = mat_def.conductivity.to(ureg.W / (ureg.m * ureg.K)).m # checking for mass properties at begin, thus ignore type warning due to Optional[] declaration idf_mat.Density = mat_def.density.to(ureg.kg / ureg.m**3).m # type: ignore idf_mat.Specific_Heat = mat_def.specific_heat.to( ureg.J / (ureg.kg * ureg.K)).m # type: ignore idf_mat.Thermal_Absorptance = mat_def.thermal_absorptance.to( ureg.dimensionless).m idf_mat.Solar_Absorptance = mat_def.solar_absorptance.to( ureg.dimensionless).m idf_mat.Visible_Absorptance = mat_def.visible_absorptance.to( ureg.dimensionless).m
def add_material_no_mass(idf: IDF, idf_obj_name: str, mat_def: OpaqueMaterial, thermal_resistance: pint.Quantity, ureg: pint.UnitRegistry) -> None: """ For materials without mass specified (e.g. vapour barriers) :param idf: :param idf_obj_name: :param mat_def: :param thermal_resistance: :param ureg: :return: """ if not idf_writing_helpers.exists_in_idf( idf, idf_strings.IDFObjects.material_no_mass, idf_obj_name): idf_mat = idf.newidfobject(idf_strings.IDFObjects.material_no_mass) idf_mat.Name = idf_obj_name idf_mat.Roughness = get_idf_roughness_string_for(mat_def.roughness) idf_mat.Thermal_Resistance = thermal_resistance.to( (ureg.m**2 * ureg.K) / ureg.W).m idf_mat.Thermal_Absorptance = mat_def.thermal_absorptance.to( ureg.dimensionless).m idf_mat.Solar_Absorptance = mat_def.solar_absorptance.to( ureg.dimensionless).m idf_mat.Visible_Absorptance = mat_def.visible_absorptance.to( ureg.dimensionless).m
def add_window_glazing_material(idf: IDF, idf_obj_name: str, mat_def: TransparentMaterial, thickness: pint.Quantity, ureg: pint.UnitRegistry) -> None: idf_obj_type = idf_strings.IDFObjects.win_material_glazing if not idf_writing_helpers.exists_in_idf(idf, idf_obj_type, idf_obj_name): win_glazing = idf.newidfobject(idf_obj_type) win_glazing.Name = idf_obj_name win_glazing.Thickness = thickness.to(ureg.m).m win_glazing.Optical_Data_Type = idf_strings.WindowMatGlazing.optical_data_type win_glazing.Solar_Transmittance_at_Normal_Incidence = mat_def.solar_transmittance.to( ureg.dimensionless).m win_glazing.Front_Side_Solar_Reflectance_at_Normal_Incidence = mat_def.front_side_solar_reflectance.to( ureg.dimensionless).m win_glazing.Back_Side_Solar_Reflectance_at_Normal_Incidence = mat_def.back_side_solar_reflectance.to( ureg.dimensionless).m win_glazing.Visible_Transmittance_at_Normal_Incidence = mat_def.visible_transmittance.to( ureg.dimensionless).m win_glazing.Front_Side_Visible_Reflectance_at_Normal_Incidence = mat_def.front_side_visible_reflectance.to( ureg.dimensionless).m win_glazing.Back_Side_Visible_Reflectance_at_Normal_Incidence = mat_def.back_side_visible_reflectance.to( ureg.dimensionless).m win_glazing.Infrared_Transmittance_at_Normal_Incidence = mat_def.infrared_transmittance.to( ureg.dimensionless).m win_glazing.Front_Side_Infrared_Hemispherical_Emissivity = mat_def.front_side_infrared_hemispherical_emissivity.to( ureg.dimensionless).m win_glazing.Back_Side_Infrared_Hemispherical_Emissivity = mat_def.back_side_infrared_hemispherical_emissivity.to( ureg.dimensionless).m win_glazing.Conductivity = mat_def.conductivity.to(ureg.W / (ureg.m * ureg.K)).m win_glazing.Dirt_Correction_Factor_for_Solar_and_Visible_Transmittance = mat_def.dirt_correction_factor.to( ureg.dimensionless).m
def add_airgap(idf: IDF, idf_obj_name: str, thermal_resistance: pint.Quantity, ureg: pint.UnitRegistry) -> None: if not idf_writing_helpers.exists_in_idf( idf, idf_strings.IDFObjects.material_air_gap, idf_obj_name): idf_mat = idf.newidfobject(idf_strings.IDFObjects.material_air_gap) idf_mat.Name = idf_obj_name idf_mat.Thermal_Resistance = thermal_resistance.to(ureg.m**2 * ureg.K / ureg.W).m
def get_divergence_from_beam_diameter(E, beam_diameter_fwhm): """Calculate the divergence (radian) from photon energy (eV) and beam_diameter (m)""" # The rms of the amplitude distribution (Gaussian) E = Quantity(E, Unit("eV")) beam_waist = beam_diameter_fwhm / np.sqrt(2.0 * np.log(2.0)) theta = 2.0 * hbar * c / beam_waist / E.to("joule").magnitude return float(theta)
def add_window_material_gas(idf: IDF, idf_obj_name: str, thickness: pint.Quantity, mat_def: Gas, ureg: pint.UnitRegistry) -> None: if not idf_writing_helpers.exists_in_idf( idf, idf_strings.IDFObjects.win_material_gas, idf_obj_name): idf_mat = idf.newidfobject(idf_strings.IDFObjects.win_material_gas) idf_mat.Name = idf_obj_name idf_mat.Gas_Type = get_gas_type(mat_def.name) idf_mat.Thickness = thickness.to(ureg.m).m
def to_feet_and_inches( value: pint.Quantity, ) -> typing.Tuple[pint.Quantity, pint.Quantity]: """Split a quantity into feet & inches Args: value: The quantity to split """ feet = math.floor(value.to(ureg.foot).magnitude) * ureg.foot inches = (value - feet).to(ureg.inch) return feet, inches
def liquid_density(self, temperature: pint.Quantity) -> pint.Quantity: """ Liquid Density as calculated from a polynomial model """ model = self._properties["liquid density"] T_units = model["temperature units"] rho_units = model["density units"] T = temperature.to(T_units).magnitude A = model["a"] B = model["b"] C = model["c"] rho_l = ureg(rho_units) * (A + (B + C * T) * T) return(rho_l)
def vapor_pressure(self, temperature: pint.Quantity) -> pint.Quantity: """ Vapor Pressure as calculated by Antoine's equation """ model = self._properties["antoines"] T_units = model["temperature units"] P_units = model["pressure units"] base = model["base"] T = temperature.to(T_units).magnitude A = model["a"] B = model["b"] C = model["c"] p_vap = ureg(P_units) * base ** (A + B / (C + T)) return(p_vap)
def to_preferred(x: pint.Quantity) -> pint.Quantity: """From https://github.com/hgrecco/pint/issues/676#issuecomment-689157693""" dim = x.dimensionality if dim in PREFERRED_UNITS_DICT: compact_unit = x.to(PREFERRED_UNITS_DICT[dim]).to_compact() # todo: switch to decimal unit registry and then swap out the if statements below # if len(f"{compact_unit.magnitude}" + "{:~P}".format(compact_unit.units)) < len( # f"{x.magnitude}" + "{:~P}".format(x.units) # ): # return compact_unit if len("{:~P}".format(compact_unit.units)) < len("{:~P}".format(x.units)): return compact_unit return x
def _get_cost_for_layer_retrofit(self, bldg_elem: BuildingElement, layer_function: LayerFunction, insulation_thickness: pint.Quantity): """ Go through the cost table and find costs matching for the passed bldg element and layer function. Return the costs for matching layer thickness or interpolate if necessary. Extrapolation: - between thickness 0 and first entry assuming 0 costs for thickness 0. - for thickness bigger than the last entry, extrapolate with the costs/m of the last entry (assuming linear growth in costs) :param bldg_elem: BuildingElement for which to get retrofit costs :param layer_function: function of the layer that got retrofitted :param insulation_thickness: thickness of added insulation :return: costs for retrofit in CHF/m2, returns 0 if no matching cost entry was found """ return_unit_chf_m2 = self.ureg.CHF / self.ureg.m**2 insulation_thickness_in_m = insulation_thickness.to(self.ureg.m) for retrofit_cost in self.insulation_cost_lookup: if retrofit_cost.layer_function == layer_function and bldg_elem in retrofit_cost.applicable_to: last_thickness_in_m = 0 * self.ureg.m last_costs = 0 * self.ureg.CHF / self.ureg.m**2 for thickness_entry, current_costs in retrofit_cost.cost_per_thickness.items( ): current_thickness_in_m = thickness_entry.to(self.ureg.m) if insulation_thickness_in_m == current_thickness_in_m: return current_costs.to(return_unit_chf_m2) if insulation_thickness_in_m > thickness_entry.to( self.ureg.m): last_thickness_in_m = current_thickness_in_m last_costs = current_costs else: delta_thickness = current_thickness_in_m - last_thickness_in_m delta_costs = current_costs - last_costs delta_costs_per_m = delta_costs / delta_thickness delta_costs = delta_costs_per_m * ( insulation_thickness_in_m - last_thickness_in_m) costs = last_costs + delta_costs return costs.to(return_unit_chf_m2) if last_thickness_in_m.m != 0: cost_per_m = last_costs / last_thickness_in_m return (cost_per_m * insulation_thickness_in_m).to(return_unit_chf_m2) # no matching cost entry was found raise Exception( f"No cost information found for {bldg_elem.name} {layer_function.name}" )
def add_hot_water_equipment(idf, zone_idf_name, dhw_op: InstallationOperation, dhw_fraction_lost: pint.Quantity, ureg): dhw_schedule_idf_name = idf_writing_helpers.add_schedule( idf, dhw_op.fraction_schedule, required_type=cesarp.common.ScheduleTypeLimits.FRACTION()) hot_water_equ_idf_obj = idf.newidfobject( idf_strings.IDFObjects.hot_water_equipment) hot_water_equ_idf_obj.Name = idf_strings.CustomObjNames.hot_water_equipment.format( zone_idf_name) hot_water_equ_idf_obj.Zone_or_ZoneList_Name = zone_idf_name hot_water_equ_idf_obj.Schedule_Name = dhw_schedule_idf_name hot_water_equ_idf_obj.Design_Level_Calculation_Method = idf_strings.DesignLevelCalc.watts_per_area hot_water_equ_idf_obj.Power_per_Zone_Floor_Area = dhw_op.power_demand_per_area.to( ureg.W / ureg.m**2).m hot_water_equ_idf_obj.Fraction_Lost = dhw_fraction_lost.to( ureg.dimensionless).m
def gas_specific_enthalpy(self, temperature: pint.Quantity) -> pint.Quantity: """ Gas Specific Enthalpy as calculated from a polynomial model """ h_model = self._properties["gas specific enthalpy"] T_units = h_model["temperature units"] h_units = h_model["enthalpy units"] h_vap_model = self._properties["vaporization heat"] T = temperature.to(T_units).magnitude A = h_model["a"] B = h_model["b"] C = h_model["c"] h_vap = ureg(h_vap_model["units"]) * h_vap_model["value"] H = ureg(h_units) * ((A + (B/2 + C/3 * T) * T) * T) H += h_vap return(H)
def __init__(self, term: MultiTerm or Term, level: pint.Quantity, lande: float = None, parent=None, alias=None, hfA=Q_(0.0, 'gigahertz'), hfB=Q_(0.0, 'gigahertz'), hfC=Q_(0.0, 'gigahertz')): """ :param term: a Term object containing the level's quantum numbers :param level: the energy of the centroid of the level :param lande: the lande-g value of the level :param parent: the atom that the level is contained in :param hfA: the hyperfine A-coefficient :param hfB: the hyperfine B-coefficient :param hfC: the hyperfine C-coefficient """ super().__init__(term, parent, alias) self._level_Hz = level.to(Hz).magnitude self.hfA_Hz, self.hfB_Hz, self.hfC_Hz = hfA.to(Hz).magnitude, hfB.to(Hz).magnitude, hfC.to(Hz).magnitude if lande is None: self.lande = self.compute_gJ() else: self.lande = lande
def add_electric_equipment(idf, zone_idf_name, el_app_op: InstallationOperation, el_app_fraction_radiant: pint.Quantity, ureg): applicance_sched_idf_name = idf_writing_helpers.add_schedule( idf, el_app_op.fraction_schedule, required_type=cesarp.common.ScheduleTypeLimits.FRACTION()) el_equ_idf_obj = idf.newidfobject( idf_strings.IDFObjects.electric_equipment) el_equ_idf_obj.Name = idf_strings.CustomObjNames.electric_equipment.format( zone_idf_name) el_equ_idf_obj.Zone_or_ZoneList_Name = zone_idf_name el_equ_idf_obj.Schedule_Name = applicance_sched_idf_name el_equ_idf_obj.Design_Level_Calculation_Method = idf_strings.DesignLevelCalc.watts_per_area el_equ_idf_obj.Watts_per_Zone_Floor_Area = el_app_op.power_demand_per_area.to( ureg.W / ureg.m**2).m el_equ_idf_obj.Fraction_Radiant = el_app_fraction_radiant.to( ureg.dimensionless).m
def gas_specific_enthalpy_change(self, temperature: pint.Quantity) -> pint.Quantity: """ Gas Specific Enthalpy Change as calculated from a polynomial model """ h_model = self._properties["gas specific enthalpy"] T_units = h_model["temperature units"] h_units = h_model["enthalpy units"] T = temperature.to(T_units).magnitude A = h_model["a"] B = h_model["b"] C = h_model["c"] h_units += " / kelvin" dH = ureg(h_units) * (A + (B + C * T) * T) return(dH)
def add_people(idf, zone_idf_name, occupancy: Occupancy, fraction_radiant_from_activity: pint.Quantity, ureg): occupancy_sched_idf_name = idf_writing_helpers.add_schedule( idf, occupancy.occupancy_fraction_schedule, required_type=cesarp.common.ScheduleTypeLimits.FRACTION()) activity_sched_idf_name = idf_writing_helpers.add_schedule( idf, occupancy.activity_schedule, required_unit=ureg.W / ureg.person) people_idf_obj = idf.newidfobject(idf_strings.IDFObjects.people) people_idf_obj.Name = idf_strings.CustomObjNames.people.format( zone_idf_name) people_idf_obj.Zone_or_ZoneList_Name = zone_idf_name people_idf_obj.Number_of_People_Schedule_Name = occupancy_sched_idf_name people_idf_obj.Number_of_People_Calculation_Method = idf_strings.NumOfPeopleCalc.area_per_person people_idf_obj.Zone_Floor_Area_per_Person = occupancy.floor_area_per_person.to( ureg.m**2 / ureg.person).m people_idf_obj.Fraction_Radiant = fraction_radiant_from_activity.to( ureg.dimensionless).m people_idf_obj.Activity_Level_Schedule_Name = activity_sched_idf_name
def _calc_heating_emissions_and_costs( self, specific_heating_energy_demand: pint.Quantity, total_heating_energy_demand: pint.Quantity, heating_energy_carrier: EnergySource, sim_year: int, ): if heating_energy_carrier == EnergySource.NO: # no cost and emissions if energy source is NO - same as procedure in Matlab version return PerSystemResults( pen=0 * self._ureg(PEN_UNIT), co2_emission=0 * self._ureg(CO2_EMISSION_UNIT), fuel_demand=0 * self._ureg(FUEL_DEMAND_UNIT), fuel_cost=0 * self._ureg(FUEL_COST_UNIT), energy_carrier=heating_energy_carrier, ) heating_sys_eff = self._energy_strategy.system_efficiencis.get_heating_system_efficiency( heating_energy_carrier, sim_year) heating_value_factor = self._energy_strategy.system_efficiencis.get_heating_value_factor( heating_energy_carrier, sim_year) pen_factor = self._energy_strategy.energy_mix.get_pen_factor_for( heating_energy_carrier, sim_year) co2_coeff = self._energy_strategy.energy_mix.get_co2_coeff_for( heating_energy_carrier, sim_year) fuel_cost_factor = self._energy_strategy.fuel_cost_factors.get_fuel_cost_factor( heating_energy_carrier, sim_year) if heating_sys_eff == 0: raise EmissonAndCostCalculationError( f"Could not calculate heating cost and emissions because heating system efficiency for energy carrier {heating_energy_carrier} " f"and simulation year {sim_year} is 0") fuel_demand = total_heating_energy_demand / heating_sys_eff fuel_cost = (fuel_demand * fuel_cost_factor).to(FUEL_COST_UNIT) specific_heating_energy_demand = specific_heating_energy_demand.to( SPECIFIC_ENERGY_DEMAND_UNIT) co2_emission = (specific_heating_energy_demand / heating_sys_eff * co2_coeff * heating_value_factor).to(CO2_EMISSION_UNIT) pen = (specific_heating_energy_demand / heating_sys_eff * pen_factor * heating_value_factor).to(PEN_UNIT) return PerSystemResults(pen, co2_emission, fuel_demand, fuel_cost, heating_energy_carrier)
def _calc_dhw_emissions_and_costs( self, specific_dhw_energy_demand: pint.Quantity, total_dhw_energy_demand: pint.Quantity, dhw_energy_carrier: EnergySource, sim_year: int, ): if dhw_energy_carrier == EnergySource.NO: return PerSystemResults( pen=0 * self._ureg(PEN_UNIT), co2_emission=0 * self._ureg(CO2_EMISSION_UNIT), fuel_demand=0 * self._ureg(FUEL_DEMAND_UNIT), fuel_cost=0 * self._ureg(FUEL_COST_UNIT), energy_carrier=dhw_energy_carrier, ) dhw_sys_eff = self._energy_strategy.system_efficiencis.get_dhw_system_efficiency( dhw_energy_carrier, sim_year) heating_value_factor = self._energy_strategy.system_efficiencis.get_heating_value_factor( dhw_energy_carrier, sim_year) pen_factor = self._energy_strategy.energy_mix.get_pen_factor_for( dhw_energy_carrier, sim_year) co2_coeff = self._energy_strategy.energy_mix.get_co2_coeff_for( dhw_energy_carrier, sim_year) fuel_cost_factor = self._energy_strategy.fuel_cost_factors.get_fuel_cost_factor( dhw_energy_carrier, sim_year) if dhw_sys_eff == 0: raise EmissonAndCostCalculationError( f"Could not calculate dhw cost and emissions because dhw system efficiency for energy carrier {dhw_energy_carrier} " f"and simulation year {sim_year} is 0") specific_dhw_energy_demand = specific_dhw_energy_demand.to( self._ureg.MJ / self._ureg.m**2 / self._ureg.year) pen = specific_dhw_energy_demand / dhw_sys_eff * pen_factor * heating_value_factor co2_emission = specific_dhw_energy_demand / dhw_sys_eff * co2_coeff * heating_value_factor fuel_demand = total_dhw_energy_demand / dhw_sys_eff fuel_cost = (fuel_demand * fuel_cost_factor).to(FUEL_COST_UNIT) return PerSystemResults(pen, co2_emission, fuel_demand, fuel_cost, dhw_energy_carrier)
def add_outdoor_air_sepc(idf, ventilation_schedule, outdoor_air_flow_per_floor_area: pint.Quantity, name_prefix: str, ureg): ventilation_sched_idf_name = idf_writing_helpers.add_schedule( idf, ventilation_schedule, required_type=cesarp.common.ScheduleTypeLimits.FRACTION()) idf_obj_type = idf_strings.IDFObjects.design_specifictaion_outdoor_air name = name_prefix + "_" + idf_strings.CustomObjNames.outdoor_air_spec if not idf_writing_helpers.exists_in_idf(idf, idf_obj_type, name): outdoor_air_spec_idf_obj = idf.newidfobject(idf_obj_type) outdoor_air_spec_idf_obj.Name = name outdoor_air_spec_idf_obj.Outdoor_Air_Method = idf_strings.OutdoorAirCalcMethod.flow_per_area outdoor_air_spec_idf_obj.Outdoor_Air_Flow_per_Zone_Floor_Area = outdoor_air_flow_per_floor_area.to( ureg.m**3 / ureg.s / ureg.m**2).m # clean up default values: set to zero because calc method changed to flow/area outdoor_air_spec_idf_obj.Outdoor_Air_Flow_per_Person = 0 if idf.idd_version[0] < 9 and idf.idd_version[1] < 6: outdoor_air_spec_idf_obj.Outdoor_Air_Flow_Rate_Fraction_Schedule_Name = ventilation_sched_idf_name else: outdoor_air_spec_idf_obj.Outdoor_Air_Schedule_Name = ventilation_sched_idf_name return name
def to_celsius(quantity: Quantity) -> str: magnitude = quantity.to(u.degC).magnitude return f'{magnitude} °C'
def to_seconds(quantity: Quantity) -> str: magnitude = quantity.to(u.seconds).magnitude return f'{magnitude} s'
def arrhenius(self, temperature: pint.Quantity) -> pint.Quantity: T = temperature.to(ureg.kelvin) A = self.rate_parameters["A"] Ea = self.rate_parameters["Ea"] k = A * math.exp(-Ea / Rg / T) return(k)