Engine Simulatorの作法 その7

# 概要
Engine Simulatorの作法を調べてみた。
練習問題やってみた。

# 練習問題
単気筒の２サイクルエンジンを作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d9afd1e2-a0bb-0ba6-dbea-018eb975febf.png)


# サンプルコード

```
import "engine_sim.mr"
units units()
constants constants()
impulse_response_library ir_lib()

private node wires {
	output wire1: ignition_wire();
}
label cycle(2 * 360 * units.deg)

private node exhaust_cam_lobe_builder {
	alias output __out: _lobe_profile;
	function _lobe_profile(6 * units.deg)
		_lobe_profile
			.add_sample(-180 * units.deg, 9 * units.mm)
			.add_sample(-174 * units.deg, 8.9 * units.mm)
			.add_sample(-168 * units.deg, 0 * units.mm)
			.add_sample(-162 * units.deg, 0 * units.mm)
			.add_sample(-156 * units.deg, 0 * units.mm)
			.add_sample(-150 * units.deg, 0 * units.mm)
			.add_sample(-144 * units.deg, 0 * units.mm)
			.add_sample(-138 * units.deg, 0 * units.mm)
			.add_sample(-132 * units.deg, 0 * units.mm)
			.add_sample(-126 * units.deg, 0 * units.mm)
			.add_sample(-60 * units.deg, 0 * units.mm)
			.add_sample(-54 * units.deg, 0 * units.mm)
			.add_sample(-48 * units.deg, 0 * units.mm)
			.add_sample(-42 * units.deg, 0 * units.mm)
			.add_sample(-36 * units.deg, 0 * units.mm)
			.add_sample(-30 * units.deg, 0 * units.mm)
			.add_sample(-24 * units.deg, 0 * units.mm)
			.add_sample(-18 * units.deg, 0 * units.mm)
			.add_sample(-12 * units.deg, 8.5 * units.mm)
			.add_sample(-6 * units.deg, 8.9 * units.mm)
			.add_sample(0 * units.deg, 9 * units.mm)
			.add_sample(6 * units.deg, 8.9 * units.mm)
			.add_sample(12 * units.deg, 0 * units.mm)
			.add_sample(18 * units.deg, 0 * units.mm)
			.add_sample(24 * units.deg, 0 * units.mm)
			.add_sample(30 * units.deg, 0 * units.mm)
			.add_sample(36 * units.deg, 0 * units.mm)
			.add_sample(42 * units.deg, 0 * units.mm)
			.add_sample(48 * units.deg, 0 * units.mm)
			.add_sample(54 * units.deg, 0 * units.mm)
			.add_sample(60 * units.deg, 0 * units.mm)
			.add_sample(126 * units.deg, 0 * units.mm)
			.add_sample(132 * units.deg, 0 * units.mm)
			.add_sample(138 * units.deg, 0 * units.mm)
			.add_sample(144 * units.deg, 0 * units.mm)
			.add_sample(150 * units.deg, 0 * units.mm)
			.add_sample(156 * units.deg, 0 * units.mm)
			.add_sample(162 * units.deg, 0 * units.mm)
			.add_sample(168 * units.deg, 8.5 * units.mm)
			.add_sample(172 * units.deg, 8.9 * units.mm)
			.add_sample(180 * units.deg, 9 * units.mm)
}

private node intake_cam_lobe_builder {
	alias output __out: _lobe_profile;
	function _lobe_profile(6 * units.deg)
		_lobe_profile
			.add_sample(-180 * units.deg, 9 * units.mm)
			.add_sample(-174 * units.deg, 8.9 * units.mm)
			.add_sample(-168 * units.deg, 8.5 * units.mm)
			.add_sample(-162 * units.deg, 0 * units.mm)
			.add_sample(-156 * units.deg, 0 * units.mm)
			.add_sample(-150 * units.deg, 0 * units.mm)
			.add_sample(-144 * units.deg, 0 * units.mm)
			.add_sample(-138 * units.deg, 0 * units.mm)
			.add_sample(-132 * units.deg, 0 * units.mm)
			.add_sample(-126 * units.deg, 0 * units.mm)
			.add_sample(-60 * units.deg, 0 * units.mm)
			.add_sample(-54 * units.deg, 0 * units.mm)
			.add_sample(-48 * units.deg, 0 * units.mm)
			.add_sample(-42 * units.deg, 0 * units.mm)
			.add_sample(-36 * units.deg, 0 * units.mm)
			.add_sample(-30 * units.deg, 0 * units.mm)
			.add_sample(-24 * units.deg, 0 * units.mm)
			.add_sample(-18 * units.deg, 0 * units.mm)
			.add_sample(-12 * units.deg, 0 * units.mm)
			.add_sample(-6 * units.deg, 8.9 * units.mm)
			.add_sample(0 * units.deg, 9 * units.mm)
			.add_sample(6 * units.deg, 8.9 * units.mm)
			.add_sample(12 * units.deg, 8.5 * units.mm)
			.add_sample(18 * units.deg, 0 * units.mm)
			.add_sample(24 * units.deg, 0 * units.mm)
			.add_sample(30 * units.deg, 0 * units.mm)
			.add_sample(36 * units.deg, 0 * units.mm)
			.add_sample(42 * units.deg, 0 * units.mm)
			.add_sample(48 * units.deg, 0 * units.mm)
			.add_sample(54 * units.deg, 0 * units.mm)
			.add_sample(60 * units.deg, 0 * units.mm)
			.add_sample(126 * units.deg, 0 * units.mm)
			.add_sample(132 * units.deg, 0 * units.mm)
			.add_sample(138 * units.deg, 0 * units.mm)
			.add_sample(144 * units.deg, 0 * units.mm)
			.add_sample(150 * units.deg, 0 * units.mm)
			.add_sample(156 * units.deg, 0 * units.mm)
			.add_sample(162 * units.deg, 0 * units.mm)
			.add_sample(168 * units.deg, 0 * units.mm)
			.add_sample(172 * units.deg, 8.9 * units.mm)
			.add_sample(180 * units.deg, 9 * units.mm)
}
exhaust_cam_lobe_builder _exhaust_lobe()
intake_cam_lobe_builder _intake_lobe()

public node single_cyl_camshaft_builder {
	input intake_lobe_profile;
	input exhaust_lobe_profile;
	input lobe_separation: 0 * units.deg;
	input intake_lobe_center: lobe_separation;
	input exhaust_lobe_center: lobe_separation;
	input advance: -150 * units.deg;
	input base_radius: 16 * units.mm;
	output intake_cam_0: _intake_cam_0;
	output exhaust_cam_0: _exhaust_cam_0;
	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)
	label rot((360 / 1) * units.deg)
	label rot360(360 * units.deg)
	_exhaust_cam_0
		.add_lobe(rot360 - exhaust_lobe_center + 3 * rot)
		.add_lobe(rot360 - exhaust_lobe_center + 6 * rot)
	_intake_cam_0
		.add_lobe(rot360 + intake_lobe_center + 3 * rot)
		.add_lobe(rot360 + intake_lobe_center + 6 * rot)
}

public node vemsign {
	input wires;
	input timing_curve;
	input rev_limit: 13000 * units.rpm;
	alias output __out:
		ignition_module(timing_curve: timing_curve, rev_limit: rev_limit, limiter_duration: 0.04)
			.connect_wire(wires.wire1, (6 / 12.0) * cycle)
			.connect_wire(wires.wire1, (12 / 12.0) * cycle);
}

public node make {
	alias output __out: engine;
	engine engine(
		name: "test7 2st",
		starter_torque: 20 * units.lb_ft,
		starter_speed: 2500 * units.rpm,
		redline: 13000 * units.rpm,
		fuel: fuel(max_burning_efficiency: 1.2),
		hf_gain: 0.002,
		noise: 0.3,
		jitter: 0.4,
		simulation_frequency: 4000
	)
	wires wires()
	label throw(27.5)
	crankshaft c0(
		throw: throw * units.mm,
		flywheel_mass: 1.8 * units.kg,
		mass: 300 * units.g,
		friction_torque: 0.5 * units.lb_ft,
		moment_of_inertia: 0.22 * 0.2,
		position_x: 0,
		tdc: constants.pi / 2
	)
	rod_journal rj0(angle: 0 * units.deg)
	c0.add_rod_journal(rj0)
	piston_parameters piston_params(
		mass: 350 * units.g,
		compression_height: 10 * units.mm,
		wrist_pin_position: 0,
		displacement: 0
	)
	label rod_length(102)
	connecting_rod_parameters cr_params(
		mass: 300 * units.g,
		moment_of_inertia: 0.0015884918028487504,
		center_of_mass: 0.0,
		length: rod_length * units.mm
	)
	cylinder_bank_parameters bank_params(
		bore: 60 * units.mm,
		deck_height: ((throw) + rod_length + 12) * units.mm
	)
	intake intake1(
		plenum_volume: 0.2 * units.L,
		plenum_cross_section_area: 50 * units.cm2,
		intake_flow_rate: k_carb(600),
		idle_flow_rate: k_carb(0.1),
		idle_throttle_plate_position: 0.9978,
		velocity_decay: 0.1
	)
	exhaust_system_parameters exhaust_params(
		outlet_flow_rate: k_carb(600),
		primary_tube_length: 1500 * units.mm,
		primary_flow_rate: k_carb(150),
		velocity_decay: 0.2,
		volume: 5 * units.L
	)
	exhaust_system exhaust(
		exhaust_params,
		audio_volume: 0.5,
		impulse_response: ir_lib.mild_exhaust_0_reverb
	)
	cylinder_bank b0(bank_params)
	b0.add_cylinder(
		piston: piston(piston_params, blowby: k_28inH2O(0.03)),
		connecting_rod: connecting_rod(cr_params),
		rod_journal: rj0,
		intake: intake1,
		exhaust_system: exhaust,
		ignition_wire: wires.wire1
	)
	engine.add_cylinder_bank(b0)
	engine.add_crankshaft(c0)
	single_cyl_camshaft_builder camshaft(_intake_lobe, _exhaust_lobe)
	b0.set_cylinder_head(
		generic_small_engine_head(
			chamber_volume: 2 * units.cc,
			intake_camshaft: camshaft.intake_cam_0,
			exhaust_camshaft: camshaft.exhaust_cam_0,
			flow_attenuation: 2.5,
			intake_runner_cross_section_area: 7.0 * units.cm2,
			exhaust_runner_cross_section_area: 10.0 * units.cm2
		)
	)
	function timing_curve(1000 * units.rpm)
	timing_curve
		.add_sample(0000 * units.rpm, 0 * units.deg)
		.add_sample(1000 * units.rpm, 2 * units.deg)
		.add_sample(2000 * units.rpm, 4 * units.deg)
		.add_sample(3000 * units.rpm, 6 * units.deg)
		.add_sample(4000 * units.rpm, 8 * units.deg)
		.add_sample(5000 * units.rpm, 10 * units.deg)
		.add_sample(6000 * units.rpm, 12 * units.deg)
		.add_sample(7000 * units.rpm, 14 * units.deg)
		.add_sample(8000 * units.rpm, 16 * units.deg)
		.add_sample(9000 * units.rpm, 18 * units.deg)
		.add_sample(10000 * units.rpm, 20 * units.deg)
		.add_sample(11000 * units.rpm, 22 * units.deg)
		.add_sample(12000 * units.rpm, 24 * units.deg)
		.add_sample(13000 * units.rpm, 26 * units.deg)
	engine.add_ignition_module(
		vemsign(
			wires: wires,
			timing_curve: timing_curve
		)
	)
}

run(engine: make())



```


以上。