예제 #1
0
def calc_per_veh_tech_costs(averages_dict):
    """
    
    Parameters::
        averages_dict: Dictionary; contains average direct and indirect costs per vehicle.

    Returns:
        The averages_dict dictionary updated with average tech costs per vehicle (direct plus indirect).

    Note:
        Direct and indirect costs apply only for ageID=0 (i.e., new sales).

    """
    print('\nCalculating per vehicle technology costs...')
    calcs_avg = FleetAverages(averages_dict)

    age0_keys = [k for k, v in averages_dict.items() if v['ageID'] == 0]

    for key in age0_keys:
        cost = calcs_avg.get_attribute_value(key, 'DirectCost_AvgPerVeh')
        cost += calcs_avg.get_attribute_value(key, 'IndirectCost_AvgPerVeh')

        temp_dict = {'TechCost_AvgPerVeh': cost}
        calcs_avg.update_dict(key, temp_dict)

    return averages_dict
예제 #2
0
def create_weighted_cost_dict(settings, averages_dict, arg_to_weight, arg_to_weight_by):
    """
    This function weights 'arg_to_weight' attributes by the 'arg_to_weight_by' attribute.

    Parameters::
        settings: The SetInputs class.\n
        averages_dict: Dictionary; contains fleet average data (e.g., miles/year, cost/year, cost/mile).\n
        arg_to_weight: String; the attribute to be weighted by the arg_to_weight_by argument.\n
        arg_to_weight_by: String; the argument to weight by.

    Returns:
        A dictionary of arguments weighted by the weight_by argument.

    Note:
        The weighting is limited by the number of years (ages) to be included which is set in the general inputs file. The weighting is also
        limited to model years for which sufficient data exits to include all of those ages. For example, if the maximum calendar year included
        in the input data is 2045, and the maximum numbers of ages of data to include for each model year is 9 (which would be 10 years of age
        since year 1 is age 0) then the maximum model year included will be 2035.

    """
    print(f'\nCalculating weighted {arg_to_weight}...')
    calcs_avg = FleetAverages(averages_dict)

    wtd_result_dict = dict()
    weighted_results_dict = dict()
    for key in averages_dict.keys():
        vehicle, alt, model_year, age_id = key[0], key[1], key[2], key[3]
        st, rc, ft = vehicle
        if arg_to_weight == 'DEFCost_AvgPerMile' and ft != 2:
            pass
        else:
            if model_year <= (settings.year_max - settings.max_age_included - 1):
                wtd_result_dict_id = (vehicle, alt, model_year)
                numerator, denominator = 0, 0
                if wtd_result_dict_id in wtd_result_dict:
                    numerator = wtd_result_dict[wtd_result_dict_id]['numerator']
                    denominator = wtd_result_dict[wtd_result_dict_id]['denominator']
                else:
                    pass
                if age_id <= settings.max_age_included:
                    arg_weight = calcs_avg.get_attribute_value(key, arg_to_weight)
                    arg_weight_by = calcs_avg.get_attribute_value(key, arg_to_weight_by)
                    numerator += arg_weight * arg_weight_by
                    denominator += calcs_avg.get_attribute_value(key, 'VMT_AvgPerVeh')
                    wtd_result_dict[wtd_result_dict_id] = {'numerator': numerator, 'denominator': denominator}
    for key in wtd_result_dict.keys():
        numerator = wtd_result_dict[key]['numerator']
        denominator = wtd_result_dict[key]['denominator']
        vehicle, alt = key[0], key[1]
        st, rc, ft = vehicle
        source_type = Vehicle(st).sourcetype_name()
        weighted_results_dict[key] = {'optionID': alt, 'sourceTypeName': source_type, 'cents_per_mile': 100 * numerator / denominator}

    return weighted_results_dict
