<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>플라이휠 &#8211; MyEngNote</title>
	<atom:link href="https://myengnote.com/tag/%ed%94%8c%eb%9d%bc%ec%9d%b4%ed%9c%a0/feed/" rel="self" type="application/rss+xml" />
	<link>https://myengnote.com</link>
	<description></description>
	<lastBuildDate>Wed, 08 Jul 2026 04:43:02 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.2</generator>
	<item>
		<title>플라이휠 관성 계산기 &#038; 시뮬레이터</title>
		<link>https://myengnote.com/flywheel-energy-storage-calculator-simulator/</link>
					<comments>https://myengnote.com/flywheel-energy-storage-calculator-simulator/#respond</comments>
		
		<dc:creator><![CDATA[동동]]></dc:creator>
		<pubDate>Wed, 01 Jul 2026 21:25:11 +0000</pubDate>
				<category><![CDATA[공학계산기]]></category>
		<category><![CDATA[맥동저감]]></category>
		<category><![CDATA[속도변동계수]]></category>
		<category><![CDATA[에너지저장]]></category>
		<category><![CDATA[플라이휠]]></category>
		<category><![CDATA[회전관성모멘트]]></category>
		<guid isPermaLink="false">https://myengnote.com/flywheel-energy-storage-calculator-simulator/</guid>

					<description><![CDATA[플라이휠의 질량, 반경 치수, 평균 회전 속도 및 엔진 맥동 에너지에 따른 회전 관성 모멘트(I), 운동 에너지 저장량, 회전 속도 변동 계수(Cf)를 실시간 연산하고 속도 주기 맥동을 그래픽 시각화하는 초정밀 2D 시뮬레이터입니다. <a href="https://myengnote.com/flywheel-energy-storage-calculator-simulator/" style="text-decoration:none; color:#0073aa; font-weight:bold;">[본문 전체보기 >]</a>]]></description>
										<content:encoded><![CDATA[
<h2 style="font-size: 1.6em; font-weight: 800; color: #0c0e25; border-bottom: 2px solid #00f2fe; padding-bottom: 8px; margin-bottom: 20px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 플라이휠 관성 계산기 &#038; 시뮬레이터</h2>


<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&#038;family=Outfit:wght@400;500;600;700;800&#038;display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* Scoped & Isolated Styles for flywheel-calculator-wrapper */
        /* Modern Reset and Design Tokens */
        .flywheel-calculator-wrapper *, .flywheel-calculator-wrapper *::before, .flywheel-calculator-wrapper *::after {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        .flywheel-calculator-wrapper {
            --color-bg-dark: #f8f9fd;
            --color-bg-deep: #ffffff;
            --color-panel-bg: rgba(255, 255, 255, 0.85);
            --color-border: rgba(0, 0, 0, 0.06);
            --color-border-hover: rgba(0, 0, 0, 0.12);
            --color-text-main: #1e293b;
            --color-text-muted: #475569;
            --color-text-dark: #94a3b8;
            --color-cyan: #0284c7;
            --color-cyan-glow: rgba(2, 132, 199, 0.15);
            --color-magenta: #db2777;
            --color-magenta-glow: rgba(219, 39, 119, 0.15);
            --color-purple: #7c3aed;
            --color-purple-glow: rgba(124, 58, 237, 0.12);
            --color-success: #10b981;
            --color-warning: #f59e0b;
            --gradient-primary: linear-gradient(135deg, var(--color-cyan) 0%, var(--color-purple) 100%);
            --gradient-accent: linear-gradient(135deg, var(--color-magenta) 0%, var(--color-purple) 100%);
            --gradient-panel: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(248, 250, 252, 0.95) 100%);
            --font-heading: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
            --shadow-neon-cyan: 0 0 15px var(--color-cyan-glow);
            --shadow-neon-magenta: 0 0 15px var(--color-magenta-glow);
            --shadow-card: 0 8px 32px 0 rgba(15, 23, 42, 0.05);
            --blur-glass: blur(16px);
        }
        .flywheel-calculator-wrapper {
            background-color: var(--color-bg-dark);
            color: var(--color-text-main);
            font-family: var(--font-body);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            overflow-x: hidden;
            position: relative;
        }
        .app-background-glow {
            position: absolute;
            top: 0; left: 0; width: 100%; height: 100%;
            z-index: -1; overflow: hidden; pointer-events: none;
        }
        .app-background-glow::before, 
        .app-background-glow::after {
            content: ''; position: absolute; width: 600px; height: 600px; border-radius: 50%; filter: blur(140px); opacity: 0.12;
        }
        .app-background-glow::before { background: var(--color-cyan); top: -10%; right: -5%; animation: pulse-slow 15s infinite alternate; }
        .app-background-glow::after { background: var(--color-purple); bottom: -10%; left: -5%; animation: pulse-slow 20s infinite alternate-reverse; }
        @keyframes pulse-slow {
            0% { transform: scale(1) translate(0, 0); opacity: 0.08; }
            100% { transform: scale(1.2) translate(50px, 50px); opacity: 0.15; }
        }
        .app-container {
            width: 100%; max-width: 1440px; padding: 24px; display: flex; flex-direction: column; gap: 24px;
        }
        .app-header {
            display: flex; justify-content: space-between; align-items: center; padding: 20px 24px;
            background: var(--color-panel-bg); backdrop-filter: var(--blur-glass); border: 1px solid var(--color-border); border-radius: 16px; box-shadow: var(--shadow-card);
        }
        .logo-area { display: flex; align-items: center; gap: 16px; }
        .logo-icon {
            font-size: 32px; background: linear-gradient(135deg, var(--color-cyan), var(--color-magenta)); -webkit-background-clip: text; -webkit-text-fill-color: transparent;
            display: flex; align-items: center; justify-content: center;
        }
        .logo-area h1 {
            font-family: var(--font-heading); font-weight: 800; font-size: 24px; letter-spacing: 1.5px;
            background: linear-gradient(90deg, var(--color-text-main), var(--color-text-dark)); -webkit-background-clip: text; -webkit-text-fill-color: transparent;
        }
        .logo-area .subtitle { font-size: 12px; color: var(--color-text-muted); font-weight: 500; letter-spacing: 0.5px; }
        .header-badge {
            display: flex; align-items: center; gap: 10px; background: rgba(2, 132, 199, 0.1); border: 1px solid rgba(2, 132, 199, 0.2); padding: 6px 14px; border-radius: 20px;
        }
        .pulse-dot {
            width: 8px; height: 8px; background-color: var(--color-cyan); border-radius: 50%; box-shadow: 0 0 10px var(--color-cyan); animation: pulse-dot-anim 1.5s infinite;
        }
        @keyframes pulse-dot-anim {
            0% { transform: scale(0.9); opacity: 0.6; }
            50% { transform: scale(1.2); opacity: 1; }
            100% { transform: scale(0.9); opacity: 0.6; }
        }
        .badge-text { font-size: 11px; font-weight: 600; color: var(--color-cyan); letter-spacing: 0.5px; }
        .app-main-grid { display: grid; grid-template-columns: 340px 1fr 340px; gap: 24px; align-items: start; }
        .panel {
            background: var(--gradient-panel); backdrop-filter: var(--blur-glass); border: 1px solid var(--color-border); border-radius: 20px; padding: 24px; box-shadow: var(--shadow-card);
            display: flex; flex-direction: column; gap: 18px; transition: border-color 0.3s ease, box-shadow 0.3s ease;
        }
        .panel:hover { border-color: var(--color-border-hover); }
        .panel-header { display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--color-border); padding-bottom: 14px; }
        .panel-header i { font-size: 18px; }
        .panel-header h2 { font-family: var(--font-heading); font-size: 18px; font-weight: 600; letter-spacing: 0.5px; }
        .text-cyan { color: var(--color-cyan); }
        .text-magenta { color: var(--color-magenta); }
        .text-purple { color: var(--color-purple); }
        .control-panel { grid-column: 1; }
        .input-group { display: flex; flex-direction: column; gap: 8px; }
        .input-label-row { display: flex; justify-content: space-between; align-items: center; }
        .input-label-row label { font-size: 13px; font-weight: 600; color: var(--color-text-main); display: flex; align-items: center; gap: 8px; }
        .helper-text { font-size: 10px; color: var(--color-text-muted); font-weight: 500; }
                .number-input-wrapper {
            display: flex;
            position: relative;
            border-radius: 8px;
            overflow: hidden;
            border: 1px solid var(--color-border);
            background: #ffffff;
            transition: all 0.2s ease;
        }
        .number-input-wrapper:focus-within {
            border-color: var(--color-cyan);
            box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .number-input-wrapper:focus-within { border-color: var(--color-cyan); box-shadow: 0 0 10px var(--color-cyan-glow); }
                .custom-number-input {
            flex: 1;
            width: 0;
            min-width: 0;
            background: #f8fafc !important;
            border: none !important;
            outline: none !important;
            color: #0f172a !important;
            padding: 10px 14px !important;
            font-family: var(--font-body) !important;
            font-size: 15px !important;
            font-weight: 700 !important;
            text-align: right !important;
            box-shadow: none !important;
            -webkit-appearance: none !important;
            -moz-appearance: textfield !important;
        }
        .custom-number-input::-webkit-outer-spin-button,
        .custom-number-input::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }
        .custom-number-input::-webkit-outer-spin-button, .custom-number-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
                .unit-badge {
            background: rgba(0, 0, 0, 0.03);
            color: var(--color-text-muted);
            font-size: 11px;
            font-weight: 700;
            padding: 0 14px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-left: 1px solid var(--color-border);
            pointer-events: none;
            flex-shrink: 0;
        }
        .custom-slider {
            -webkit-appearance: none; width: 100%; height: 6px; border-radius: 3px; background: rgba(0, 0, 0, 0.05); outline: none; margin: 4px 0; transition: background 0.2s ease;
        }
        .custom-slider::-webkit-slider-thumb {
            -webkit-appearance: none; appearance: none; width: 18px; height: 18px; border-radius: 50%; cursor: pointer; transition: transform 0.1s ease, box-shadow 0.2s ease;
        }
        .slider-cyan::-webkit-slider-thumb { background: var(--color-cyan); box-shadow: 0 0 8px var(--color-cyan); }
        .slider-cyan::-webkit-slider-thumb:hover { transform: scale(1.2); }
        .slider-magenta::-webkit-slider-thumb { background: var(--color-magenta); box-shadow: 0 0 8px var(--color-magenta); }
        .slider-magenta::-webkit-slider-thumb:hover { transform: scale(1.2); }
        .slider-purple::-webkit-slider-thumb { background: var(--color-purple); box-shadow: 0 0 8px var(--color-purple); }
        .slider-purple::-webkit-slider-thumb:hover { transform: scale(1.2); }
        .slider-cyan::-moz-range-thumb { width: 18px; height: 18px; border: none; border-radius: 50%; background: var(--color-cyan); }
        .slider-magenta::-moz-range-thumb { width: 18px; height: 18px; border: none; border-radius: 50%; background: var(--color-magenta); }
        .slider-purple::-moz-range-thumb { width: 18px; height: 18px; border: none; border-radius: 50%; background: var(--color-purple); }
        .presets-section { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--color-border); padding-top: 16px; }
        .presets-section h3 { font-size: 13px; font-weight: 700; color: var(--color-text-main); display: flex; align-items: center; gap: 8px; }
        .presets-grid { display: flex; flex-direction: column; gap: 8px; }
        .preset-btn {
            background: rgba(0, 0, 0, 0.015); border: 1px solid var(--color-border); border-radius: 10px; padding: 8px 12px; cursor: pointer; color: var(--color-text-main);
            display: flex; align-items: center; gap: 12px; text-align: left; transition: all 0.2s ease;
        }
        .preset-btn:hover { background: rgba(0, 0, 0, 0.04); transform: translateX(4px); }
        .preset-btn.active {
            background: linear-gradient(90deg, var(--color-cyan-glow), var(--color-magenta-glow)); border-color: var(--color-cyan); box-shadow: 0 0 10px var(--color-cyan-glow);
        }
        .preset-icon {
            width: 28px; height: 28px; background: rgba(0, 0, 0, 0.02); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 12px; color: var(--color-cyan);
        }
        .preset-btn:hover .preset-icon, .preset-btn.active .preset-icon { background: var(--gradient-primary); color: #fff; }
        .preset-name { font-size: 12px; font-weight: 600; }
        .simulation-panel { grid-column: 2; align-self: start; }
        .canvas-wrapper {
            position: relative; width: 100%; background: radial-gradient(circle at center, #ffffff 0%, #f1f5f9 100%); border: 1px solid rgba(0, 0, 0, 0.06); border-radius: 16px;
            overflow: hidden; display: flex; align-items: center; justify-content: center; 
        }
        #physics-canvas { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; }
        .canvas-overlay-data { position: absolute; top: 16px; left: 16px; pointer-events: none; display: flex; flex-direction: column; gap: 6px; }
        .overlay-item {
            background: rgba(255, 255, 255, 0.9); color: var(--color-text-main); backdrop-filter: blur(4px); border: 1px solid var(--color-border); padding: 6px 12px; border-radius: 8px;
            display: flex; align-items: center; gap: 8px; font-size: 11px;
        }
        .overlay-item .label { color: var(--color-text-muted); font-weight: 500; }
        .overlay-item .value { font-weight: 700; }
        .simulation-metrics-strip {
            display: flex; background: rgba(0, 0, 0, 0.01); border: 1px solid var(--color-border); border-radius: 12px; padding: 12px 20px;
            justify-content: space-around; align-items: center; gap: 10px; margin-top: 10px;
        }
        .mini-metric { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; }
        .mini-metric .label { font-size: 10px; font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
        .mini-metric .value { font-size: 14px; font-weight: 700; color: var(--color-text-main); font-family: var(--font-heading); }
        .mini-divider { width: 1px; height: 24px; background: var(--color-border); }
        .results-panel { grid-column: 3; }
        .ratio-readout-box {
            background: linear-gradient(135deg, var(--color-cyan-glow) 0%, var(--color-purple-glow) 100%); border: 1px solid rgba(2, 132, 199, 0.15); border-radius: 16px;
            padding: 20px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 6px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.02);
        }
        .ratio-title { font-size: 11px; font-weight: 700; color: var(--color-cyan); letter-spacing: 1px; text-transform: uppercase; }
        .ratio-value {
            font-family: var(--font-heading); font-weight: 800; font-size: 24px; background: linear-gradient(90deg, var(--color-text-main), var(--color-cyan));
            -webkit-background-clip: text; -webkit-text-fill-color: transparent;
        }
        .ratio-type { font-size: 11px; font-weight: 600; color: var(--color-text-muted); }
        .results-grid { display: flex; flex-direction: column; gap: 12px; }
        .result-card {
            background: rgba(255, 255, 255, 0.85); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03); border: 1px solid var(--color-border); border-radius: 12px;
            padding: 12px 16px; display: flex; align-items: center; gap: 16px; transition: all 0.2s ease;
        }
        .result-card:hover { transform: translateY(-2px); border-color: var(--color-cyan); background: var(--color-cyan-glow); }
        .card-icon {
            width: 38px; height: 38px; background: rgba(0, 0, 0, 0.015); border: 1px solid var(--color-border); border-radius: 10px;
            display: flex; align-items: center; justify-content: center; font-size: 14px; color: var(--color-text-muted);
        }
        .result-card:hover .card-icon { color: var(--color-cyan); border-color: var(--color-cyan); background: var(--color-cyan-glow); }
        .card-content { display: flex; flex-direction: column; gap: 2px; }
        .card-unit { font-size: 11px; font-weight: 600; color: var(--color-text-muted); }
        .card-value { font-family: var(--font-heading); font-weight: 700; font-size: 17px; color: var(--color-text-main); }
        .formula-card {
            background: #ffffff; border: 1px solid var(--color-border); border-radius: 12px; padding: 16px; display: flex; flex-direction: column; gap: 8px; font-size: 12px;
        }
        .formula-card h4 { font-weight: 700; color: var(--color-text-main); }
        .formula-equation {
            font-family: 'Outfit', 'Cambria Math', 'Times New Roman', monospace; color: #0284c7; font-size: 13px; background: #f8fafc; border-color: var(--color-border);
            padding: 8px 10px; border-radius: 6px;
        }
        @container flywheel-container (max-width: 1100px) {
            .app-main-grid {
                grid-template-columns: 1fr 1fr;
                gap: 20px;
            }
            .control-panel {
                grid-column: 1;
            }
            .simulation-panel {
                grid-column: 2;
            }
            .results-panel {
                grid-column: 1 / span 2;
            }
        }
        @container flywheel-container (max-width: 768px) {
            .app-main-grid {
                grid-template-columns: 1fr;
            }
            .control-panel, .simulation-panel, .results-panel {
                grid-column: 1;
            }
            .simulation-panel {
                order: -1;
            }
            .app-header {
                flex-direction: column;
                gap: 16px;
                text-align: center;
            }
            .logo-area {
                flex-direction: column;
                gap: 8px;
            }
        }
        @container flywheel-container (max-width: 480px) {
            .app-container {
                padding: 12px;
                gap: 16px;
            }
            .panel {
                padding: 16px;
            }
            .simulation-metrics-strip {
                flex-direction: column;
                gap: 12px;
            }
            .mini-divider {
                width: 80%;
                height: 1px;
            }
        }
        .preset-details {
            display: flex;
            flex-direction: column;
            gap: 2px;
            align-items: flex-start;
            text-align: left;
        }
        .preset-spec {
            font-size: 11px;
            color: var(--color-text-muted);
            font-weight: 500;
        }
        .preset-name {
            font-size: 13px !important;
        }
/* ━━ WordPress 레이아웃 Override: 디자인 1 (2열 컴팩트 대칭 레이아웃) ━━ */
.flywheel-calculator-wrapper .app-main-grid,
.flywheel-calculator-wrapper .main-grid,
.flywheel-calculator-wrapper .sim-grid {
    display: grid !important;
    grid-template-columns: 340px 1fr !important;
    gap: 24px !important;
    align-items: start !important;
}
/* 3열 레이아웃을 2열 레이아웃으로 변경하는 특화 스타일 */
.flywheel-calculator-wrapper .right-column {
    display: flex !important;
    flex-direction: column !important;
    gap: 24px !important;
    min-width: 0 !important;
    grid-column: 2 !important;
}
.flywheel-calculator-wrapper .simulation-panel,
.flywheel-calculator-wrapper .canvas-panel,
.flywheel-calculator-wrapper .sim-panel {
    grid-column: auto !important;
    order: 1 !important;
    align-self: stretch !important;
}
.flywheel-calculator-wrapper .control-panel {
    grid-column: 1 !important;
}
/* 2열 통합 결과 분석 영역 레이아웃 */
.flywheel-calculator-wrapper .simulation-results-section {
    display: grid !important;
    grid-template-columns: 1.1fr 1.3fr !important;
    gap: 20px !important;
    border-top: 1px solid var(--color-border) !important;
    padding-top: 20px !important;
    margin-top: 10px !important;
    align-items: stretch !important;
}
/* Readout Box 스타일 */
.flywheel-calculator-wrapper .simulation-results-section .ratio-readout-box,
.flywheel-calculator-wrapper .simulation-results-section .re-readout-box,
.flywheel-calculator-wrapper .simulation-results-section .status-readout-box,
.flywheel-calculator-wrapper .simulation-results-section .flow-readout-box,
.flywheel-calculator-wrapper .simulation-results-section [class*="readout-box"],
.flywheel-calculator-wrapper .simulation-results-section .gauge-container {
    grid-column: 1 !important;
    grid-row: 1 !important;
    margin: 0 !important;
    height: auto !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
}
.flywheel-calculator-wrapper .simulation-results-section .results-grid {
    grid-column: 2 !important;
    grid-row: 1 / span 2 !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 12px !important;
    justify-content: flex-start !important;
}
.flywheel-calculator-wrapper .simulation-results-section .results-grid .result-card {
    flex: none !important;
    display: flex !important;
    align-items: center !important;
    min-height: 72px !important;
    height: auto !important;
    padding: 12px 16px !important;
}
.flywheel-calculator-wrapper .simulation-results-section .formula-card {
    grid-column: 1 !important;
    grid-row: 2 !important;
}
/* 모바일/반응형 (800px 이하) ── 항상 세로형(1열) 정렬 및 시뮬레이터 캔버스 최상단 배치 */
@media (max-width: 800px) {
    .flywheel-calculator-wrapper .app-main-grid,
    .flywheel-calculator-wrapper .main-grid,
    .flywheel-calculator-wrapper .sim-grid {
        grid-template-columns: 1fr !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .flywheel-calculator-wrapper .control-panel {
        order: 2 !important;
        width: 100% !important;
    }
    .flywheel-calculator-wrapper .right-column {
        order: 1 !important;
        width: 100% !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .flywheel-calculator-wrapper .simulation-panel,
    .flywheel-calculator-wrapper .canvas-panel,
    .flywheel-calculator-wrapper .sim-panel,
    .flywheel-calculator-wrapper .canvas-section {
        order: -1 !important;
    }
    .flywheel-calculator-wrapper .simulation-results-section {
        grid-template-columns: 1fr !important;
    }
    .flywheel-calculator-wrapper .simulation-results-section .ratio-readout-box,
    .flywheel-calculator-wrapper .simulation-results-section .re-readout-box,
    .flywheel-calculator-wrapper .simulation-results-section .status-readout-box,
    .flywheel-calculator-wrapper .simulation-results-section .flow-readout-box,
    .flywheel-calculator-wrapper .simulation-results-section [class*="readout-box"],
    .flywheel-calculator-wrapper .simulation-results-section .gauge-container {
        grid-column: 1 !important;
        grid-row: auto !important;
        height: auto !important;
    }
    .flywheel-calculator-wrapper .simulation-results-section .results-grid {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
    .flywheel-calculator-wrapper .simulation-results-section .formula-card {
        grid-column: 1 !important;
        grid-row: auto !important;
    }
}
.flywheel-calculator-wrapper .app-container,
.flywheel-calculator-wrapper .main-container {
    max-width: 100% !important;
    padding: 12px !important;
}
/* Premium Advice/Formula Card & Typography Overrides */
.flywheel-calculator-wrapper .simulation-results-section .formula-card,
.flywheel-calculator-wrapper .results-panel .formula-card {
    background: #ffffff !important;
    border: 1px solid var(--color-border) !important;
    border-radius: 12px !important;
    padding: 16px !important;
    box-shadow: var(--shadow-card) !important;
    transition: all 0.2s ease !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    gap: 8px !important;
}
.flywheel-calculator-wrapper .simulation-results-section .formula-card h4,
.flywheel-calculator-wrapper .results-panel .formula-card h4 {
    font-size: 14px !important;
    font-weight: 700 !important;
    color: var(--color-text-main) !important;
    margin-top: 0 !important;
    margin-bottom: 4px !important;
    word-break: keep-all !important;
    line-height: 1.4 !important;
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
}
.flywheel-calculator-wrapper .formula-equation {
    font-family: 'Outfit', 'Cambria Math', 'Times New Roman', monospace !important;
    white-space: nowrap !important;
    overflow-x: auto !important;
    word-break: keep-all !important;
    text-align: center !important;
}
.flywheel-calculator-wrapper #text-judgment {
    font-size: 12px !important;
    font-weight: 500 !important;
    color: var(--color-text-muted) !important;
    line-height: 1.6 !important;
    word-break: keep-all !important;
}
</style>
<div class="flywheel-calculator-wrapper" style="position: relative; width: 100%; box-sizing: border-box; overflow: hidden; margin: 30px auto; border-radius: 20px;">
    <div class="app-background-glow" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; overflow: hidden;"></div>
    <div style="position: relative; z-index: 2; width: 100%;">
    <div class="app-container">
        <!-- Header -->
        <header class="app-header">
            <div class="logo-area">
                <div class="logo-icon"><i class="fa-solid fa-circle-notch"></i></div>
                <div>
                    <h1>FLYWHEEL ENERGY</h1>
                    <div class="subtitle">플라이휠 에너지 저장 및 맥동 감쇠 시뮬레이터</div>
                </div>
            </div>
            <div class="header-badge">
                <div class="pulse-dot"></div>
                <div class="badge-text">DYNAMICS MODEL ACTIVE</div>
            </div>
        </header>
        <!-- Main Layout Grid -->
        <main class="app-main-grid">
            <!-- Left Panel: Controls -->
            <section class="panel control-panel">
                <div class="panel-header">
                    <i class="fa-solid fa-sliders text-cyan"></i>
                    <h2>물리 설계 변수</h2>
                </div>
                <!-- Flywheel Mass M -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label for="input-mass"><i class="fa-solid fa-weight-hanging text-cyan"></i> 플라이휠 질량 (M)</label>
                        <span class="helper-text">(1.0 ~ 500.0 kg)</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-mass" class="custom-number-input" min="1" max="500" value="80" step="any">
                        <div class="unit-badge">kg</div>
                    </div>
                    <input type="range" id="slider-mass" class="custom-slider slider-cyan" min="1" max="500" value="80">
                </div>
                <!-- Outer Radius Ro -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label for="input-outer-r"><i class="fa-solid fa-circle text-magenta"></i> 플라이휠 외경 (Ro)</label>
                        <span class="helper-text">(0.10 ~ 2.00 m)</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-outer-r" class="custom-number-input" min="0.1" max="2" value="0.60" step="any">
                        <div class="unit-badge">m</div>
                    </div>
                    <input type="range" id="slider-outer-r" class="custom-slider slider-magenta" min="10" max="200" value="60">
                </div>
                <!-- Inner Radius Ri -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label for="input-inner-r"><i class="fa-solid fa-circle-notch text-cyan"></i> 플라이휠 내경 (Ri)</label>
                        <span class="helper-text">(0.00 ~ 1.80 m)</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-inner-r" class="custom-number-input" min="0" max="1.8" value="0.40" step="any">
                        <div class="unit-badge">m</div>
                    </div>
                    <input type="range" id="slider-inner-r" class="custom-slider slider-cyan" min="0" max="180" value="40">
                </div>
                <!-- Mean Speed N -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label for="input-rpm"><i class="fa-solid fa-gauge text-purple"></i> 평균 운전 속도 (N)</label>
                        <span class="helper-text">(100 ~ 5000 RPM)</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-rpm" class="custom-number-input" min="100" max="5000" value="1200" step="any">
                        <div class="unit-badge">RPM</div>
                    </div>
                    <input type="range" id="slider-rpm" class="custom-slider slider-purple" min="100" max="5000" value="1200">
                </div>
                <!-- Fluctuation Energy dE -->
                <div class="input-group">
                    <div class="input-label-row">
                        <label for="input-de"><i class="fa-solid fa-bolt text-magenta"></i> 변동 부하 에너지 (&Delta;E)</label>
                        <span class="helper-text">(10 ~ 5000 J)</span>
                    </div>
                    <div class="number-input-wrapper">
                        <input type="number" id="input-de" class="custom-number-input" min="10" max="5000" value="450" step="any">
                        <div class="unit-badge">J</div>
                    </div>
                    <input type="range" id="slider-de" class="custom-slider slider-magenta" min="10" max="5000" value="450">
                </div>
                <!-- Presets -->
                <div class="presets-section">
                    <h3><i class="fa-solid fa-tags text-cyan"></i> 장비 관성 프리셋</h3>
                    <div class="presets-grid">
                        <button class="preset-btn active" id="preset-generator">
                            <div class="preset-icon"><i class="fa-solid fa-plug"></i></div>
                            <div class="preset-details"><span class="preset-name">교류 동기 발전기</span><span class="preset-spec">정밀 속도 유지용</span></div>
                        </button>
                        <button class="preset-btn" id="preset-punch">
                            <div class="preset-icon"><i class="fa-solid fa-industry"></i></div>
                            <div class="preset-details"><span class="preset-name">산업용 펀치 가공기</span><span class="preset-spec">순간 에너지 방출형</span></div>
                        </button>
                        <button class="preset-btn" id="preset-diesel">
                            <div class="preset-icon"><i class="fa-solid fa-truck"></i></div>
                            <div class="preset-details"><span class="preset-name">대형 단기통 디젤 엔진</span><span class="preset-spec">격렬한 폭발 맥동</span></div>
                        </button>
                    </div>
                </div>
            </section>
            <!-- Auto Injected Right Column wrapper for Design 1 -->
            <div class="right-column">
                <section class="panel simulation-panel">
                                <div class="panel-header">
                                    <i class="fa-solid fa-dharmachakra text-magenta"></i>
                                    <h2>실시간 회전 맥동 관찰 및 가감속 그래프</h2>
                                </div>
                                <div class="canvas-wrapper">
                                    <canvas id="physics-canvas" width="640" height="400"></canvas>
                                    <div class="canvas-overlay-data">
                                        <div class="overlay-item">
                                            <span class="label">맥동 제어 상태:</span>
                                            <span class="value" id="overlay-run-status">정상 평활 운전</span>
                                        </div>
                                    </div>
                                </div>
                                <div class="simulation-metrics-strip">
                                    <div class="mini-metric">
                                        <span class="label">관성 모멘트 (I)</span>
                                        <span class="value" id="val-inertia">20.80 kg·m²</span>
                                    </div>
                                    <div class="mini-divider"></div>
                                    <div class="mini-metric">
                                        <span class="label">회전 속도 변동 (Min ~ Max)</span>
                                        <span class="value" id="val-speed-limits">1180 ~ 1220 RPM</span>
                                    </div>
                                    <div class="mini-divider"></div>
                                    <div class="mini-metric">
                                        <span class="label">실시간 속도 변동 계수 (Cf)</span>
                                        <span class="value" id="val-cf">0.034</span>
                                    </div>
                                </div>
                            <div class="simulation-results-section">
                                <div class="ratio-readout-box">
                                    <div class="ratio-title">저장된 평균 운동에너지 (Ek)</div>
                                    <div class="ratio-value" id="txt-kinetic-energy">164.2 kJ</div>
                                    <div class="ratio-type" id="txt-cf-percent">회전속도 리플: 3.4% (Cf = 0.034)</div>
                                </div>
                                <div class="results-grid">
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-arrows-spin"></i></div>
                                        <div class="card-content">
                                            <span class="card-unit">관성 모멘트 (I)</span>
                                            <span class="card-value" id="res-inertia">20.80 kg·m²</span>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-gauge-simple-high"></i></div>
                                        <div class="card-content">
                                            <span class="card-unit">최대 / 최소 운전 속도</span>
                                            <span class="card-value" id="res-rpm-range">1220 / 1180 RPM</span>
                                        </div>
                                    </div>
                                    <div class="result-card">
                                        <div class="card-icon"><i class="fa-solid fa-heart-circle-check"></i></div>
                                        <div class="card-content">
                                            <span class="card-unit">시스템 운전 적합성 판정</span>
                                            <span class="card-value" id="res-status">적합 (매우 안정적)</span>
                                        </div>
                                    </div>
                                </div>
                                <div class="formula-card">
                                    <h4><i class="fa-solid fa-circle-info text-cyan"></i> 플라이휠 역학 공식</h4>
                                    <div class="formula-equation">
                                        I = 0.5 × M × (Ro^2 + Ri^2)
                                    </div>
                                    <div class="formula-equation">
                                        Cf = &Delta;E / (I × &omega;^2)
                                    </div>
                                </div>
                            </div>
                </section>
            </div>
        </main>
        <!-- Disclaimer Footer -->
        <footer class="app-disclaimer" style="margin-top: 20px; padding: 12px 16px; background: rgba(0, 0, 0, 0.015); border: 1px solid var(--color-border); border-radius: 12px; font-size: 11px; color: var(--color-text-muted); line-height: 1.5; text-align: left; display: flex; gap: 10px; align-items: flex-start; clear: both;">
            <i class="fa-solid fa-circle-info" style="color: var(--color-cyan); font-size: 14px; margin-top: 2px; flex-shrink: 0;"></i>
            <span><strong>면책 조항 (Disclaimer):</strong> 본 시뮬레이터의 계산 결과는 교육 및 참고용으로만 제공되며, 실제 제품 설계나 제작 시에는 반드시 최신 공학 규격 및 공식 표준 설계 기준을 재확인하시기 바랍니다. 계산 값의 무결성을 보장하지 않으며, 이로 인해 발생하는 직접적/간접적 손해에 대해 제작자 및 본 블로그는 어떠한 책임을 지지 않습니다.</span>
        </footer>
</div>
    <!-- CORE INTERACTIVE ENGINE -->
    </div>
</div>
<script>
    // Polyfill for CanvasRenderingContext2D.roundRect for backward compatibility
    if (typeof CanvasRenderingContext2D !== 'undefined') {
        if (!CanvasRenderingContext2D.prototype.roundRect) {
        CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) {
            if (typeof r === 'number') r = [r];
            if (!Array.isArray(r)) r = [0];
            const rad = r[0] || 0;
            this.beginPath();
            this.moveTo(x + rad, y);
            this.lineTo(x + w - rad, y);
            this.quadraticCurveTo(x + w, y, x + w, y + rad);
            this.lineTo(x + w, y + h - rad);
            this.quadraticCurveTo(x + w, y + h, x + w - rad, y + h);
            this.lineTo(x + rad, y + h);
            this.quadraticCurveTo(x, y + h, x, y + h - rad);
            this.lineTo(x, y + rad);
            this.quadraticCurveTo(x, y, x + rad, y);
            this.closePath();
            return this;
        };
      }
    }
        (function() {
            if (window.__flywheel_initialized) return;
            window.__flywheel_initialized = true;
            const inputMass = document.getElementById('input-mass');
            const sliderMass = document.getElementById('slider-mass');
            const inputOuterR = document.getElementById('input-outer-r');
            const sliderOuterR = document.getElementById('slider-outer-r');
            const inputInnerR = document.getElementById('input-inner-r');
            const sliderInnerR = document.getElementById('slider-inner-r');
            const inputRpm = document.getElementById('input-rpm');
            const sliderRpm = document.getElementById('slider-rpm');
            const inputDe = document.getElementById('input-de');
            const sliderDe = document.getElementById('slider-de');
            const txtKineticEnergy = document.getElementById('txt-kinetic-energy');
            const txtCfPercent = document.getElementById('txt-cf-percent');
            const valInertia = document.getElementById('val-inertia');
            const valSpeedLimits = document.getElementById('val-speed-limits');
            const valCf = document.getElementById('val-cf');
            const resInertia = document.getElementById('res-inertia');
            const resRpmRange = document.getElementById('res-rpm-range');
            const resStatus = document.getElementById('res-status');
            const overlayRunStatus = document.getElementById('overlay-run-status');
            const state = {
                mass: 80.0,
                outerR: 0.60,
                innerR: 0.40,
                rpm: 1200,
                de: 450.0,
                inertia: 0.0,
                ek: 0.0,
                cf: 0.0,
                angle: 0.0,
                speedHistory: []
            };
            const ranges = {
                mass: { min: 1.0, max: 500.0 },
                outerR: { min: 0.10, max: 2.00 },
                innerR: { min: 0.00, max: 1.80 },
                rpm: { min: 100.0, max: 5000.0 },
                de: { min: 10.0, max: 5000.0 }
            };
            // Setup speed history for graph
            for (let i = 0; i < 110; i++) {
                state.speedHistory.push(1200);
            }
            function calculateFlywheel() {
                // Keep inner diameter always less than outer diameter
                if (state.innerR >= state.outerR - 0.02) {
                    state.innerR = state.outerR - 0.05;
                    if (state.innerR < 0.0) { state.innerR = 0.0; }
                    inputInnerR.value = state.innerR.toFixed(2);
                    sliderInnerR.value = Math.round(state.innerR * 100);
                }
                // Moment of Inertia: I = 0.5 * M * (Ro^2 + Ri^2)
                const I = 0.5 * state.mass * (Math.pow(state.outerR, 2) + Math.pow(state.innerR, 2));
                state.inertia = I;
                // Mean angular velocity omega
                const omega = (2.0 * Math.PI * state.rpm) / 60.0;
                // Kinetic Energy: Ek = 0.5 * I * omega^2
                const Ek = 0.5 * I * Math.pow(omega, 2);
                state.ek = Ek;
                // Speed fluctuation coefficient: Cf = de / (I * omega^2)
                let cf = 0.0;
                const denominator = I * Math.pow(omega, 2);
                if (denominator > 0) {
                    cf = state.de / denominator;
                }
                // Safety bound to avoid extreme overflow in visualization
                if (cf > 1.2) { cf = 1.2; }
                state.cf = cf;
                // Speeds limits
                let rpmMax = state.rpm * (1.0 + cf / 2.0);
                let rpmMin = state.rpm * (1.0 - cf / 2.0);
                if (rpmMin < 0) { rpmMin = 0; }
                state.rpmMax = rpmMax;
                state.rpmMin = rpmMin;
                updateUIValues();
            }
            function syncMassFromInput() {
                let val = parseFloat(inputMass.value);
                if (isNaN(val)) { val = ranges.mass.min; }
                if (val < ranges.mass.min) { val = ranges.mass.min; }
                if (val > ranges.mass.max) { val = ranges.mass.max; }
                state.mass = val;
                inputMass.value = val.toFixed(1);
                sliderMass.value = Math.round(val);
                calculateFlywheel();
            }
            function syncMassFromSlider() {
                state.mass = parseFloat(sliderMass.value);
                inputMass.value = state.mass.toFixed(1);
                calculateFlywheel();
            }
            function syncOuterRFromInput() {
                let val = parseFloat(inputOuterR.value);
                if (isNaN(val)) { val = ranges.outerR.min; }
                if (val < ranges.outerR.min) { val = ranges.outerR.min; }
                if (val > ranges.outerR.max) { val = ranges.outerR.max; }
                state.outerR = val;
                inputOuterR.value = val.toFixed(2);
                sliderOuterR.value = Math.round(val * 100);
                calculateFlywheel();
            }
            function syncOuterRFromSlider() {
                state.outerR = parseFloat(sliderOuterR.value) / 100;
                inputOuterR.value = state.outerR.toFixed(2);
                calculateFlywheel();
            }
            function syncInnerRFromInput() {
                let val = parseFloat(inputInnerR.value);
                if (isNaN(val)) { val = ranges.innerR.min; }
                if (val < ranges.innerR.min) { val = ranges.innerR.min; }
                if (val > ranges.innerR.max) { val = ranges.innerR.max; }
                state.innerR = val;
                inputInnerR.value = val.toFixed(2);
                sliderInnerR.value = Math.round(val * 100);
                calculateFlywheel();
            }
            function syncInnerRFromSlider() {
                state.innerR = parseFloat(sliderInnerR.value) / 100;
                inputInnerR.value = state.innerR.toFixed(2);
                calculateFlywheel();
            }
            function syncRpmFromInput() {
                let val = parseFloat(inputRpm.value);
                if (isNaN(val)) { val = ranges.rpm.min; }
                if (val < ranges.rpm.min) { val = ranges.rpm.min; }
                if (val > ranges.rpm.max) { val = ranges.rpm.max; }
                state.rpm = val;
                inputRpm.value = val.toFixed(0);
                sliderRpm.value = Math.round(val);
                calculateFlywheel();
            }
            function syncRpmFromSlider() {
                state.rpm = parseFloat(sliderRpm.value);
                inputRpm.value = state.rpm.toFixed(0);
                calculateFlywheel();
            }
            function syncDeFromInput() {
                let val = parseFloat(inputDe.value);
                if (isNaN(val)) { val = ranges.de.min; }
                if (val < ranges.de.min) { val = ranges.de.min; }
                if (val > ranges.de.max) { val = ranges.de.max; }
                state.de = val;
                inputDe.value = val.toFixed(0);
                sliderDe.value = Math.round(val);
                calculateFlywheel();
            }
            function syncDeFromSlider() {
                state.de = parseFloat(sliderDe.value);
                inputDe.value = state.de.toFixed(0);
                calculateFlywheel();
            }
            function updateUIValues() {
                // Kinetic energy text unit formatting
                if (state.ek >= 1000.0) {
                    txtKineticEnergy.innerText = (state.ek / 1000.0).toFixed(1) + ' kJ';
                } else {
                    txtKineticEnergy.innerText = state.ek.toFixed(0) + ' J';
                }
                txtCfPercent.innerText = '회전 속도 리플: ' + (state.cf * 100.0).toFixed(2) + '% (Cf = ' + state.cf.toFixed(3) + ')';
                valInertia.innerText = state.inertia.toFixed(2) + ' kg·m²';
                valSpeedLimits.innerText = state.rpmMin.toFixed(0) + ' ~ ' + state.rpmMax.toFixed(0) + ' RPM';
                valCf.innerText = state.cf.toFixed(3);
                resInertia.innerText = state.inertia.toFixed(2) + ' kg·m²';
                resRpmRange.innerText = state.rpmMin.toFixed(0) + ' ~ ' + state.rpmMax.toFixed(0) + ' RPM';
                // Damping assessment status
                if (state.cf < 0.01) {
                    resStatus.innerText = '우수 (정밀 전자기 가동 적합)';
                    resStatus.style.color = '#10b981';
                    overlayRunStatus.innerText = '안정적 운전 (Cf < 1%)';
                    overlayRunStatus.style.color = '#10b981';
                } else {
                    if (state.cf < 0.05) {
                        resStatus.innerText = '양호 (일반 기계설비 표준)';
                        resStatus.style.color = '#0284c7';
                        overlayRunStatus.innerText = '안정적 운전 (Cf < 5%)';
                        overlayRunStatus.style.color = '#0284c7';
                    } else {
                        if (state.cf < 0.10) {
                            resStatus.innerText = '경고 (맥동 진동 경계 구역)';
                            resStatus.style.color = '#f59e0b';
                            overlayRunStatus.innerText = '맥동 발생 (주의 요망)';
                            overlayRunStatus.style.color = '#f59e0b';
                        } else {
                            resStatus.innerText = '위험 (극심한 맥동 파손 우려)';
                            resStatus.style.color = '#db2777';
                            overlayRunStatus.innerText = '격렬한 회전 맥동 발생!';
                            overlayRunStatus.style.color = '#db2777';
                        }
                    }
                }
            }
            // Presets
            document.getElementById('preset-generator').addEventListener('click', function() {
                setActivePreset('preset-generator');
                state.mass = 120.0;
                state.outerR = 0.85;
                state.innerR = 0.65;
                state.rpm = 1500;
                state.de = 250.0;
                syncControlsToState();
                calculateFlywheel();
            });
            document.getElementById('preset-punch').addEventListener('click', function() {
                setActivePreset('preset-punch');
                state.mass = 350.0;
                state.outerR = 1.10;
                state.innerR = 0.80;
                state.rpm = 400;
                state.de = 2800.0;
                syncControlsToState();
                calculateFlywheel();
            });
            document.getElementById('preset-diesel').addEventListener('click', function() {
                setActivePreset('preset-diesel');
                state.mass = 45.0;
                state.outerR = 0.50;
                state.innerR = 0.00;
                state.rpm = 900;
                state.de = 1950.0;
                syncControlsToState();
                calculateFlywheel();
            });
            function setActivePreset(id) {
                document.getElementById('preset-generator').classList.remove('active');
                document.getElementById('preset-punch').classList.remove('active');
                document.getElementById('preset-diesel').classList.remove('active');
                document.getElementById(id).classList.add('active');
            }
            function syncControlsToState() {
                inputMass.value = state.mass.toFixed(1);
                sliderMass.value = Math.round(state.mass);
                inputOuterR.value = state.outerR.toFixed(2);
                sliderOuterR.value = Math.round(state.outerR * 100);
                inputInnerR.value = state.innerR.toFixed(2);
                sliderInnerR.value = Math.round(state.innerR * 100);
                inputRpm.value = state.rpm;
                sliderRpm.value = state.rpm;
                inputDe.value = state.de.toFixed(0);
                sliderDe.value = Math.round(state.de);
            }
            // Bind Event Listeners
            inputMass.addEventListener('change', syncMassFromInput);
            sliderMass.addEventListener('input', syncMassFromSlider);
            inputOuterR.addEventListener('change', syncOuterRFromInput);
            sliderOuterR.addEventListener('input', syncOuterRFromSlider);
            inputInnerR.addEventListener('change', syncInnerRFromInput);
            sliderInnerR.addEventListener('input', syncInnerRFromSlider);
            inputRpm.addEventListener('change', syncRpmFromInput);
            sliderRpm.addEventListener('input', syncRpmFromSlider);
            inputDe.addEventListener('change', syncDeFromInput);
            sliderDe.addEventListener('input', syncDeFromSlider);
            // Canvas drawing
            const canvas = document.getElementById('physics-canvas');
            const ctx = canvas.getContext('2d');
            function getDPR() { return window.devicePixelRatio || 1; }
            function initCanvas() {
                const dpr = getDPR();
                const rect = canvas.getBoundingClientRect();
                canvas.width = rect.width * dpr;
                canvas.height = rect.height * dpr;
                ctx.scale(dpr, dpr);
            }
            window.addEventListener('resize', initCanvas);
            initCanvas();
            let lastTime = 0;
            function animate(currentTime) {
                if (lastTime === 0) { lastTime = currentTime; }
                const dt = (currentTime - lastTime) / 1000;
                lastTime = currentTime;
                const dpr = getDPR();
                const width = canvas.width / dpr;
                const height = canvas.height / dpr;
                ctx.clearRect(0, 0, width, height);
                // Grid
                ctx.strokeStyle = 'rgba(2, 132, 199, 0.05)';
                ctx.lineWidth = 1;
                const gridSize = 25;
                for (let x = 0; x < width; x += gridSize) {
                    ctx.beginPath();
                    ctx.moveTo(x, 0);
                    ctx.lineTo(x, height);
                    ctx.stroke();
                }
                for (let y = 0; y < height; y += gridSize) {
                    ctx.beginPath();
                    ctx.moveTo(0, y);
                    ctx.lineTo(width, y);
                    ctx.stroke();
                }
                const scale = Math.min(width / 640, height / 400);
                const cx = width / 2 + 60 * scale; // offset flywheel center to right to make room for graph
                const cy = height / 2;
                // Speed oscillation calculation: Single-cylinder torque fluctuation has 2 power cycles per revolution (2.0*angle)
                const baseOmega = (2.0 * Math.PI * state.rpm) / 60.0;
                const dynamicOmega = baseOmega * (1.0 + (state.cf / 2.0) * Math.sin(2.0 * state.angle));
                state.angle += dynamicOmega * dt;
                const currentRpm = (dynamicOmega * 60.0) / (2.0 * Math.PI);
                // Track history (FIFO queue of 110 data points)
                state.speedHistory.push(currentRpm);
                if (state.speedHistory.length > 110) {
                    state.speedHistory.shift();
                }
                // Visual scaling: map outer radius 2.0m to 120px, dynamically scaled
                const drawRo = (35.0 + (state.outerR / 2.0) * 95.0) * scale;
                const drawRi = drawRo * (state.innerR / state.outerR);
                // 1. Draw Rotating Flywheel
                ctx.save();
                ctx.translate(cx, cy);
                ctx.rotate(state.angle);
                // Central steel shaft hub
                ctx.fillStyle = '#64748b';
                ctx.beginPath();
                ctx.arc(0, 0, 16 * scale, 0, Math.PI * 2);
                ctx.fill();
                ctx.lineWidth = 2.5 * scale;
                ctx.strokeStyle = '#334155';
                ctx.stroke();
                // Hub boundary
                ctx.strokeStyle = 'rgba(255,255,255,0.2)';
                ctx.lineWidth = 2 * scale;
                ctx.beginPath();
                ctx.arc(0, 0, 10 * scale, 0, Math.PI * 2);
                ctx.stroke();
                // 6 spokes
                ctx.strokeStyle = '#94a3b8';
                ctx.lineWidth = 9 * scale;
                for (let i = 0; i < 6; i++) {
                    const spAngle = (i * Math.PI) / 3;
                    ctx.beginPath();
                    ctx.moveTo(0, 0);
                    ctx.lineTo(Math.cos(spAngle) * drawRo, Math.sin(spAngle) * drawRo);
                    ctx.stroke();
                }
                // Inner ring edge line (if innerR > 0)
                if (state.innerR > 0) {
                    ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
                    ctx.beginPath();
                    ctx.arc(0, 0, drawRi, 0, Math.PI * 2);
                    ctx.fill();
                }
                // Massive outer rim (rendered as a ring)
                ctx.save();
                ctx.strokeStyle = '#475569';
                const rimWidth = drawRo - drawRi;
                ctx.lineWidth = rimWidth;
                ctx.beginPath();
                ctx.arc(0, 0, drawRo - rimWidth / 2, 0, Math.PI * 2);
                ctx.stroke();
                ctx.restore();
                // Add nice rim highlight lines to show rotation speed
                ctx.strokeStyle = '#94a3b8';
                ctx.lineWidth = 2 * scale;
                ctx.beginPath();
                ctx.arc(0, 0, drawRo - 1 * scale, 0, Math.PI * 2);
                ctx.stroke();
                if (state.innerR > 0.0) {
                    ctx.beginPath();
                    ctx.arc(0, 0, drawRi + 1 * scale, 0, Math.PI * 2);
                    ctx.stroke();
                }
                // Glowing energy dots inside rim
                const glowIntensity = Math.min(state.ek / 80000.0, 1.0);
                if (glowIntensity > 0.05) {
                    ctx.save();
                    ctx.fillStyle = 'rgba(2, 132, 199, ' + (0.2 + glowIntensity * 0.4) + ')';
                    ctx.shadowBlur = 8 * scale;
                    ctx.shadowColor = '#0284c7';
                    const dotCount = 8;
                    const rMid = (drawRo + drawRi) / 2;
                    for (let i = 0; i < dotCount; i++) {
                        const dotAngle = (i * Math.PI * 2) / dotCount;
                        ctx.beginPath();
                        ctx.arc(Math.cos(dotAngle) * rMid, Math.sin(dotAngle) * rMid, 4 * scale, 0, Math.PI * 2);
                        ctx.fill();
                    }
                    ctx.restore();
                }
                ctx.restore();
                // 2. Draw Real-time Speed Pulsation Wave Chart (Bottom Left: scaled)
                const gx = 30 * scale;
                const gy = height - 130 * scale;
                const gw = 200 * scale;
                const gh = 90 * scale;
                ctx.save();
                // Chart Panel back
                ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
                ctx.roundRect(gx, gy, gw, gh, 8 * scale);
                ctx.fill();
                ctx.strokeStyle = '#e2e8f0';
                ctx.lineWidth = 1.5 * scale;
                ctx.stroke();
                // Grid inside graph
                ctx.strokeStyle = 'rgba(0,0,0,0.03)';
                ctx.lineWidth = 1 * scale;
                for (let lx = gx + 40 * scale; lx < gx + gw; lx += 40 * scale) {
                    ctx.beginPath(); ctx.moveTo(lx, gy); ctx.lineTo(lx, gy + gh); ctx.stroke();
                }
                ctx.beginPath();
                ctx.moveTo(gx, gy + gh / 2);
                ctx.lineTo(gx + gw, gy + gh / 2);
                ctx.stroke();
                 // Draw line wave representing history
                 ctx.strokeStyle = '#db2777';
                 ctx.lineWidth = 3.0 * scale;
                 ctx.beginPath();
                 // Map history points: Y axis scales dynamic around state.rpm
                 // Limit minimum scale margin to 0.003 (0.3%) so the wave is always beautifully visible and pulsating
                 const margin = state.rpm * Math.max(state.cf, 0.003) * 1.3;
                 const minScale = state.rpm - margin;
                 const maxScale = state.rpm + margin;
                 for (let i = 0; i < state.speedHistory.length; i++) {
                     const spVal = state.speedHistory[i];
                     const hx = gx + (i / 110.0) * gw;
                     let normY = 0.5;
                     const scaleDiff = maxScale - minScale;
                     if (scaleDiff > 0) {
                         normY = (spVal - minScale) / scaleDiff;
                     }
                     // Clamp normY beautifully inside the white graph box boundaries [0.05, 0.95]
                     normY = Math.min(Math.max(normY, 0.05), 0.95);
                     const hy = gy + gh - (normY * gh);
                     if (i === 0) {
                         ctx.moveTo(hx, hy);
                     } else {
                         ctx.lineTo(hx, hy);
                     }
                 }
                 ctx.stroke();
                // Chart text overlays
                ctx.fillStyle = '#475569';
                ctx.font = 'bold ' + Math.max(8, Math.round(9 * scale)) + 'px Inter';
                ctx.fillText(maxScale.toFixed(0) + ' RPM', gx + 6 * scale, gy + 12 * scale);
                ctx.fillText(minScale.toFixed(0) + ' RPM', gx + 6 * scale, gy + gh - 6 * scale);
                ctx.fillStyle = '#1e293b';
                ctx.font = 'bold ' + Math.max(9, Math.round(10 * scale)) + 'px Inter';
                ctx.fillText('실시간 회전 속도 파형 (N)', gx + 6 * scale, gy - 8 * scale);
                ctx.restore();
                requestAnimationFrame(animate);
            }
            requestAnimationFrame(animate);
            // Initial calculation
            calculateFlywheel();
            // Right click / Copy Protection
            (function() {
                function blockEvents() {
                    document.addEventListener('contextmenu', function(e) {
                        e.preventDefault();
                        alert("이 콘텐츠는 저작권법의 보호를 받습니다. 무단 복제 및 우클릭을 금지합니다.");
                        return false;
                    }, { capture: true });
                    document.addEventListener('selectstart', function(e) {
                        e.preventDefault();
                        return false;
                    }, { capture: true });
                }
                if (document.readyState === 'complete' || document.readyState === 'interactive') {
                    blockEvents();
                } else {
                    document.addEventListener('DOMContentLoaded', blockEvents);
                }
            })();
        })();
</script>


<div style="background: linear-gradient(135deg, rgba(0,242,254,0.03), rgba(138,43,226,0.03)); border: 1px solid rgba(0,242,254,0.15); border-radius: 12px; padding: 18px 24px; margin: 25px auto 35px auto; font-size: 0.95em; color: #4b5563; line-height: 1.7; font-family: sans-serif;">
    <strong style="color: #1f2937; font-size: 1.05em; display: flex; align-items: center; gap: 8px;">
        <span style="font-size: 1.2em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span> 간편 사용 설명서
    </strong>
    <ol style="margin: 10px 0 0 0; padding-left: 20px;">
        <li style="margin-bottom: 6px;"><strong>플라이휠 외형 설계: 플라이휠의 외경(Ro), 내경(Ri), 그리고 질량(M) 슬라이더를 부품 형상에 맞게 설정합니다. (관성 모멘트가 자동 계산됩니다.)</strong></li>
<li style="margin-bottom: 6px;">평균 운전 RPM 설정: 시스템의 평균 운전 속도(N)를 입력합니다.</li>
<li style="margin-bottom: 6px;">변동 에너지 부하 입력: 크랭크 축 1사이클 동안 발생하는 회전 에너지 변동량(dE)을 기정합니다. (통상 단기통 엔진일수록 큽니다.)</li>
<li style="margin-bottom: 6px;">실시간 회전 맥동 및 감쇠 확인: 2D 시뮬레이터 속 플라이휠이 회전합니다. 관성이 작거나 변동 에너지가 크면 회전 속도가 &#8216;울컥&#8217;거리며 심하게 가감속되는 맥동 현상(Cf 가시화)을 눈으로 직접 확인합니다.</li>
<li style="margin-bottom: 6px;">속도 변동 그래프 분석: 실시간으로 플라이휠 속도의 맥동 파형 그래프가 감쇠되는 정도를 비교 관찰하여 목표 속도변동계수 이내로 관성이 확보되었는지 판단합니다.</li>
    </ol>
</div>


<details class="premium-seo-accordion" style="border: 1px solid rgba(0,0,0,0.08); border-radius: 12px; background: #fbfbfc; padding: 0; margin: 30px auto; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.01); font-family: sans-serif;">
    <summary style="display: flex; justify-content: space-between; align-items: center; padding: 20px 24px; font-size: 1.1em; font-weight: 700; color: #1f2937; cursor: pointer; user-select: none; outline: none; list-style: none;">
        <span><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 상세 기계공학 해설 및 플라이휠 설계 규격 확인하기</span>
        <span class="accordion-arrow" style="font-size: 0.9em; color: #9ca3af; transition: transform 0.2s ease;">▼</span>
    </summary>
    <div style="padding: 0 24px 24px 24px; border-top: 1px solid rgba(0,0,0,0.04); background: #ffffff; border-radius: 0 0 12px 12px; font-size: 0.98em; color: #374151; line-height: 1.8;">
        <div style="margin-top: 20px;">
            <h3>1. 내연기관 및 왕복 압축기에서 플라이휠(Flywheel)의 물리학적 역할</h3>
<p>왕복동 엔진(Reciprocating Engine)이나 단기통 크랭크 프레스 등은 피스톤의 직선 운동을 크랭크 축의 회전 운동으로 변환하는 과정에서 크랭크 각도에 따라 발생하는 토크가 매우 불균일합니다. 4행정 단기통 엔진의 경우 폭발 행정에서 막대한 토크가 발생하지만, 나머지 흡입, 압축, 배기 행정에서는 동력을 소비하여 축 회전 속도가 급격히 요동치게 됩니다.</p><p><strong>플라이휠(Flywheel)</strong>은 이러한 회전계에 장착되는 거대한 질량의 회전 원판으로, <em>폭발 행정의 잉여 에너지를 회전 운동 에너지로 흡수·저장하고, 동력이 없는 행정 동안 에너지를 방출하여 축의 회전 속도를 평활화(Damping / Smoothing)</em>하는 역할을 담당합니다. 즉 회전식 에너지를 임시 축적하는 기계적 축전기(Battery)라 할 수 있습니다.</p>
<h3>2. 회전 관성 모멘트 및 회전 에너지 공식</h3>
<p>일반적으로 두께를 가진 중공 원통(Rim) 형태 플라이휠의 <strong>관성 모멘트(Moment of Inertia, I)</strong>는 질량 <code>M</code>, 외경 <code>R<sub>o</sub></code>, 내경 <code>R<sub>i</sub></code>에 의해 결정됩니다:</p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">I = 1/2 &middot; M &middot; (R<sub>o</sub><sup>2</sup> + R<sub>i</sub><sup>2</sup>) &nbsp;[kg&middot;m<sup>2</sup>]</p><p>평균 각속도 <code>&omega; = (2&pi; &middot; N) / 60</code>에 의해 저장되는 총 <strong>회전 운동 에너지 (Kinetic Energy, E<sub>k</sub>)</strong>는 다음과 같습니다:</p><p style="text-align: center; font-weight: bold; background: #f3f4f6; padding: 12px; border-radius: 8px;">E<sub>k</sub> = 1/2 &middot; I &middot; &omega;<sup>2</sup> &nbsp;[Joule]</p><p>여기에 크랭크 사이클 당 공급-소비 에너지 오차인 변동 에너지 <code>&Delta;E</code>가 인가되면, 시스템의 <strong>속도 변동 계수 (Coefficient of Speed Fluctuation, C<sub>f</sub>)</strong>는 다음과 같이 유도됩니다:</p><p style="text-align: center; font-weight: bold; background: #e0f2fe; padding: 16px; border-radius: 8px; font-size: 1.1em; color: #0369a1;">C<sub>f</sub> = (N<sub>max</sub> &#8211; N<sub>min</sub>) / N &nbsp;=&nbsp; &Delta;E / (I &middot; &omega;<sup>2</sup>)</p>
<h3>3. 산업 기계별 권장 속도 변동 계수 (Cf) 표준</h3>
<p>플라이휠이 가벼울수록 회전 가속은 빠르나 맥동이 커지며, 너무 무거우면 축 베어링 부하와 재료 원가가 증가하므로 용도에 따른 최적화 설계가 필수적입니다:</p><ul><li><strong>발전용 교류 동기기 (주파수 정밀 제어 필수):</strong> C<sub>f</sub> &le; 0.003 ~ 0.005 (0.3% ~ 0.5% 변동)</li><li><strong>정밀 제직기 및 공작기계:</strong> C<sub>f</sub> &le; 0.01 ~ 0.02 (1% ~ 2% 변동)</li><li><strong>일반 산업용 다기통 디젤 엔진:</strong> C<sub>f</sub> &le; 0.03 ~ 0.05</li><li><strong>파쇄기 및 공기 압축기:</strong> C<sub>f</sub> &le; 0.05 ~ 0.10 (5% ~ 10% 변동 허용)</li></ul>
        </div>
    </div>
</details>
<style>
details.premium-seo-accordion[open] summary .accordion-arrow { transform: rotate(180deg); color: #00f2fe; }
details.premium-seo-accordion summary::-webkit-details-marker { display: none; }
details.premium-seo-accordion:hover { border-color: rgba(0,242,254,0.3); }
</style>


<h2 style="font-size: 1.4em; font-weight: 700; color: #1f2937; margin-top: 40px; margin-bottom: 15px; border-left: 4px solid #3b82f6; padding-left: 10px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 함께 보면 좋은 공학 글</h2>


<a href="https://myengnote.com/machining-drill-rpm-feedrate-calculator-simulator/" style="text-decoration: none; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); padding: 15px; margin: 12px 0; transition: box-shadow 0.2s; display: table; width: 100%; box-sizing: border-box;">
    <span style="display: table-cell; vertical-align: middle;">
        <span style="font-size: 30px; margin-right: 15px; float: left;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span>
        <span style="display: block; overflow: hidden;">
            <span style="display: block; font-size: 0.9em; color: #6b7280; margin-bottom: 4px;">함께 보면 좋은 글</span>
            <span style="display: block; font-size: 1.1em; font-weight: bold; color: #111827;">드릴 회전수 계산기 &#038; 시뮬레이터</span>
        </span>
    </span>
    <span style="display: table-cell; vertical-align: middle; width: 40px; text-align: right; color: #3b82f6; font-size: 24px; font-weight: bold;">→</span>
</a>


<a href="https://myengnote.com/machining-cutting-speed-roughness-calculator-simulator/" style="text-decoration: none; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); padding: 15px; margin: 12px 0; transition: box-shadow 0.2s; display: table; width: 100%; box-sizing: border-box;">
    <span style="display: table-cell; vertical-align: middle;">
        <span style="font-size: 30px; margin-right: 15px; float: left;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span>
        <span style="display: block; overflow: hidden;">
            <span style="display: block; font-size: 0.9em; color: #6b7280; margin-bottom: 4px;">함께 보면 좋은 글</span>
            <span style="display: block; font-size: 1.1em; font-weight: bold; color: #111827;">선삭 절삭 속도 계산기 &#038; 시뮬레이터</span>
        </span>
    </span>
    <span style="display: table-cell; vertical-align: middle; width: 40px; text-align: right; color: #3b82f6; font-size: 24px; font-weight: bold;">→</span>
</a>
]]></content:encoded>
					
					<wfw:commentRss>https://myengnote.com/flywheel-energy-storage-calculator-simulator/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
