Skip to content

TCOCalc Sub-Module

t3co.tco.tcocalc

TCOCalc

Source code in src/t3co/tco/tcocalc.py
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
class TCOCalc:
    year_number: int = None
    total_cost_dol_per_yr: float = None
    disc_total_cost_dol_per_yr: float = None
    cap_costs_dol: CapitalCosts = None
    oper_costs_dol: OperatingCosts = None
    oppy_costs_dol: OpportunityCosts = None

    def __new__(cls, *args, **kwargs):
        """
        Creates a new instance of the TCOCalc class.
        """
        instance = super(TCOCalc, cls).__new__(cls)
        return instance

    def __init__(
        self,
        year_index: int,
        vehicle: Vehicle,
        scenario: Scenario,
        energy: Energy,
        payload_cap_cost_multiplier: float = None,
        cap_costs: CapitalCosts = None,
    ):
        """
        Initializes the TCOCalc instance.

        Args:
            year_index (int): The year index.
            vehicle (Vehicle): The vehicle instance.
            scenario (Scenario): The scenario instance.
            energy (Energy): The energy instance.
            payload_cap_cost_multiplier (float, optional): Payload capacity cost multiplier. Defaults to None.
            cap_costs (CapitalCosts, optional): Capital costs instance. Defaults to None.
        """
        self.year_number = year_index + 1
        if self.year_number == 1:
            self.calculate_capital_costs(vehicle=vehicle, scenario=scenario)

        if cap_costs:
            self.cap_costs_dol = cap_costs
        else:
            self.calculate_capital_costs(vehicle=vehicle, scenario=scenario)

        self.calculate_opportunity_costs(
            vehicle=vehicle, scenario=scenario, energy=energy
        )
        if payload_cap_cost_multiplier:
            self.oppy_costs_dol.payload_cap_cost_multiplier = (
                payload_cap_cost_multiplier
            )

        self.calculate_operating_costs(
            vehicle=vehicle, scenario=scenario, energy=energy
        )
        self.set_total_cost(scenario=scenario)
        self.set_disc_total_cost(
            vehicle=vehicle,
            scenario=scenario,
            payload_cap_cost_multiplier=payload_cap_cost_multiplier,
        )

    def calculate_capital_costs(self, vehicle: Vehicle, scenario: Scenario) -> None:
        """
        Calculates the capital costs.

        Args:
            vehicle (Vehicle): The vehicle instance.
            scenario (Scenario): The scenario instance.
        """
        self.cap_costs_dol = CapitalCosts(
            vehicle=vehicle, scenario=scenario, msrp_total_dol=scenario.msrp_total_dol
        )

    def calculate_opportunity_costs(
        self, vehicle: Vehicle, scenario: Scenario, energy: Energy
    ) -> None:
        """
        Calculates the opportunity costs.

        Args:
            vehicle (Vehicle): The vehicle instance.
            scenario (Scenario): The scenario instance.
            energy (Energy): The energy instance.
        """
        self.oppy_costs_dol = OpportunityCosts(
            year_number=self.year_number,
            vehicle=vehicle,
            scenario=scenario,
            energy=energy,
        )

    def calculate_operating_costs(
        self, vehicle: Vehicle, scenario: Scenario, energy: Energy
    ) -> None:
        """
        Calculates the operating costs.

        Args:
            vehicle (Vehicle): The vehicle instance.
            scenario (Scenario): The scenario instance.
            energy (Energy): The energy instance.
        """
        self.oper_costs_dol = OperatingCosts(
            year_number=self.year_number,
            cap_costs=self.cap_costs_dol,
            vehicle=vehicle,
            scenario=scenario,
            energy=energy,
            oppy_costs=self.oppy_costs_dol,
        )

    def set_total_cost(self, scenario: Scenario) -> None:
        """
        Sets the total cost for the year.

        Args:
            scenario (Scenario): The scenario instance.
        """
        self.total_cost_dol_per_yr = (
            (self.cap_costs_dol.net_capital_cost_dol if self.year_number == 1 else 0)
            + self.oper_costs_dol.net_oper_cost_dol_per_yr
            + self.oppy_costs_dol.net_downtime_oppy_cost_dol_per_yr
            + (
                self.cap_costs_dol.residual_cost_dol
                if self.year_number == scenario.vehicle_life_yr
                else 0
            )
        )

    def set_disc_total_cost(
        self,
        vehicle: Vehicle,
        scenario: Scenario,
        payload_cap_cost_multiplier: float = None,
        TCO_switch="DIRECT",
    ) -> None:
        """
        Sets the discounted total cost for the year.

        Args:
            vehicle (Vehicle): The vehicle instance.
            scenario (Scenario): The scenario instance.
            payload_cap_cost_multiplier (float, optional): Payload capacity cost multiplier. Defaults to None.
            TCO_switch (str, optional): TCO calculation method. Defaults to "DIRECT".
        """
        if (
            payload_cap_cost_multiplier is not None
            and not self.oppy_costs_dol.payload_cap_cost_multiplier
        ):
            self.oppy_costs_dol.payload_cap_cost_multiplier = (
                payload_cap_cost_multiplier
            )
        elif self.oppy_costs_dol.payload_cap_cost_multiplier:
            pass
        else:
            self.oppy_costs_dol.set_payload_cap_cost_multiplier(
                vehicle=vehicle, scenario=scenario
            )

        if TCO_switch == "DIRECT":
            self.disc_total_cost_dol_per_yr = (
                self.oppy_costs_dol.payload_cap_cost_multiplier
                * (
                    self.cap_costs_dol.net_capital_cost_dol
                    + self.oper_costs_dol.disc_oper_cost_dol_per_yr
                    + self.oppy_costs_dol.disc_downtime_oppy_cost_dol
                )
            )
            self.oppy_costs_dol.payload_capacity_cost_dol = (
                (self.oppy_costs_dol.payload_cap_cost_multiplier - 1)
                / self.oppy_costs_dol.payload_cap_cost_multiplier
                * self.disc_total_cost_dol_per_yr
            )

        elif TCO_switch == "EFFICIENCY":
            disc_VMT_sum = scenario.get_discounted_value(
                value=scenario.vmt[self.year_number - 1], year_number=self.year_number
            )

            downtime_efficiency = 1 / (
                1
                + scenario.avg_speed_mph
                * self.oppy_costs_dol.disc_downtime_oppy_cost_dol
                / disc_VMT_sum
            )
            self.disc_total_cost_dol_per_yr = (
                self.oppy_costs_dol.payload_cap_cost_multiplier
                * (
                    (
                        self.cap_costs_dol.net_capital_cost_dol
                        + self.oper_costs_dol.disc_oper_cost_dol_per_yr
                    )
                    / downtime_efficiency
                    + self.cap_costs_dol.residual_cost_dol
                )
            )
            self.oppy_costs_dol.disc_downtime_oppy_cost_dol = (
                self.cap_costs_dol.net_capital_cost_dol
                + self.oper_costs_dol.disc_oper_cost_dol_per_yr
                + self.oppy_costs_dol.disc_downtime_oppy_cost_dol
            ) * (1 / downtime_efficiency - 1)

            self.oppy_costs_dol.payload_capacity_cost_dol = (
                (self.oppy_costs_dol.payload_cap_cost_multiplier - 1)
                / self.oppy_costs_dol.payload_cap_cost_multiplier
                * self.disc_total_cost_dol_per_yr
            )

    def __str__(self) -> str:
        """
        Returns a string representation of the TCOCalc instance.

        Returns:
            str: String representation of the TCOCalc instance.
        """
        return obj_to_string(self)