예제 #3
0
def calc_per_veh_direct_costs(yoy_costs_per_step_dict, cost_steps, averages_dict, program):
    """

    Parameters:
        yoy_costs_per_step_dict: Dictionary; contains the package cost and cumulative sales used to calculate that package cost (learning effects depend on cumulative
        sales) for the passed unit in the given model year and complying with the standards set in the given cost step. \n
        cost_steps: List; provides the cost steps (as strings) associated with the direct costs being calculated.\n
        averages_dict: Dictionary; into which tech package direct costs/vehicle will be updated.\n
        program: String; the program identifier (i.e., 'CAP' or 'GHG').

    Returns:
        The averages_dict dictionary updated with tech package costs/vehicle.

    """
    print(f'\nCalculating {program} costs per vehicle...')

    calcs_avg = FleetAverages(averages_dict)

    age0_keys = [k for k, v in averages_dict.items() if v['ageID'] == 0]

    for key in age0_keys:
        vehicle, alt, model_year, age_id, disc_rate = key
        st, rc, ft = vehicle
        engine = (rc, ft)

        if program == 'CAP': unit = engine
        else: unit = vehicle

        if alt == 0:
            cost = yoy_costs_per_step_dict[(unit, alt, model_year, cost_steps[0])]['Cost_AvgPerVeh']
        else:
            cost = yoy_costs_per_step_dict[(unit, 0, model_year, cost_steps[0])]['Cost_AvgPerVeh']
            for step in cost_steps:
                if model_year >= int(step):
                    cost += yoy_costs_per_step_dict[(unit, alt, model_year, step)]['Cost_AvgPerVeh']

        if program == 'GHG':
            # GHG program costs are to be averaged over all VPOP for the given unit
            vpop_with_tech = calcs_avg.get_attribute_value(key, 'VPOP_withTech')
            vpop = calcs_avg.get_attribute_value(key, 'VPOP')
            cost = cost * vpop_with_tech / vpop
            temp_dict = {'TechCost_AvgPerVeh': cost}
            calcs_avg.update_dict(key, temp_dict)
        else:
            temp_dict = {'DirectCost_AvgPerVeh': cost}
            calcs_avg.update_dict(key, temp_dict)

    return averages_dict
예제 #4
0
def calc_direct_costs(totals_dict, averages_dict, sales_arg, program):
    """

    Parameters:
        totals_dict: Dictionary; into which tech package direct costs will be updated.\n
        averages_dict: Dictionary; contains tech package direct costs/vehicle.\n
        sales_arg: String; specifies the sales attribute to use (e.g., "VPOP" or "VPOP_withTech")\n
        program: String; the program identifier (i.e., 'CAP' or 'GHG').

    Returns:
        The totals_dict dictionary updated with tech package direct costs (package cost * sales).

    """
    if program == 'CAP': arg = 'Direct'
    else: arg = 'Tech'

    print(f'\nCalculating {program} {arg} total costs...')

    calcs = FleetTotals(totals_dict)
    calcs_avg = FleetAverages(averages_dict)

    age0_keys = [k for k, v in totals_dict.items() if v['ageID'] == 0]

    for key in age0_keys:
        cost_per_veh = calcs_avg.get_attribute_value(key, f'{arg}Cost_AvgPerVeh')
        sales = calcs.get_attribute_value(key, sales_arg)
        cost = cost_per_veh * sales

        temp_dict = {f'{arg}Cost': cost}
        calcs.update_dict(key, temp_dict)

    return totals_dict
예제 #5
0
def calc_typical_vmt_per_year(settings, vehicle, alt, model_year, averages_dict):
    """
    This function calculates a typical annual VMT/vehicle over a set number of years as set via the General Inputs workbook. This typical annual VMT/vehicle
    can then be used to estimate the ages at which warranty and useful life will be reached. When insufficient years are available -- e.g., if the typical_vmt_thru_ageID
    is set to >5 years and the given vehicle is a MY2041 vintage vehicle and the fleet input file contains data only thru CY2045, then insufficient data exist to
    calculate the typical VMT for that vehicle -- the typical VMT for that vehicle will be set equal to the last prior MY vintage for which sufficient data were present.

    Parameters:
        settings: The SetInputs class.\n
        vehicle: Tuple; represents a sourcetype_regclass_fueltype vehicle.\n
        alt: Numeric; the Alternative or option ID.\n
        model_year: Numeric; the model year of the passed vehicle.\n
        averages_dict: Dictionary; contains cumulative annual average VMT/vehicle.

    Returns:
        A single typical annual VMT/veh value for the passed vehicle of the given model year.

    """
    calcs_avg = FleetAverages(averages_dict)

    vmt_thru_age_id = settings.repair_inputs_dict['typical_vmt_thru_ageID']['Value']
    if model_year + vmt_thru_age_id <= settings.year_max:
        year = model_year
    else:
        year = settings.year_max - vmt_thru_age_id # can't get cumulative VMT when model_year + vmt_thru_age_id exceeds data

    cumulative_vmt = calcs_avg.get_attribute_value((vehicle, alt, year, vmt_thru_age_id, 0), 'VMT_AvgPerVeh_Cumulative')
    typical_vmt = cumulative_vmt / (vmt_thru_age_id + 1)

    return typical_vmt
