% Create Energy Balance Output Report

%% calculate kinetic energy change and roadload losses
audit.energy_balance.KE_delta_kJ = audit.energy_balance.system_KE_kJ - audit.energy_balance.system_KE_kJ(1);

audit.energy_balance.gradient_loss_kJ   = audit.mech.vehicle.gradient_drag_neg_kJ;
audit.energy_balance.gradient_gain_kJ   = audit.mech.vehicle.gradient_drag_pos_kJ;

if vehicle.use_abc_roadload
    audit.energy_balance.roadload_loss_kJ   = audit.energy_balance.gradient_loss_kJ + audit.mech.vehicle.ABC_drag_neg_kJ;
else
    audit.energy_balance.aero_drag_loss_kJ  = audit.mech.vehicle.aerodynamic_drag_neg_kJ;
    audit.energy_balance.roadload_loss_kJ   = audit.energy_balance.aero_drag_loss_kJ + audit.energy_balance.gradient_loss_kJ + audit.energy_balance.rolling_resistance_loss_kJ;
end

%% calculate engine fuel and crankshaft energy
audit.energy_balance.eng_fuel_energy_in_kJ          = datalog.engine.fuel_consumed_g * engine.fuel.energy_density_MJpkg;
audit.energy_balance.eng_crankshaft_energy_out_kJ = audit.mech.engine.crankshaft_gross_kJ;

%% calculate stored energy change
if isfield(audit,'elec')
    try
        audit.energy_balance.stored_energy_delta_kJ = audit.elec.battery.energy_delta_kJ;
        audit.energy_balance.battery_loss_kJ        = audit.elec.battery.loss_kJ;
    catch
        audit.energy_balance.stored_energy_delta_kJ = audit.elec.battery_energy_delta_kJ;
        audit.energy_balance.battery_loss_kJ        = audit.elec.battery_loss_kJ;
    end
    audit.energy_balance.stored_energy_net_kJ   = audit.elec.battery_kJ;
    audit.energy_balance.stored_energy_delta_Wh = -audit.energy_balance.stored_energy_delta_kJ * 1000 / 3600;
else
    audit.energy_balance.stored_energy_delta_kJ = 0;
    audit.energy_balance.stored_energy_net_kJ   = 0;
    audit.energy_balance.stored_energy_delta_Wh = 0;
    audit.energy_balance.battery_loss_kJ        = 0;
end

%% calculate total energy consumed and total energy provided to driveline
audit.energy_balance.total_energy_in_kJ =   audit.energy_balance.eng_fuel_energy_in_kJ + ...
    max(0, -audit.energy_balance.stored_energy_delta_kJ) + ...
    max(0, -audit.energy_balance.KE_delta_kJ) + ...
    audit.energy_balance.gradient_gain_kJ;

% max(0, -audit.energy_balance.stored_energy_net_kJ) + ...
audit.energy_balance.net_energy_in_kJ = max(0, audit.energy_balance.eng_crankshaft_energy_out_kJ) + ...
    max(0, -audit.elec.battery_kJ) + ...
    max(0, -audit.energy_balance.KE_delta_kJ) + ...
    audit.energy_balance.gradient_gain_kJ;

%% calculate losses

% calc launch device losses ----------------------------------------------
if  isfield(audit.mech,'torque_converter')
    audit.mech.gearbox.pumploss_kJ = audit.mech.torque_converter.pumploss_kJ;
    audit.energy_balance.launch_device_loss_kJ = audit.mech.torque_converter.loss_kJ - audit.mech.torque_converter.pumploss_kJ;
elseif isfield(audit.mech,'dual_clutch')
    audit.mech.gearbox.pumploss_kJ = zeros(size(time));	% No Pump Losses
    audit.energy_balance.launch_device_loss_kJ = audit.mech.dual_clutch.loss_kJ - audit.mech.dual_clutch.input_torque_loss_kJ;  % dual_clutch.input_torque_loss_kJ are attributed to 'gearbox' losses
elseif isfield(audit.mech,'clutch')
    audit.mech.gearbox.pumploss_kJ = zeros(size(time));	% No Pump Losses
    audit.energy_balance.launch_device_loss_kJ = audit.mech.clutch.loss_kJ;
else
    error( 'Unknown launch device');
end

% calc gearbox losses ----------------------------------------------------
if isfield(audit.mech,'dual_clutch')
    audit.energy_balance.gearbox_loss_kJ = audit.mech.dual_clutch.input_torque_loss_kJ + ...
        audit.mech.gearbox1.loss_kJ + ...
        audit.mech.gearbox1.inertia_KE_loss_kJ + ...
        audit.mech.gearbox1.inertia_spinup_loss_kJ + ...
        audit.mech.gearbox2.loss_kJ + ...
        audit.mech.gearbox2.inertia_KE_loss_kJ + ...
        audit.mech.gearbox2.inertia_spinup_loss_kJ;