__new__(*args, **kwargs)

Creates a new instance of the TCOCalc class.

Source code in src/t3co/tco/tcocalc.py
18
19
20
21
22
23
def __new__(cls, *args, **kwargs):
    """
    Creates a new instance of the TCOCalc class.
    """
    instance = super(TCOCalc, cls).__new__(cls)
    return instance

__init__(year_index, vehicle, scenario, energy, payload_cap_cost_multiplier=None, cap_costs=None)

Initializes the TCOCalc instance.

Parameters:

Name Type Description Default
year_index int

The year index.

required
vehicle Vehicle

The vehicle instance.

required
scenario Scenario

The scenario instance.

required
energy Energy

The energy instance.

required
payload_cap_cost_multiplier float

Payload capacity cost multiplier. Defaults to None.

None
cap_costs CapitalCosts

Capital costs instance. Defaults to None.

None
Source code in src/t3co/tco/tcocalc.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
def __init__(
    self,
    year_index: int,
    vehicle: Vehicle,
    scenario: Scenario,
    energy: Energy,
    payload_cap_cost_multiplier: float = None,
    cap_costs: CapitalCosts = None,
):
    """
    Initializes the TCOCalc instance.

    Args:
        year_index (int): The year index.
        vehicle (Vehicle): The vehicle instance.
        scenario (Scenario): The scenario instance.
        energy (Energy): The energy instance.
        payload_cap_cost_multiplier (float, optional): Payload capacity cost multiplier. Defaults to None.
        cap_costs (CapitalCosts, optional): Capital costs instance. Defaults to None.
    """
    self.year_number = year_index + 1
    if self.year_number == 1:
        self.calculate_capital_costs(vehicle=vehicle, scenario=scenario)

    if cap_costs:
        self.cap_costs_dol = cap_costs
    else:
        self.calculate_capital_costs(vehicle=vehicle, scenario=scenario)

    self.calculate_opportunity_costs(
        vehicle=vehicle, scenario=scenario, energy=energy
    )
    if payload_cap_cost_multiplier:
        self.oppy_costs_dol.payload_cap_cost_multiplier = (
            payload_cap_cost_multiplier
        )

    self.calculate_operating_costs(
        vehicle=vehicle, scenario=scenario, energy=energy
    )
    self.set_total_cost(scenario=scenario)
    self.set_disc_total_cost(
        vehicle=vehicle,
        scenario=scenario,
        payload_cap_cost_multiplier=payload_cap_cost_multiplier,
    )