예제 #6
0
def calc_emission_repair_costs(totals_dict, averages_dict, vpop_arg):
    """

    Parameters:
        totals_dict: Dictionary; contains annual vehicle populations (VPOP).\n
        averages_dict: Dictionary; contains annual average emission repair costs/mile.\n
        vpop_arg: String; specifies the population attribute to use (e.g., "VPOP" or "VPOP_withTech")

    Returns:
        The totals_dict dictionary updated with annual emission repair costs for all vehicles.

    """
    print(f'\nCalculating total emission repair costs...')

    calcs_avg = FleetAverages(averages_dict)
    calcs = FleetTotals(totals_dict)

    for key in totals_dict.keys():
        cost_per_veh = calcs_avg.get_attribute_value(key, 'EmissionRepairCost_AvgPerVeh')
        vpop = calcs.get_attribute_value(key, vpop_arg)
        cost = cost_per_veh * vpop

        temp_dict = {'EmissionRepairCost': cost}
        calcs.update_dict(key, temp_dict)

    return totals_dict
예제 #7
0
def calc_tech_costs(totals_dict, averages_dict, sales_arg):
    """

    Parameters::
        totals_dict: Dictionary; contains vehicle population (VPOP) data.\n
        averages_dict: Dictionary; contains average tech costs per vehicle.
        sales_arg: String; specifies the sales attribute to use (e.g., "VPOP" or "VPOP_withTech")

    Returns:
        The totals_dict dictionary updated with annual technology costs for all vehicles.

    """
    print('\nCalculating total technology costs...')

    calcs_avg = FleetAverages(averages_dict)
    calcs = FleetTotals(totals_dict)

    age0_keys = [k for k, v in totals_dict.items() if v['ageID'] == 0]

    for key in age0_keys:
        cost_per_veh = calcs_avg.get_attribute_value(key, 'TechCost_AvgPerVeh')
        sales = calcs.get_attribute_value(key, sales_arg)
        cost = cost_per_veh * sales

        temp_dict = {'TechCost': cost}
        calcs.update_dict(key, temp_dict)

    return totals_dict
예제 #8
0
def calc_indirect_costs(settings, totals_dict, averages_dict, sales_arg):
    """

    Parameters:
        settings: The SetInputs class.\n
        totals_dict: Dictionary; contains sales data (e.g., sales_arg at age=0).\n
        averages_dict: Dictionary; contains individual indirect costs per vehicle.\n
        sales_arg: String; specifies the sales attribute to use (e.g., "VPOP" or "VPOP_withTech")

    Returns:
        The totals_dict dictionary updated with total indirect costs for each individual indirect cost property and a summation of those.

    """
    print('\nCalculating CAP total indirect costs...')

    markup_factors = settings.markup_factors_unique_names.copy()
    markup_factors.append('Indirect')

    calcs_avg = FleetAverages(averages_dict)
    calcs = FleetTotals(totals_dict)

    age0_keys = [k for k, v in totals_dict.items() if v['ageID'] == 0]

    for key in age0_keys:
        temp_dict = dict()
        for markup_factor in markup_factors:
            cost_per_veh = calcs_avg.get_attribute_value(
                key, f'{markup_factor}Cost_AvgPerVeh')
            sales = calcs.get_attribute_value(key, sales_arg)
            cost = cost_per_veh * sales
            temp_dict[f'{markup_factor}Cost'] = cost

        calcs.update_dict(key, temp_dict)

    return totals_dict
예제 #9
0
def calc_per_veh_emission_repair_costs(averages_dict):
    """

    Parameters:
        averages_dict: Dictionary; contains annual emission repair costs/mile.

    Returns:
        The passed dictionary updated with annual emission repair costs/vehicle for each dictionary key.

    """
    print('\nCalculating emission repair costs per vehicle...')
    calcs_avg = FleetAverages(averages_dict)

    for key in averages_dict.keys():
        repair_cpm = calcs_avg.get_attribute_value(key, 'EmissionRepairCost_AvgPerMile')
        vmt_per_veh = calcs_avg.get_attribute_value(key, 'VMT_AvgPerVeh')
        cost_per_veh = repair_cpm * vmt_per_veh

        temp_dict = {'EmissionRepairCost_AvgPerVeh': cost_per_veh}
        calcs_avg.update_dict(key, temp_dict)

    return averages_dict