else
    audit.energy_balance.gearbox_loss_kJ = audit.mech.gearbox.loss_kJ + ...
        audit.mech.gearbox.pumploss_kJ + ...
        audit.mech.gearbox.inertia_KE_loss_kJ + ...
        audit.mech.gearbox.inertia_spinup_loss_kJ;
end

% calc  battery and accessory losses -------------------------------------
audit.energy_balance.battery_charge_gain_kJ = max(0, audit.energy_balance.stored_energy_delta_kJ(end));


audit.energy_balance.accessory_loss_kJ = ...
    audit.mech.accessories.total_neg_kJ + ...
    audit.mech.starter.loss_kJ + ...
    audit.mech.alternator.loss_kJ + ...
    audit.elec.accessories.total_kJ + ...
    max(0, audit.energy_balance.stored_energy_net_kJ);




% calc axles losses ------------------------------------------------------
%audit.energy_balance.tire_loss_kJ = (audit.mech.drive_axle1.tire.input_pos_kJ - audit.mech.drive_axle1.tire.output_pos_kJ) + ...
%    (audit.mech.drive_axle1.tire.output_neg_kJ - audit.mech.drive_axle1.tire.input_neg_kJ);

audit.energy_balance.tire_loss_kJ      = audit.mech.drive_axle1.tire.loss_kJ;

audit.energy_balance.driveline_loss_kJ = audit.energy_balance.launch_device_loss_kJ + ...
    audit.energy_balance.gearbox_loss_kJ + ...
    audit.energy_balance.prop_axle_loss_kJ + ...
    audit.energy_balance.tire_loss_kJ;

if	isfield(audit.mech.gearbox,'inertia_brake_kJ')      % add audit for AMT inertia brake...
    audit.energy_balance.driveline_loss_kJ = audit.energy_balance.driveline_loss_kJ + audit.mech.gearbox.inertia_brake_kJ;
end

if isfield(audit.mech,'transfer_case')      % Add transfer case if present
    audit.energy_balance.driveline_loss_kJ = audit.energy_balance.driveline_loss_kJ + audit.mech.transfer_case.loss_kJ;
end

if isfield(audit.mech,'driveshaft')         % Add driveshaft if present
    audit.energy_balance.driveline_loss_kJ = audit.energy_balance.driveline_loss_kJ + audit.mech.driveshaft.loss_kJ;
end

% calc total losses ------------------------------------------------------
audit.energy_balance.total_loss_kJ = audit.energy_balance.accessory_loss_kJ + audit.energy_balance.driveline_loss_kJ + audit.energy_balance.brake_loss_kJ + audit.energy_balance.roadload_loss_kJ + max(0, audit.energy_balance.KE_delta_kJ) + max(0, -audit.energy_balance.eng_crankshaft_energy_out_kJ);

audit.energy_balance.simulation_error_kJ       = audit.energy_balance.net_energy_in_kJ - audit.energy_balance.total_loss_kJ;
audit.energy_balance.energy_conservation_pct   = audit.energy_balance.total_loss_kJ ./ audit.energy_balance.net_energy_in_kJ * 100;