calculate_capital_costs(vehicle, scenario)

Calculates the capital costs.

Parameters:

Name Type Description Default
vehicle Vehicle

The vehicle instance.

required
scenario Scenario

The scenario instance.

required
Source code in src/t3co/tco/tcocalc.py
72
73
74
75
76
77
78
79
80
81
82
def calculate_capital_costs(self, vehicle: Vehicle, scenario: Scenario) -> None:
    """
    Calculates the capital costs.

    Args:
        vehicle (Vehicle): The vehicle instance.
        scenario (Scenario): The scenario instance.
    """
    self.cap_costs_dol = CapitalCosts(
        vehicle=vehicle, scenario=scenario, msrp_total_dol=scenario.msrp_total_dol
    )

calculate_opportunity_costs(vehicle, scenario, energy)

Calculates the opportunity costs.

Parameters:

Name Type Description Default
vehicle Vehicle

The vehicle instance.

required
scenario Scenario

The scenario instance.

required
energy Energy

The energy instance.

required
Source code in src/t3co/tco/tcocalc.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
def calculate_opportunity_costs(
    self, vehicle: Vehicle, scenario: Scenario, energy: Energy
) -> None:
    """
    Calculates the opportunity costs.

    Args:
        vehicle (Vehicle): The vehicle instance.
        scenario (Scenario): The scenario instance.
        energy (Energy): The energy instance.
    """
    self.oppy_costs_dol = OpportunityCosts(
        year_number=self.year_number,
        vehicle=vehicle,
        scenario=scenario,
        energy=energy,
    )

calculate_operating_costs(vehicle, scenario, energy)

Calculates the operating costs.

Parameters:

Name Type Description Default
vehicle Vehicle

The vehicle instance.

required
scenario Scenario

The scenario instance.

required
energy Energy

The energy instance.

required
Source code in src/t3co/tco/tcocalc.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def calculate_operating_costs(
    self, vehicle: Vehicle, scenario: Scenario, energy: Energy
) -> None:
    """
    Calculates the operating costs.

    Args:
        vehicle (Vehicle): The vehicle instance.
        scenario (Scenario): The scenario instance.
        energy (Energy): The energy instance.
    """
    self.oper_costs_dol = OperatingCosts(
        year_number=self.year_number,
        cap_costs=self.cap_costs_dol,
        vehicle=vehicle,
        scenario=scenario,
        energy=energy,
        oppy_costs=self.oppy_costs_dol,
    )

set_total_cost(scenario)

Sets the total cost for the year.

Parameters:

Name Type Description Default
scenario Scenario

The scenario instance.

required
Source code in src/t3co/tco/tcocalc.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
def set_total_cost(self, scenario: Scenario) -> None:
    """
    Sets the total cost for the year.

    Args:
        scenario (Scenario): The scenario instance.
    """
    self.total_cost_dol_per_yr = (
        (self.cap_costs_dol.net_capital_cost_dol if self.year_number == 1 else 0)
        + self.oper_costs_dol.net_oper_cost_dol_per_yr
        + self.oppy_costs_dol.net_downtime_oppy_cost_dol_per_yr
        + (
            self.cap_costs_dol.residual_cost_dol
            if self.year_number == scenario.vehicle_life_yr
            else 0
        )
    )

