Пример #1
0
def create_load(occupancy, at_home):

    # *hg Decide for either relative or absolute path
    if False:
        db_path = os.path.join(os.getcwd(), "data/swh_input_weather_cons.db")
    else:
        db_path = "data/swh_input_weather_cons.db"

    # Connecting to database
    try:
        db = Sql(db_path)
    except:
        log.error("Failed to connect to database.")

    # Converting sql to pandas DataFrame
    try:
        inputs = db.tables2dict(close=True)
    except:
        log.error("Failed to read input tables from DataFrame.")

    load, loadid_peakload = SourceAndSink._make_example_loading_inputs(
        inputs,
        CONSUMER_LABELS,
        get_np_random_state(),
        occupancy=occupancy,
        at_home=at_home,
    )
    return load
Пример #2
0
def climate_populate(request):

    # Use path to SWH database defined in settings.py
    swh_db_path = settings.SWH_DATABASE
    log.info('Using SWH database "{}"'.format(swh_db_path))

    db = Sql(swh_db_path)
    log.info("Connected to database.")

    try:
        inputs = db.tables2dict(close=True)
        log.info("Converted sql to pandas DataFrame.")
    except:
        msg = "Failed to read input tables from {}."
        log.info(msg.format(inputs))

    weather = SourceAndSink(input_dfs=inputs)
    log.info("Created SourceAndSink object")

    # Delete all previously stored climate objects before populating them
    n_climate_zones = Climate.objects.all().count()
    if n_climate_zones > 0:
        Climate.objects.all().delete()
        log.info("Deleted {} Climate object(s) from database.".format(
            n_climate_zones))
        n_climate_zones = 0

    # Use climate data source as defined in settings.py
    data_source = settings.CLIMATE_DATA_SOURCE

    # Cycle from 1 to 16 (these are the climate zone IDs in the external database)
    for climate_zone_id in range(1, 17):

        climate_zone_id_str = "{:02d}".format(climate_zone_id)

        climate_data = weather.irradiation_and_water_main(
            climate_zone_id_str,
            method="isotropic diffuse",
            weather_data_source=data_source,
        )

        climate = Climate.objects.create_climate(
            name=get_climate_zone_name(climate_zone_id_str),
            climate_zone=climate_zone_id_str,
            data_source=data_source,
        )
        log.info("\nCreated Climate object {} successfully.".format(climate))

        climate.populate_data(climate_data)
        log.info("Populated data of Climate object {} successfully.".format(
            climate))

        n_climate_zones += 1

    msg = "\nPopulated {} climate zones.".format(n_climate_zones)
    log.info(msg)

    return redirect("sys:config_home")
Пример #3
0
    def setUpClass(cls):
        """Initiates the sqlite db engine
        for the test db file.
        """
        test_db_name = "test.db"
        test_db_fulpath = os.path.join(os.path.dirname(__file__), test_db_name)
        cls.test_db_fulpath = test_db_fulpath

        print(test_db_fulpath)
        # create test db if it does not exist

        if not os.path.exists(test_db_fulpath):
            os.system("touch " + test_db_fulpath)

        cls.sql_api = Sql(test_db_fulpath)

        # example dict to write to db
        cls.df = pd.DataFrame(data=[["a", 1], ["b", 2]],
                              columns=["comp", "cost"])

        # example dict to write to db as table
        cls.dict = {"k1": [12, 13, 14], "k2": ["a", "b", "c"]}

        # example csv data
        cls.path_to_csv = os.path.join(os.path.dirname(__file__), "table.csv")

        # sql code to execute
        cls.raw_sql = """CREATE TABLE sys_components
Пример #4
0
    def setUpClass(cls):
        """Initiates the sqlite db engine
        for the test db file.
        """
        test_db_name = 'test.db'
        test_db_fulpath = os.path.join(
            os.path.dirname(__file__), test_db_name)
        cls.test_db_fulpath = test_db_fulpath

        print(test_db_fulpath)
        # create test db if it does not exist

        if not os.path.exists(test_db_fulpath):
            os.system('touch ' + test_db_fulpath)

        cls.sql_api = Sql(test_db_fulpath)

        # example dict to write to db
        cls.df = pd.DataFrame(
            data=[['a', 1], ['b', 2]],
            columns=['comp', 'cost'])

        # example dict to write to db as table
        cls.dict = {'k1': [12, 13, 14],
                    'k2': ['a', 'b', 'c']}

        # example csv data
        cls.path_to_csv = os.path.join(
            os.path.dirname(__file__), 'table.csv')

        # sql code to execute
        cls.raw_sql = '''CREATE TABLE sys_components
Пример #5
0
    def setUp(self):
        """Instantiates a test object"""
        # read in data from the database
        # assuming tests are run from swh
        # directory
        weather_db_path = os.path.join(os.getcwd(),
                                       "mswh/comm/mswh_system_input.db")

        # connect to the database
        db = Sql(weather_db_path)

        try:
            # read table names for all tables in a
            # {table name : sheet name} form
            inputs = db.tables2dict(close=True)
        except:
            msg = "Failed to read input tables from {}."
            log.error(msg.format(weather_db_path))

        self.weather = SourceAndSink(input_dfs=inputs)

        # get labels
        self.c = SwhLabels().set_hous_labels()
Пример #6
0
    def setUpClass(self):
        """Assigns values to test variables."""
        random_state = np.random.RandomState(123)

        self.plot_results = True
        # it will save under img on the test directory
        self.outpath = os.path.dirname(__file__)

        # get labels
        self.c = SwhLabels().set_hous_labels()
        self.s = SwhLabels().set_prod_labels()
        self.r = SwhLabels().set_res_labels()

        # generate weather data and annual hourly
        # water draw profile

        weather_db_path = os.path.join(os.getcwd(),
                                       "mswh/comm/mswh_system_input.db")

        db = Sql(weather_db_path)

        try:
            inputs = db.tables2dict(close=True)
        except:
            msg = "Failed to read inputs from {}."
            log.error(msg.format(weather_db_path))

        source_and_sink = SourceAndSink(input_dfs=inputs)

        # SF climate is 03, 16 is cold
        self.weather = source_and_sink.irradiation_and_water_main(
            "03", method="isotropic diffuse")

        # community scale household occupancies for 4 households
        occ_com = [4, 4, 3, 5]
        # individual scale household occupancy
        occ_ind = [4]

        # are people at home during the day in any of the households:
        # 'y' or 'n'
        at_home_com = ["n", "n", "n", "n"]
        at_home_ind = ["n"]

        loads_com, peakload_com = SourceAndSink._make_example_loading_inputs(
            inputs,
            self.c,
            random_state,
            occupancy=occ_com,
            at_home=at_home_com,
        )

        (
            loads_indiv,
            peakload_indiv,
        ) = SourceAndSink._make_example_loading_inputs(
            inputs,
            self.c,
            random_state,
            occupancy=occ_ind,
            at_home=at_home_ind,
        )

        # scaled loads to match 300 L/day
        load_array_val = (loads_indiv["End-Use Load"][0] *
                          (300 * 365 * 0.001) /
                          loads_indiv["End-Use Load"][0].sum())

        loads_indiv_val = pd.DataFrame(
            data=[[1, occ_ind[0], load_array_val]],
            columns=[self.c["id"], self.c["occ"], self.c["load_m3"]],
        )

        # performance parameters

        # solar thermal
        sol_the_sys_params = pd.DataFrame(
            data=[
                [self.s["the_sto"], self.s["f_upper_vol"], 0.5],
                [self.s["the_sto"], self.s["ins_thi"], 0.085],
                [self.s["the_sto"], self.s["spec_hea_con"], 0.04],
                [self.s["the_sto"], self.s["t_tap_set"], 322.04],
                [self.s["the_sto"], self.s["h_vs_r"], 6.0],
                [self.s["the_sto"], self.s["dt_appr"], 2.0],
                [self.s["the_sto"], self.s["t_max_tank"], 344.15],
                [self.s["the_sto"], self.s["eta_coil"], 0.84],
                [self.s["the_sto"], self.s["circ"], 0.0],
                [self.s["sol_col"], self.s["interc_hwb"], 0.753],
                [self.s["sol_col"], self.s["slope_hwb"], -4.025],
                [self.s["sol_pump"], self.s["eta_sol_pump"], 0.85],
                [self.s["piping"], self.s["pipe_spec_hea_con"], 0.0175],
                [self.s["piping"], self.s["pipe_ins_thick"], 0.008],
                [self.s["piping"], self.s["flow_factor"], 0.8],
                [self.s["piping"], self.s["dia_len_exp"], 0.43082708345352605],
                [
                    self.s["piping"],
                    self.s["dia_len_sca"],
                    0.007911283766743384,
                ],
                [
                    self.s["piping"],
                    self.s["discr_diam_m"],
                    "[0.0127, 0.01905, 0.0254, 0.03175, 0.0381,"
                    "0.0508, 0.0635, 0.0762, 0.1016]",
                ],
                [self.s["piping"], self.s["circ"], False],
                [self.s["piping"], self.s["long_br_len_fr"], 1.0],
                [self.s["dist_pump"], self.s["eta_dist_pump"], 0.85],
            ],
            columns=[self.s["comp"], self.s["param"], self.s["param_value"]],
        )

        last_row_for_indiv = (
            sol_the_sys_params.shape[0] - 1 -
            sol_the_sys_params.loc[sol_the_sys_params[self.s["comp"]] ==
                                   self.s["dist_pump"], :].shape[0])

        # conventional gas tank wh
        # ~R2.1, EL 1 from the rulemaking analysis
        gas_tank_wh_params = pd.DataFrame(
            data=[
                [self.s["gas_tank"], self.s["tank_re"], 0.78],
                [self.s["gas_tank"], self.s["ins_thi"], 0.03],
                [self.s["gas_tank"], self.s["spec_hea_con"], 0.081],
                [self.s["gas_tank"], self.s["t_tap_set"], 322.04],
            ],
            columns=[self.s["comp"], self.s["param"], self.s["param_value"]],
        )

        # gas tankless backup
        sol_the_inst_gas_bckp_params = pd.DataFrame(
            data=[[self.s["gas_burn"], self.s["comb_eff"], 0.85]],
            columns=[self.s["comp"], self.s["param"], self.s["param_value"]],
        )

        # sizing

        # assume 4 occupants
        # basecase gas tank WH: DOE sizing rule based on
        # peak hourly demand +/-2 gal, assuming +/- 0
        gas_tank_size_indiv = UnitConv(
            peakload_indiv.loc[0, self.c["max_load"]]).m3_gal(unit_in="gal")

        gas_tank_wh_size = pd.DataFrame(
            data=[[self.s["gas_tank"], gas_tank_size_indiv]],
            columns=[self.s["comp"], self.s["cap"]],
        )

        # individual scale retrofit backup
        sol_the_gas_tank_bckp_size = pd.DataFrame(
            data=[[1, self.s["gas_tank"], gas_tank_size_indiv]],
            columns=[self.c["id"], self.s["comp"], self.s["cap"]],
        )

        # CSI sizing rules
        def demand_estimate(occ):
            if occ == 1:
                return 20.0
            if occ == 2:
                return 35.0
            else:
                return 35.0 + 10.0 * (occ - 2.0)

        peakload_com[self.c["dem_estimate"]] = loads_com[self.c["occ"]].apply(
            lambda x: demand_estimate(x))

        demand_estimate_ind = demand_estimate(occ_ind[0])

        demand_estimate_com = peakload_com[self.c["dem_estimate"]].sum()

        col_area_scaler = 1.2  # (CSI sizing rule: upper limit 1.25)
        tank_vol_scaler = 1.3  # (CSI sizing rule: lower limit 1.25)

        col_area_ind_sqft = demand_estimate_ind * col_area_scaler
        col_area_com_sqft = demand_estimate_com * col_area_scaler

        tank_vol_ind_gal = col_area_ind_sqft * tank_vol_scaler
        tank_vol_com_gal = col_area_com_sqft * tank_vol_scaler

        col_area_ind = UnitConv(col_area_ind_sqft).sqft_m2()
        col_area_com = UnitConv(col_area_com_sqft).sqft_m2()

        tank_vol_ind = UnitConv(tank_vol_ind_gal).m3_gal(unit_in="gal")
        tank_vol_com = UnitConv(tank_vol_com_gal).m3_gal(unit_in="gal")

        # piping
        pipe_m_per_hhld = 3.048
        detached_k = 6.0
        attached_k = 3.0

        # distribution pump
        dist_pump_size = 10.4376 * len(occ_com)**0.9277

        # solar pump
        com_solar_pump_size = 7.5101 * sum(occ_com)**0.5322
        indiv_solar_pump_size = 7.5101 * sum(occ_ind)**0.5322

        # individual
        sol_the_sys_sizes_indiv = pd.DataFrame(
            data=[
                [self.s["sol_col"], col_area_ind],
                [self.s["the_sto"], tank_vol_ind],
                [self.s["sol_pump"], indiv_solar_pump_size],
                [self.s["piping"], pipe_m_per_hhld],
            ],
            columns=[self.s["comp"], self.s["cap"]],
        )

        sol_the_inst_gas_bckp_size = pd.DataFrame(
            data=[[1, self.s["gas_burn"], 50972]],
            columns=[self.c["id"], self.s["comp"], self.s["cap"]],
        )

        # piping for single family attached
        sol_the_sys_sizes_com = pd.DataFrame(
            data=[
                [self.s["sol_col"], col_area_com],
                [self.s["the_sto"], tank_vol_com],
                [self.s["sol_pump"], com_solar_pump_size],
                [self.s["dist_pump"], dist_pump_size],
                [
                    self.s["piping"],
                    attached_k * pipe_m_per_hhld * len(occ_com),
                ],
            ],
            columns=[self.s["comp"], self.s["cap"]],
        )

        # gas tank backup
        sol_the_gas_tank_bckp_params = gas_tank_wh_params.copy()

        peakload_com["gas_tank_size_com"] = peakload_com[self.c[
            "max_load"]].apply(lambda x: UnitConv(x).m3_gal(unit_in="gal"))

        peakload_com.index = peakload_com[self.c["id"]]

        sol_the_gas_tank_bckp_sizes_com = pd.DataFrame(
            columns=[self.c["id"], self.s["comp"], self.s["cap"]],
            index=peakload_com.index,
        )

        for i in peakload_com.index:
            sol_the_gas_tank_bckp_sizes_com.loc[i, self.c["id"]] = i
            sol_the_gas_tank_bckp_sizes_com.loc[
                i, self.s["comp"]] = self.s["gas_tank"]
            sol_the_gas_tank_bckp_sizes_com.loc[
                i, self.s["cap"]] = peakload_com.loc[i, "gas_tank_size_com"]

        sol_the_gas_tank_bckp_sizes_com.index = range(
            sol_the_gas_tank_bckp_sizes_com.shape[0])

        sol_the_inst_gas_bckp_sizes_com = pd.DataFrame(
            columns=[self.c["id"], self.s["comp"], self.s["cap"]],
            index=peakload_com.index,
        )

        def gas_tankles_size_W(occupancy):
            size = 24875.0 * occupancy**0.5175
            return size

        for i in peakload_com.index:
            sol_the_inst_gas_bckp_sizes_com.loc[i, self.c["id"]] = i
            sol_the_inst_gas_bckp_sizes_com.loc[
                i, self.s["comp"]] = self.s["gas_burn"]
            sol_the_inst_gas_bckp_sizes_com.loc[
                i, self.s["cap"]] = gas_tankles_size_W(occ_com[i - 1])

        sol_the_inst_gas_bckp_sizes_com.index = range(
            sol_the_inst_gas_bckp_sizes_com.shape[0])

        # instantiate systems

        # individual system
        self.sol_wh_indiv_new = System(
            sys_params=sol_the_sys_params.loc[:last_row_for_indiv, :],
            backup_params=sol_the_inst_gas_bckp_params,
            sys_sizes=sol_the_sys_sizes_indiv,
            backup_sizes=sol_the_inst_gas_bckp_size,
            weather=self.weather,
            loads=loads_indiv,
        )

        msg = ("Set up the individual solar thermal system with tankless "
               "backup test case.")
        log.info(msg)

        self.sol_wh_indiv_retr = System(
            sys_params=sol_the_sys_params.loc[:last_row_for_indiv, :],
            backup_params=sol_the_gas_tank_bckp_params,
            sys_sizes=sol_the_sys_sizes_indiv,
            backup_sizes=sol_the_gas_tank_bckp_size,
            weather=self.weather,
            loads=loads_indiv,
        )

        msg = ("Set up the individual solar thermal system with gas tank "
               "backup test case.")
        log.info(msg)

        # community system
        self.sol_wh_com_new = System(
            sys_params=sol_the_sys_params,
            backup_params=sol_the_inst_gas_bckp_params,
            sys_sizes=sol_the_sys_sizes_com,
            backup_sizes=sol_the_inst_gas_bckp_sizes_com,
            weather=self.weather,
            loads=loads_com,
        )

        msg = ("Set up the community solar thermal system with tankless "
               "backup test case.")
        log.info(msg)

        self.sol_wh_com_retr = System(
            sys_params=sol_the_sys_params,
            backup_params=sol_the_gas_tank_bckp_params,
            sys_sizes=sol_the_sys_sizes_com,
            backup_sizes=sol_the_gas_tank_bckp_sizes_com,
            weather=self.weather,
            loads=loads_com,
        )

        msg = ("Set up the community solar thermal system with gas tank "
               "backup test case.")
        log.info(msg)

        # solar thermal validation

        # individual new with
        # tank and collector size from
        # https://secure.solar-rating.org/Certification/Ratings/#
        # RatingsReport.aspx?device=6926&units=METRICS
        # solar thermal retrofit solar fractions in the rating sheets are low
        # - for the same
        # size of collector and storage the new and retrofit should have the
        # same solar fraction
        # by definition https://en.wikipedia.org/wiki/Solar_savings_fraction

        # sizes based on several observed rated systems from OG-300
        # with an 80 gal tank and gas tankless backup
        sol_the_sys_sizes_val = pd.DataFrame(
            data=[
                [self.s["sol_col"], 3.9],
                [self.s["the_sto"],
                 UnitConv(80.0).m3_gal(unit_in="gal")],
                [self.s["sol_pump"], indiv_solar_pump_size],
                [self.s["piping"], 0.0],
            ],
            columns=[self.s["comp"], self.s["cap"]],
        )

        self.val_sol_wh = System(
            sys_params=sol_the_sys_params.loc[:last_row_for_indiv, :],
            backup_params=sol_the_inst_gas_bckp_params,
            sys_sizes=sol_the_sys_sizes_val,
            backup_sizes=sol_the_inst_gas_bckp_size,
            weather=self.weather,
            loads=loads_indiv_val,
        )

        msg = ("Set up the individual solar thermal system validation "
               "test case.")
        log.info(msg)

        self.conv_wh = System(
            sys_params=gas_tank_wh_params,
            sys_sizes=gas_tank_wh_size,
            weather=self.weather,
            loads=loads_indiv,
        )

        msg = "Set up the conventional tank wh test case."
        log.info(msg)

        # With baseline tank with a slightly higher RE and insulation set to
        # R12, as used for the solar tank
        gas_tank_wh_params_val = pd.DataFrame(
            data=[
                [self.s["gas_tank"], self.s["tank_re"], 0.82, "-"],
                [self.s["gas_tank"], self.s["ins_thi"], 0.04, "m"],
                [self.s["gas_tank"], self.s["spec_hea_con"], 0.085, "W/mK"],
                [self.s["gas_tank"], self.s["t_tap_set"], 322.04, "K"],
            ],
            columns=[
                self.s["comp"],
                self.s["param"],
                self.s["param_value"],
                self.s["param_unit"],
            ],
        )

        # with validation loads and validation parameters
        self.conv_wh_val = System(
            sys_params=gas_tank_wh_params_val,
            sys_sizes=gas_tank_wh_size,
            weather=self.weather,
            loads=loads_indiv_val,
        )

        msg = "Set up the conventional tank wh validation test case."
        log.info(msg)

        # project level component parameter
        # dataframe for solar electric system
        # with an inst. gas backup
        sol_el_tank_params = pd.DataFrame(
            data=[
                [self.s["hp"], self.s["c1_cop"], 1.229e00],
                [self.s["hp"], self.s["c2_cop"], 5.549e-02],
                [self.s["hp"], self.s["c3_cop"], 1.139e-04],
                [self.s["hp"], self.s["c4_cop"], -1.128e-02],
                [self.s["hp"], self.s["c5_cop"], -3.570e-06],
                [self.s["hp"], self.s["c6_cop"], -7.234e-04],
                [self.s["hp"], self.s["c1_heat_cap"], 7.055e-01],
                [self.s["hp"], self.s["c2_heat_cap"], 3.945e-02],
                [self.s["hp"], self.s["c3_heat_cap"], 1.433e-04],
                [self.s["hp"], self.s["c4_heat_cap"], 2.768e-03],
                [self.s["hp"], self.s["c5_heat_cap"], -1.069e-04],
                [self.s["hp"], self.s["c6_heat_cap"], -2.494e-04],
                [self.s["hp"], self.s["heat_cap_rated"], 2350.0],
                [self.s["hp"], self.s["cop_rated"], 2.43],
                [self.s["pv"], self.s["eta_pv"], 0.16],
                [self.s["pv"], self.s["f_act"], 1.0],
                [self.s["pv"], self.s["irrad_ref"], 1000.0],
                [self.s["inv"], self.s["eta_dc_ac"], 0.85],
                [self.s["the_sto"], self.s["f_upper_vol"], 0.5],
                [self.s["the_sto"], self.s["ins_thi"], 0.04],
                [self.s["the_sto"], self.s["spec_hea_con"], 0.04],
                [self.s["the_sto"], self.s["t_tap_set"], 322.04],
                [self.s["the_sto"], self.s["h_vs_r"], 6.0],
                [self.s["the_sto"], self.s["dt_appr"], 2.0],
                [self.s["the_sto"], self.s["t_max_tank"], 344.15],
                [self.s["piping"], self.s["pipe_spec_hea_con"], 0.0175],
                [self.s["piping"], self.s["pipe_ins_thick"], 0.008],
                [self.s["piping"], self.s["flow_factor"], 0.8],
                [self.s["piping"], self.s["dia_len_exp"], 0.43082708345352605],
                [
                    self.s["piping"],
                    self.s["dia_len_sca"],
                    0.007911283766743384,
                ],
                [
                    self.s["piping"],
                    self.s["discr_diam_m"],
                    "[0.0127, 0.01905, 0.0254, 0.03175, 0.0381,"
                    "0.0508, 0.0635, 0.0762, 0.1016]",
                ],
                [self.s["piping"], self.s["circ"], False],
                [self.s["piping"], self.s["long_br_len_fr"], 1.0],
            ],
            columns=[self.s["comp"], self.s["param"], self.s["param_value"]],
        )

        # test sizing
        sol_el_tank_sizes_indiv = pd.DataFrame(
            data=[
                [self.s["hp"], 2350.0],
                [self.s["pv"], 6.25],
                [self.s["the_sto"], UnitConv(80).m3_gal()],
                [self.s["dist_pump"], dist_pump_size],
                [self.s["piping"], pipe_m_per_hhld],
            ],
            columns=[self.s["comp"], self.s["cap"]],
        )

        # electric resistance backup parameters
        sol_el_tank_inst_gas_bckp_params = pd.DataFrame(
            data=[[self.s["el_res"], self.s["eta_el_res"], 1.0]],
            columns=[self.s["comp"], self.s["param"], self.s["param_value"]],
        )

        # electric resistance backup size
        sol_el_tank_inst_el_res_bckp_size = pd.DataFrame(
            data=[[1, self.s["el_res"], 6500.0]],
            columns=[self.c["id"], self.s["comp"], self.s["cap"]],
        )

        self.hp_wh = System(
            sys_params=sol_el_tank_params,
            backup_params=sol_el_tank_inst_gas_bckp_params,
            sys_sizes=sol_el_tank_sizes_indiv,
            backup_sizes=sol_el_tank_inst_el_res_bckp_size,
            weather=self.weather,
            loads=loads_indiv,
        )
Пример #7
0
    def setUpClass(self):
        """Assigns values to test variables.
        """
        random_state = np.random.RandomState(123)

        self.plot_results = True
        # it will save under img on the test directory
        self.outpath = os.path.dirname(__file__)

        # get labels
        self.c = SwhLabels().set_hous_labels()
        self.s = SwhLabels().set_prod_labels()
        self.r = SwhLabels().set_res_labels()

        # generate weather data and annual hourly
        # water draw profile

        weather_db_path = os.path.join(os.getcwd(),
                                       'mswh/comm/mswh_system_input.db')

        db = Sql(weather_db_path)

        try:
            # read table names for all tables in a
            # {table name : sheet name} form
            inputs = db.tables2dict(close=True)
        except:
            msg = 'Failed to read input tables from {}.'
            log.error(msg.format(inpath))

        source_and_sink = SourceAndSink(input_dfs=inputs)

        # SF climate is 03, 16 is cold
        self.weather = source_and_sink.irradiation_and_water_main(
            '03', method='isotropic diffuse')

        # community scale household occupancies for 4 households
        occ_com = [4, 4, 3, 5]
        # individual scale household occupancy
        occ_ind = [4]

        # are people at home during the day in any of the households:
        # 'y' or 'n'
        at_home_com = ['n', 'n', 'n', 'n']
        at_home_ind = ['n']

        loads_com, peakload_com = SourceAndSink._make_example_loading_inputs(
            inputs,
            self.c,
            random_state,
            occupancy=occ_com,
            at_home=at_home_com)

        loads_indiv, peakload_indiv = SourceAndSink._make_example_loading_inputs(
            inputs,
            self.c,
            random_state,
            occupancy=occ_ind,
            at_home=at_home_ind)

        # scaled loads to match 300 L/day
        load_array_val = (loads_indiv['End-Use Load'][0] * (300 * 365 * .001) /
                          loads_indiv['End-Use Load'][0].sum())

        loads_indiv_val = pd.DataFrame(
            data=[[1, occ_ind[0], load_array_val]],
            columns=[self.c['id'], self.c['occ'], self.c['load_m3']])

        # performance parameters

        # solar thermal
        sol_the_sys_params = pd.DataFrame(
            data=[[self.s['the_sto'], self.s['f_upper_vol'], .5],
                  [self.s['the_sto'], self.s['ins_thi'], .085],
                  [self.s['the_sto'], self.s['spec_hea_con'], .04],
                  [self.s['the_sto'], self.s['t_tap_set'], 322.04],
                  [self.s['the_sto'], self.s['h_vs_r'], 6.],
                  [self.s['the_sto'], self.s['dt_appr'], 2.],
                  [self.s['the_sto'], self.s['t_max_tank'], 344.15],
                  [self.s['the_sto'], self.s['eta_coil'], .84],
                  [self.s['the_sto'], self.s['circ'], 0.],
                  [self.s['sol_col'], self.s['interc_hwb'], .753],
                  [self.s['sol_col'], self.s['slope_hwb'], -4.025],
                  [self.s['sol_pump'], self.s['eta_sol_pump'], .85],
                  [self.s['piping'], self.s['pipe_spec_hea_con'], .0175],
                  [self.s['piping'], self.s['pipe_ins_thick'], .008],
                  [self.s['piping'], self.s['flow_factor'], .8],
                  [self.s['piping'], self.s['dia_len_exp'],
                   0.43082708345352605],
                  [self.s['piping'], self.s['dia_len_sca'],
                   0.007911283766743384],
                  [self.s['piping'], self.s['discr_diam_m'],
                  '[0.0127, 0.01905, 0.0254, 0.03175, 0.0381,'\
                   '0.0508, 0.0635, 0.0762, 0.1016]'],
                  [self.s['piping'], self.s['circ'], False],
                  [self.s['piping'], self.s['long_br_len_fr'], 1.],
                  [self.s['dist_pump'], self.s['eta_dist_pump'], .85]],
            columns=[self.s['comp'], self.s['param'], self.s['param_value']])

        last_row_for_indiv = (
            sol_the_sys_params.shape[0] - 1 -
            sol_the_sys_params.loc[sol_the_sys_params[self.s['comp']] ==
                                   self.s['dist_pump'], :].shape[0])

        # conventional gas tank wh
        # ~R2.1, EL 1 from the rulemaking analysis
        gas_tank_wh_params = pd.DataFrame(
            data=[[self.s['gas_tank'], self.s['tank_re'], .78],
                  [self.s['gas_tank'], self.s['ins_thi'], .03],
                  [self.s['gas_tank'], self.s['spec_hea_con'], .081],
                  [self.s['gas_tank'], self.s['t_tap_set'], 322.04]],
            columns=[self.s['comp'], self.s['param'], self.s['param_value']])

        # gas tankless backup
        sol_the_inst_gas_bckp_params = pd.DataFrame(
            data=[[self.s['gas_burn'], self.s['comb_eff'], .85]],
            columns=[self.s['comp'], self.s['param'], self.s['param_value']])

        # sizing

        # assume 4 occupants
        # basecase gas tank WH: DOE sizing rule based on
        # peak hourly demand +/-2 gal, assuming +/- 0
        gas_tank_size_indiv = UnitConv(
            peakload_indiv.loc[0, self.c['max_load']]).m3_gal(unit_in='gal')

        gas_tank_wh_size = pd.DataFrame(
            data=[[self.s['gas_tank'], gas_tank_size_indiv]],
            columns=[self.s['comp'], self.s['cap']])

        # individual scale retrofit backup
        sol_the_gas_tank_bckp_size = pd.DataFrame(
            data=[[1, self.s['gas_tank'], gas_tank_size_indiv]],
            columns=[self.c['id'], self.s['comp'], self.s['cap']])

        # CSI sizing rules
        def demand_estimate(occ):
            if occ == 1:
                return 20.
            if occ == 2:
                return 35.
            else:
                return 35. + 10. * (occ - 2.)

        peakload_com[self.c['dem_estimate']] = \
            loads_com[self.c['occ']].apply(lambda x: demand_estimate(x))

        demand_estimate_ind = demand_estimate(occ_ind[0])

        demand_estimate_com = \
            peakload_com[self.c['dem_estimate']].sum()

        col_area_scaler = 1.2  # (CSI sizing rule: upper limit 1.25)
        tank_vol_scaler = 1.3  # (CSI sizing rule: lower limit 1.25)

        col_area_ind_sqft = demand_estimate_ind * col_area_scaler
        col_area_com_sqft = demand_estimate_com * col_area_scaler

        tank_vol_ind_gal = col_area_ind_sqft * tank_vol_scaler
        tank_vol_com_gal = col_area_com_sqft * tank_vol_scaler

        col_area_ind = UnitConv(col_area_ind_sqft).sqft_m2()
        col_area_com = UnitConv(col_area_com_sqft).sqft_m2()

        tank_vol_ind = UnitConv(tank_vol_ind_gal).m3_gal(unit_in='gal')
        tank_vol_com = UnitConv(tank_vol_com_gal).m3_gal(unit_in='gal')

        # piping
        pipe_m_per_hhld = 3.048
        detached_k = 6.
        attached_k = 3.

        # distribution pump
        dist_pump_size = 10.4376 * len(occ_com)**0.9277

        # solar pump
        com_solar_pump_size = 7.5101 * sum(occ_com)**0.5322
        indiv_solar_pump_size = 7.5101 * sum(occ_ind)**0.5322

        # individual
        sol_the_sys_sizes_indiv = pd.DataFrame(
            data=[[self.s['sol_col'], col_area_ind],
                  [self.s['the_sto'], tank_vol_ind],
                  [self.s['sol_pump'], indiv_solar_pump_size],
                  [self.s['piping'], pipe_m_per_hhld]],
            columns=[self.s['comp'], self.s['cap']])

        sol_the_inst_gas_bckp_size = pd.DataFrame(
            data=[[1, self.s['gas_burn'], 50972]],
            columns=[self.c['id'], self.s['comp'], self.s['cap']])

        # piping for single family attached
        sol_the_sys_sizes_com = pd.DataFrame(
            data=[[self.s['sol_col'], col_area_com],
                  [self.s['the_sto'], tank_vol_com],
                  [self.s['sol_pump'], com_solar_pump_size],
                  [self.s['dist_pump'], dist_pump_size],
                  [
                      self.s['piping'],
                      attached_k * pipe_m_per_hhld * len(occ_com)
                  ]],
            columns=[self.s['comp'], self.s['cap']])

        # gas tank backup
        sol_the_gas_tank_bckp_params = gas_tank_wh_params.copy()

        peakload_com['gas_tank_size_com'] = peakload_com[self.c[
            'max_load']].apply(lambda x: UnitConv(x).m3_gal(unit_in='gal'))

        peakload_com.index = peakload_com[self.c['id']]

        sol_the_gas_tank_bckp_sizes_com = pd.DataFrame(
            columns=[self.c['id'], self.s['comp'], self.s['cap']],
            index=peakload_com.index)

        for i in peakload_com.index:
            sol_the_gas_tank_bckp_sizes_com.loc[i, self.c['id']] = i
            sol_the_gas_tank_bckp_sizes_com.loc[
                i, self.s['comp']] = self.s['gas_tank']
            sol_the_gas_tank_bckp_sizes_com.loc[i, self.s['cap']] =\
                peakload_com.loc[i, 'gas_tank_size_com']

        sol_the_gas_tank_bckp_sizes_com.index = \
            range(sol_the_gas_tank_bckp_sizes_com.shape[0])

        sol_the_inst_gas_bckp_sizes_com = pd.DataFrame(
            columns=[self.c['id'], self.s['comp'], self.s['cap']],
            index=peakload_com.index)

        def gas_tankles_size_W(occupancy):
            size = 24875. * occupancy**0.5175
            return size

        for i in peakload_com.index:
            sol_the_inst_gas_bckp_sizes_com.loc[i, self.c['id']] = i
            sol_the_inst_gas_bckp_sizes_com.loc[
                i, self.s['comp']] = self.s['gas_burn']
            sol_the_inst_gas_bckp_sizes_com.loc[i,  self.s['cap']] = \
                gas_tankles_size_W(occ_com[i - 1])

        sol_the_inst_gas_bckp_sizes_com.index =\
            range(sol_the_inst_gas_bckp_sizes_com.shape[0])

        # instantiate systems

        # individual system
        self.sol_wh_indiv_new = System(
            sys_params=sol_the_sys_params.loc[:last_row_for_indiv, :],
            backup_params=sol_the_inst_gas_bckp_params,
            sys_sizes=sol_the_sys_sizes_indiv,
            backup_sizes=sol_the_inst_gas_bckp_size,
            weather=self.weather,
            loads=loads_indiv)

        msg = 'Set up the individual solar thermal system with tankless '\
              'backup test case.'
        log.info(msg)

        self.sol_wh_indiv_retr = System(
            sys_params=sol_the_sys_params.loc[:last_row_for_indiv, :],
            backup_params=sol_the_gas_tank_bckp_params,
            sys_sizes=sol_the_sys_sizes_indiv,
            backup_sizes=sol_the_gas_tank_bckp_size,
            weather=self.weather,
            loads=loads_indiv)

        msg = 'Set up the individual solar thermal system with gas tank '\
              'backup test case.'
        log.info(msg)

        # community system
        self.sol_wh_com_new = System(
            sys_params=sol_the_sys_params,
            backup_params=sol_the_inst_gas_bckp_params,
            sys_sizes=sol_the_sys_sizes_com,
            backup_sizes=sol_the_inst_gas_bckp_sizes_com,
            weather=self.weather,
            loads=loads_com)

        msg = 'Set up the community solar thermal system with tankless '\
              'backup test case.'
        log.info(msg)

        self.sol_wh_com_retr = System(
            sys_params=sol_the_sys_params,
            backup_params=sol_the_gas_tank_bckp_params,
            sys_sizes=sol_the_sys_sizes_com,
            backup_sizes=sol_the_gas_tank_bckp_sizes_com,
            weather=self.weather,
            loads=loads_com)

        msg = 'Set up the community solar thermal system with gas tank '\
              'backup test case.'
        log.info(msg)

        # solar thermal validation

        # individual new with
        # tank and collector size from
        # https://secure.solar-rating.org/Certification/Ratings/#
        # RatingsReport.aspx?device=6926&units=METRICS
        # solar thermal retrofit solar fractions in the rating sheets are low
        # - for the same
        # size of collector and storage the new and retrofit should have the
        # same solar fraction
        # by definition https://en.wikipedia.org/wiki/Solar_savings_fraction

        # sizes based on several observed rated systems from OG-300
        # with an 80 gal tank and gas tankless backup
        sol_the_sys_sizes_val = pd.DataFrame(
            data=[[self.s['sol_col'], 3.9],
                  [self.s['the_sto'],
                   UnitConv(80.).m3_gal(unit_in='gal')],
                  [self.s['sol_pump'], indiv_solar_pump_size],
                  [self.s['piping'], 0.]],
            columns=[self.s['comp'], self.s['cap']])

        self.val_sol_wh = System(
            sys_params=sol_the_sys_params.loc[:last_row_for_indiv, :],
            backup_params=sol_the_inst_gas_bckp_params,
            sys_sizes=sol_the_sys_sizes_val,
            backup_sizes=sol_the_inst_gas_bckp_size,
            weather=self.weather,
            loads=loads_indiv_val)

        msg = 'Set up the individual solar thermal system validation '\
            'test case.'
        log.info(msg)

        self.conv_wh = System(sys_params=gas_tank_wh_params,
                              sys_sizes=gas_tank_wh_size,
                              weather=self.weather,
                              loads=loads_indiv)

        msg = 'Set up the conventional tank wh test case.'
        log.info(msg)

        # With baseline tank with a slightly higher RE and insulation set to
        # R12, as used for the solar tank
        gas_tank_wh_params_val = pd.DataFrame(
            data=[[self.s['gas_tank'], self.s['tank_re'], .82, '-'],
                  [self.s['gas_tank'], self.s['ins_thi'], .04, 'm'],
                  [self.s['gas_tank'], self.s['spec_hea_con'], .085, 'W/mK'],
                  [self.s['gas_tank'], self.s['t_tap_set'], 322.04, 'K']],
            columns=[
                self.s['comp'], self.s['param'], self.s['param_value'],
                self.s['param_unit']
            ])

        # with validation loads and validation parameters
        self.conv_wh_val = System(sys_params=gas_tank_wh_params_val,
                                  sys_sizes=gas_tank_wh_size,
                                  weather=self.weather,
                                  loads=loads_indiv_val)

        msg = 'Set up the conventional tank wh validation test case.'
        log.info(msg)

        # project level component parameter
        # dataframe for solar electric system
        # with an inst. gas backup
        sol_el_tank_params = pd.DataFrame(
            data=[[self.s['hp'], self.s['c1_cop'], 1.229E+00],
                  [self.s['hp'], self.s['c2_cop'], 5.549E-02],
                  [self.s['hp'], self.s['c3_cop'], 1.139E-04],
                  [self.s['hp'], self.s['c4_cop'], -1.128E-02],
                  [self.s['hp'], self.s['c5_cop'], -3.570E-06],
                  [self.s['hp'], self.s['c6_cop'], -7.234E-04],
                  [self.s['hp'], self.s['c1_heat_cap'], 7.055E-01],
                  [self.s['hp'], self.s['c2_heat_cap'], 3.945E-02],
                  [self.s['hp'], self.s['c3_heat_cap'], 1.433E-04],
                  [self.s['hp'], self.s['c4_heat_cap'], 2.768E-03],
                  [self.s['hp'], self.s['c5_heat_cap'], -1.069E-04],
                  [self.s['hp'], self.s['c6_heat_cap'], -2.494E-04],
                  [self.s['hp'], self.s['heat_cap_rated'], 2350.],
                  [self.s['hp'], self.s['cop_rated'], 2.43],
                  [self.s['pv'], self.s['eta_pv'], .16],
                  [self.s['pv'], self.s['f_act'], 1.],
                  [self.s['pv'], self.s['irrad_ref'], 1000.],
                  [self.s['inv'], self.s['eta_dc_ac'], .85],
                  [self.s['the_sto'], self.s['f_upper_vol'], .5],
                  [self.s['the_sto'], self.s['ins_thi'], .04],
                  [self.s['the_sto'], self.s['spec_hea_con'], .04],
                  [self.s['the_sto'], self.s['t_tap_set'], 322.04],
                  [self.s['the_sto'], self.s['h_vs_r'], 6.],
                  [self.s['the_sto'], self.s['dt_appr'], 2.],
                  [self.s['the_sto'], self.s['t_max_tank'], 344.15],
                  [self.s['piping'], self.s['pipe_spec_hea_con'], .0175],
                  [self.s['piping'], self.s['pipe_ins_thick'], .008],
                  [self.s['piping'], self.s['flow_factor'], .8],
                  [self.s['piping'], self.s['dia_len_exp'],
                   .43082708345352605],
                  [self.s['piping'], self.s['dia_len_sca'],
                   .007911283766743384],
                  [self.s['piping'], self.s['discr_diam_m'],
                  '[0.0127, 0.01905, 0.0254, 0.03175, 0.0381,'\
                   '0.0508, 0.0635, 0.0762, 0.1016]'],
                  [self.s['piping'], self.s['circ'], False],
                  [self.s['piping'], self.s['long_br_len_fr'], 1.]],
            columns=[self.s['comp'], self.s['param'], self.s['param_value']])

        # test sizing
        sol_el_tank_sizes_indiv = pd.DataFrame(
            data=[[self.s['hp'], 2350.], [self.s['pv'], 6.25],
                  [self.s['the_sto'], UnitConv(80).m3_gal()],
                  [self.s['dist_pump'], dist_pump_size],
                  [self.s['piping'], pipe_m_per_hhld]],
            columns=[self.s['comp'], self.s['cap']])

        # electric resistance backup parameters
        sol_el_tank_inst_gas_bckp_params = pd.DataFrame(
            data=[[self.s['el_res'], self.s['eta_el_res'], 1.0]],
            columns=[self.s['comp'], self.s['param'], self.s['param_value']])

        # electric resistance backup size
        sol_el_tank_inst_el_res_bckp_size = pd.DataFrame(
            data=[[1, self.s['el_res'], 6500.]],
            columns=[self.c['id'], self.s['comp'], self.s['cap']])

        self.hp_wh = System(sys_params=sol_el_tank_params,
                            backup_params=sol_el_tank_inst_gas_bckp_params,
                            sys_sizes=sol_el_tank_sizes_indiv,
                            backup_sizes=sol_el_tank_inst_el_res_bckp_size,
                            weather=self.weather,
                            loads=loads_indiv)