%% generate audit printout
if exist('REVS','var') && REVS.verbose
    if isfield(REVS,'output_fid')
        output_fid = REVS.output_fid;
    else
        output_fid = 1;
    end

    fprintf(output_fid,'\n-- Audit data for %s drive cycle --\n\n',drive_cycle.name);
    fprintf(output_fid, '\n         ---- Energy Audit Report ----\n');
    fprintf(output_fid,'Total Energy Consumed            = %8.2f kJ\n', audit.energy_balance.total_energy_in_kJ(end));
    fprintf(output_fid,'    Fuel Energy                  = %8.2f kJ\n', audit.energy_balance.eng_fuel_energy_in_kJ(end));
    fprintf(output_fid,'    Stored Energy                = %8.2f kJ\n', max(0, -audit.energy_balance.stored_energy_delta_kJ(end)));
    fprintf(output_fid,'         Battery Internal Losses = %8.2f kJ  %8.2f%%\n', audit.energy_balance.battery_loss_kJ(end), audit.energy_balance.battery_loss_kJ(end) / audit.energy_balance.total_energy_in_kJ(end)*100);
    
    fprintf(output_fid,'    Kinetic Energy               = %8.2f kJ\n', max(0, -audit.energy_balance.KE_delta_kJ(end)));
    fprintf(output_fid,'    Potential Energy             = %8.2f kJ\n\n', audit.energy_balance.gradient_gain_kJ(end));
    
    fprintf(output_fid,'Usable System Energy Provided    = %8.2f kJ\n', audit.energy_balance.net_energy_in_kJ(end));
    fprintf(output_fid,'    Engine Energy                = %8.2f kJ\n', audit.energy_balance.eng_crankshaft_energy_out_kJ(end));
    fprintf(output_fid,'         Engine Efficiency       = %8.2f %%\n', max(0, audit.energy_balance.eng_crankshaft_energy_out_kJ(end) / audit.energy_balance.eng_fuel_energy_in_kJ(end) * 100));
    fprintf(output_fid,'    Stored Energy                = %8.2f kJ\n', max(0, -audit.energy_balance.stored_energy_net_kJ(end)));
    fprintf(output_fid,'    Kinetic Energy               = %8.2f kJ\n', max(0, -audit.energy_balance.KE_delta_kJ(end)));
    fprintf(output_fid,'    Potential Energy             = %8.2f kJ\n\n', audit.energy_balance.gradient_gain_kJ(end));
    if vehicle.use_abc_roadload
        fprintf(output_fid,'Energy Consumed by ABC roadload  = %8.2f kJ  %8.2f%%\n', audit.energy_balance.roadload_loss_kJ(end) - audit.energy_balance.gradient_loss_kJ(end), (audit.energy_balance.roadload_loss_kJ(end) - audit.energy_balance.gradient_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    else
        fprintf(output_fid,'Energy Consumed by Crr           = %8.2f kJ  %8.2f%%\n', audit.energy_balance.rolling_resistance_loss_kJ(end),(audit.energy_balance.rolling_resistance_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
        fprintf(output_fid,'Energy Consumed by Cd            = %8.2f kJ  %8.2f%%\n', audit.energy_balance.aero_drag_loss_kJ(end),(audit.energy_balance.aero_drag_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    end
    fprintf(output_fid,'Energy Consumed by gradient      = %8.2f kJ  %8.2f%%\n', audit.energy_balance.gradient_loss_kJ(end),(audit.energy_balance.gradient_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid,'Energy Consumed by brakes        = %8.2f kJ  %8.2f%%\n', audit.energy_balance.brake_loss_kJ(end),(audit.energy_balance.brake_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid,'Energy Consumed by Accessories   = %8.2f kJ  %8.2f%%\n', audit.energy_balance.accessory_loss_kJ(end),(audit.energy_balance.accessory_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Starter                      = %8.2f kJ  %8.2f%%\n', audit.mech.starter.loss_kJ(end), audit.mech.starter.loss_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Alternator                   = %8.2f kJ  %8.2f%%\n', audit.mech.alternator.loss_kJ(end), audit.mech.alternator.loss_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Battery Stored Charge        = %8.2f kJ  %8.2f%%\n', max(0, audit.energy_balance.stored_energy_net_kJ(end)), max(0, audit.energy_balance.stored_energy_net_kJ(end)) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Engine Fan                   = %8.2f kJ  %8.2f%%\n', (audit.mech.accessories.fan_neg_kJ(end) + audit.elec.accessories.fan_kJ(end)), (audit.mech.accessories.fan_neg_kJ(end) + audit.elec.accessories.fan_kJ(end)) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Electrical              = %8.2f kJ  %8.2f%%\n', audit.elec.accessories.fan_kJ(end), audit.elec.accessories.fan_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Mechanical              = %8.2f kJ  %8.2f%%\n', audit.mech.accessories.fan_neg_kJ(end), audit.mech.accessories.fan_neg_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Power Steering               = %8.2f kJ  %8.2f%%\n', (audit.mech.accessories.power_steering_neg_kJ(end) + audit.elec.accessories.power_steering_kJ(end)), (audit.mech.accessories.power_steering_neg_kJ(end) + audit.elec.accessories.power_steering_kJ(end)) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Electrical              = %8.2f kJ  %8.2f%%\n', audit.elec.accessories.power_steering_kJ(end), audit.elec.accessories.power_steering_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Mechanical              = %8.2f kJ  %8.2f%%\n', audit.mech.accessories.power_steering_neg_kJ(end), audit.mech.accessories.power_steering_neg_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Air Conditioning             = %8.2f kJ  %8.2f%%\n', (audit.mech.accessories.air_conditioner_neg_kJ(end) + audit.elec.accessories.air_conditioner_kJ(end)), (audit.mech.accessories.air_conditioner_neg_kJ(end) + audit.elec.accessories.air_conditioner_kJ(end)) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Electrical              = %8.2f kJ  %8.2f%%\n', audit.elec.accessories.air_conditioner_kJ(end), audit.elec.accessories.air_conditioner_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Mechanical              = %8.2f kJ  %8.2f%%\n', audit.mech.accessories.air_conditioner_neg_kJ(end), audit.mech.accessories.air_conditioner_neg_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Generic Loss                 = %8.2f kJ  %8.2f%%\n', (audit.mech.accessories.generic_loss_neg_kJ(end) + audit.elec.accessories.generic_loss_kJ(end)), (audit.mech.accessories.generic_loss_neg_kJ(end) + audit.elec.accessories.generic_loss_kJ(end)) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Electrical              = %8.2f kJ  %8.2f%%\n', audit.elec.accessories.generic_loss_kJ(end), audit.elec.accessories.generic_loss_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '         Mechanical              = %8.2f kJ  %8.2f%%\n', audit.mech.accessories.generic_loss_neg_kJ(end), audit.mech.accessories.generic_loss_neg_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Total Electrical Accessories = %8.2f kJ  %8.2f%%\n', audit.elec.accessories.total_kJ(end), audit.elec.accessories.total_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid, '    Total Mechanical Accessories = %8.2f kJ  %8.2f%%\n', audit.mech.accessories.total_neg_kJ(end), audit.mech.accessories.total_neg_kJ(end) / audit.energy_balance.total_loss_kJ(end)*100);
    
    
    fprintf(output_fid,'Energy Consumed by Driveline     = %8.2f kJ  %8.2f%%\n', audit.energy_balance.driveline_loss_kJ(end), audit.energy_balance.driveline_loss_kJ(end)/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid,'     Launch Device               = %8.2f kJ  %8.2f%%\n', audit.energy_balance.launch_device_loss_kJ(end), audit.energy_balance.launch_device_loss_kJ(end)/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid,'     Gearbox                     = %8.2f kJ  %8.2f%%\n', audit.energy_balance.gearbox_loss_kJ(end), audit.energy_balance.gearbox_loss_kJ(end)/audit.energy_balance.total_loss_kJ(end)*100);
    
    try
        fprintf(output_fid,'         Pump Loss               = %8.2f kJ  %8.2f%%\n', audit.mech.gearbox.pumploss_kJ(end), audit.mech.gearbox.pumploss_kJ(end)/audit.energy_balance.total_loss_kJ(end)*100);
        fprintf(output_fid,'         Spin Loss               = %8.2f kJ  %8.2f%%\n', audit.mech.gearbox.input_torque_loss_kJ(end) + audit.mech.gearbox.output_torque_loss_kJ(end), (audit.mech.gearbox.input_torque_loss_kJ(end) + audit.mech.gearbox.output_torque_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
        fprintf(output_fid,'         Gear/Inertia Loss       = %8.2f kJ  %8.2f%%\n', audit.energy_balance.gearbox_loss_kJ(end) - audit.mech.gearbox.pumploss_kJ(end) - audit.mech.gearbox.input_torque_loss_kJ(end) - audit.mech.gearbox.output_torque_loss_kJ(end),(audit.energy_balance.gearbox_loss_kJ(end) - audit.mech.gearbox.pumploss_kJ(end) - audit.mech.gearbox.input_torque_loss_kJ(end) - audit.mech.gearbox.output_torque_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    end
    
    fprintf(output_fid,'     Final Drive                 = %8.2f kJ  %8.2f%%\n', audit.energy_balance.prop_axle_loss_kJ(end),(audit.energy_balance.prop_axle_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid,'     Tire Slip                   = %8.2f kJ  %8.2f%%\n', audit.energy_balance.tire_loss_kJ(end),(audit.energy_balance.tire_loss_kJ(end))/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid,'Net System Kinetic Energy Change = %8.2f kJ  %8.2f%%\n', max(0, audit.energy_balance.KE_delta_kJ(end)),(max(0, audit.energy_balance.KE_delta_kJ(end)))/audit.energy_balance.total_loss_kJ(end)*100);
    fprintf(output_fid,'                                    ------------\n');
    fprintf(output_fid,'Total Loss Energy                = %8.2f kJ\n', audit.energy_balance.total_loss_kJ(end));
    fprintf(output_fid,'Simulation Error                 = %8.2f kJ\n', audit.energy_balance.simulation_error_kJ(end));
    fprintf(output_fid,'Energy Conservation              = %8.3f %%\n', audit.energy_balance.energy_conservation_pct(end));
    fprintf(output_fid,'\n');
    
    %    fplothg(time, audit.energy_balance.net_energy_in_kJ - audit.energy_balance.total_loss_kJ,'m.-');   % plot simulation error energy
    
end

%% export energy balance data to results array:
temp.fnames = fields(audit.energy_balance);

% for f = 1:length(temp.fnames)
%     evalin('base',['results(REVS.simulation_index).' temp.fnames{f} ' = audit.energy_balance.' temp.fnames{f} '(end);']);
% end
% clear f;

clear temp;