set_disc_total_cost(vehicle, scenario, payload_cap_cost_multiplier=None, TCO_switch='DIRECT')

Sets the discounted total cost for the year.

Parameters:

Name Type Description Default
vehicle Vehicle

The vehicle instance.

required
scenario Scenario

The scenario instance.

required
payload_cap_cost_multiplier float

Payload capacity cost multiplier. Defaults to None.

None
TCO_switch str

TCO calculation method. Defaults to "DIRECT".

'DIRECT'
Source code in src/t3co/tco/tcocalc.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def set_disc_total_cost(
    self,
    vehicle: Vehicle,
    scenario: Scenario,
    payload_cap_cost_multiplier: float = None,
    TCO_switch="DIRECT",
) -> None:
    """
    Sets the discounted total cost for the year.

    Args:
        vehicle (Vehicle): The vehicle instance.
        scenario (Scenario): The scenario instance.
        payload_cap_cost_multiplier (float, optional): Payload capacity cost multiplier. Defaults to None.
        TCO_switch (str, optional): TCO calculation method. Defaults to "DIRECT".
    """
    if (
        payload_cap_cost_multiplier is not None
        and not self.oppy_costs_dol.payload_cap_cost_multiplier
    ):
        self.oppy_costs_dol.payload_cap_cost_multiplier = (
            payload_cap_cost_multiplier
        )
    elif self.oppy_costs_dol.payload_cap_cost_multiplier:
        pass
    else:
        self.oppy_costs_dol.set_payload_cap_cost_multiplier(
            vehicle=vehicle, scenario=scenario
        )

    if TCO_switch == "DIRECT":
        self.disc_total_cost_dol_per_yr = (
            self.oppy_costs_dol.payload_cap_cost_multiplier
            * (
                self.cap_costs_dol.net_capital_cost_dol
                + self.oper_costs_dol.disc_oper_cost_dol_per_yr
                + self.oppy_costs_dol.disc_downtime_oppy_cost_dol
            )
        )
        self.oppy_costs_dol.payload_capacity_cost_dol = (
            (self.oppy_costs_dol.payload_cap_cost_multiplier - 1)
            / self.oppy_costs_dol.payload_cap_cost_multiplier
            * self.disc_total_cost_dol_per_yr
        )

    elif TCO_switch == "EFFICIENCY":
        disc_VMT_sum = scenario.get_discounted_value(
            value=scenario.vmt[self.year_number - 1], year_number=self.year_number
        )

        downtime_efficiency = 1 / (
            1
            + scenario.avg_speed_mph
            * self.oppy_costs_dol.disc_downtime_oppy_cost_dol
            / disc_VMT_sum
        )
        self.disc_total_cost_dol_per_yr = (
            self.oppy_costs_dol.payload_cap_cost_multiplier
            * (
                (
                    self.cap_costs_dol.net_capital_cost_dol
                    + self.oper_costs_dol.disc_oper_cost_dol_per_yr
                )
                / downtime_efficiency
                + self.cap_costs_dol.residual_cost_dol
            )
        )
        self.oppy_costs_dol.disc_downtime_oppy_cost_dol = (
            self.cap_costs_dol.net_capital_cost_dol
            + self.oper_costs_dol.disc_oper_cost_dol_per_yr
            + self.oppy_costs_dol.disc_downtime_oppy_cost_dol
        ) * (1 / downtime_efficiency - 1)

        self.oppy_costs_dol.payload_capacity_cost_dol = (
            (self.oppy_costs_dol.payload_cap_cost_multiplier - 1)
            / self.oppy_costs_dol.payload_cap_cost_multiplier
            * self.disc_total_cost_dol_per_yr
        )

__str__()

Returns a string representation of the TCOCalc instance.

Returns:

Name Type Description
str str

String representation of the TCOCalc instance.

Source code in src/t3co/tco/tcocalc.py
219
220
221
222
223
224
225
226
def __str__(self) -> str:
    """
    Returns a string representation of the TCOCalc instance.

    Returns:
        str: String representation of the TCOCalc instance.
    """
    return obj_to_string(self)