예제 #10
0
def calc_per_veh_indirect_costs(settings, averages_dict):
    """
    
    Parameters:
        settings: The SetInputs class.\n
        averages_dict: Dictionary; contains tech package direct costs/vehicle.

    Returns:
        The averages_dict dictionary updated with indirect costs associated with each markup value along with the summation of those individual indirect
        costs as "IndirectCost_AvgPerVeh."

    """
    print('\nCalculating CAP per vehicle indirect costs...')
    calcs_avg = FleetAverages(averages_dict)
    markup_factors = settings.markup_factors_unique_names.copy()

    age0_keys = [k for k, v in averages_dict.items() if v['ageID'] == 0]

    for key in age0_keys:
        vehicle, alt, model_year, age_id, disc_rate = key
        st, rc, ft = vehicle
        engine = (rc, ft)

        temp_dict = dict()
        ic_sum = 0
        for markup_factor in markup_factors:
            markup_value = calc_project_markup_value(settings, engine, alt,
                                                     markup_factor, model_year)
            per_veh_direct_cost = calcs_avg.get_attribute_value(
                key, 'DirectCost_AvgPerVeh')
            cost = markup_value * per_veh_direct_cost
            temp_dict[f'{markup_factor}Cost_AvgPerVeh'] = cost
            ic_sum += cost

        temp_dict['IndirectCost_AvgPerVeh'] = ic_sum
        calcs_avg.update_dict(key, temp_dict)

    return averages_dict
예제 #11
0
def calc_emission_repair_costs_per_mile(settings, averages_dict):
    """

    Parameters:
        settings: The SetInputs class.\n
        averages_dict: Dictionary; contains tech package direct costs/vehicle and cumulative annual average VMT/vehicle.

    Returns:
        The averages_dict dictionary updated to include emission repair costs/mile for each dictionary key.\n
        A repair cost/mile dictionary containing details used in the calculation of repair cost/mile and which is then written to an output file for the given run.\n
        An 'estimated ages' dictionary containing details behind the calculations and which is then written to an output file for the given run.

    """
    print('\nCalculating emission repair costs per mile...')
    calcs_avg = FleetAverages(averages_dict)

    repair_cpm_dict = dict()
    estimated_ages_dict = dict()
    for key in averages_dict.keys():
        vehicle, alt, model_year, age_id, disc_rate = key

        reference_direct_cost = calcs_avg.get_attribute_value(((61, 47, 2), 0, model_year, 0, 0), 'DirectCost_AvgPerVeh') # sourcetype here is arbitrary provided it is of diesel regclass 47
        direct_cost = calcs_avg.get_attribute_value((vehicle, alt, model_year, 0, 0), 'DirectCost_AvgPerVeh')
        direct_cost_scaler = direct_cost / reference_direct_cost

        typical_vmt = calc_typical_vmt_per_year(settings, vehicle, alt, model_year, averages_dict)
        warranty_estimated_age, estimated_ages_dict = calc_estimated_age(settings, vehicle, alt, model_year, 'Warranty', typical_vmt, estimated_ages_dict)
        usefullife_estimated_age, estimated_ages_dict = calc_estimated_age(settings, vehicle, alt, model_year, 'Usefullife', typical_vmt, estimated_ages_dict)

        in_warranty_cpm = settings.repair_inputs_dict['in-warranty_R&M_CPM']['Value'] \
                          * settings.repair_inputs_dict['emission_repair_share']['Value'] \
                          * direct_cost_scaler
        at_usefullife_cpm = settings.repair_inputs_dict['at-usefullife_R&M_CPM']['Value'] \
                          * settings.repair_inputs_dict['emission_repair_share']['Value'] \
                          * direct_cost_scaler

        if usefullife_estimated_age > warranty_estimated_age:
            slope_within_usefullife = (at_usefullife_cpm - in_warranty_cpm) / (usefullife_estimated_age - warranty_estimated_age)
        else:
            slope_within_usefullife = 0

        max_cpm = settings.repair_inputs_dict['max_R&M_CPM']['Value'] \
                  * settings.repair_inputs_dict['emission_repair_share']['Value'] \
                  * direct_cost_scaler

        # now calulate the cost per mile
        if (age_id + 1) < warranty_estimated_age:
            cpm = in_warranty_cpm
        elif warranty_estimated_age <= (age_id + 1) < usefullife_estimated_age:
            cpm = slope_within_usefullife * ((age_id + 1) - warranty_estimated_age) + in_warranty_cpm
        elif (age_id + 1) == usefullife_estimated_age:
            cpm = at_usefullife_cpm
        else:
            cpm = max_cpm

        temp_dict = {'EmissionRepairCost_AvgPerMile': cpm}
        calcs_avg.update_dict(key, temp_dict)

        repair_cpm_dict[key] = {'reference_direct_cost': reference_direct_cost,
                                'direct_cost_scaler': direct_cost_scaler,
                                'warranty_estimated_age': warranty_estimated_age,
                                'usefullife_estimated_age': usefullife_estimated_age,
                                'in_warranty_cpm': in_warranty_cpm,
                                'at_usefullife_cpm': at_usefullife_cpm,
                                'slope_within_usefullife': slope_within_usefullife,
                                'max_cpm': max_cpm,
                                'cpm': cpm
                                }
    return averages_dict, repair_cpm_dict, estimated_ages_dict