> ## Documentation Index
> Fetch the complete documentation index at: https://docs.models.dunsky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# EVA adoption and charging specification

> Define EVA availability, ownership economics, diffusion calibration, drivetrain competition, mandates, stock accounting, charging and load contracts.

EVA has adoption, charging and load modes. Adoption combines market potentials into BEV/PHEV sales and stock; charging evaluates infrastructure constraints; load delegates transportation demand calculations to the End-Use Load package.

## Input and dimensional contract

`AdoptionInputs` combines scenarios, availability options, economic trajectories, calibration settings, charging constraints, vehicle-fleet collections and initial cumulative car sales. Option names selected by a `Scenario` must exist in the corresponding dictionaries. Arrays and year indices must align by vehicle subsegment, drivetrain and scenario. BEV, PHEV and ICE identifiers must match the model constants.

Use fractions for shares, years for lifetime and market age, currency for vehicle costs, currency per corresponding energy unit for rates, distance/year for travel and energy/distance for efficiency. Battery kWh divided by kWh/distance produces range; battery kWh divided by charging kW produces hours. The implementation generally performs arithmetic on supplied units rather than converting labels. Fields without declared defaults are required constructor arguments, not automatically inferred workbook values.

## Availability

For local availability $l_y$, define $\bar l_0=l_0$ and $\bar l_y=(l_y+l_{y-1})/2$ thereafter:

$$
L_y=1-(1-\bar l_y)^2
$$

Global availability categories map through `GLOBAL_AVAILABILITY_FACTORS`; unrecognized/missing values are filled as implemented by the conversion. Numeric factors become:

$$
G'_y=\frac{2}{1+e^{-0.7x_y}}-1
$$

For consecutive labelled years, $G_y=(G_{y-1}+G'_y)/2$. This is recursive smoothing using the already modified previous value, not a two-point mean of the original series.

## Upfront and ownership economics

Purchase price is rounded to the nearest hundred after adding the scenario battery cost. Upfront cost subtracts EV incentives and adds home charging costs. ICE battery adders and EV incentives are zeroed in that branch.

For purchase year $y$ and supplied lifetime $L_y$, annual maintenance and energy are summed from array position $y$ through the position before $y+L_y$, truncated at available data. There is no discounting. BEV energy cost is rate × electric efficiency × distance. ICE uses fuel rate × ICE efficiency × distance. PHEV combines electric cost and ICE fuel cost using its electric driving fraction. Compare each EV with ICE to obtain incremental upfront cost $x$ and incremental ownership cost $z$.

$$
U_+(x)=1.004545455-0.000400507x+6.06498\!\times\!10^{-8}x^2-3.63054\!\times\!10^{-12}x^3+6.11888\!\times\!10^{-17}x^4
$$

For $x>11020$, the positive-cost response is zero. For $x<0$:

$$
U_-(x)=1.005244755-3.90346\!\times\!10^{-5}x-7.8817\!\times\!10^{-9}x^2-5.07964\!\times\!10^{-12}x^3-2.18531\!\times\!10^{-16}x^4
$$

Clip the applicable upfront response to $[0,1]$. Ownership response is $T(z)=\operatorname{clip}(0.4936-0.00003z+10^{-10}z^2,0.08,1)$. With ownership weight $w$:

$$
P^{economic}_y=\min(1,(1-w_y)U(x_y)+w_yT(z_y))
$$

The response is behavioural, not a least-cost purchase constraint. The 0.08 floor applies to the ownership response only.

## Diffusion and calibration

For a cohort beginning at $c$, the Bass kernel is $B_c(t)=[1-e^{-(p_c+q_c)(t-c)}]/[1+(q_c/p_c)e^{-(p_c+q_c)(t-c)}]$. The code forms multiple cohort curves, differences their consecutive values for the annual component, adds a historical component shifted by `t0`, and caps the combined result at one. Scenario market adders modify $q$ before curve construction. Do not replace this sequence with one cumulative Bass curve.

Optional calibration minimizes the square root of weighted squared errors for historical BEV and PHEV sales divided by the historical PHEV series length. Innovation parameters have bounds 0.001 to 0.01; imitation parameters 0.1 to 1; six binary selectors represent candidate initial market ages 1 to 6; the two imitation values differ by at most 0.1. The implementation uses IPOPT and rounds the resulting age when creating forecast parameters. Solver availability and a returned solution do not establish global optimality or exact integer feasibility; inspect calibration outputs and fit. Calibration mutates the inputs' scenario/parameter selections, so isolate inputs when reusing them across runs.

## Charging range and time response

BEV range is $R=B/e$. DCFC time is $t_c=Bd_c/P$ for charging-depth fraction $d_c$ and charger output $P$. With desired range $R^*$ and desired charging-time input $t^*$:

$$
P_R=\min\left(\frac{100R/(R^*-40)-30.1829}{100},1\right),\qquad P_t=\min(0.8131(t_c+t^*)^{-0.4545},1)
$$

The intermediary BEV charging potential is $(P_R+P_t)/2$; PHEV is one at this stage. The range response has no lower clipping here and is singular at desired range 40. Charging power must be positive. Infrastructure stages then compare public energy demand, usable port capacity and corridor coverage; home charging is excluded from the public-cluster sum and PHEV cluster accounting uses L2. A demand array containing any zero is skipped in the relevant cluster accumulation.

### Public infrastructure constraints

For port-count constraints, sum selected actual-port / unconstrained-port ratios across eligible location/level pairs and cap the total at one. BEV includes eligible L2 and DCFC; PHEV includes L2. Skip a ratio array if any unconstrained-port value is zero. The energy-capacity alternative sums usable public charging energy and divides by summed daily public demand, capped at one.

Required corridor ports are highway length / ideal spacing. With second-gas-car fraction $a$ and selected DCFC port count $N$, corridor potential is $\min(1,a+(1-a)N/N_{required})$. Final BEV charging potential multiplies intermediary range/time potential × cluster potential × corridor potential. For PHEV, the application branch replaces the value with the elementwise maximum of cluster potential and that vehicle type's economic potential. These stages therefore do not apply the same formula to both drivetrains.

## Competition, mandates and smoothing

For each drivetrain, multiply the included potentials and cap at one to obtain pre-competition shares $b$ and $p$. The combined EV market $V$ is formed by multiplying the maximum BEV/PHEV value of each availability/economic/charging factor, with diffusion included when present, then capping at one.

$$
b'=\max\left(\frac{b}{b+p}V,b\right),\qquad p'=V-b'
$$

A zero $b+p$ uses a missing denominator in the implementation; no independent fallback is inserted by this specification. For mandate $m$ and post-competition drivetrain share $s$, the adjusted share is $\max(s,ms/(b'+p'))$, with the proportional term zero if the denominator is zero.

Normally apply a centred three-year mean with at least one observation. For a positive mandate, use the mandate-adjusted share directly instead of the smoothed value. Annual sales are rounded share × total annual vehicle sales. This order matters: smoothing after rounding does not reproduce outputs.

## Vehicle stock and reporting

Cumulative EV sales are grouped by vehicle type/drivetrain and include configured initial car sales. For reporting year $y$, subtract annual modelled sales with year $\le y-L_y$ if that target year occurs in the input year vector. This is a reporting-year lifetime rule, not a separate survival distribution for each purchase cohort. Initial stock is not aged out by that subtraction of modelled sales.

Stock share divides adjusted cumulative EV sales by the selected total cumulative vehicle fleet. Reporting aggregates vehicle types and reconstructs percentage denominators from the scenario-selected total fleets. Preserve scenario, potential type, measure, vehicle type, drivetrain and year when joining outputs. Intermediary willingness, pre/post-competition shares, annual sales/share and stock/share have different meanings.

Load mode calls `eul.transportation.ev_load_forecast` for each scenario, defaulting to hourly granularity and weekday/weekend and summer/winter mappings. The actual load/temperature schema belongs to that dependency and is not inferred from adoption percentages. A complete independent specification of EUL requires its own package specification.

## Validation and failure boundaries

Verify zero/one potential cases, polynomial bounds, horizon truncation, zero competition denominators, mandate years, centred-window endpoints, stock retirements and calibration residuals. For 10,000 total sales and final share 0.20, rounded EV sales are 2,000. At zero ownership-cost difference, the ownership response is 0.4936 before weighting, not one.

Existing tests cover availability, diffusion, economic response, input reading, adoption/load integration and subprocess execution. They do not establish out-of-sample forecast accuracy. Missing option keys or incompatible array lengths can raise lookup/alignment errors; monetary coefficients must not be used with a different cost scale without recalibration.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.