Created
June 14, 2025 20:10
-
-
Save nknighta/bac0b35d5e57db5ff45d3b65501d7818 to your computer and use it in GitHub Desktop.
engine simulator script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import "engine_sim.mr" | |
units units() | |
constants constants() | |
impulse_response_library ir_lib() | |
label cycle(2 * 360 * units.deg) | |
private node wires { | |
output wire1: ignition_wire(); | |
output wire2: ignition_wire(); | |
output wire3: ignition_wire(); | |
output wire4: ignition_wire(); | |
output wire5: ignition_wire(); | |
output wire6: ignition_wire(); | |
output wire7: ignition_wire(); | |
output wire8: ignition_wire(); | |
} | |
private node v10_72_head { | |
input intake_camshaft; | |
input exhaust_camshaft; | |
input chamber_volume: 1.5 * 25 * units.cc; | |
input intake_runner_volume: 149.6 * units.cc; | |
input intake_runner_cross_section_area: 1.75 * units.inch * 1.75 * units.inch; | |
input exhaust_runner_volume: 50.0 * units.cc; | |
input exhaust_runner_cross_section_area: 2.5 * units.inch * 2.5 * units.inch; | |
input flow_attenuation: 1.0; | |
input lift_scale: 1.0; | |
input flip_display: false; | |
alias output __out: head; | |
function intake_flow(50 * units.thou) | |
intake_flow | |
.add_flow_sample(0 * lift_scale, 0 * flow_attenuation) | |
.add_flow_sample(50 * lift_scale, 58 * flow_attenuation) | |
.add_flow_sample(100 * lift_scale, 103 * flow_attenuation) | |
.add_flow_sample(150 * lift_scale, 156 * flow_attenuation) | |
.add_flow_sample(200 * lift_scale, 214 * flow_attenuation) | |
.add_flow_sample(250 * lift_scale, 249 * flow_attenuation) | |
.add_flow_sample(300 * lift_scale, 268 * flow_attenuation) | |
.add_flow_sample(350 * lift_scale, 280 * flow_attenuation) | |
.add_flow_sample(400 * lift_scale, 280 * flow_attenuation) | |
.add_flow_sample(450 * lift_scale, 281 * flow_attenuation) | |
function exhaust_flow(50 * units.thou) | |
exhaust_flow | |
.add_flow_sample(0 * lift_scale, 0 * flow_attenuation) | |
.add_flow_sample(50 * lift_scale, 37 * flow_attenuation) | |
.add_flow_sample(100 * lift_scale, 72 * flow_attenuation) | |
.add_flow_sample(150 * lift_scale, 113 * flow_attenuation) | |
.add_flow_sample(200 * lift_scale, 160 * flow_attenuation) | |
.add_flow_sample(250 * lift_scale, 196 * flow_attenuation) | |
.add_flow_sample(300 * lift_scale, 222 * flow_attenuation) | |
.add_flow_sample(350 * lift_scale, 235 * flow_attenuation) | |
.add_flow_sample(400 * lift_scale, 245 * flow_attenuation) | |
.add_flow_sample(450 * lift_scale, 246 * flow_attenuation) | |
generic_cylinder_head head( | |
chamber_volume: chamber_volume, | |
intake_runner_volume: intake_runner_volume, | |
intake_runner_cross_section_area: intake_runner_cross_section_area, | |
exhaust_runner_volume: exhaust_runner_volume, | |
exhaust_runner_cross_section_area: exhaust_runner_cross_section_area, | |
intake_port_flow: intake_flow, | |
exhaust_port_flow: exhaust_flow, | |
valvetrain: standard_valvetrain( | |
intake_camshaft: intake_camshaft, | |
exhaust_camshaft: exhaust_camshaft | |
), | |
flip_display: flip_display | |
) | |
} | |
private node v10_72_camshaft { | |
input lobe_profile; | |
input intake_lobe_profile: lobe_profile; | |
input exhaust_lobe_profile: lobe_profile; | |
input lobe_separation: 114 * units.deg; | |
input intake_lobe_center: lobe_separation; | |
input exhaust_lobe_center: lobe_separation; | |
input advance: 0 * units.deg; | |
input base_radius: 0.5 * units.inch; | |
output intake_cam_0: _intake_cam_0; | |
output exhaust_cam_0: _exhaust_cam_0; | |
output intake_cam_1: _intake_cam_1; | |
output exhaust_cam_1: _exhaust_cam_1; | |
camshaft_parameters params ( | |
advance: advance, | |
base_radius: base_radius | |
) | |
camshaft _intake_cam_0(params, lobe_profile: intake_lobe_profile) | |
camshaft _exhaust_cam_0(params, lobe_profile: exhaust_lobe_profile) | |
camshaft _intake_cam_1(params, lobe_profile: intake_lobe_profile) | |
camshaft _exhaust_cam_1(params, lobe_profile: exhaust_lobe_profile) | |
label rot(72 * units.deg) | |
label rot360(360 * units.deg) | |
// 1 2 3 4 7 8 9 10 5 6 | |
_exhaust_cam_0 | |
.add_lobe(rot360 - exhaust_lobe_center + 0 * rot) // 1 | |
.add_lobe(rot360 - exhaust_lobe_center + 2 * rot) // 3 | |
.add_lobe(rot360 - exhaust_lobe_center + 8 * rot) // 5 | |
.add_lobe(rot360 - exhaust_lobe_center + 4 * rot) // 7 | |
.add_lobe(rot360 - exhaust_lobe_center + 6 * rot) // 9 | |
_intake_cam_0 | |
.add_lobe(rot360 + intake_lobe_center + 0 * rot) // 1 | |
.add_lobe(rot360 + intake_lobe_center + 2 * rot) // 3 | |
.add_lobe(rot360 + intake_lobe_center + 8 * rot) // 5 | |
.add_lobe(rot360 + intake_lobe_center + 4 * rot) // 7 | |
.add_lobe(rot360 + intake_lobe_center + 6 * rot) // 9 | |
_exhaust_cam_1 | |
.add_lobe(rot360 - exhaust_lobe_center + 1 * rot) // 2 | |
.add_lobe(rot360 - exhaust_lobe_center + 3 * rot) // 4 | |
.add_lobe(rot360 - exhaust_lobe_center + 9 * rot) // 6 | |
.add_lobe(rot360 - exhaust_lobe_center + 5 * rot) // 8 | |
.add_lobe(rot360 - exhaust_lobe_center + 7 * rot) // 10 | |
_intake_cam_1 | |
.add_lobe(rot360 + intake_lobe_center + 1 * rot) // 2 | |
.add_lobe(rot360 + intake_lobe_center + 3 * rot) // 4 | |
.add_lobe(rot360 + intake_lobe_center + 9 * rot) // 6 | |
.add_lobe(rot360 + intake_lobe_center + 5 * rot) // 8 | |
.add_lobe(rot360 + intake_lobe_center + 7 * rot) // 10 | |
} | |
public node lr_gue_v10 { | |
alias output __out: engine; | |
engine engine( | |
name: "AS408RS", | |
starter_torque: 150 * units.lb_ft, | |
starter_speed: 700 * units.rpm, | |
redline: 9400 * units.rpm, | |
throttle_gamma: 2.0, | |
fuel: fuel( | |
max_turbulence_effect: 10.0, | |
max_dilution_effect: 20.0, | |
burning_efficiency_randomness: 0.25, | |
max_burning_efficiency: 1.0 | |
), | |
hf_gain: 0.01, | |
noise: 1.0, | |
jitter: 0.1, | |
simulation_frequency: 6500 | |
) | |
wires wires() | |
label stroke(68 * units.mm) | |
label bore(100 * units.mm) | |
label rod_length(125 * units.mm) | |
label rod_mass(60 * units.g) | |
label compression_height(1.0 * units.inch) | |
label crank_mass(40 * units.lb) | |
label flywheel_mass(30 * units.lb) | |
label flywheel_radius(6.5 * units.inch) | |
label crank_moment( | |
disk_moment_of_inertia(mass: crank_mass, radius: stroke) | |
) | |
label flywheel_moment( | |
disk_moment_of_inertia(mass: flywheel_mass, radius: flywheel_radius) | |
) | |
label other_moment( // Moment from cams, pulleys, etc [estimated] | |
disk_moment_of_inertia(mass: 1 * units.kg, radius: 1.0 * units.cm) | |
) | |
label v_angle(80 * units.deg) | |
crankshaft c0( | |
throw: stroke / 2, | |
flywheel_mass: flywheel_mass, | |
mass: crank_mass, | |
friction_torque: 0.0 * units.lb_ft, | |
moment_of_inertia: | |
crank_moment + flywheel_moment + other_moment, | |
position_x: 0.0, | |
position_y: 0.0, | |
tdc: 90 * units.deg + (v_angle / 2.0) | |
) | |
// 72 degrees | |
rod_journal rj0(angle: 0 * v_angle) | |
rod_journal rj1(angle: 2 * v_angle) | |
rod_journal rj2(angle: 3 * v_angle) | |
rod_journal rj3(angle: 4 * v_angle) | |
rod_journal rj4(angle: 1 * v_angle) | |
c0 | |
.add_rod_journal(rj0) | |
.add_rod_journal(rj1) | |
.add_rod_journal(rj2) | |
.add_rod_journal(rj3) | |
.add_rod_journal(rj4) | |
piston_parameters piston_params( | |
mass: (100) * units.g, // 414 - piston mass, 152 - pin weight | |
compression_height: compression_height, | |
wrist_pin_position: 0.0, | |
displacement: 0.0 | |
) | |
connecting_rod_parameters cr_params( | |
mass: rod_mass, | |
moment_of_inertia: rod_moment_of_inertia( | |
mass: rod_mass, | |
length: rod_length | |
), | |
center_of_mass: 0.0, | |
length: rod_length | |
) | |
intake intake( | |
plenum_volume: 1.325 * units.L, | |
plenum_cross_section_area: 20.0 * units.cm2, | |
intake_flow_rate: k_carb(1000.0), | |
runner_flow_rate: k_carb(200.0), | |
runner_length: 4.0 * units.inch, | |
idle_flow_rate: k_carb(0.0), | |
idle_throttle_plate_position: 0.997, | |
velocity_decay: 0.5 | |
) | |
exhaust_system_parameters es_params( | |
outlet_flow_rate: k_carb(2000.0), | |
primary_tube_length: 50.0 * units.inch, | |
primary_flow_rate: k_carb(1000.0), | |
velocity_decay: 1.0 | |
) | |
exhaust_system exhaust0( | |
es_params, | |
audio_volume: 2.0, | |
length: 100 * units.inch, | |
impulse_response: ir_lib.mild_exhaust_0_reverb | |
) | |
exhaust_system exhaust1( | |
es_params, | |
audio_volume: 2.0, | |
length: 100.5 * units.inch, | |
impulse_response: ir_lib.mild_exhaust_0_reverb | |
) | |
cylinder_bank_parameters bank_params( | |
bore: bore, | |
deck_height: stroke / 2 + rod_length + compression_height | |
) | |
cylinder_bank b0(bank_params, angle: v_angle / 2.0) | |
cylinder_bank b1(bank_params, angle: -v_angle / 2.0) | |
b0 | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj0, | |
intake: intake, | |
exhaust_system: exhaust1, | |
ignition_wire: wires.wire1, | |
sound_attenuation: 0.8, | |
primary_length: 5 * units.cm | |
) | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj1, | |
intake: intake, | |
exhaust_system: exhaust1, | |
ignition_wire: wires.wire3, | |
sound_attenuation: 1.0, | |
primary_length: 4 * units.cm | |
) | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj2, | |
intake: intake, | |
exhaust_system: exhaust1, | |
ignition_wire: wires.wire5, | |
sound_attenuation: 1.1, | |
primary_length: 3 * units.cm | |
) | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj3, | |
intake: intake, | |
exhaust_system: exhaust1, | |
ignition_wire: wires.wire7, | |
sound_attenuation: 0.9, | |
primary_length: 2 * units.cm | |
) | |
.set_cylinder_head( | |
v10_72_head( | |
intake_camshaft: camshaft.intake_cam_0, | |
exhaust_camshaft: camshaft.exhaust_cam_0, | |
flip_display: true, | |
flow_attenuation: 1.5) | |
) | |
b1 | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj0, | |
intake: intake, | |
exhaust_system: exhaust0, | |
ignition_wire: wires.wire2, | |
sound_attenuation: 0.7, | |
primary_length: 5 * units.cm | |
) | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj1, | |
intake: intake, | |
exhaust_system: exhaust0, | |
ignition_wire: wires.wire4, | |
sound_attenuation: 0.8, | |
primary_length: 4 * units.cm | |
) | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj2, | |
intake: intake, | |
exhaust_system: exhaust0, | |
ignition_wire: wires.wire6, | |
primary_length: 3 * units.cm | |
) | |
.add_cylinder( | |
piston: piston(piston_params, blowby: k_28inH2O(0.0)), | |
connecting_rod: connecting_rod(cr_params), | |
rod_journal: rj3, | |
intake: intake, | |
exhaust_system: exhaust0, | |
ignition_wire: wires.wire8, | |
sound_attenuation: 1.1, | |
primary_length: 2 * units.cm | |
) | |
.set_cylinder_head( | |
v10_72_head( | |
intake_camshaft: camshaft.intake_cam_1, | |
exhaust_camshaft: camshaft.exhaust_cam_1, | |
flow_attenuation: 1.5) | |
) | |
engine | |
.add_cylinder_bank(b0) | |
.add_cylinder_bank(b1) | |
engine.add_crankshaft(c0) | |
harmonic_cam_lobe intake_lobe( | |
duration_at_50_thou: 230 * units.deg, | |
gamma: 1.1, | |
lift: 15.95 * units.mm, | |
steps: 100 | |
) | |
harmonic_cam_lobe exhaust_lobe( | |
duration_at_50_thou: 230 * units.deg, | |
gamma: 1.1, | |
lift: 15.95 * units.mm, | |
steps: 100 | |
) | |
v10_72_camshaft camshaft( | |
lobe_profile: "N/A", | |
intake_lobe_profile: intake_lobe, | |
exhaust_lobe_profile: exhaust_lobe, | |
intake_lobe_center: 110 * units.deg, | |
exhaust_lobe_center: 112 * units.deg, | |
base_radius: 0.9 * units.inch | |
) | |
function timing_curve(4000 * units.rpm) | |
timing_curve | |
.add_sample(0000 * units.rpm, 12 * units.deg) | |
.add_sample(4000 * units.rpm, 40 * units.deg) | |
.add_sample(8000 * units.rpm, 40 * units.deg) | |
.add_sample(12000 * units.rpm, 40 * units.deg) | |
.add_sample(14000 * units.rpm, 40 * units.deg) | |
.add_sample(18000 * units.rpm, 40 * units.deg) | |
ignition_module ignition_module( | |
timing_curve: timing_curve, | |
rev_limit: 9700 * units.rpm, | |
limiter_duration: 0.1) | |
ignition_module | |
.connect_wire(wires.wire1, 0 * 72 * units.deg) | |
.connect_wire(wires.wire2, 1 * 72 * units.deg) | |
.connect_wire(wires.wire3, 2 * 72 * units.deg) | |
.connect_wire(wires.wire4, 3 * 72 * units.deg) | |
.connect_wire(wires.wire7, 4 * 72 * units.deg) | |
.connect_wire(wires.wire8, 5 * 72 * units.deg) | |
.connect_wire(wires.wire5, 8 * 72 * units.deg) | |
.connect_wire(wires.wire6, 9 * 72 * units.deg) | |
engine.add_ignition_module(ignition_module) | |
} | |
private node s44 { | |
alias output __out: | |
vehicle( | |
mass: 1264 * units.kg, | |
drag_coefficient: 0.3, | |
cross_sectional_area: (72 * units.inch) * (50 * units.inch), | |
diff_ratio: 3.42, | |
tire_radius: 11 * units.inch, | |
rolling_resistance: 200 * units.N | |
); | |
} | |
private node lfa_transmission { | |
alias output __out: | |
transmission( | |
max_clutch_torque: 1100 * units.lb_ft | |
) | |
.add_gear(3.23) | |
.add_gear(2.19) | |
.add_gear(1.61) | |
.add_gear(1.23) | |
.add_gear(0.97) | |
.add_gear(0.83) | |
.add_gear(0.70); | |
} | |
public node main { | |
run( | |
engine: lr_gue_v10(), | |
vehicle: s44(), | |
transmission: lfa_transmission() | |
) | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment