diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fa6f77..aa38048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.2.0] - 2026-04-07 + +### Added +- ✨ 新增“算例演示(Case Demo)”标签页,位于根轨迹与智能问答之间 +- ✨ 新增 `case_demo_functions.py`,支持参数化工况运行完整混动模型 +- ✨ 新增图文输出:转速响应、功率分配、电气状态、关键时刻数据表 +- ✨ 新增算例结果自动解读(最大转速误差、SOC变化、平均功率、平均燃油流量) + +### Changed +- 🔧 `Model/src/series_hybrid_sim.py` 改为按 Model 目录定位 GPR 数据与权重 +- 🔧 `requirements.txt` 固定关键依赖版本并加入 PyTorch CPU 下载源 +- 🔧 文档更新:README 与 GUIDANCE 同步为“五大功能”结构与最新运行方式 + +### Removed +- 🧹 精简 `Model` 目录:移除 `scripts/`、`EngineData.xlsx`、`.git/`、`.claude/`、`README.md`、`LICENSE`、`environment.yml`、`figures/`、`.gitignore` + ## [1.0.0] - 2025-10-15 ### Added diff --git a/GUIDANCE.md b/GUIDANCE.md index dd1e7dd..f83ccd4 100644 --- a/GUIDANCE.md +++ b/GUIDANCE.md @@ -10,12 +10,13 @@ ## 二、平台功能简介 -本平台是《自动控制理论》课程的配套学习工具,提供四大核心功能: +本平台是《自动控制理论》课程的配套学习工具,提供五大核心功能: 1. **时域分析** - 分析系统的阶跃响应和脉冲响应 2. **频域分析** - 绘制Bode图和Nyquist图,分析系统稳定性 3. **根轨迹分析** - 观察增益变化对系统极点的影响 -4. **AI智能问答** - 24小时在线的自动控制理论助教 +4. **算例演示** - 基于完整混动发动机模型的参数化仿真 +5. **AI智能问答** - 24小时在线的自动控制理论助教 --- @@ -107,7 +108,38 @@ --- -### 3.4 AI智能问答 +### 3.4 算例演示 + +#### 3.4.1 功能说明 + +通过完整混动模型进行系统级算例仿真,输出图文结果用于教学演示与参数对比。 + +#### 3.4.2 使用步骤 + +1. 点击顶部"算例演示"标签页 +2. 设置工况模板与参数: + - 仿真时长、仿真步长 + - 初始SOC、初始发动机功率 + - 目标转速缩放系数、负载转矩缩放系数 +3. 点击"运行混动算例" +4. 查看三联图、结果解读与关键时刻数据表 + +#### 3.4.3 输出结果 + +- **推进轴转速响应图**:目标与实际转速跟踪 +- **功率分配图**:电机需求、发动机输出、电池功率 +- **电气状态图**:母线电压与SOC +- **结果解读**:最大转速误差、SOC变化、平均功率、平均燃油流量 + +#### 3.4.4 结果解释要点 + +- 仿真时长是模型时间,不等于程序实际等待时间 +- 电池功率正值表示放电,负值表示充电 +- 输入超限时会自动裁剪到安全范围 + +--- + +### 3.5 AI智能问答 #### 3.4.1 功能说明 @@ -268,12 +300,12 @@ ### 9.1 平台特色功能 1. **实时在线人数统计** - 页面顶部显示当前在线用户数 -2. **自动保存会话** - AI问答记录自动保存 +2. **图文联动演示** - 算例演示支持图、表、文本同步展示 3. **LaTeX公式支持** - 完美显示数学公式 4. **响应式设计** - 适配不同屏幕尺寸 ### 9.2 更新说明 -- 版本: v1.1.0 -- 更新日期: 2025年10月19日 -- 主要更新: 新增实时在线人数统计功能 +- 版本: v1.2.0 +- 更新日期: 2026年4月7日 +- 主要更新: 新增算例演示模块与完整混动模型联动 diff --git a/Model/data/Cleaned_Engine_Data_Full.csv b/Model/data/Cleaned_Engine_Data_Full.csv new file mode 100644 index 0000000..fab5d45 --- /dev/null +++ b/Model/data/Cleaned_Engine_Data_Full.csv @@ -0,0 +1,785 @@ +Altitude_m,Mach,RPM,SFC,Power_kW,Inlet_T2_K,Inlet_P2_kPa,RPM_Rel_Phys,RPM_Rel_Corr,Flight_Vel_kmh,WF_kg_h +0.0,0.0,58000.0,0.517840950638725,249.582776334593,288.15,101.325005740179,1.0,1.00000000810418,0.0,129.24418216015792 +0.0,0.0,56550.0,0.523671728560371,225.628264104881,288.15,101.325005740179,0.975,0.975000007901579,0.0,118.15514307587895 +0.0,0.0,55100.0,0.541853755600857,199.858261719303,288.15,101.325005740179,0.95,0.950000007698975,0.0,108.29394970046332 +0.0,0.0,53650.0,0.574210664480304,172.570200963337,288.15,101.325005740179,0.925,0.92500000749637,0.0,99.09164976465733 +0.0,0.0,52200.0,0.634153554768018,141.195238600974,288.15,101.325005740179,0.9,0.900000007293765,0.0,89.53946247512614 +0.0,0.0,50750.0,0.739625131431326,108.051321175276,288.15,101.325005740179,0.875,0.875000007091161,0.0,79.91747262559193 +0.0,0.0,49300.0,0.889708703850822,80.8082872194116,288.15,101.325005740179,0.85,0.850000006888556,0.0,71.89583648238764 +0.0,0.0,47850.0,1.08140792247008,60.7887493798357,288.15,101.325005740179,0.825,0.825000006685951,0.0,65.7374351764025 +0.0,0.0,46400.0,1.29064944286157,47.6405112445542,288.15,101.325005740179,0.8,0.800000006483347,0.0,61.48719929542423 +0.0,0.0,44950.0,1.51493801357613,38.5098458611298,288.15,101.325005740179,0.775,0.775000006280742,0.0,58.340029391982924 +0.0,0.0,43500.0,1.77665628493182,31.3519538053187,288.15,101.325005740179,0.75,0.750000006078138,0.0,55.70164577311156 +0.0,0.0,42050.0,2.13113424114961,24.9483532621358,288.15,101.325005740179,0.725,0.725000005875533,0.0,53.168289897234175 +0.0,0.0,40600.0,2.66079262801875,19.0435113641824,288.15,101.325005740179,0.7,0.700000005672928,0.0,50.67083464940782 +0.0,0.0,0.0,0.0,0.0,288.15,101.325005740179,0.0,0.0,0.0,0.0 +0.0,0.05,58000.0,0.516516781939578,250.658217899343,288.294288851519,101.50245395591,1.0,0.999749731014721,61.2540781071208,129.46917607607816 +0.0,0.05,56550.0,0.522545552740258,226.315592419349,288.294288851519,101.50245395591,0.975,0.974755987739353,61.2540781071208,118.26020633450767 +0.0,0.05,55100.0,0.540702165324945,200.446769067162,288.294288851519,101.50245395591,0.95,0.949762244463985,61.2540781071208,108.3820020670037 +0.0,0.05,53650.0,0.572924816015739,173.069984669624,288.294288851519,101.50245395591,0.925,0.924768501188617,61.2540781071208,99.15608912469109 +0.0,0.05,52200.0,0.632705856008601,141.575524377551,288.294288851519,101.50245395591,0.9,0.899774757913249,61.2540781071208,89.57566334116497 +0.0,0.05,50750.0,0.73790833583659,108.30563465016,288.294288851519,101.50245395591,0.875,0.874781014637881,61.2540781071208,79.91963062642529 +0.0,0.05,49300.0,0.887385695585721,81.0001237411043,288.294288851519,101.50245395591,0.85,0.849787271362513,61.2540781071208,71.87835114852932 +0.0,0.05,47850.0,1.07779232680311,60.9732715859449,288.294288851519,101.50245395591,0.825,0.824793528087145,61.2540781071208,65.7165242554135 +0.0,0.05,46400.0,1.28582871717267,47.7971346450755,288.294288851519,101.50245395591,0.8,0.799799784811776,61.2540781071208,61.45892832520682 +0.0,0.05,44950.0,1.50879846329932,38.6449856348878,288.294288851519,101.50245395591,0.775,0.774806041536408,61.2540781071208,58.307494940143016 +0.0,0.05,43500.0,1.76929731842248,31.4626795287867,288.294288851519,101.50245395591,0.75,0.74981229826104,61.2540781071208,55.66683452066817 +0.0,0.05,42050.0,2.12262473079863,25.0296488161928,288.294288851519,101.50245395591,0.725,0.724818554985672,61.2540781071208,53.12855158045549 +0.0,0.05,40600.0,2.65054955410193,19.0998400915557,288.294288851519,101.50245395591,0.7,0.699824811710304,61.2540781071208,50.62507263809112 +0.0,0.05,0.0,0.0,0.0,288.15,101.50245395591,0.0,0.0,0.0,0.0 +0.0,0.1,58000.0,0.513436195618546,252.835841959937,288.727155406076,102.036129697856,1.0,0.999000025738633,122.508156214242,129.815072811922 +0.0,0.1,56550.0,0.519207561513579,228.379823641232,288.727155406076,102.036129697856,0.975,0.974025025095167,122.508156214242,118.57653133166531 +0.0,0.1,55100.0,0.537279892817707,202.216306865266,288.727155406076,102.036129697856,0.95,0.949050024451701,122.508156214242,108.64675567856268 +0.0,0.1,53650.0,0.569111688484241,174.569497630313,288.727155406076,102.036129697856,0.925,0.924075023808235,122.508156214242,99.34954155423314 +0.0,0.1,52200.0,0.628416151322243,142.713704486095,288.727155406076,102.036129697856,0.9,0.899100023164769,122.508156214242,89.68359691409175 +0.0,0.1,50750.0,0.732800403291141,109.070720613081,288.727155406076,102.036129697856,0.875,0.874125022521303,122.508156214242,79.92706805252112 +0.0,0.1,49300.0,0.880428242025916,81.5850645288629,288.727155406076,102.036129697856,0.85,0.849150021877838,122.508156214242,71.82979493871768 +0.0,0.1,47850.0,1.06703252243469,61.529752385002,288.727155406076,102.036129697856,0.825,0.824175021234372,122.508156214242,65.65424689215057 +0.0,0.1,46400.0,1.27139563873693,48.2751901598378,288.727155406076,102.036129697856,0.8,0.799200020590906,122.508156214242,61.37686622841374 +0.0,0.1,44950.0,1.49055357865882,39.0529730041172,288.727155406076,102.036129697856,0.775,0.77422501994744,122.508156214242,58.21054866855318 +0.0,0.1,43500.0,1.74741166189252,31.7971341312229,288.727155406076,102.036129697856,0.75,0.749250019303974,122.508156214242,55.56268299565958 +0.0,0.1,42050.0,2.09733168791679,25.274786200372,288.727155406076,102.036129697856,0.725,0.724275018660508,122.508156214242,53.00961000336219 +0.0,0.1,40600.0,2.6200205283376,19.2702125463316,288.727155406076,102.036129697856,0.7,0.699300018017043,122.508156214242,50.488352456817566 +0.0,0.1,0.0,0.0,0.0,288.727155406076,102.036129697856,0.0,0.0,0.0,0.0 +0.0,0.15,58000.0,0.508303822197168,256.522280001327,289.448599663671,102.930036212294,1.0,0.997754256213846,183.762234321362,130.39125540340663 +0.0,0.15,56550.0,0.513768108402086,231.834139600599,289.448599663671,102.930036212294,0.975,0.9728103998085,183.762234321362,119.10898736562488 +0.0,0.15,55100.0,0.53169036295966,205.18808691688,289.448599663671,102.930036212294,0.95,0.947866543403153,183.762234321362,109.09652840783419 +0.0,0.15,53650.0,0.562885984655253,177.074104192777,289.448599663671,102.930036212294,0.925,0.922922686997807,183.762234321362,99.67253149549815 +0.0,0.15,52200.0,0.621415585310371,144.607194862463,289.448599663671,102.930036212294,0.9,0.897978830592461,183.762234321362,89.8611646355483 +0.0,0.15,50750.0,0.724398298070544,110.353702900077,289.448599663671,102.930036212294,0.875,0.873034974187115,183.762234321362,79.94003456659823 +0.0,0.15,49300.0,0.868963419440882,82.5696612854769,289.448599663671,102.930036212294,0.85,0.848091117781769,183.762234321362,71.75001521270342 +0.0,0.15,47850.0,1.04936322033586,62.4692059005246,289.448599663671,102.930036212294,0.825,0.823147261376423,183.762234321362,65.5528870755984 +0.0,0.15,46400.0,1.24760086285893,49.0811249323403,289.448599663671,102.930036212294,0.8,0.798203404971076,183.762234321362,61.2336538156747 +0.0,0.15,44950.0,1.46065400610989,39.7418051078847,289.448599663671,102.930036212294,0.775,0.77325954856573,183.762234321362,58.04902684087028 +0.0,0.15,43500.0,1.71166228196001,32.3575211803761,289.448599663671,102.930036212294,0.75,0.748315692160384,183.762234321362,55.385148542171905 +0.0,0.15,42050.0,2.05587560606064,25.6882448380733,289.448599663671,102.930036212294,0.725,0.723371835755038,183.762234321362,52.81183592510804 +0.0,0.15,40600.0,2.56982715771228,19.5585663923114,289.448599663671,102.930036212294,0.7,0.698427979349692,183.762234321362,50.262135080880526 +0.0,0.15,0.0,0.0,0.0,289.448599663671,102.930036212294,0.0,0.0,0.0,0.0 +0.0,0.2,58000.0,0.501250800659334,261.759459202845,290.458621624305,104.190878817561,1.0,0.996017982548927,245.016312428483,131.20713850558033 +0.0,0.2,56550.0,0.506402418440838,236.701150317205,290.458621624305,104.190878817561,0.975,0.971117532985204,245.016312428483,119.86603496836094 +0.0,0.2,55100.0,0.524081760131972,209.382452906353,290.458621624305,104.190878817561,0.95,0.946217083421481,245.016312428483,109.73352445991122 +0.0,0.2,53650.0,0.554408655520227,180.606119878927,290.458621624305,104.190878817561,0.925,0.921316633857758,245.016312428483,100.12959610080085 +0.0,0.2,52200.0,0.611924089122952,147.248936419038,290.458621624305,104.190878817561,0.9,0.896416184294035,245.016312428483,90.1051712925433 +0.0,0.2,50750.0,0.712867614487687,112.162709165899,290.458621624305,104.190878817561,0.875,0.871515734730311,245.016312428483,79.95716291757064 +0.0,0.2,49300.0,0.853191265962915,83.9669272358269,290.458621624305,104.190878817561,0.85,0.846615285166588,245.016312428483,71.63984894735111 +0.0,0.2,47850.0,1.02520783334495,63.8070427154862,290.458621624305,104.190878817561,0.825,0.821714835602865,245.016312428483,65.41548001449227 +0.0,0.2,46400.0,1.21506130958451,50.2323898197981,290.458621624305,104.190878817561,0.8,0.796814386039142,245.016312428483,61.03543335800349 +0.0,0.2,44950.0,1.41996403959041,40.7236070141082,290.458621624305,104.190878817561,0.775,0.771913936475419,245.016312428483,57.82605752244543 +0.0,0.2,43500.0,1.66295238675979,33.1619847107919,290.458621624305,104.190878817561,0.75,0.747013486911695,245.016312428483,55.14680162450305 +0.0,0.2,42050.0,1.99941687675703,26.2756343548397,290.458621624305,104.190878817561,0.725,0.722113037347972,245.016312428483,52.53594677656331 +0.0,0.2,40600.0,2.50119886215125,19.9707328363875,290.458621624305,104.190878817561,0.7,0.697212587784249,245.016312428483,49.95077424669903 +0.0,0.2,0.0,0.0,0.0,290.458621624305,104.190878817561,0.0,0.0,0.0,0.0 +0.0,0.25,58000.0,0.492562714842441,268.601992942731,291.757221287976,105.828114886451,1.0,0.993798892524202,306.270390535604,132.30332685596176 +0.0,0.25,56550.0,0.497354898953314,243.004445916489,291.757221287976,105.828114886451,0.975,0.968953920211097,306.270390535604,120.85945164400144 +0.0,0.25,55100.0,0.514640513982778,214.839918815304,291.757221287976,105.828114886451,0.95,0.944108947897992,306.270390535604,110.56532624312635 +0.0,0.25,53650.0,0.543944515764917,185.170887141512,291.757221287976,105.828114886451,0.925,0.919263975584887,306.270390535604,100.72268853994983 +0.0,0.25,52200.0,0.600220793043495,150.628263370275,291.757221287976,105.828114886451,0.9,0.894419003271782,306.270390535604,90.41021569487089 +0.0,0.25,50750.0,0.698506218063967,114.489697130401,291.757221287976,105.828114886451,0.875,0.869574030958677,306.270390535604,79.97176534984541 +0.0,0.25,49300.0,0.83342174200584,85.8000169578578,291.757221287976,105.828114886451,0.85,0.844729058645572,306.270390535604,71.50759959714846 +0.0,0.25,47850.0,0.995097049054201,65.5677696774729,291.757221287976,105.828114886451,0.825,0.819884086332467,306.270390535604,65.2462941191188 +0.0,0.25,46400.0,1.17446559612791,51.7593888654142,291.757221287976,105.828114886451,0.8,0.795039114019362,306.270390535604,60.789621499035 +0.0,0.25,44950.0,1.36938137294802,42.0245346692307,291.757221287976,105.828114886451,0.775,0.770194141706257,306.270390535604,57.5476149828528 +0.0,0.25,43500.0,1.60268807424156,34.2200050133504,291.757221287976,105.828114886451,0.75,0.745349169393151,306.270390535604,54.84399393538308 +0.0,0.25,42050.0,1.92925158155243,27.0448145664854,291.757221287976,105.828114886451,0.725,0.720504197080046,306.270390535604,52.17625127518416 +0.0,0.25,40600.0,2.41452165781416,20.5214146028223,291.757221287976,105.828114886451,0.7,0.695659224766941,306.270390535604,49.549400007498214 +0.0,0.25,0.0,0.0,0.0,291.757221287976,105.828114886451,0.0,0.0,0.0,0.0 +0.0,0.3,58000.0,0.482367372847481,277.126239778584,293.344398654686,107.854024062161,1.0,0.991106708010945,367.524468642725,133.67665622909666 +0.0,0.3,56550.0,0.486870031914151,250.789144178591,293.344398654686,107.854024062161,0.975,0.966329040310672,367.524468642725,122.10171862995321 +0.0,0.3,55100.0,0.503598043800678,221.611062031802,293.344398654686,107.854024062161,0.95,0.941551372610398,367.524468642725,111.60289732380618 +0.0,0.3,53650.0,0.531818601227221,190.750348595921,293.344398654686,107.854024062161,0.925,0.916773704910124,367.524468642725,101.44458357388751 +0.0,0.3,52200.0,0.586686128176419,154.692509344946,293.344398654686,107.854024062161,0.9,0.891996037209851,367.524468642725,90.75594936548087 +0.0,0.3,50750.0,0.681053189804184,117.520945887004,293.344398654686,107.854024062161,0.875,0.867218369509577,367.524468642725,80.03801506514897 +0.0,0.3,49300.0,0.810028838788352,88.0704136228099,293.344398654686,107.854024062161,0.85,0.842440701809304,367.524468642725,71.33957487849456 +0.0,0.3,47850.0,0.959664690959701,67.7841412516794,293.344398654686,107.854024062161,0.825,0.81766303410903,367.524468642725,65.05004696626163 +0.0,0.3,46400.0,1.12676432858678,53.6995558374525,293.344398654686,107.854024062161,0.8,0.792885366408756,367.524468642725,60.50674397859547 +0.0,0.3,44950.0,1.31026983912815,43.6700802700707,293.344398654686,107.854024062161,0.775,0.768107698708483,367.524468642725,57.21958905017893 +0.0,0.3,43500.0,1.53250532677088,35.5476521639635,293.344398654686,107.854024062161,0.75,0.743330031008209,367.524468642725,54.47696629547246 +0.0,0.3,42050.0,1.84715125774841,28.0133860735945,293.344398654686,107.854024062161,0.725,0.718552363307935,367.524468642725,51.74496131963187 +0.0,0.3,40600.0,2.31213798797291,21.2209657867659,293.344398654686,107.854024062161,0.7,0.693774695607662,367.524468642725,49.06580113705487 +0.0,0.3,0.0,0.0,0.0,293.344398654686,107.854024062161,0.0,0.0,0.0,0.0 +0.0,0.35,58000.0,0.470982676252837,287.448191862454,295.220153724433,110.283798947079,1.0,0.987953068515966,428.778546749846,135.38311868741755 +0.0,0.35,56550.0,0.475218114456363,260.108270129808,295.220153724433,110.283798947079,0.975,0.963254241803067,428.778546749846,123.60816168559369 +0.0,0.35,55100.0,0.491174946865564,229.795617605291,295.220153724433,110.283798947079,0.95,0.938555415090168,428.778546749846,112.86985026721827 +0.0,0.35,53650.0,0.518318948567858,197.334217399414,295.220153724433,110.283798947079,0.925,0.913856588377269,428.778546749846,102.28206407892537 +0.0,0.35,52200.0,0.571682608308068,159.409924689662,295.220153724433,110.283798947079,0.9,0.889157761664369,428.778546749846,91.13188153677866 +0.0,0.35,50750.0,0.66132568386357,121.135080521774,295.220153724433,110.283798947079,0.875,0.86445893495147,428.778546749846,80.10973996593081 +0.0,0.35,49300.0,0.783144154629023,90.8624063235755,295.220153724433,110.283798947079,0.85,0.839760108238571,428.778546749846,71.15836238783533 +0.0,0.35,47850.0,0.91948639236671,70.5006201141703,295.220153724433,110.283798947079,0.825,0.815061281525672,428.778546749846,64.82436084839436 +0.0,0.35,46400.0,1.0730676040304,56.0937180021038,295.220153724433,110.283798947079,0.8,0.790362454812773,428.778546749846,60.19235157767444 +0.0,0.35,44950.0,1.24430053465644,45.6846095464051,295.220153724433,110.283798947079,0.775,0.765663628099874,428.778546749846,56.84538408416257 +0.0,0.35,43500.0,1.45417587540355,37.1632115898238,295.220153724433,110.283798947079,0.75,0.740964801386974,428.778546749846,54.041845746439385 +0.0,0.35,42050.0,1.75444595442007,29.1975393285886,295.220153724433,110.283798947079,0.725,0.716265974674075,428.778546749846,51.22550475406315 +0.0,0.35,40600.0,2.19546192091381,22.0904790876996,295.220153724433,110.283798947079,0.7,0.691567147961176,428.778546749846,48.49880565178731 +0.0,0.35,0.0,0.0,0.0,295.220153724433,110.283798947079,0.0,0.0,0.0,0.0 +1000.0,0.0,58000.0,0.515510044506519,231.347045275657,281.65,89.8745653777784,1.0,1.01147333392362,0.0,119.26172560650562 +1000.0,0.0,56550.0,0.521319051346396,208.529434436095,281.65,89.8745653777784,0.975,0.986186500575529,0.0,108.71036693802552 +1000.0,0.0,55100.0,0.533408708360696,186.672798453626,281.65,89.8745653777784,0.95,0.960899667227439,0.0,99.57289630922517 +1000.0,0.0,53650.0,0.561805068138577,162.286894360006,281.65,89.8745653777784,0.925,0.935612833879348,0.0,91.17359974392122 +1000.0,0.0,52200.0,0.608779472420338,136.377620387831,281.65,89.8745653777784,0.9,0.910326000531258,0.0,83.0238957896449 +1000.0,0.0,50750.0,0.698825801404107,106.340081289564,281.65,89.8745653777784,0.875,0.885039167183167,0.0,74.31319252855745 +1000.0,0.0,49300.0,0.837141835069454,79.542500537258,281.65,89.8745653777784,0.85,0.859752333835077,0.0,66.5883548657732 +1000.0,0.0,47850.0,1.02541544810262,59.0387574346416,281.65,89.8745653777784,0.825,0.834465500486986,0.0,60.53925391026491 +1000.0,0.0,46400.0,1.24073035229992,45.3425702128889,281.65,89.8745653777784,0.8,0.809178667138896,0.0,56.25790311442151 +1000.0,0.0,44950.0,1.47134751687178,36.1922572739731,281.65,89.8745653777784,0.775,0.783891833790805,0.0,53.25138787004494 +1000.0,0.0,43500.0,1.73333034540858,29.3477867111523,281.65,89.8745653777784,0.75,0.758605000442715,0.0,50.869409277018946 +1000.0,0.0,42050.0,2.07333744397542,23.4978035602648,281.65,89.8745653777784,0.725,0.733318167094624,0.0,48.71887597267594 +1000.0,0.0,40600.0,2.58613994598036,18.0061465244471,281.65,89.8745653777784,0.7,0.708031333746534,0.0,46.56641480004807 +0.0,0.0,0.0,0.0,0.0,281.65,89.8745653777784,0.0,0.0,0.0,0.0 +1000.0,0.05,58000.0,0.514407544001346,232.057071431022,281.791043194302,90.0319709371256,1.0,1.01122016887588,60.5612300201938,119.37190818297695 +1000.0,0.05,56550.0,0.520197895272965,209.155609403893,281.791043194302,90.0319709371256,0.975,0.985939664653983,60.5612300201938,108.80230779643951 +1000.0,0.05,55100.0,0.532275217566708,187.223180163877,281.791043194302,90.0319709371256,0.95,0.960659160432086,60.5612300201938,99.65425895525861 +1000.0,0.05,53650.0,0.56055009449265,162.762944486508,281.791043194302,90.0319709371256,0.925,0.935378656210189,60.5612300201938,91.236783911814 +1000.0,0.05,52200.0,0.607406502827473,136.748078761447,281.791043194302,90.0319709371256,0.9,0.910098151988292,60.5612300201938,83.06167228886636 +1000.0,0.05,50750.0,0.697187921761441,106.606249474818,281.791043194302,90.0319709371256,0.875,0.884817647766395,60.5612300201938,74.32458951813007 +1000.0,0.05,49300.0,0.835046324508423,79.7276235815022,281.791043194302,90.0319709371256,0.85,0.859537143544498,60.5612300201938,66.57625903352448 +1000.0,0.05,47850.0,1.02226108118176,59.2005754221843,281.791043194302,90.0319709371256,0.825,0.834256639322601,60.5612300201938,60.518444237664454 +1000.0,0.05,46400.0,1.2361741222274,45.487062658334,281.791043194302,90.0319709371256,0.8,0.808976135100704,60.5612300201938,56.229929754368776 +1000.0,0.05,44950.0,1.46543348145882,36.3170660139083,281.791043194302,90.0319709371256,0.775,0.783695630878807,60.5612300201938,53.22024448513143 +1000.0,0.05,43500.0,1.7260791323154,29.4521460135816,281.791043194302,90.0319709371256,0.75,0.75841512665691,60.5612300201938,50.8367346359494 +1000.0,0.05,42050.0,2.06476425078307,23.577492698345,281.791043194302,90.0319709371256,0.725,0.733134622435013,60.5612300201938,48.681964046641625 +1000.0,0.05,40600.0,2.57601707924468,18.0605120273877,281.791043194302,90.0319709371256,0.7,0.707854118213116,60.5612300201938,46.524187442454675 +1000.0,0.05,0.0,0.0,0.0,281.791043194302,90.0319709371256,0.0,0.0,0.0,0.0 +1000.0,0.1,58000.0,0.511323931509567,234.051973284574,282.214172777207,90.5053684407736,1.0,1.01046181279174,121.122460040388,119.67637515744052 +1000.0,0.1,56550.0,0.516860901055493,211.043872820739,282.214172777207,90.5053684407736,0.975,0.985200267471946,121.122460040388,109.08032626836803 +1000.0,0.1,55100.0,0.528913100039104,188.876591961705,282.214172777207,90.5053684407736,0.95,0.959938722152153,121.122460040388,99.8993037792863 +1000.0,0.1,53650.0,0.556815473768111,164.196894302291,282.214172777207,90.5053684407736,0.925,0.934677176832359,121.122460040388,91.42737149218262 +1000.0,0.1,52200.0,0.603333857444066,137.857859017078,282.214172777207,90.5053684407736,0.9,0.909415631512566,121.122460040388,83.17431385975388 +1000.0,0.1,50750.0,0.692315772188055,107.405528367254,282.214172777207,90.5053684407736,0.875,0.884154086192772,121.122460040388,74.3585413088415 +1000.0,0.1,49300.0,0.828802161037887,80.2847066192652,282.214172777207,90.5053684407736,0.85,0.858892540872979,121.122460040388,66.54013834433974 +1000.0,0.1,47850.0,1.01285752406058,59.6891383315025,282.214172777207,90.5053684407736,0.825,0.833630995553185,121.122460040388,60.45659286375508 +1000.0,0.1,46400.0,1.22260490227503,45.9239216945485,282.214172777207,90.5053684407736,0.8,0.808369450233392,121.122460040388,56.1468117954496 +1000.0,0.1,44950.0,1.44784591856524,36.6940706105627,282.214172777207,90.5053684407736,0.775,0.783107904913598,121.122460040388,53.12736036904792 +1000.0,0.1,43500.0,1.70447817617648,29.7676876469067,282.214172777207,90.5053684407736,0.75,0.757846359593805,121.122460040388,50.73837394939067 +1000.0,0.1,42050.0,2.03934058277994,23.8173918741994,282.214172777207,90.5053684407736,0.725,0.732584814274011,121.122460040388,48.57177382502802 +1000.0,0.1,40600.0,2.54582687956037,18.2250708190903,282.214172777207,90.5053684407736,0.7,0.707323268954218,121.122460040388,46.39787517313141 +1000.0,0.1,0.0,0.0,0.0,282.214172777207,90.5053684407736,0.0,0.0,0.0,0.0 +1000.0,0.15,58000.0,0.506314395500302,237.404529912313,282.919388748717,91.2983092035152,1.0,1.00920166864562,181.683690060581,120.20133105158612 +1000.0,0.15,56550.0,0.511387888409563,214.222716976481,282.919388748717,91.2983092035152,0.975,0.983971626929483,181.683690060581,109.55090288396205 +1000.0,0.15,55100.0,0.52341748065481,191.646427610897,282.919388748717,91.2983092035152,0.95,0.958741585213343,181.683690060581,100.31109031659012 +1000.0,0.15,53650.0,0.550690020565192,166.605593921518,282.919388748717,91.2983092035152,0.925,0.933511543497202,181.683690060581,91.74803794291677 +1000.0,0.15,52200.0,0.596790691764497,139.667866391822,282.919388748717,91.2983092035152,0.9,0.908281501781062,181.683690060581,83.35248260124679 +1000.0,0.15,50750.0,0.684314755335882,108.744814355104,282.919388748717,91.2983092035152,0.875,0.883051460064921,181.683690060581,74.41568102945891 +1000.0,0.15,49300.0,0.818584457801641,81.2116685319316,282.919388748717,91.2983092035152,0.85,0.85782141834878,181.683690060581,66.47860965237781 +1000.0,0.15,47850.0,0.997361889035037,60.5150997924293,282.919388748717,91.2983092035152,0.825,0.83259137663264,181.683690060581,60.355454244121056 +1000.0,0.15,46400.0,1.20030024896332,46.6640080678968,282.919388748717,91.2983092035152,0.8,0.807361334916499,181.683690060581,56.01082050152291 +1000.0,0.15,44950.0,1.41899676814152,37.3320805814069,282.919388748717,91.2983092035152,0.775,0.782131293200358,181.683690060581,52.97410169301519 +1000.0,0.15,43500.0,1.66918699537015,30.2996289602214,282.919388748717,91.2983092035152,0.75,0.756901251484218,181.683690060581,50.57574662494234 +1000.0,0.15,42050.0,1.99770934875897,24.2225459222734,282.919388748717,91.2983092035152,0.725,0.731671209768077,181.683690060581,48.389606439669045 +1000.0,0.15,40600.0,2.49619212322723,18.5037167448737,282.919388748717,91.2983092035152,0.7,0.706441168051937,181.683690060581,46.188831988981526 +1000.0,0.15,0.0,0.0,0.0,289.448599663671,102.930036212294,0.0,0.0,0.0,0.0 +1000.0,0.2,58000.0,0.499500545527715,242.133031404394,283.90669110883,92.4167415738559,1.0,1.00744536106482,242.244920080775,120.94558127677415 +1000.0,0.2,56550.0,0.503928165349098,218.725359848472,283.90669110883,92.4167415738559,0.975,0.982259227038199,242.244920080775,110.22186930376176 +1000.0,0.2,55100.0,0.515952727887589,195.550713428736,283.90669110883,92.4167415738559,0.95,0.957073093011579,242.244920080775,100.89492403392052 +1000.0,0.2,53650.0,0.542317761076815,170.019365303365,283.90669110883,92.4167415738559,0.925,0.931886958984958,242.244920080775,92.20452153102202 +1000.0,0.2,52200.0,0.587897595951998,142.199704887738,283.90669110883,92.4167415738559,0.9,0.906700824958338,242.244920080775,83.59886464858474 +1000.0,0.2,50750.0,0.673398464263004,110.622962113858,283.90669110883,92.4167415738559,0.875,0.881514690931717,242.244920080775,74.49333279969645 +1000.0,0.2,49300.0,0.804574283732402,82.5201578438976,283.90669110883,92.4167415738559,0.85,0.856328556905097,242.244920080775,66.39359689073866 +1000.0,0.2,47850.0,0.976056231812973,61.6956889529813,283.90669110883,92.4167415738559,0.825,0.831142422878476,242.244920080775,60.21846167855219 +1000.0,0.2,46400.0,1.16979524635858,47.7229964225794,283.90669110883,92.4167415738559,0.8,0.805956288851856,242.244920080775,55.82613435712089 +1000.0,0.2,44950.0,1.37966973395626,38.2438230126976,283.90669110883,92.4167415738559,0.775,0.780770154825235,242.244920080775,52.76384512139879 +1000.0,0.2,43500.0,1.621139175837,31.0584541615992,283.90669110883,92.4167415738559,0.75,0.755584020798615,242.244920080775,50.35007678230617 +1000.0,0.2,42050.0,1.94088839464961,24.7984406532303,283.90669110883,92.4167415738559,0.725,0.730397886771994,242.244920080775,48.13100566926179 +1000.0,0.2,40600.0,2.42776174404928,18.9045997432519,283.90669110883,92.4167415738559,0.7,0.705211752745374,242.244920080775,45.8958640432308 +1000.0,0.2,0.0,0.0,0.0,283.90669110883,92.4167415738559,0.0,0.0,0.0,0.0 +1000.0,0.25,58000.0,0.491106870834565,248.295084764935,285.176079857547,93.8690552767738,1.0,1.00520066703131,302.806150100969,121.93942212251031 +1000.0,0.25,56550.0,0.494674130615802,224.619478913764,285.176079857547,93.8690552767738,0.975,0.980070650355526,302.806150100969,111.11344545104068 +1000.0,0.25,55100.0,0.506710974296498,200.636726936331,285.176079857547,93.8690552767738,0.95,0.954940633679743,302.806150100969,101.66483138556872 +1000.0,0.25,53650.0,0.531891669068342,174.48256837113,285.176079857547,93.8690552767738,0.925,0.92981061700396,302.806150100969,92.80582451425141 +1000.0,0.25,52200.0,0.576834995127259,145.458943806754,285.176079857547,93.8690552767738,0.9,0.904680600328178,302.806150100969,83.90580914198519 +1000.0,0.25,50750.0,0.659833245731738,113.042614094839,285.176079857547,93.8690552767738,0.875,0.879550583652395,302.806150100969,74.58927496419793 +1000.0,0.25,49300.0,0.787113280285323,84.2161426694686,285.176079857547,93.8690552767738,0.85,0.854420566976612,302.806150100969,66.28764430954219 +1000.0,0.25,47850.0,0.949270548719875,63.2601066250733,285.176079857547,93.8690552767738,0.825,0.829290550300829,302.806150100969,60.05095612806113 +1000.0,0.25,46400.0,1.13176060787858,49.1256977066405,285.176079857547,93.8690552767738,0.8,0.804160533625047,302.806150100969,55.598529498926816 +1000.0,0.25,44950.0,1.33080591702903,39.4500197423346,285.176079857547,93.8690552767738,0.775,0.779030516949264,302.806150100969,52.500319700010934 +1000.0,0.25,43500.0,1.56164397544693,32.0589300930277,285.176079857547,93.8690552767738,0.75,0.753900500273481,302.806150100969,50.06463503905099 +1000.0,0.25,42050.0,1.87068932127897,25.5556436643225,285.176079857547,93.8690552767738,0.725,0.728770483597698,302.806150100969,47.80666970125866 +1000.0,0.25,40600.0,2.34272339485242,19.434349895432,285.176079857547,93.8690552767738,0.7,0.703640466921916,302.806150100969,45.529306163776226 +1000.0,0.25,0.0,0.0,0.0,285.176079857547,93.8690552767738,0.0,0.0,0.0,0.0 +1000.0,0.3,58000.0,0.481334847455855,255.920202280522,286.727554994867,95.6661437070395,1.0,1.00247742120916,363.367380121163,123.18331152556661 +1000.0,0.3,56550.0,0.483921798146751,231.894451240306,286.727554994867,95.6661437070395,0.975,0.977415485678929,363.367380121163,112.21877982446296 +1000.0,0.3,55100.0,0.495933328551175,206.933825773019,286.727554994867,95.6661437070395,0.95,0.9523535501487,363.367380121163,102.62538100544224 +1000.0,0.3,53650.0,0.519736573799463,179.984095165987,286.727554994867,95.6661437070395,0.925,0.927291614618471,363.367380121163,93.54431695996658 +1000.0,0.3,52200.0,0.563971973204375,149.462959868794,286.727554994867,95.6661437070395,0.9,0.902229679088242,363.367380121163,84.29292039817007 +1000.0,0.3,50750.0,0.643942242463018,115.999665097739,286.727554994867,95.6661437070395,0.875,0.877167743558013,363.367380121163,74.69708446799713 +1000.0,0.3,49300.0,0.766418607040161,86.3322915762664,286.727554994867,95.6661437070395,0.85,0.852105808027784,363.367380121163,66.16667465246712 +1000.0,0.3,47850.0,0.917325200115547,65.2429981447152,286.727554994867,95.6661437070395,0.825,0.827043872497555,363.367380121163,59.84904632923913 +1000.0,0.3,46400.0,1.08686716694676,50.9079859557327,286.727554994867,95.6661437070395,0.8,0.801981936967326,363.367380121163,55.33021847067264 +1000.0,0.3,44950.0,1.27353794841834,40.9857875552953,286.727554994867,95.6661437070395,0.775,0.776920001437097,363.367380121163,52.19695579748071 +1000.0,0.3,43500.0,1.49236777331988,33.3168463018979,286.727554994867,95.6661437070395,0.75,0.751858065906868,363.367380121163,49.72098772960404 +1000.0,0.3,42050.0,1.78881980291953,26.5065014540787,286.727554994867,95.6661437070395,0.725,0.726796130376639,363.367380121163,47.41535470717129 +1000.0,0.3,40600.0,2.24145710517143,20.1131429503249,286.727554994867,95.6661437070395,0.7,0.70173419484641,363.367380121163,45.082747173334404 +1000.0,0.3,0.0,0.0,0.0,286.727554994867,95.6661437070395,0.0,0.0,0.0,0.0 +1000.0,0.35,58000.0,0.47039404555375,265.043478251638,288.561116520791,97.8214843854198,1.0,0.999287398130672,423.928610141357,124.67487398242535 +1000.0,0.35,56550.0,0.472045317312734,240.596937246103,288.561116520791,97.8214843854198,0.975,0.974305213177405,423.928610141357,113.57265758680865 +1000.0,0.35,55100.0,0.48389604314158,214.471789263338,288.561116520791,97.8214843854198,0.95,0.949323028224138,423.928610141357,103.78205019002407 +1000.0,0.35,53650.0,0.506310938509629,186.502342985338,288.561116520791,97.8214843854198,0.925,0.924340843270871,423.928610141357,94.42817631115122 +1000.0,0.35,52200.0,0.549551042070556,154.193828903687,288.561116520791,97.8214843854198,0.9,0.899358658317605,423.928610141357,84.73737935487021 +1000.0,0.35,50750.0,0.625907160843942,119.560597867778,288.561116520791,97.8214843854198,0.875,0.874376473364338,423.928610141357,74.8338343602252 +1000.0,0.35,49300.0,0.742637052860997,88.9166687625891,288.561116520791,97.8214843854198,0.85,0.849394288411071,423.928610141357,66.03281284006664 +1000.0,0.35,47850.0,0.88132580473439,67.6577944554284,288.561116520791,97.8214843854198,0.825,0.824412103457804,423.928610141357,59.62856014498439 +1000.0,0.35,46400.0,1.03637969937351,53.1367453506142,288.561116520791,97.8214843854198,0.8,0.799429918504537,423.928610141357,55.069844172156294 +1000.0,0.35,44950.0,1.20954895436051,42.8644097074849,288.561116520791,97.8214843854198,0.775,0.774447733551271,423.928610141357,51.84660194096886 +1000.0,0.35,43500.0,1.41534127897073,34.842722610254,288.561116520791,97.8214843854198,0.75,0.749465548598004,423.928610141357,49.31434358201927 +1000.0,0.35,42050.0,1.69712370225193,27.6602108108716,288.561116520791,97.8214843854198,0.725,0.724483363644737,423.928610141357,46.94279937641527 +1000.0,0.35,40600.0,2.17503761097496,20.0585876591485,288.561116520791,97.8214843854198,0.7,0.69950117869147,423.928610141357,43.62818258168617 +1000.0,0.35,0.0,0.0,0.0,288.561116520791,97.8214843854198,0.0,0.0,0.0,0.0 +2000.0,0.0,58000.0,0.515040664520812,213.569545962531,275.15,79.495201431303,1.0,1.02335085536676,0.0,109.99700087395007 +2000.0,0.0,56550.0,0.519299186792368,192.755816584944,275.15,79.495201431303,0.975,0.997767083982586,0.0,100.09793880206026 +2000.0,0.0,55100.0,0.528089114170692,173.16041580167,275.15,79.495201431303,0.95,0.972183312598417,0.0,91.44413059013262 +2000.0,0.0,53650.0,0.550795550902113,152.166960620804,275.15,79.495201431303,0.925,0.946599541214248,0.0,83.81288490423586 +2000.0,0.0,52200.0,0.590253307886354,129.83818614625,275.15,79.495201431303,0.9,0.92101576983008,0.0,76.63741886278824 +2000.0,0.0,50750.0,0.663847887312897,104.040691406009,275.15,79.495201431303,0.875,0.895431998445911,0.0,69.06719318445215 +2000.0,0.0,49300.0,0.788899101634556,78.3153168982003,275.15,79.495201431303,0.85,0.869848227061742,0.0,61.78288314521578 +2000.0,0.0,47850.0,0.967447846640383,57.8097254335603,275.15,79.495201431303,0.825,0.844264455677573,0.0,55.927894385569694 +2000.0,0.0,46400.0,1.18925988996186,43.3988491834337,275.15,79.495201431303,0.8,0.818680684293404,0.0,51.61251060436172 +2000.0,0.0,44950.0,1.42866392429822,34.1105861782349,275.15,79.495201431303,0.775,0.793096912909235,0.0,48.732563909509686 +2000.0,0.0,43500.0,1.69672297450453,27.4562797051368,275.15,79.495201431303,0.75,0.767513141525066,0.0,46.585700570128076 +2000.0,0.0,42050.0,2.02976391081085,22.0427161641825,275.15,79.495201431303,0.725,0.741929370140897,0.0,44.74150976630461 +2000.0,0.0,40600.0,2.52252750412449,17.0250742966338,275.15,79.495201431303,0.7,0.716345598756728,0.0,42.94621817302166 +2000.0,0.0,0.0,0.0,0.0,275.15,79.495201431303,0.0,0.0,0.0,0.0 +2000.0,0.05,58000.0,0.513998514586902,214.194454653585,275.287797113977,79.6344377189261,1.0,1.02309470081355,59.8602712653275,110.09563152469424 +2000.0,0.05,56550.0,0.518292761439053,193.248370151508,275.287797113977,79.6344377189261,0.975,0.997517333293213,59.8602712653275,100.15923140942135 +2000.0,0.05,55100.0,0.526954837499877,173.679538868261,275.287797113977,79.6344377189261,0.95,0.971939965772874,59.8602712653275,91.52127318137805 +2000.0,0.05,53650.0,0.549638241152388,152.602234420244,275.287797113977,79.6344377189261,0.925,0.946362598252535,59.8602712653275,83.87602372266733 +2000.0,0.05,52200.0,0.588924479021849,130.206082713338,275.287797113977,79.6344377189261,0.9,0.920785230732197,59.8602712653275,76.68154942742835 +2000.0,0.05,50750.0,0.662263113328942,104.324346491018,275.287797113977,79.6344377189261,0.875,0.895207863211858,59.8602712653275,69.09016650314888 +2000.0,0.05,49300.0,0.787023024813282,78.4974207861195,275.287797113977,79.6344377189261,0.85,0.869630495691519,59.8602712653275,61.77927754713277 +2000.0,0.05,47850.0,0.96477046936105,57.9481248111078,275.287797113977,79.6344377189261,0.825,0.84405312817118,59.8602712653275,55.90663957260519 +2000.0,0.05,46400.0,1.18493401412138,43.5394583586965,275.287797113977,79.6344377189261,0.8,0.818475760650841,59.8602712653275,51.591385165640915 +2000.0,0.05,44950.0,1.42299961041599,34.2275854226577,275.287797113977,79.6344377189261,0.775,0.792898393130502,59.8602712653275,48.70584072192192 +2000.0,0.05,43500.0,1.68953382430745,27.5545073182161,275.287797113977,79.6344377189261,0.75,0.767321025610164,59.8602712653275,46.55427212625327 +2000.0,0.05,42050.0,2.02157328496948,22.1156665748395,275.287797113977,79.6344377189261,0.725,0.741743658089825,59.8602712653275,44.70844072698802 +2000.0,0.05,40600.0,2.51233778089155,17.0812536237758,275.287797113977,79.6344377189261,0.7,0.716166290569486,59.8602712653275,42.913878824002644 +2000.0,0.05,0.0,0.0,0.0,275.287797113977,79.6344377189261,0.0,0.0,59.8602712653275,0.0 +2000.0,0.1,58000.0,0.510919083743302,216.065589871836,275.70118845591,80.0531911732792,1.0,1.0223273897384,119.720542530655,110.39203320577452 +2000.0,0.1,56550.0,0.515125202745729,194.911234844513,275.70118845591,80.0531911732792,0.975,0.996769204994944,119.720542530655,100.40368936670016 +2000.0,0.1,55100.0,0.523544919442829,175.258927837278,275.70118845591,80.0531911732792,0.95,0.971211020251484,119.720542530655,91.75592125620429 +2000.0,0.1,53650.0,0.546104394811035,153.922796754545,275.70118845591,80.0531911732792,0.925,0.945652835508024,119.720542530655,84.05791576926275 +2000.0,0.1,52200.0,0.584972407301244,131.296458225794,275.70118845591,80.0531911732792,0.9,0.920094650764564,119.720542530655,76.80480523846994 +2000.0,0.1,50750.0,0.657612822883715,105.15383292654,275.70118845591,80.0531911732792,0.875,0.894536466021103,119.720542530655,69.15050890786452 +2000.0,0.1,49300.0,0.78139803562091,79.0433486403363,275.70118845591,80.0531911732792,0.85,0.868978281277643,119.720542530655,61.76431735645752 +2000.0,0.1,47850.0,0.956657672643004,58.3836603153741,275.70118845591,80.0531911732792,0.825,0.843420096534183,119.720542530655,55.853176597685504 +2000.0,0.1,46400.0,1.17240468553146,43.9430413111819,275.70118845591,80.0531911732792,0.8,0.817861911790723,119.720542530655,51.51902752973217 +2000.0,0.1,44950.0,1.4060986663735,34.579567492174,275.70118845591,80.0531911732792,0.775,0.792303727047263,119.720542530655,48.6222837345183 +2000.0,0.1,43500.0,1.66820357321683,27.852059961693,275.70118845591,80.0531911732792,0.75,0.766745542303803,119.720542530655,46.46290594954567 +2000.0,0.1,42050.0,1.99603555324785,22.3509269040472,275.70118845591,80.0531911732792,0.725,0.741187357560343,119.720542530655,44.613244748522106 +2000.0,0.1,40600.0,2.4821583380156,17.2427048424978,275.70118845591,80.0531911732792,0.7,0.715629172816883,119.720542530655,42.79912359474788 +2000.0,0.1,0.0,0.0,0.0,275.70118845591,80.0531911732792,0.0,0.0,119.720542530655,0.0 +2000.0,0.15,58000.0,0.505940469287619,219.170507032382,276.390174025797,80.7546033876493,1.0,1.02105236552231,179.580813795983,110.88722918196876 +2000.0,0.15,56550.0,0.509876075856986,197.741197803105,276.390174025797,80.7546033876493,0.975,0.995526056384251,179.580813795983,100.82350597110724 +2000.0,0.15,55100.0,0.517965667072572,177.90754201704,276.390174025797,80.7546033876493,0.95,0.969999747246193,179.580813795983,92.14999867809775 +2000.0,0.15,53650.0,0.540326499367254,156.13910437807,276.390174025797,80.7546033876493,0.925,0.944473438108135,179.580813795983,84.36609568294084 +2000.0,0.15,52200.0,0.578528560029528,133.112833708327,276.390174025797,80.7546033876493,0.9,0.918947128970078,179.580813795983,77.00957600672844 +2000.0,0.15,50750.0,0.650061689936006,106.523511684329,276.390174025797,80.7546033876493,0.875,0.89342081983202,179.580813795983,69.24685402343279 +2000.0,0.15,49300.0,0.772130195036696,79.9603355666991,276.390174025797,80.7546033876493,0.85,0.867894510693962,179.580813795983,61.73978949631503 +2000.0,0.15,47850.0,0.943383685282142,59.1134126225871,276.390174025797,80.7546033876493,0.825,0.842368201555904,179.580813795983,55.76662904950011 +2000.0,0.15,46400.0,1.15182262373302,44.6256045231463,276.390174025797,80.7546033876493,0.8,0.816841892417847,179.580813795983,51.4007808875225 +2000.0,0.15,44950.0,1.37839265567595,35.1750628777158,276.390174025797,80.7546033876493,0.775,0.791315583279789,179.580813795983,48.48504833358321 +2000.0,0.15,43500.0,1.63334259022189,28.3538801484714,276.390174025797,80.7546033876493,0.75,0.765789274141731,179.580813795983,46.31160004454531 +2000.0,0.15,42050.0,1.95393164948942,22.7457146696403,276.390174025797,80.7546033876493,0.725,0.740262965003674,179.580813795983,44.44357178326597 +2000.0,0.15,40600.0,2.43216017712677,17.5175992884029,276.390174025797,80.7546033876493,0.7,0.714736655865616,179.580813795983,42.60560738811777 +2000.0,0.15,0.0,0.0,0.0,276.390174025797,80.7546033876493,0.0,0.0,179.580813795983,0.0 +2000.0,0.2,58000.0,0.499232130684788,223.499410948191,277.35475382364,81.7439364407149,1.0,1.01927531957574,239.44108506131,111.57808713446043 +2000.0,0.2,56550.0,0.502718503653552,201.74576590171,277.35475382364,81.7439364407149,0.975,0.993793436586342,239.44108506131,101.42132955254743 +2000.0,0.2,55100.0,0.510439467551189,181.625973772937,277.35475382364,81.7439364407149,0.95,0.968311553596949,239.44108506131,92.70906534612416 +2000.0,0.2,53650.0,0.532446869721074,159.26960906653,277.35475382364,81.7439364407149,0.925,0.942829670607555,239.44108506131,84.80260478917309 +2000.0,0.2,52200.0,0.569771402012033,135.661668382115,277.35475382364,81.7439364407149,0.9,0.917347787618162,239.44108506131,77.29613899336915 +2000.0,0.2,50750.0,0.639810490337827,108.43542661099,277.35475382364,81.7439364407149,0.875,0.891865904628768,239.44108506131,69.37812346996897 +2000.0,0.2,49300.0,0.759387811981252,81.2584775475928,277.35475382364,81.7439364407149,0.85,0.866384021639375,239.44108506131,61.70669746979419 +2000.0,0.2,47850.0,0.925360676952596,60.138363527241,277.35475382364,81.7439364407149,0.825,0.840902138649982,239.44108506131,55.649676784389044 +2000.0,0.2,46400.0,1.12346899321624,45.6108797381169,277.35475382364,81.7439364407149,0.8,0.815420255660588,239.44108506131,51.2424091390892 +2000.0,0.2,44950.0,1.34057128208328,36.0265684010973,277.35475382364,81.7439364407149,0.775,0.789938372671195,239.44108506131,48.296182990519995 +2000.0,0.2,43500.0,1.58591300908105,29.0694892137872,277.35475382364,81.7439364407149,0.75,0.764456489681801,239.44108506131,46.101681111486386 +2000.0,0.2,42050.0,1.89686191592384,23.3095712875742,277.35475382364,81.7439364407149,0.725,0.738974606692408,239.44108506131,44.21503805191133 +2000.0,0.2,40600.0,2.3640887401846,17.9122257023548,277.35475382364,81.7439364407149,0.7,0.713492723703015,239.44108506131,42.34609109458217 +2000.0,0.2,0.0,0.0,0.0,277.35475382364,81.7439364407149,0.0,0.0,239.44108506131,0.0 +2000.0,0.25,58000.0,0.490943210954541,229.083884602049,278.594927849437,83.0286121259999,1.0,1.01700412121317,299.301356326638,112.46717788446948 +2000.0,0.25,56550.0,0.493825203742373,206.98265691698,278.594927849437,83.0286121259999,0.975,0.991579018182845,299.301356326638,102.21325272316534 +2000.0,0.25,55100.0,0.501186802222428,186.431460591808,278.594927849437,83.0286121259999,0.95,0.966153915152516,299.301356326638,93.43698756766484 +2000.0,0.25,53650.0,0.52264881073961,163.35157559787,278.594927849437,83.0286121259999,0.925,0.940728812122187,299.301356326638,85.37550671866826 +2000.0,0.25,52200.0,0.55891656606103,138.962133832492,278.594927849437,83.0286121259999,0.9,0.915303709091857,299.301356326638,77.6682386541697 +2000.0,0.25,50750.0,0.627151765084877,110.880795710008,278.594927849437,83.0286121259999,0.875,0.889878606061528,299.301356326638,69.53908674354717 +2000.0,0.25,49300.0,0.743417723081925,82.9462259129654,278.594927849437,83.0286121259999,0.85,0.864453503031198,299.301356326638,61.663694406455704 +2000.0,0.25,47850.0,0.902422639815665,61.497550318509,278.594927849437,83.0286121259999,0.825,0.839028400000869,299.301356326638,55.496781700625576 +2000.0,0.25,46400.0,1.08805487679301,46.9318427594,278.594927849437,83.0286121259999,0.8,0.81360329697054,299.301356326638,51.064420391247886 +2000.0,0.25,44950.0,1.29379201367826,37.1450034063478,278.594927849437,83.0286121259999,0.775,0.78817819394021,299.301356326638,48.05790875518454 +2000.0,0.25,43500.0,1.52724022403009,30.0105866069096,278.594927849437,83.0286121259999,0.75,0.762753090909881,299.301356326638,45.83337501281104 +2000.0,0.25,42050.0,1.82625085802079,24.0544040573426,278.594927849437,83.0286121259999,0.725,0.737327987879551,299.301356326638,43.92937604890069 +2000.0,0.25,40600.0,2.27925095605852,18.434278259216,278.594927849437,83.0286121259999,0.7,0.711902884849222,299.301356326638,42.01634634656686 +2000.0,0.25,0.0,0.0,0.0,278.594927849437,83.0286121259999,0.0,0.0,299.301356326638,0.0 +2000.0,0.3,58000.0,0.481312194233186,235.949797564156,280.110696103189,84.618267061966,1.0,1.01424872185047,359.161627591965,113.56551479447997 +2000.0,0.3,56550.0,0.483411445566456,213.536169122694,280.110696103189,84.618267061966,0.975,0.988892503804209,359.161627591965,103.22582819632473 +2000.0,0.3,55100.0,0.490485005697224,192.340298597972,280.110696103189,84.618267061966,0.95,0.963536285757948,359.161627591965,94.34003245363206 +2000.0,0.3,53650.0,0.511129913146882,168.431204556053,280.110696103189,84.618267061966,0.925,0.938180067711686,359.161627591965,86.09022695596009 +2000.0,0.3,52200.0,0.54627806233195,143.008985787908,280.110696103189,84.618267061966,0.9,0.912823849665424,359.161627591965,78.12267165227576 +2000.0,0.3,50750.0,0.612417604594913,113.852681014766,280.110696103189,84.618267061966,0.875,0.887467631619162,359.161627591965,69.72538618377173 +2000.0,0.3,49300.0,0.724501331066055,85.0427936768085,280.110696103189,84.618267061966,0.85,0.8621114135729,359.161627591965,61.61361721642364 +2000.0,0.3,47850.0,0.875007223444898,63.2213183382253,280.110696103189,84.618267061966,0.825,0.836755195526639,359.161627591965,55.31911022165654 +2000.0,0.3,46400.0,1.0468720270292,48.5772676411829,280.110696103189,84.618267061966,0.8,0.811398977480377,359.161627591965,50.85418264306511 +2000.0,0.3,44950.0,1.23898811000289,38.5602010579051,280.110696103189,84.618267061966,0.775,0.786042759434115,359.161627591965,47.77563063006528 +2000.0,0.3,43500.0,1.45886596464954,31.196860542239,280.110696103189,84.618267061966,0.75,0.760686541387853,359.161627591965,45.512038048990675 +2000.0,0.3,42050.0,1.7440198811413,24.9846441432261,280.110696103189,84.618267061966,0.725,0.735330323341591,359.161627591965,43.573716109026854 +2000.0,0.3,40600.0,2.22439955238856,18.3610232895413,280.110696103189,84.618267061966,0.7,0.70997410529533,359.161627591965,40.84225198665159 +2000.0,0.3,0.0,0.0,0.0,280.110696103189,84.618267061966,0.0,0.0,359.161627591965,0.0 +2000.0,0.35,58000.0,0.470566372455659,244.132662822051,281.902058584896,86.5248238705945,1.0,1.01102103578495,419.021898857293,114.88062154211308 +2000.0,0.35,56550.0,0.471779071681757,221.429485396085,281.902058584896,86.5248238705945,0.975,0.985745509890324,419.021898857293,104.46579706313415 +2000.0,0.35,55100.0,0.478606798245897,199.386389652093,281.902058584896,86.5248238705945,0.95,0.960469983995701,419.021898857293,95.42768156519708 +2000.0,0.35,53650.0,0.498152985137602,174.60167917058,281.902058584896,86.5248238705945,0.925,0.935194458101077,419.021898857293,86.9783476888623 +2000.0,0.35,52200.0,0.532149599633283,147.79918290782,281.902058584896,86.5248238705945,0.9,0.909918932206453,419.021898857293,78.65127601052278 +2000.0,0.35,50750.0,0.596055825341059,117.300089959081,281.902058584896,86.5248238705945,0.875,0.884643406311829,419.021898857293,69.9174019331405 +2000.0,0.35,49300.0,0.702768369468572,87.603531790668,281.902058584896,86.5248238705945,0.85,0.859367880417206,419.021898857293,61.56499119621596 +2000.0,0.35,47850.0,0.843455670817316,65.3619111562417,281.902058584896,86.5248238705945,0.825,0.834092354522582,419.021898857293,55.12987462018965 +2000.0,0.35,46400.0,1.00062754679037,50.5876558682368,281.902058584896,86.5248238705945,0.8,0.808816828627958,419.021898857293,50.61940198930926 +2000.0,0.35,44950.0,1.17751547849603,40.3045624359361,281.902058584896,86.5248238705945,0.775,0.783541302733334,419.021898857293,47.45924612232441 +2000.0,0.35,43500.0,1.38261523588192,32.6536229148696,281.902058584896,86.5248238705945,0.75,0.758265776838711,419.021898857293,45.1473965488417 +2000.0,0.35,42050.0,1.65968933222744,25.845334524983,281.902058584896,86.5248238705945,0.725,0.732990250944087,419.021898857293,42.89522599896383 +2000.0,0.35,40600.0,2.1101137137546,19.1389319939315,281.902058584896,86.5248238705945,0.7,0.707714725049463,419.021898857293,40.38532286701153 +2000.0,0.35,0.0,0.0,0.0,281.902058584896,86.5248238705945,0.0,0.0,419.021898857293,0.0 +3000.0,0.0,58000.0,0.516198592397567,195.639492579802,268.65,70.108523423274,1.0,1.03565687626109,0.0,100.98883068706806 +3000.0,0.0,56550.0,0.517518224001758,178.107075009453,268.65,70.108523423274,0.975,1.00976545435457,0.0,92.17365714104001 +3000.0,0.0,55100.0,0.526298404523301,159.542557524104,268.65,70.108523423274,0.95,0.983874032448039,0.0,83.96699347850291 +3000.0,0.0,53650.0,0.542169860110265,141.998290178002,268.65,70.108523423274,0.925,0.957982610541512,0.0,76.98719312170417 +3000.0,0.0,52200.0,0.577299820106671,122.140961867175,268.65,70.108523423274,0.9,0.932091188634984,0.0,70.5119553135759 +3000.0,0.0,50750.0,0.635607020742967,100.847615486545,268.65,70.108523423274,0.875,0.906199766728457,0.0,64.09945242843517 +3000.0,0.0,49300.0,0.74551022679156,77.029406676729,268.65,70.108523423274,0.85,0.88030834482193,0.0,57.426210441187536 +3000.0,0.0,47850.0,0.91260806276764,56.8060837234955,268.65,70.108523423274,0.825,0.854416922915402,0.0,51.84169002031559 +3000.0,0.0,46400.0,1.13593142382492,41.88698292111,268.65,70.108523423274,0.8,0.828525501008875,0.0,47.580740149306585 +3000.0,0.0,44950.0,1.38709060620493,32.2798747866438,268.65,70.108523423274,0.775,0.802634079102348,0.0,44.775111086024985 +3000.0,0.0,43500.0,1.66645574471295,25.7003648976502,268.65,70.108523423274,0.75,0.77674265719582,0.0,42.82852072490822 +3000.0,0.0,42050.0,2.00192509947777,20.6096542931463,268.65,70.108523423274,0.725,0.750851235289293,0.0,41.25898422100936 +3000.0,0.0,40600.0,2.47533674011158,16.0905941489086,268.65,70.108523423274,0.7,0.724959813382765,0.0,39.82963886701788 +3000.0,0.0,0.0,0.0,0.0,268.65,70.108523423274,0.0,0.0,0.0,0.0 +3000.0,0.05,58000.0,0.515231915059655,196.194005351224,268.784550610546,70.2313268802712,1.0,1.03539762455165,59.1509135005756,101.08541310033536 +3000.0,0.05,56550.0,0.516512621894976,178.58707151681,268.784550610546,70.2313268802712,0.975,1.00951268393785,59.1509135005756,92.24247654569312 +3000.0,0.05,55100.0,0.525172172581759,160.029535187731,268.784550610546,70.2313268802712,0.95,0.983627743324063,59.1509135005756,84.04305867178974 +3000.0,0.05,53650.0,0.541029319101805,142.406353030404,268.784550610546,70.2313268802712,0.925,0.957742802710272,59.1509135005756,77.04601221581073 +3000.0,0.05,52200.0,0.575988523705559,122.497476600987,268.784550610546,70.2313268802712,0.9,0.931857862096481,59.1509135005756,70.55714070505876 +3000.0,0.05,50750.0,0.634221898516558,101.09491519428,268.784550610546,70.2313268802712,0.875,0.90597292148269,59.1509135005756,64.11660904488669 +3000.0,0.05,49300.0,0.743690340587394,77.2205723755214,268.784550610546,70.2313268802712,0.85,0.880087980868899,59.1509135005756,57.42819377030502 +3000.0,0.05,47850.0,0.910238011377281,56.9410124794452,268.784550610546,70.2313268802712,0.825,0.854203040255108,59.1509135005756,51.82987396509914 +3000.0,0.05,46400.0,1.13211118338588,42.0112243748278,268.784550610546,70.2313268802712,0.8,0.828318099641316,59.1509135005756,47.56137694247602 +3000.0,0.05,44950.0,1.38149285186014,32.3952482558376,268.784550610546,70.2313268802712,0.775,0.802433159027525,59.1509135005756,44.75380389967431 +3000.0,0.05,43500.0,1.65940716359725,25.7917096490945,268.784550610546,70.2313268802712,0.75,0.776548218413734,59.1509135005756,42.79894775312773 +3000.0,0.05,42050.0,1.99374360102655,20.6815217588909,268.784550610546,70.2313268802712,0.725,0.750663277799943,59.1509135005756,41.23365166628009 +3000.0,0.05,40600.0,2.4653435716055,16.1429138507143,268.784550610546,70.2313268802712,0.7,0.724778337186152,59.1509135005756,39.79782888883989 +3000.0,0.05,0.0,0.0,0.0,268.784550610546,70.2313268802712,0.0,0.0,59.1509135005756,0.0 +3000.0,0.1,58000.0,0.512345912060705,197.86374949014,269.188202442184,70.6006586189506,1.0,1.0346210360193,118.301827001151,101.37468319627664 +3000.0,0.1,56550.0,0.513413933056788,180.101323052972,269.188202442184,70.6006586189506,0.975,1.00875551011882,118.301827001151,92.4665286173575 +3000.0,0.1,55100.0,0.52175065401875,161.479481606083,269.188202442184,70.6006586189506,0.95,0.982889984218339,118.301827001151,84.25202513858251 +3000.0,0.1,53650.0,0.537576876437044,143.647704717215,269.188202442184,70.6006586189506,0.925,0.957024458317857,118.301827001151,77.22168440923126 +3000.0,0.1,52200.0,0.572048276498673,123.573915217015,269.188202442184,70.6006586189506,0.9,0.931158932417374,118.301827001151,70.69024522008657 +3000.0,0.1,50750.0,0.629858992528352,101.905019044549,269.188202442184,70.6006586189506,0.875,0.905293406516891,118.301827001151,64.18579262898216 +3000.0,0.1,49300.0,0.738307215403671,77.7996067229204,269.188202442184,70.6006586189506,0.85,0.879427880616409,118.301827001151,57.44001099910008 +3000.0,0.1,47850.0,0.903148621554008,57.3434133381391,269.188202442184,70.6006586189506,0.825,0.853562354715926,118.301827001151,51.78962471154205 +3000.0,0.1,46400.0,1.12074221435107,42.3846174863529,269.188202442184,70.6006586189506,0.8,0.827696828815443,118.301827001151,47.50223005607823 +3000.0,0.1,44950.0,1.36543973089148,32.7185689600467,269.188202442184,70.6006586189506,0.775,0.801831302914961,118.301827001151,44.675233995960504 +3000.0,0.1,43500.0,1.63845504536074,26.0687311518205,269.188202442184,70.6006586189506,0.75,0.775965777014478,118.301827001151,42.71244408185299 +3000.0,0.1,42050.0,1.96772503810352,20.9056456117382,269.188202442184,70.6006586189506,0.725,0.750100251113995,118.301827001151,41.13656230793624 +3000.0,0.1,40600.0,2.43414831939933,16.3053846163222,269.188202442184,70.6006586189506,0.7,0.724234725213513,118.301827001151,39.68972456098037 +3000.0,0.1,0.0,0.0,0.0,269.188202442184,70.6006586189506,0.0,0.0,118.301827001151,0.0 +3000.0,0.15,58000.0,0.507623659124732,200.648460035772,269.860955494913,71.219289639328,1.0,1.03333059590403,177.452740501727,101.85390548110112 +3000.0,0.15,56550.0,0.508354033233313,182.639513091272,269.860955494913,71.219289639328,0.975,1.00749733100643,177.452740501727,92.84553310771658 +3000.0,0.15,55100.0,0.516147431309761,163.916869291261,269.860955494913,71.219289639328,0.95,0.981664066108829,177.452740501727,84.60527103302222 +3000.0,0.15,53650.0,0.53193673873951,145.727056071528,269.860955494913,71.219289639328,0.925,0.955830801211228,177.452740501727,77.51757495279831 +3000.0,0.15,52200.0,0.565577151470904,125.385421266134,269.860955494913,71.219289639328,0.9,0.929997536313627,177.452740501727,70.91512939567939 +3000.0,0.15,50750.0,0.622738403664192,103.254690685758,269.860955494913,71.219289639328,0.875,0.904164271416027,177.452740501727,64.30066124848885 +3000.0,0.15,49300.0,0.729483424920677,78.7676699438951,269.860955494913,71.219289639328,0.85,0.878331006518426,177.452740501727,57.45970964369407 +3000.0,0.15,47850.0,0.891377571043883,58.0225717220937,269.860955494913,71.219289639328,0.825,0.852497741620825,177.452740501727,51.72001904735938 +3000.0,0.15,46400.0,1.10212242624491,43.011546952595,269.860955494913,71.219289639328,0.8,0.826664476723224,177.452740501727,47.403990483940866 +3000.0,0.15,44950.0,1.33916696062851,33.2638563590631,269.860955494913,71.219289639328,0.775,0.800831211825623,177.452740501727,44.54585741914986 +3000.0,0.15,43500.0,1.60422105198309,26.5349844446992,269.860955494913,71.219289639328,0.75,0.774997946928023,177.452740501727,42.56798066023028 +3000.0,0.15,42050.0,1.92529334753574,21.2868541154318,269.860955494913,71.219289639328,0.725,0.749164682030422,177.452740501727,40.98343861840464 +3000.0,0.15,40600.0,2.38352766396669,16.5791994398573,269.860955494913,71.219289639328,0.7,0.723331417132821,177.452740501727,39.51698051132093 +3000.0,0.15,0.0,0.0,0.0,269.860955494913,71.219289639328,0.0,0.0,177.452740501727,0.0 +3000.0,0.2,58000.0,0.501185432900655,204.553991144178,270.802809768734,72.0918612884988,1.0,1.0315320648,236.603654002302,102.5194806031516 +3000.0,0.2,56550.0,0.501480921468596,186.226500093892,270.802809768734,72.0918612884988,0.975,1.00574376318,236.603654002302,93.38903686895655 +3000.0,0.2,55100.0,0.508504270338231,167.375177042223,270.802809768734,72.0918612884988,0.95,0.979955461559997,236.603654002302,85.11099227458783 +3000.0,0.2,53650.0,0.524269528761642,148.660587591747,270.802809768734,72.0918612884988,0.925,0.954167159939997,236.603654002302,77.93821620215401 +3000.0,0.2,52200.0,0.556766921198546,127.94229372089,270.802809768734,72.0918612884988,0.9,0.928378858319997,236.603654002302,71.23403696605999 +3000.0,0.2,50750.0,0.613143633130921,105.122312806304,270.802809768734,72.0918612884988,0.875,0.902590556699997,236.603654002302,64.45507679718237 +3000.0,0.2,49300.0,0.717431075852181,80.1280916908039,270.802809768734,72.0918612884988,0.85,0.876802255079997,236.603654002302,57.48638302771565 +3000.0,0.2,47850.0,0.875135412441549,58.9887447443547,270.802809768734,72.0918612884988,0.825,0.851013953459997,236.603654002302,51.6231394612601 +3000.0,0.2,46400.0,1.07666913219795,43.9044758421852,270.802809768734,72.0918612884988,0.8,0.825225651839997,236.603654002302,47.2705939046114 +3000.0,0.2,44950.0,1.30327148119615,34.0429892996113,270.802809768734,72.0918612884988,0.775,0.799437350219997,236.603654002302,44.36725708884911 +3000.0,0.2,43500.0,1.55759115970373,27.201651536094,270.802809768734,72.0918612884988,0.75,0.773649048599997,236.603654002302,42.369051961961404 +3000.0,0.2,42050.0,1.86760996407068,21.8302868028718,270.802809768734,72.0918612884988,0.725,0.747860746979997,236.603654002302,40.77046115156404 +3000.0,0.2,40600.0,2.3145523285331,16.9696338616178,270.802809768734,72.0918612884988,0.7,0.722072445359997,236.603654002302,39.27710556876162 +3000.0,0.2,0.0,0.0,0.0,270.802809768734,72.0918612884988,0.0,0.0,236.603654002302,0.0 +3000.0,0.25,58000.0,0.493044736925006,209.741876091979,272.013765263647,73.2249198647342,1.0,1.02923340767317,295.754567502878,103.41212811992699 +3000.0,0.25,56550.0,0.493016086818814,190.906702601767,272.013765263647,73.2249198647342,0.975,1.00350257248134,295.754567502878,94.12007546420625 +3000.0,0.25,55100.0,0.498999810156414,171.900234685622,272.013765263647,73.2249198647342,0.95,0.977771737289507,295.754567502878,85.77818447396838 +3000.0,0.25,53650.0,0.514758053908504,152.496215317938,272.013765263647,73.2249198647342,0.925,0.952040902097678,295.754567502878,78.49865502547398 +3000.0,0.25,52200.0,0.545908562471256,131.239726557535,272.013765263647,73.2249198647342,0.9,0.926310066905848,295.754567502878,71.64489046414464 +3000.0,0.25,50750.0,0.601429440402033,107.480498771677,272.013765263647,73.2249198647342,0.875,0.900579231714019,295.754567502878,64.6419362303811 +3000.0,0.25,49300.0,0.702430133887488,81.8855611304295,272.013765263647,73.2249198647342,0.85,0.87484839652219,295.754567502878,57.518885668299674 +3000.0,0.25,47850.0,0.854709778303298,60.2570342136682,272.013765263647,73.2249198647342,0.825,0.849117561330361,295.754567502878,51.50227635397859 +3000.0,0.25,46400.0,1.04496328367278,45.0775541636288,272.013765263647,73.2249198647342,0.8,0.823386726138532,295.754567502878,47.10438901876314 +3000.0,0.25,44950.0,1.25864283323665,35.0732039986435,272.013765263647,73.2249198647342,0.775,0.797655890946703,295.754567502878,44.14463685153965 +3000.0,0.25,43500.0,1.49981457910647,28.0820201747691,272.013765263647,73.2249198647342,0.75,0.771925055754874,295.754567502878,42.11782326888072 +3000.0,0.25,42050.0,1.79627203198008,22.5473720061643,272.013765263647,73.2249198647342,0.725,0.746194220563044,295.754567502878,40.50121372932352 +3000.0,0.25,40600.0,2.27207002071196,16.8772709516511,272.013765263647,73.2249198647342,0.7,0.720463385371215,295.754567502878,38.34634136067927 +3000.0,0.25,0.0,0.0,0.0,272.013765263647,73.2249198647342,0.0,0.0,295.754567502878,0.0 +3000.0,0.3,58000.0,0.483212310229862,216.394931124031,273.493821979652,74.6269652298273,1.0,1.02644469688801,354.905481003454,104.56469459047489 +3000.0,0.3,56550.0,0.483149838965041,196.705730667205,273.493821979652,74.6269652298273,0.975,1.00078357946581,354.905481003454,95.03834209536082 +3000.0,0.3,55100.0,0.488056398822271,177.459517061511,273.493821979652,74.6269652298273,0.95,0.975122462043613,354.905481003454,86.61025283378042 +3000.0,0.3,53650.0,0.503668113657407,157.246369449317,273.493821979652,74.6269652298273,0.925,0.949461344621413,354.905481003454,79.19998228001322 +3000.0,0.3,52200.0,0.533363326042695,135.270507536815,273.493821979652,74.6269652298273,0.9,0.923800227199213,354.905481003454,72.14832781531908 +3000.0,0.3,50750.0,0.587742618221576,110.365769713501,273.493821979652,74.6269652298273,0.875,0.898139109777012,354.905481003454,64.8666664534526 +3000.0,0.3,49300.0,0.684916991699412,84.0270035167196,273.493821979652,74.6269652298273,0.85,0.872477992354812,354.905481003454,57.5515224701875 +3000.0,0.3,47850.0,0.830430214476331,61.849568649524,273.493821979652,74.6269652298273,0.825,0.846816874932611,354.905481003454,51.36175055889278 +3000.0,0.3,46400.0,1.00774747838925,46.5501145190164,273.493821979652,74.6269652298273,0.8,0.821155757510411,354.905481003454,46.91076052526959 +3000.0,0.3,44950.0,1.20633964836406,36.3788583081415,273.493821979652,74.6269652298273,0.775,0.795494640088211,354.905481003454,43.885259139329385 +3000.0,0.3,43500.0,1.43234395031108,29.1971445855973,273.493821979652,74.6269652298273,0.75,0.76983352266601,354.905481003454,41.8203534135382 +3000.0,0.3,42050.0,1.72122869963321,23.2197717618068,273.493821979652,74.6269652298273,0.725,0.74417240524381,354.905481003454,39.96653755535465 +3000.0,0.3,40600.0,2.17167754759247,17.4911434746984,273.493821979652,74.6269652298273,0.7,0.71851128782161,354.905481003454,37.985123565721054 +3000.0,0.3,0.0,0.0,0.0,273.493821979652,74.6269652298273,0.0,0.0,354.905481003454,0.0 +3000.0,0.35,58000.0,0.472377875256421,224.117498662516,275.242979916748,76.3085135953898,1.0,1.02317799153118,414.056394504029,105.86814782598309 +3000.0,0.35,56550.0,0.472087318262611,203.654671541338,275.242979916748,76.3085135953898,0.975,0.997598541742899,414.056394504029,96.14278773960314 +3000.0,0.35,55100.0,0.475974871527027,184.106553281819,275.242979916748,76.3085135953898,0.95,0.97201909195462,414.056394504029,87.63009304559755 +3000.0,0.35,53650.0,0.491299920063109,162.913180056173,275.242979916748,76.3085135953898,0.925,0.94643964216634,414.056394504029,80.03923233882468 +3000.0,0.35,52200.0,0.519409889904715,140.03975178673,275.242979916748,76.3085135953898,0.9,0.920860192378061,414.056394504029,72.73803205782905 +3000.0,0.35,50750.0,0.572378922906064,113.782313899562,275.242979916748,76.3085135953898,0.875,0.895280742589781,414.056394504029,65.12659827559096 +3000.0,0.35,49300.0,0.665146477769296,86.5752299323786,275.242979916748,76.3085135953898,0.85,0.869701292801502,414.056394504029,57.58520925158856 +3000.0,0.35,47850.0,0.802663251930636,63.7955835720671,275.242979916748,76.3085135953898,0.825,0.844121843013222,414.056394504029,51.206370568768044 +3000.0,0.35,46400.0,0.965734318974126,48.3510479578558,275.242979916748,76.3085135953898,0.8,0.818542393224943,414.056394504029,46.69426637126517 +3000.0,0.35,44950.0,1.14773031129811,37.9887663411447,275.242979916748,76.3085135953898,0.775,0.792962943436663,414.056394504029,43.60085861855317 +3000.0,0.35,43500.0,1.35782527889575,30.5736206223629,275.242979916748,76.3085135953898,0.75,0.767383493648384,414.056394504029,41.51363494841276 +3000.0,0.35,42050.0,1.6277387689257,24.3404742354921,275.242979916748,76.3085135953898,0.725,0.741804043860104,414.056394504029,39.619933567147626 +3000.0,0.35,40600.0,2.0580200828216,18.2525946417168,275.242979916748,76.3085135953898,0.7,0.716224594071825,414.056394504029,37.564206336255104 +3000.0,0.35,0.0,0.0,0.0,275.242979916748,76.3085135953898,0.0,0.0,414.056394504029,0.0 +4000.0,0.0,58000.0,0.516638281867925,178.956148146694,262.15,61.6402085371994,1.0,1.04841779681353,0.0,92.45559690820986 +4000.0,0.0,56550.0,0.517698996617252,164.099830469518,262.15,61.6402085371994,0.975,1.02220735189319,0.0,84.95431757913063 +4000.0,0.0,55100.0,0.525209218898279,147.045180231338,262.15,61.6402085371994,0.95,0.995996906972856,0.0,77.22948425205769 +4000.0,0.0,53650.0,0.537282838606111,131.501113827668,262.15,61.6402085371994,0.925,0.969786462052518,0.0,70.65329171719479 +4000.0,0.0,52200.0,0.566777606055763,114.39213394041,262.15,61.6402085371994,0.9,0.94357601713218,0.0,64.83489982635578 +4000.0,0.0,50750.0,0.615639115570513,96.2801220887395,262.15,61.6402085371994,0.875,0.917365572211841,0.0,59.2738092097326 +4000.0,0.0,49300.0,0.707528060515687,75.6053666021411,262.15,61.6402085371994,0.85,0.891155127291503,0.0,53.49291839659039 +4000.0,0.0,47850.0,0.86127605780735,55.9637237486576,262.15,61.6402085371994,0.825,0.864944682371165,0.0,48.20021537046338 +4000.0,0.0,46400.0,1.08140224846311,40.784742447101,262.15,61.6402085371994,0.8,0.838734237450826,0.0,44.10471218528387 +4000.0,0.0,44950.0,1.34659370617067,30.7113471726083,262.15,61.6402085371994,0.775,0.812523792530488,0.0,41.35570681065674 +4000.0,0.0,43500.0,1.64321324926485,24.0962641608192,262.15,61.6402085371994,0.75,0.78631334761015,0.0,39.59530052684387 +4000.0,0.0,42050.0,1.99155360744515,19.2292285894136,262.15,61.6402085371994,0.725,0.760102902689811,0.0,38.296039565634075 +4000.0,0.0,40600.0,2.45997578782358,15.1243510158406,262.15,61.6402085371994,0.7,0.733892457769473,0.0,37.20553730551285 +4000.0,0.0,0.0,0.0,0.0,262.15,61.6402085371994,0.0,0.0,0.0,0.0 +4000.0,0.05,58000.0,0.515718549742496,179.461260957381,262.281303684007,61.7481857507349,1.0,1.04815533366707,58.4328508421484,92.55150123590015 +4000.0,0.05,56550.0,0.516669155633388,164.564005923171,262.281303684007,61.7481857507349,0.975,1.02195145032539,58.4328508421484,85.02514598797262 +4000.0,0.05,55100.0,0.524093387193184,147.458148552501,262.281303684007,61.7481857507349,0.95,0.995747566983717,58.4328508421484,77.28184054411595 +4000.0,0.05,53650.0,0.536108567854045,131.895209701211,262.281303684007,61.7481857507349,0.925,0.96954368364204,58.4328508421484,70.71015197972518 +4000.0,0.05,52200.0,0.565545873010277,114.716405982292,262.281303684007,61.7481857507349,0.9,0.943339800300364,58.4328508421484,64.8773899698567 +4000.0,0.05,50750.0,0.614212120107261,96.5530506540875,262.281303684007,61.7481857507349,0.875,0.917135916958687,58.4328508421484,59.30405394507085 +4000.0,0.05,49300.0,0.705841729967435,75.8030453697481,262.281303684007,61.7481857507349,0.85,0.89093203361701,58.4328508421484,53.50495268058297 +4000.0,0.05,47850.0,0.859104489425206,56.0955551086461,262.281303684007,61.7481857507349,0.825,0.864728150275333,58.4328508421484,48.191943230636916 +4000.0,0.05,46400.0,1.07814530639424,40.8877165887748,262.281303684007,61.7481857507349,0.8,0.838524266933656,58.4328508421484,44.08289972936546 +4000.0,0.05,44950.0,1.3413713649141,30.8152345613731,262.281303684007,61.7481857507349,0.775,0.81232038359198,58.4328508421484,41.33467324373718 +4000.0,0.05,43500.0,1.6363091413416,24.1796892362239,262.281303684007,61.7481857507349,0.75,0.786116500250303,58.4328508421484,39.56544653203226 +4000.0,0.05,42050.0,1.98263996649043,19.3003093545278,262.281303684007,61.7481857507349,0.725,0.759912616908626,58.4328508421484,38.265564691915934 +4000.0,0.05,40600.0,2.44952867467539,15.1753102954739,262.281303684007,61.7481857507349,0.7,0.733708733566949,58.4328508421484,37.17235771585998 +4000.0,0.05,0.0,0.0,0.0,262.281303684007,61.7481857507349,0.0,0.0,58.4328508421484,0.0 +4000.0,0.1,58000.0,0.512933719785062,180.987461006568,262.675214736028,62.0729275737883,1.0,1.04736912535132,116.865701684297,92.83457160855278 +4000.0,0.1,56550.0,0.513583714575495,165.986526452651,262.675214736028,62.0729275737883,0.975,1.02118489721753,116.865701684297,85.24797682503616 +4000.0,0.1,55100.0,0.520828743115578,148.736826411575,262.675214736028,62.0729275737883,0.95,0.995000669083752,116.865701684297,77.46641435494053 +4000.0,0.1,53650.0,0.532572195102974,133.0967600745,262.675214736028,62.0729275737883,0.925,0.968816440949969,116.865701684297,70.88363367397034 +4000.0,0.1,52200.0,0.561835821096151,115.69705645734,262.675214736028,62.0729275737883,0.9,0.942632212816186,116.865701684297,65.00275071311736 +4000.0,0.1,50750.0,0.610020844493543,97.3398208671766,262.675214736028,62.0729275737883,0.875,0.916447984682403,116.865701684297,59.379319728245264 +4000.0,0.1,49300.0,0.700814883149515,76.3816585593923,262.675214736028,62.0729275737883,0.85,0.89026375654862,116.865701684297,53.529403118066675 +4000.0,0.1,47850.0,0.852606428977874,56.4915958370926,262.675214736028,62.0729275737883,0.825,0.864079528414837,116.865701684297,48.16509779392486 +4000.0,0.1,46400.0,1.06829204463706,41.2124099743184,262.675214736028,62.0729275737883,0.8,0.837895300281054,116.865701684297,44.02688971588537 +4000.0,0.1,44950.0,1.32630913954704,31.1100782357251,262.675214736028,62.0729275737883,0.775,0.811711072147271,116.865701684297,41.26158109606566 +4000.0,0.1,43500.0,1.6157012281043,24.4363880379284,262.675214736028,62.0729275737883,0.75,0.785526844013488,116.865701684297,39.48190216331414 +4000.0,0.1,42050.0,1.95625449809703,19.514952149108,262.675214736028,62.0729275737883,0.725,0.759342615879705,116.865701684297,38.17621292184083 +4000.0,0.1,40600.0,2.4619611768912,14.8444101225498,262.675214736028,62.0729275737883,0.7,0.733158387745922,116.865701684297,36.54636141556835 +4000.0,0.1,0.0,0.0,0.0,262.675214736028,62.0729275737883,0.0,0.0,116.865701684297,0.0 +4000.0,0.15,58000.0,0.508376710865291,183.535093910855,263.331733156064,62.6168706187689,1.0,1.046062700507,175.298552526445,93.30496737075278 +4000.0,0.15,56550.0,0.508557778227161,168.353315696433,263.331733156064,62.6168706187689,0.975,1.01991113299433,175.298552526445,85.61738818775379 +4000.0,0.15,55100.0,0.515479501869442,150.886396013128,263.331733156064,62.6168706187689,0.95,0.993759565481654,175.298552526445,77.77884425572259 +4000.0,0.15,53650.0,0.526819807149964,135.101380841619,263.331733156064,62.6168706187689,0.925,0.967607997968979,175.298552526445,71.17408340067557 +4000.0,0.15,52200.0,0.555758111444936,117.342763698527,263.331733156064,62.6168706187689,0.9,0.941456430456304,175.298552526445,65.21419274482275 +4000.0,0.15,50750.0,0.603163986723064,98.6553333328164,263.331733156064,62.6168706187689,0.875,0.915304862943629,175.298552526445,59.50534416451433 +4000.0,0.15,49300.0,0.69259042623058,77.3477011375684,263.331733156064,62.6168706187689,0.85,0.889153295430954,175.298552526445,53.57027729882401 +4000.0,0.15,47850.0,0.841914795667452,57.15716419971,263.331733156064,62.6168706187689,0.825,0.863001727918279,175.298552526445,48.12146221812985 +4000.0,0.15,46400.0,1.05206836997687,41.7603409950361,263.331733156064,62.6168706187689,0.8,0.836850160405603,175.298552526445,43.93473388032589 +4000.0,0.15,44950.0,1.30150643971779,31.6106594905969,263.331733156064,62.6168706187689,0.775,0.810698592892928,175.298552526445,41.14147689073814 +4000.0,0.15,43500.0,1.58198593134005,24.8703737906756,263.331733156064,62.6168706187689,0.75,0.784547025380253,175.298552526445,39.34458144401711 +4000.0,0.15,42050.0,1.91314195786026,19.8776161794593,263.331733156064,62.6168706187689,0.725,0.758395457867578,175.298552526445,38.028701535165546 +4000.0,0.15,40600.0,2.40762299842655,15.1147622768858,263.331733156064,62.6168706187689,0.7,0.732243890354903,175.298552526445,36.390649273580294 +4000.0,0.15,0.0,0.0,0.0,263.331733156064,62.6168706187689,0.0,0.0,175.298552526445,0.0 +4000.0,0.2,58000.0,0.502168900435508,187.114078592016,264.250858944113,63.3840961442688,1.0,1.04424189146032,233.731403368594,93.9628711025559 +4000.0,0.2,56550.0,0.501751601103474,171.650832615857,264.250858944113,63.3840961442688,0.975,1.01813584417381,233.731403368594,86.12608009575068 +4000.0,0.2,55100.0,0.508189938401694,153.908131483308,264.250858944113,63.3840961442688,0.95,0.9920297968873,233.731403368594,78.21456385802212 +4000.0,0.2,53650.0,0.519052011049344,137.912781865048,264.250858944113,63.3840961442688,0.925,0.965923749600792,233.731403368594,71.58390677646265 +4000.0,0.2,52200.0,0.547479239939111,119.66833950462,264.250858944113,63.3840961442688,0.9,0.939817702314284,233.731403368594,65.51593155676484 +4000.0,0.2,50750.0,0.593837641984712,100.502751764912,264.250858944113,63.3840961442688,0.875,0.913711655027776,233.731403368594,59.6823171210502 +4000.0,0.2,49300.0,0.681342529901859,78.7155195007167,264.250858944113,63.3840961442688,0.85,0.887605607741268,233.731403368594,53.632231199157424 +4000.0,0.2,47850.0,0.827192207199755,58.1013211484694,264.250858944113,63.3840961442688,0.825,0.86149956045476,233.731403368594,48.06096008202421 +4000.0,0.2,46400.0,1.02979139836151,42.5414906100068,264.250858944113,63.3840961442688,0.8,0.835393513168252,233.731403368594,43.80886110366194 +4000.0,0.2,44950.0,1.26765700172921,32.3255071750987,264.250858944113,63.3840961442688,0.775,0.809287465881744,233.731403368594,40.97765550496168 +4000.0,0.2,43500.0,1.53603185614274,25.4910973063103,264.250858944113,63.3840961442688,0.75,0.783181418595236,233.731403368594,39.15513751052701 +4000.0,0.2,42050.0,1.86206441271866,20.2138617108206,264.250858944113,63.3840961442688,0.725,0.757075371308729,233.731403368594,37.63951253533537 +4000.0,0.2,40600.0,2.33409278241193,15.4982133670753,264.250858944113,63.3840961442688,0.7,0.730969324022221,233.731403368594,36.17426796037055 +4000.0,0.2,0.0,0.0,0.0,264.250858944113,63.3840961442688,0.0,0.0,233.731403368594,0.0 +4000.0,0.25,58000.0,0.494475248953783,191.734501623019,265.432592100177,64.3803604853571,1.0,1.04191476235198,292.164254210742,94.80796542307183 +4000.0,0.25,56550.0,0.493365083126142,175.872416132395,265.432592100177,64.3803604853571,0.975,1.01586689329318,292.164254210742,86.76930920475449 +4000.0,0.25,55100.0,0.499125808819755,157.858373934168,265.432592100177,64.3803604853571,0.95,0.989819024234382,292.164254210742,78.79118856886292 +4000.0,0.25,53650.0,0.509523423044994,141.535532357995,265.432592100177,64.3803604853571,0.925,0.963771155175582,292.164254210742,72.11566892954113 +4000.0,0.25,52200.0,0.537167924883246,122.702242161566,265.432592100177,64.3803604853571,0.9,0.937723286116782,292.164254210742,65.91170880044996 +4000.0,0.25,50750.0,0.582274081387425,102.892641336406,265.432592100177,64.3803604853571,0.875,0.911675417057983,292.164254210742,59.911718215681596 +4000.0,0.25,49300.0,0.667353118463615,80.476115534608,265.432592100177,64.3803604853571,0.85,0.885627547999183,292.164254210742,53.705986663858816 +4000.0,0.25,47850.0,0.808694238182032,59.3365047668264,265.432592100177,64.3803604853571,0.825,0.859579678940384,292.164254210742,47.98508951879319 +4000.0,0.25,46400.0,1.00186962694388,43.5736359433813,265.432592100177,64.3803604853571,0.8,0.833531809881584,292.164254210742,43.65510238718387 +4000.0,0.25,44950.0,1.22553591142411,33.2706443864228,265.432592100177,64.3803604853571,0.775,0.807483940822785,292.164254210742,40.77436949178212 +4000.0,0.25,43500.0,1.47888500326836,26.3330207379641,265.432592100177,64.3803604853571,0.75,0.781436071763985,292.164254210742,38.94350946012983 +4000.0,0.25,42050.0,1.79121279155016,20.8770024138194,265.432592100177,64.3803604853571,0.725,0.755388202705186,292.164254210742,37.39515377285688 +4000.0,0.25,40600.0,2.24542999254096,15.9862819365947,265.432592100177,64.3803604853571,0.7,0.729340333646386,292.164254210742,35.896076929645524 +4000.0,0.25,0.0,0.0,0.0,265.432592100177,64.3803604853571,0.0,0.0,292.164254210742,0.0 +4000.0,0.3,58000.0,0.485532677801374,197.394491551304,266.876932624255,65.6131378025166,1.0,1.03909151095035,350.597105052891,95.84147606614532 +4000.0,0.3,56550.0,0.48360563114096,181.054193388126,266.876932624255,65.6131378025166,0.975,1.01311422317659,350.597105052891,87.5588274641821 +4000.0,0.3,55100.0,0.488481730885005,162.804575019183,266.876932624255,65.6131378025166,0.95,0.987136935402833,350.597105052891,79.52706060136816 +4000.0,0.3,53650.0,0.498527594105241,145.971240863982,266.876932624255,65.6131378025166,0.925,0.961159647629074,350.597105052891,72.77069151647758 +4000.0,0.3,52200.0,0.524997145147183,126.483473437772,266.876932624255,65.6131378025166,0.9,0.935182359855315,350.597105052891,66.40346246312986 +4000.0,0.3,50750.0,0.568786919643188,105.83109792579,266.876932624255,65.6131378025166,0.875,0.909205072081557,350.597105052891,60.19534419166668 +4000.0,0.3,49300.0,0.651058929903836,82.6256711002017,266.876932624255,65.6131378025166,0.85,0.883227784307798,350.597105052891,53.79418100908362 +4000.0,0.3,47850.0,0.786726708471003,60.8800948269685,266.876932624255,65.6131378025166,0.825,0.857250496534039,350.597105052891,47.89599661462347 +4000.0,0.3,46400.0,0.968749806762913,44.8820304414574,266.876932624255,65.6131378025166,0.8,0.83127320876028,350.597105052891,43.47945831728904 +4000.0,0.3,44950.0,1.17618719502159,34.467582189139,266.876932624255,65.6131378025166,0.775,0.805295920986521,350.597105052891,40.54032881421952 +4000.0,0.3,43500.0,1.41427442105397,27.342512298392,266.876932624255,65.6131378025166,0.75,0.779318633212763,350.597105052891,38.6698157509694 +4000.0,0.3,42050.0,1.7082615092622,21.7155865051318,266.876932624255,65.6131378025166,0.725,0.753341345439004,350.597105052891,37.09590057777031 +4000.0,0.3,40600.0,2.14154137657687,16.6055717053225,266.876932624255,65.6131378025166,0.7,0.727364057665245,350.597105052891,35.56151888866227 +4000.0,0.3,0.0,0.0,0.0,266.876932624255,65.6131378025166,0.0,0.0,350.597105052891,0.0 +4000.0,0.35,58000.0,0.475456837401016,204.141883290552,268.583880516348,67.0916752949494,1.0,1.03578434646499,409.029955895039,97.06065421041316 +4000.0,0.35,56550.0,0.47277658919466,187.206355165262,268.583880516348,67.0916752949494,0.975,1.00988973780337,409.029955895039,88.50678207059669 +4000.0,0.35,55100.0,0.476535241522749,168.796656640343,268.583880516348,67.0916752949494,0.95,0.983995129141743,409.029955895039,80.4375555403384 +4000.0,0.35,53650.0,0.486357558404709,151.237415439444,268.583880516348,67.0916752949494,0.925,0.958100520480118,409.029955895039,73.55546011256662 +4000.0,0.35,52200.0,0.511244289102639,131.108869816639,268.583880516348,67.0916752949494,0.9,0.932205911818494,409.029955895039,67.02866094445804 +4000.0,0.35,50750.0,0.553861843741355,109.264491838343,268.583880516348,67.0916752949494,0.875,0.906311303156869,409.029955895039,60.517432905046896 +4000.0,0.35,49300.0,0.63294534978744,85.1316129863787,268.583880516348,67.0916752949494,0.85,0.880416694495244,409.029955895039,53.88365855963244 +4000.0,0.35,47850.0,0.761655798536187,62.752862602764,268.583880516348,67.0916752949494,0.825,0.854522085833619,409.029955895039,47.79608167613984 +4000.0,0.35,46400.0,0.930928272769655,46.509216683074,268.583880516348,67.0916752949494,0.8,0.828627477171994,409.029955895039,43.2967447546437 +4000.0,0.35,44950.0,1.12092406496459,35.9535859074632,268.583880516348,67.0916752949494,0.775,0.802732868510369,409.029955895039,40.30123966544725 +4000.0,0.35,43500.0,1.34214772117032,28.5745316319166,268.583880516348,67.0916752949494,0.75,0.776838259848744,409.029955895039,38.351242513286095 +4000.0,0.35,42050.0,1.61627594977978,22.7349539579851,268.583880516348,67.0916752949494,0.725,0.75094365118712,409.029955895039,36.74595930164193 +4000.0,0.35,40600.0,2.02665080752162,17.3504035569554,268.583880516348,67.0916752949494,0.7,0.725049042525495,409.029955895039,35.16320937952965 +4000.0,0.35,0.0,0.0,0.0,268.583880516348,67.0916752949494,0.0,0.0,409.029955895039,0.0 +5000.0,0.0,58000.0,0.518246696506667,162.250085387309,255.65,54.019881314929,1.0,1.06166235198407,0.0,84.08557075989754 +5000.0,0.0,56550.0,0.520357994792976,149.523156804776,255.65,54.019881314929,0.975,1.03512079318447,0.0,77.80557005004896 +5000.0,0.0,55100.0,0.524609481589099,135.569262000759,255.65,54.019881314929,0.95,1.00857923438487,0.0,71.12092025763492 +5000.0,0.0,53650.0,0.5368267262803,120.847121314339,255.65,54.019881314929,0.925,0.982037675585263,0.0,64.87396451557488 +5000.0,0.0,52200.0,0.559100659317848,106.631628146617,255.65,54.019881314929,0.9,0.955496116785662,0.0,59.617813600909166 +5000.0,0.0,50750.0,0.60284323239843,90.714670469783,255.65,54.019881314929,0.875,0.92895455798606,0.0,54.68672517196239 +5000.0,0.0,49300.0,0.678084139353396,73.4642188139315,255.65,54.019881314929,0.85,0.902412999186458,0.0,49.814921587714295 +5000.0,0.0,47850.0,0.815852899049915,55.1401506458041,255.65,54.019881314929,0.825,0.875871440386856,0.0,44.98625175842832 +5000.0,0.0,46400.0,1.02765242307153,40.0283700761439,255.65,54.019881314929,0.8,0.849329881587255,0.0,41.135251500353206 +5000.0,0.0,44950.0,1.30750823132573,29.4222992632827,255.65,54.019881314929,0.775,0.822788322787653,0.0,38.469898471271094 +5000.0,0.0,43500.0,1.62754845803272,22.6782115758849,255.65,54.019881314929,0.75,0.796246763988051,0.0,36.90988828127125 +5000.0,0.0,42050.0,2.00920504969854,17.7874094625612,255.65,54.019881314929,0.725,0.76970520518845,0.0,35.73855291323356 +5000.0,0.0,40600.0,2.53137262768456,13.7163011931135,255.65,54.019881314929,0.7,0.743163646388848,0.0,34.72106939332458 +5000.0,0.0,0.0,0.0,0.0,255.65,54.019881314929,0.0,0.0,0.0,0.0 +5000.0,0.05,58000.0,0.516752133377032,163.140244444615,255.778056334361,54.1145158994384,1.0,1.06139655590359,57.7057583324503,84.30306935640529 +5000.0,0.05,56550.0,0.519348214207269,149.959118413857,255.778056334361,54.1145158994384,0.975,1.034861642006,57.7057583324503,77.88100035233302 +5000.0,0.05,55100.0,0.52354921624391,135.9323215579,255.778056334361,54.1145158994384,0.95,1.00832672810841,57.7057583324503,71.1672604138537 +5000.0,0.05,53650.0,0.535656256196874,121.20968523407,255.778056334361,54.1145158994384,0.925,0.981791814210823,57.7057583324503,64.92672620728345 +5000.0,0.05,52200.0,0.557879248119083,106.935379836636,255.778056334361,54.1145158994384,0.9,0.955256900313234,57.7057583324503,59.657029300591034 +5000.0,0.05,50750.0,0.601373549085895,90.988630071994,255.778056334361,54.1145158994384,0.875,0.928721986415644,57.7057583324503,54.71815539285863 +5000.0,0.05,49300.0,0.676409044927178,73.6675888993647,255.778056334361,54.1145158994384,0.85,0.902187072518054,57.7057583324503,49.82942344950726 +5000.0,0.05,47850.0,0.813876312979595,55.2611344518302,255.778056334361,54.1145158994384,0.825,0.875652158620464,57.7057583324503,44.975728358725235 +5000.0,0.05,46400.0,1.02479297251044,40.124902133305,255.778056334361,54.1145158994384,0.8,0.849117244722874,57.7057583324503,41.11971772888013 +5000.0,0.05,44950.0,1.30272446539547,29.5149982537354,255.778056334361,54.1145158994384,0.775,0.822582330825284,57.7057583324503,38.449910321245675 +5000.0,0.05,43500.0,1.62097077598601,22.7534387908991,255.778056334361,54.1145158994384,0.75,0.796047416927694,57.7057583324503,36.882659333233896 +5000.0,0.05,42050.0,2.00014863712078,17.8538244868514,255.778056334361,54.1145158994384,0.725,0.769512503030105,57.7057583324503,35.71030271476944 +5000.0,0.05,40600.0,2.51826202008928,13.7757528719333,255.778056334361,54.1145158994384,0.7,0.742977589132515,57.7057583324503,34.69095525552545 +5000.0,0.05,0.0,0.0,0.0,255.778056334361,54.1145158994384,0.0,0.0,57.7057583324503,0.0 +5000.0,0.1,58000.0,0.514061195005615,164.53000982987,256.162225337444,54.3991297683344,1.0,1.0606003638621,115.411516664901,84.57849346742856 +5000.0,0.1,56550.0,0.516403351526352,151.233341263994,256.162225337444,54.3991297683344,0.975,1.03408535476554,115.411516664901,78.09740429125505 +5000.0,0.1,55100.0,0.52037921011584,137.069207099578,256.162225337444,54.3991297683344,0.95,1.00757034566899,115.411516664901,71.32796572168289 +5000.0,0.1,53650.0,0.532100729294331,122.302942562597,256.162225337444,54.3991297683344,0.925,0.981055336572438,115.411516664901,65.07748493240054 +5000.0,0.1,52200.0,0.554240267534791,107.855611882432,256.162225337444,54.3991297683344,0.9,0.954540327475886,115.411516664901,59.7779231848477 +5000.0,0.1,50750.0,0.597131775319073,91.7763464848068,256.162225337444,54.3991297683344,0.875,0.928025318379333,115.411516664901,54.802572708771045 +5000.0,0.1,49300.0,0.671621908208454,74.2457866475003,256.162225337444,54.3991297683344,0.85,0.901510309282781,115.411516664901,49.865096904631905 +5000.0,0.1,47850.0,0.80776230960516,55.6637293383272,256.162225337444,54.3991297683344,0.825,0.874995300186229,115.411516664901,44.96306257156369 +5000.0,0.1,46400.0,1.016187976604,40.4183748079322,256.162225337444,54.3991297683344,0.8,0.848480291089676,115.411516664901,41.07266651369471 +5000.0,0.1,44950.0,1.28869709034324,29.7833759864807,256.162225337444,54.3991297683344,0.775,0.821965281993124,115.411516664901,38.381749974376405 +5000.0,0.1,43500.0,1.60067732113231,22.9914708974933,256.162225337444,54.3991297683344,0.75,0.795450272896571,115.411516664901,36.801926045091044 +5000.0,0.1,42050.0,1.97378083969854,18.0491697188451,256.162225337444,54.3991297683344,0.725,0.768935263800019,115.411516664901,35.62510536352354 +5000.0,0.1,40600.0,2.48476694708568,13.9231822780183,256.162225337444,54.3991297683344,0.7,0.742420254703466,115.411516664901,34.59586312266898 +5000.0,0.1,0.0,0.0,0.0,256.162225337444,54.3991297683344,0.0,0.0,115.411516664901,0.0 +5000.0,0.15,58000.0,0.509665687846681,166.847026869279,256.80250700925,54.8758585840331,1.0,1.05927734954021,173.117274997351,85.03620471450475 +5000.0,0.15,56550.0,0.511582403647968,153.361047009971,256.80250700925,54.8758585840331,0.975,1.0327954158017,173.117274997351,78.45681305532999 +5000.0,0.15,55100.0,0.515201040467881,138.97416770803,256.80250700925,54.8758585840331,0.95,1.0063134820632,173.117274997351,71.59963580133484 +5000.0,0.15,53650.0,0.526284008552761,124.139105285384,256.80250700925,54.8758585840331,0.925,0.979831548324692,173.117274997351,65.33242594774514 +5000.0,0.15,52200.0,0.548288180075291,109.396571893106,256.80250700925,54.8758585840331,0.9,0.953349614586187,173.117274997351,59.98084730974682 +5000.0,0.15,50750.0,0.590209970057099,93.0925277401187,256.80250700925,54.8758585840331,0.875,0.926867680847682,173.117274997351,54.94413801003511 +5000.0,0.15,49300.0,0.663809295181086,75.2082030440106,256.80250700925,54.8758585840331,0.85,0.900385747109176,173.117274997351,49.92390425448068 +5000.0,0.15,47850.0,0.797710521235381,56.3395856202963,256.80250700925,54.8758585840331,0.825,0.873903813370671,173.117274997351,44.942680211351934 +5000.0,0.15,46400.0,1.00197401193305,40.9148193761549,256.80250700925,54.8758585840331,0.8,0.847421879632166,173.117274997351,40.99558571784202 +5000.0,0.15,44950.0,1.26567357092106,30.2369737876224,256.80250700925,54.8758585840331,0.775,0.820939945893661,173.117274997351,38.27013858762653 +5000.0,0.15,43500.0,1.56731641897143,23.4118194340459,256.80250700925,54.8758585840331,0.75,0.794458012155155,173.117274997351,36.69372899697455 +5000.0,0.15,42050.0,1.9298587367802,18.3867953502695,256.80250700925,54.8758585840331,0.725,0.76797607841665,173.117274997351,35.48391764810716 +5000.0,0.15,40600.0,2.42799850768839,14.1835499643512,256.80250700925,54.8758585840331,0.7,0.741494144678145,173.117274997351,34.437638147168435 +5000.0,0.15,0.0,0.0,0.0,256.80250700925,54.8758585840331,0.0,0.0,173.117274997351,0.0 +5000.0,0.2,58000.0,0.503682619646487,170.103179946096,257.698901349778,55.5482795233554,1.0,1.05743341970528,230.823033329801,85.6780152854474 +5000.0,0.2,56550.0,0.505010022911426,156.34762318493,257.698901349778,55.5482795233554,0.975,1.03099758421265,230.823033329801,78.95711676676851 +5000.0,0.2,55100.0,0.508167038876388,141.670991185465,257.698901349778,55.5482795233554,0.95,1.00456174872002,230.823033329801,71.99252808540062 +5000.0,0.2,53650.0,0.518368571739874,126.736775213638,257.698901349778,55.5482795233554,0.925,0.978125913227389,230.823033329801,65.696361154411 +5000.0,0.2,52200.0,0.540193858126767,111.573229634416,257.698901349778,55.5482795233554,0.9,0.951690077734756,230.823033329801,60.27117337987891 +5000.0,0.2,50750.0,0.58082043821956,94.9414649814655,257.698901349778,55.5482795233554,0.875,0.925254242242124,230.823033329801,55.1439432957418 +5000.0,0.2,49300.0,0.653209833004123,76.5545862467353,257.698901349778,55.5482795233554,0.85,0.898818406749492,230.823033329801,50.0062084979297 +5000.0,0.2,47850.0,0.783910839193015,57.2999926042574,257.698901349778,55.5482795233554,0.825,0.87238257125686,230.823033329801,44.918085288156966 +5000.0,0.2,46400.0,0.982401190970184,41.6218796168076,257.698901349778,55.5482795233554,0.8,0.845946735764228,230.823033329801,40.889384105969405 +5000.0,0.2,44950.0,1.23436798291207,30.8845483361624,257.698901349778,55.5482795233554,0.775,0.819510900271596,230.823033329801,38.12289763285911 +5000.0,0.2,43500.0,1.5231168603958,23.9732411175547,257.698901349778,55.5482795233554,0.75,0.793075064778964,230.823033329801,36.51404774448142 +5000.0,0.2,42050.0,1.87093761994391,18.8588917074703,257.698901349778,55.5482795233554,0.725,0.766639229286331,230.823033329801,35.283809965954426 +5000.0,0.2,40600.0,2.35143380383289,14.5519079497807,257.698901349778,55.5482795233554,0.7,0.740203393793699,230.823033329801,34.217848263378905 +5000.0,0.2,0.0,0.0,0.0,257.698901349778,55.5482795233554,0.0,0.0,230.823033329801,0.0 +5000.0,0.25,58000.0,0.496269569012698,174.310139200679,258.851408359027,56.4214379510871,1.0,1.05507674141852,288.528791662252,86.50481765566435 +5000.0,0.25,56550.0,0.496464296105077,160.450868675724,258.851408359027,56.4214379510871,0.975,1.02869982288306,288.528791662252,79.65812757654146 +5000.0,0.25,55100.0,0.499446311519522,145.189820087766,258.851408359027,56.4214379510871,0.95,1.00232290434759,288.528791662252,72.51452011301774 +5000.0,0.25,53650.0,0.508581518588864,130.117500739234,258.851408359027,56.4214379510871,0.925,0.97594598581213,288.528791662252,66.17535612094727 +5000.0,0.25,52200.0,0.53013046932598,114.426528276526,258.851408359027,56.4214379510871,0.9,0.949569067276667,288.528791662252,60.66098913857724 +5000.0,0.25,50750.0,0.569241427319018,97.3287721396932,258.851408359027,56.4214379510871,0.875,0.923192148741204,288.528791662252,55.40356917200643 +5000.0,0.25,49300.0,0.640269463105119,78.2384621958888,258.851408359027,56.4214379510871,0.85,0.896815230205741,288.528791662252,50.09369818433187 +5000.0,0.25,47850.0,0.766549266745674,58.566909883541,258.851408359027,56.4214379510871,0.825,0.870438311670278,288.528791662252,44.894421826788324 +5000.0,0.25,46400.0,0.957751001746161,42.5542026670322,258.851408359027,56.4214379510871,0.8,0.844061393134815,288.528791662252,40.75633023285925 +5000.0,0.25,44950.0,1.19568715192549,31.7336567136248,258.851408359027,56.4214379510871,0.775,0.817684474599352,288.528791662252,37.943525616095236 +5000.0,0.25,43500.0,1.46878284327374,24.7023528818067,258.851408359027,56.4214379510871,0.75,0.791307556063889,288.528791662252,36.28239210129131 +5000.0,0.25,42050.0,1.79847970184233,19.476505362586,258.851408359027,56.4214379510871,0.725,0.764930637528426,288.528791662252,35.02809955743421 +5000.0,0.25,40600.0,2.25744822074899,15.0341447328158,258.851408359027,56.4214379510871,0.7,0.738553718992963,288.528791662252,33.938803277577826 +5000.0,0.25,0.0,0.0,0.0,258.851408359027,56.4214379510871,0.0,0.0,288.528791662252,0.0 +5000.0,0.3,58000.0,0.487662021753793,179.468275106696,260.260028036999,57.5018848914076,1.0,1.0522176425886,346.234549994702,87.5198618791973 +5000.0,0.3,56550.0,0.486415677723434,165.5637012311,260.260028036999,57.5018848914076,0.975,1.02591220152388,346.234549994702,80.53277994072566 +5000.0,0.3,55100.0,0.489294715862642,149.53961475835,260.260028036999,57.5018848914076,0.95,0.999606760459169,346.234549994702,73.16894331339581 +5000.0,0.3,53650.0,0.497210226659682,134.310029846869,260.260028036999,57.5018848914076,0.925,0.973301319394454,346.234549994702,66.7803203828304 +5000.0,0.3,52200.0,0.518382091033499,117.966171682858,260.260028036999,57.5018848914076,0.9,0.946995878329739,346.234549994702,61.15155074817667 +5000.0,0.3,50750.0,0.555831972579993,100.251942339675,260.260028036999,57.5018848914076,0.875,0.920690437265024,346.234549994702,55.72323486563727 +5000.0,0.3,49300.0,0.625154691193909,80.306424242145,260.260028036999,57.5018848914076,0.85,0.894384996200309,346.234549994702,50.2039378479852 +5000.0,0.3,47850.0,0.746160611162508,60.1269160590895,260.260028036999,57.5018848914076,0.825,0.868079555135594,346.234549994702,44.86433643396704 +5000.0,0.3,46400.0,0.928393195741348,43.7297595932427,260.260028036999,57.5018848914076,0.8,0.841774114070879,346.234549994702,40.59841125777146 +5000.0,0.3,44950.0,1.14915440809038,32.861443769403,260.260028036999,57.5018848914076,0.775,0.815468673006164,346.234549994702,37.76287296382361 +5000.0,0.3,43500.0,1.40495722142123,25.626168079065,260.260028036999,57.5018848914076,0.75,0.789163231941449,346.234549994702,36.003669900036584 +5000.0,0.3,42050.0,1.71394150336082,20.2586663607693,260.260028036999,57.5018848914076,0.725,0.762857790876734,346.234549994702,34.72216907846221 +5000.0,0.3,40600.0,2.14906839885651,15.6355707659906,260.260028036999,57.5018848914076,0.7,0.736552349812019,346.234549994702,33.60191103127507 +5000.0,0.3,0.0,0.0,0.0,260.260028036999,57.5018848914076,0.0,0.0,346.234549994702,0.0 +5000.0,0.35,58000.0,0.477992679080351,185.614795451357,261.924760383694,58.7977254249342,1.0,1.04886848821832,403.940308327152,88.72251335474547 +5000.0,0.35,56550.0,0.475370462771992,171.484393631987,261.924760383694,58.7977254249342,0.975,1.02264677601286,403.940308327152,81.51861555901209 +5000.0,0.35,55100.0,0.477907872516205,154.761344679709,261.924760383694,58.7977254249342,0.95,0.996425063807402,403.940308327152,73.96166498362683 +5000.0,0.35,53650.0,0.484659200087829,139.314594418563,261.924760383694,58.7977254249342,0.925,0.970203351601944,403.940308327152,67.52009989146106 +5000.0,0.35,52200.0,0.505291171575943,122.181028947528,261.924760383694,58.7977254249342,0.9,0.943981639396486,403.940308327152,61.73699526125064 +5000.0,0.35,50750.0,0.541001583571571,103.693233504967,261.924760383694,58.7977254249342,0.875,0.917759927191029,403.940308327152,56.09820353184383 +5000.0,0.35,49300.0,0.608169538484932,82.7604256728757,261.924760383694,58.7977254249342,0.85,0.891538214985571,403.940308327152,50.332369886289335 +5000.0,0.35,47850.0,0.723175117926988,61.989703384996,261.924760383694,58.7977254249342,0.825,0.865316502780113,403.940308327152,44.82941105570349 +5000.0,0.35,46400.0,0.894678133453339,45.1829233542759,261.924760383694,58.7977254249342,0.8,0.839094790574655,403.940308327152,40.424173530568844 +5000.0,0.35,44950.0,1.09794357801275,34.181649826939,261.924760383694,58.7977254249342,0.775,0.812873078369197,403.940308327152,37.529522913368304 +5000.0,0.35,43500.0,1.33244623474888,26.7778106171551,261.924760383694,58.7977254249342,0.75,0.786651366163739,403.940308327152,35.67999293164689 +5000.0,0.35,42050.0,1.61977017962671,21.218800450405,261.924760383694,58.7977254249342,0.725,0.760429653958281,403.940308327152,34.36958021701582 +5000.0,0.35,40600.0,2.0294520043276,16.3628368561968,261.924760383694,58.7977254249342,0.7,0.734207941752823,403.940308327152,33.207592054294125 +5000.0,0.35,0.0,0.0,0.0,261.924760383694,58.7977254249342,0.0,0.0,403.940308327152,0.0 +6000.0,0.0,58000.0,0.519421974629505,146.994605171756,249.15,47.1809940960953,1.0,1.07542188384738,0.0,76.35222807819795 +6000.0,0.0,56550.0,0.522390341017192,136.109005418484,249.15,47.1809940960953,0.975,1.04853633675119,0.0,71.10202975607268 +6000.0,0.0,55100.0,0.526598698087967,124.487524313818,249.15,47.1809940960953,0.95,1.02165078965501,0.0,65.5549682318507 +6000.0,0.0,53650.0,0.537728139104616,111.096684704469,249.15,47.1809940960953,0.925,0.994765242558824,0.0,59.739813526826374 +6000.0,0.0,52200.0,0.55634468508304,98.5370676395621,249.15,47.1809940960953,0.9,0.967879695462639,0.0,54.82057386493839 +6000.0,0.0,50750.0,0.594812343494651,84.8301673978975,249.15,47.1809940960953,0.875,0.940994148366455,0.0,50.45803066898695 +6000.0,0.0,49300.0,0.658749085046626,70.33002629933,249.15,47.1809940960953,0.85,0.91410860127027,0.0,46.32984047598878 +6000.0,0.0,47850.0,0.777981532592966,54.210008964547,249.15,47.1809940960953,0.825,0.887223054174086,0.0,42.1743858561167 +6000.0,0.0,46400.0,0.978919894518656,39.4580930582098,249.15,47.1809940960953,0.8,0.860337507077901,0.0,38.626312294450045 +6000.0,0.0,44950.0,1.27203213569009,28.4183197959078,249.15,47.1809940960953,0.775,0.833451959981717,0.0,36.149016022712566 +6000.0,0.0,43500.0,1.62309360609651,21.4650660149825,249.15,47.1809940960953,0.75,0.806566412885532,0.0,34.839811403357594 +6000.0,0.0,42050.0,2.04901075732315,16.6026403188136,249.15,47.1809940960953,0.725,0.779680865789348,0.0,34.018988613216116 +6000.0,0.0,40600.0,2.61365991407012,12.8016103699634,249.15,47.1809940960953,0.7,0.752795318693164,0.0,33.459055859517704 +6000.0,0.0,0.0,0.0,0.0,249.15,47.1809940960953,0.0,0.0,0.0,0.0 +6000.0,0.05,58000.0,0.51854347292176,147.411856458091,249.274808561608,47.2636533672839,1.0,1.07515262546503,56.9692902316657,76.43945599762247 +6000.0,0.05,56550.0,0.521394409909503,136.501385666879,249.274808561608,47.2636533672839,0.975,1.04827380982841,56.9692902316657,71.17105943161187 +6000.0,0.05,55100.0,0.52550481611347,124.8544335046,249.274808561608,47.2636533672839,0.95,1.02139499419178,56.9692902316657,65.61160611978629 +6000.0,0.05,53650.0,0.536557136616859,111.410600251112,249.274808561608,47.2636533672839,0.925,0.994516178555157,56.9692902316657,59.77815265950217 +6000.0,0.05,52200.0,0.555067283055608,98.8345736352427,249.274808561608,47.2636533672839,0.9,0.967637362918531,56.9692902316657,54.8598382596736 +6000.0,0.05,50750.0,0.593392260774357,85.0864123936198,249.274808561608,47.2636533672839,0.875,0.940758547281905,56.9692902316657,50.48961861142932 +6000.0,0.05,49300.0,0.657195368081725,70.5162165438766,249.274808561608,47.2636533672839,0.85,0.913879731645279,56.9692902316657,46.3429308872836 +6000.0,0.05,47850.0,0.776029279771654,54.3441851185059,249.274808561608,47.2636533672839,0.825,0.887000916008653,56.9692902316657,42.17267883729157 +6000.0,0.05,46400.0,0.976289906106596,39.5509834458122,249.274808561608,47.2636533672839,0.8,0.860122100372027,56.9692902316657,38.61322591473553 +6000.0,0.05,44950.0,1.26773469405731,28.4966659519572,249.274808561608,47.2636533672839,0.775,0.833243284735401,56.9692902316657,36.12621209225782 +6000.0,0.05,43500.0,1.61654797284725,21.5353334936601,249.274808561608,47.2636533672839,0.75,0.806364469098775,56.9692902316657,34.81289970376572 +6000.0,0.05,42050.0,2.03949511551869,16.6648825708255,249.274808561608,47.2636533672839,0.725,0.77948565346215,56.9692902316657,33.98794660389115 +6000.0,0.05,40600.0,2.60080971040092,12.8514909917473,249.274808561608,47.2636533672839,0.7,0.752606837825524,56.9692902316657,33.424282564466324 +6000.0,0.05,0.0,0.0,0.0,249.274808561608,47.2636533672839,0.0,0.0,56.9692902316657,0.0 +6000.0,0.1,58000.0,0.51593294559035,148.664911279609,249.649234246432,47.5122514767502,1.0,1.07434606217843,113.938580463331,76.70112558241671 +6000.0,0.1,56550.0,0.518512989274105,137.666796989054,249.649234246432,47.5122514767502,0.975,1.04748741062397,113.938580463331,71.38202243058576 +6000.0,0.1,55100.0,0.522302392234581,125.935010293652,249.649234246432,47.5122514767502,0.95,1.02062875906951,113.938580463331,65.77615714246102 +6000.0,0.1,53650.0,0.53316050953024,112.356015049348,249.649234246432,47.5122514767502,0.925,0.993770107515046,113.938580463331,59.90379023249769 +6000.0,0.1,52200.0,0.551267581796574,99.7361184988789,249.649234246432,47.5122514767502,0.9,0.966911455960585,113.938580463331,54.981288862653514 +6000.0,0.1,50750.0,0.589339234790663,85.8055511150101,249.649234246432,47.5122514767502,0.875,0.940052804406124,113.938580463331,50.568577834911174 +6000.0,0.1,49300.0,0.652501701367449,71.0768539446014,249.649234246432,47.5122514767502,0.85,0.913194152851664,113.938580463331,46.37776812669809 +6000.0,0.1,47850.0,0.770183251363122,54.7559110875161,249.649234246432,47.5122514767502,0.825,0.886335501297203,113.938580463331,42.17208563273317 +6000.0,0.1,46400.0,0.968351353235641,39.8342696780011,249.649234246432,47.5122514767502,0.8,0.859476849742742,113.938580463331,38.57356894784583 +6000.0,0.1,44950.0,1.25516810155459,28.7329702282286,249.649234246432,47.5122514767502,0.775,0.832618198188282,113.938580463331,36.06470769339024 +6000.0,0.1,43500.0,1.59732133956316,21.7421347968869,249.649234246432,47.5122514767502,0.75,0.805759546633821,113.938580463331,34.72917587872618 +6000.0,0.1,42050.0,2.01219775433977,16.8441208754777,249.649234246432,47.5122514767502,0.725,0.77890089507936,113.938580463331,33.893702199463874 +6000.0,0.1,40600.0,2.56349539615701,12.9977845937861,249.649234246432,47.5122514767502,0.7,0.752042243524899,113.938580463331,33.31976096641118 +6000.0,0.1,0.0,0.0,0.0,249.649234246432,47.5122514767502,0.0,0.0,113.938580463331,0.0 +6000.0,0.15,58000.0,0.511666632756061,150.758337253728,250.273277054471,47.9286539563753,1.0,1.07300581445337,170.907870694997,77.13801078251763 +6000.0,0.15,56550.0,0.513801571809086,139.612977518912,250.273277054471,47.9286539563753,0.975,1.04618066909203,170.907870694997,71.73336729416359 +6000.0,0.15,55100.0,0.517087747546741,127.728380060473,250.273277054471,47.9286539563753,0.95,1.0193555237307,170.907870694997,66.04678034326405 +6000.0,0.15,53650.0,0.527594177261484,113.945886755664,250.273277054471,47.9286539563753,0.925,0.992530378369365,170.907870694997,60.11718637518479 +6000.0,0.15,52200.0,0.54508784018803,101.239779239551,250.273277054471,47.9286539563753,0.9,0.965705233008031,170.907870694997,55.18457260679981 +6000.0,0.15,50750.0,0.582704078485421,87.0124366179705,250.273277054471,47.9286539563753,0.875,0.938880087646697,170.907870694997,50.702501696245605 +6000.0,0.15,49300.0,0.644917072832505,72.0152639667671,250.273277054471,47.9286539563753,0.85,0.912054942285362,170.907870694997,46.4438732367076 +6000.0,0.15,47850.0,0.760616440723587,55.443324431916,250.273277054471,47.9286539563753,0.825,0.885229796924028,170.907870694997,42.17110409128704 +6000.0,0.15,46400.0,0.955247121055815,40.3125431622509,250.273277054471,47.9286539563753,0.8,0.858404651562694,170.907870694997,38.50844079817845 +6000.0,0.15,44950.0,1.23443206088574,29.1317686919852,250.273277054471,47.9286539563753,0.775,0.83157950620136,170.907870694997,35.96118926369397 +6000.0,0.15,43500.0,1.56572815453965,22.0929485185965,250.273277054471,47.9286539563753,0.75,0.804754360840025,170.907870694997,34.59155151236159 +6000.0,0.15,42050.0,1.9670599793759,17.1517038027952,250.273277054471,47.9286539563753,0.725,0.777929215478691,170.907870694997,33.73843012858787 +6000.0,0.15,40600.0,2.50279438630843,13.2438941140896,250.273277054471,47.9286539563753,0.7,0.751104070117357,170.907870694997,33.14674384160671 +6000.0,0.15,0.0,0.0,0.0,250.273277054471,47.9286539563753,0.0,0.0,170.907870694997,0.0 +6000.0,0.2,58000.0,0.505864891457361,153.700777797242,251.146936985726,48.5159855226555,1.0,1.07113786638299,227.877160926663,77.7518272773138 +6000.0,0.2,56550.0,0.507392989345275,142.345605149098,251.146936985726,48.5159855226555,0.975,1.04435941972341,227.877160926663,72.225162116763 +6000.0,0.2,55100.0,0.510034086417718,130.224684851585,251.146936985726,48.5159855226555,0.95,1.01758097306384,227.877160926663,66.4190281673134 +6000.0,0.2,53650.0,0.519990518043506,116.203031514792,251.146936985726,48.5159855226555,0.925,0.990802526404261,227.877160926663,60.42447455560255 +6000.0,0.2,52200.0,0.536745159875203,103.346528724363,251.146936985726,48.5159855226555,0.9,0.964024079744687,227.877160926663,55.470749082705474 +6000.0,0.2,50750.0,0.573647549349413,88.7218749112501,251.146936985726,48.5159855226555,0.875,0.937245633085112,227.877160926663,50.895086116523785 +6000.0,0.2,49300.0,0.634591892855428,73.3328971215598,251.146936985726,48.5159855226555,0.85,0.910467186425537,227.877160926663,46.536461992943 +6000.0,0.2,47850.0,0.747581910092109,56.4074168636116,251.146936985726,48.5159855226555,0.825,0.883688739765963,227.877160926663,42.1691644422606 +6000.0,0.2,46400.0,0.937205126358831,40.9940513762024,251.146936985726,48.5159855226555,0.8,0.856910293106388,227.877160926663,38.41983509999418 +6000.0,0.2,44950.0,1.20460278836965,29.7646651348364,251.146936985726,48.5159855226555,0.775,0.830131846446813,227.877160926663,35.85459861631283 +6000.0,0.2,43500.0,1.5225040511401,22.5956859684225,251.146936985726,48.5159855226555,0.75,0.803353399787239,227.877160926663,34.402023425212775 +6000.0,0.2,42050.0,1.90603560984566,17.5881147407626,251.146936985726,48.5159855226555,0.725,0.776574953127664,227.877160926663,33.52357300594488 +6000.0,0.2,40600.0,2.42080085784825,13.5934340955407,251.146936985726,48.5159855226555,0.7,0.749796506468089,227.877160926663,32.90699691958858 +6000.0,0.2,0.0,0.0,0.0,251.146936985726,48.5159855226555,0.0,0.0,227.877160926663,0.0 +6000.0,0.25,58000.0,0.498686027959403,157.503529780503,252.270214040197,49.2786533779784,1.0,1.0687504919372,284.846451158329,78.54480965582457 +6000.0,0.25,56550.0,0.499450656659723,145.875853827004,252.270214040197,49.2786533779784,0.975,1.04203172963877,284.846451158329,72.85779098469492 +6000.0,0.25,55100.0,0.501350186123495,133.417788537055,252.270214040197,49.2786533779784,0.95,1.01531296734034,284.846451158329,66.88903311523762 +6000.0,0.25,53650.0,0.510527450271479,119.160385753063,252.270214040197,49.2786533779784,0.925,0.988594205041908,284.846451158329,60.83464791187713 +6000.0,0.25,52200.0,0.526561585642671,106.045392962282,252.270214040197,49.2786533779784,0.9,0.961875442743478,284.846451158329,55.83943026831935 +6000.0,0.25,50750.0,0.56235489453584,90.9591973628607,252.270214040197,49.2786533779784,0.875,0.935156680445049,284.846451158329,51.151349840056184 +6000.0,0.25,49300.0,0.621788633876176,75.0338018194786,252.270214040197,49.2786533779784,0.85,0.908437918146618,284.846451158329,46.655165127869324 +6000.0,0.25,47850.0,0.731391381819095,57.6554094288205,252.270214040197,49.2786533779784,0.825,0.881719155848188,284.846451158329,42.1686695714907 +6000.0,0.25,46400.0,0.914474868477157,41.8936517333171,252.270214040197,49.2786533779784,0.8,0.855000393549759,284.846451158329,38.310691658852974 +6000.0,0.25,44950.0,1.16852411481809,30.5328814412811,252.270214040197,49.2786533779784,0.775,0.828281631251329,284.846451158329,35.67840825901869 +6000.0,0.25,43500.0,1.46795912647773,23.2706495400573,252.270214040197,49.2786533779784,0.75,0.801562868952899,284.846451158329,34.160362371391905 +6000.0,0.25,42050.0,1.83063475960272,18.1640745685555,252.270214040197,49.2786533779784,0.725,0.774844106654469,284.846451158329,33.25178628121348 +6000.0,0.25,40600.0,2.32024196895106,14.0514983283886,252.270214040197,49.2786533779784,0.7,0.748125344356039,284.846451158329,32.602876148172896 +6000.0,0.25,0.0,0.0,0.0,252.270214040197,49.2786533779784,0.0,0.0,284.846451158329,0.0 +6000.0,0.3,58000.0,0.490355368823204,162.17156541481,253.643108217884,50.2223799446227,1.0,1.06585415420823,341.815741389994,79.52169777161552 +6000.0,0.3,56550.0,0.490230015520132,150.194515838868,253.643108217884,50.2223799446227,0.975,1.03920780035303,341.815741389994,73.62985983072697 +6000.0,0.3,55100.0,0.491270347633714,137.307598486989,253.643108217884,50.2223799446227,0.95,1.01256144649782,341.815741389994,67.45515164145351 +6000.0,0.3,53650.0,0.499436382162378,122.840419870291,253.643108217884,50.2223799446227,0.925,0.985915092642614,341.815741389994,61.35097488332563 +6000.0,0.3,52200.0,0.514875974769656,109.329710607968,253.643108217884,50.2223799446227,0.9,0.959268738787408,341.815741389994,56.291241320561916 +6000.0,0.3,50750.0,0.549133428852494,93.7290481476368,253.643108217884,50.2223799446227,0.875,0.932622384932202,341.815741389994,51.4697535923923 +6000.0,0.3,49300.0,0.606806016429206,77.1385360951671,253.643108217884,50.2223799446227,0.85,0.905976031076996,341.815741389994,46.808127801088865 +6000.0,0.3,47850.0,0.712495760913284,59.1889680071433,253.643108217884,50.2223799446227,0.825,0.879329677221791,341.815741389994,42.17188879792159 +6000.0,0.3,46400.0,0.887450965694075,43.0247513456544,253.643108217884,50.2223799446227,0.8,0.852683323366585,341.815741389994,38.18235713044845 +6000.0,0.3,44950.0,1.12633670920937,31.4866362157395,253.643108217884,50.2223799446227,0.775,0.826036969511379,341.815741389994,35.464554219308596 +6000.0,0.3,43500.0,1.4034241986148,24.134415868178,253.643108217884,50.2223799446227,0.75,0.799390615656173,341.815741389994,33.87082324883402 +6000.0,0.3,42050.0,1.74296021254557,18.8911699676513,253.643108217884,50.2223799446227,0.725,0.772744261800967,341.815741389994,32.926557622052 +6000.0,0.3,40600.0,2.20412661882757,14.6262318459538,253.643108217884,50.2223799446227,0.7,0.746097907945762,341.815741389994,32.23806694481028 +6000.0,0.3,0.0,0.0,0.0,253.643108217884,50.2223799446227,0.0,0.0,341.815741389994,0.0 +6000.0,0.35,58000.0,0.481024129071741,167.733120980767,255.265619518787,51.3542451430885,1.0,1.06246138002961,398.78503162166,80.68367843625842 +6000.0,0.35,56550.0,0.479815230117078,155.374522056274,255.265619518787,51.3542451430885,0.975,1.03589984552887,398.78503162166,74.55106205476213 +6000.0,0.35,55100.0,0.480073596902173,141.88945996365,255.265619518787,51.3542451430885,0.95,1.00933831102813,398.78503162166,68.11738340725633 +6000.0,0.35,53650.0,0.486963945452877,127.295930681106,255.265619518787,51.3542451430885,0.925,0.982776776527389,398.78503162166,61.98852864456732 +6000.0,0.35,52200.0,0.501935998523042,113.225016032718,255.265619518787,51.3542451430885,0.9,0.956215242026649,398.78503162166,56.83171148016976 +6000.0,0.35,50750.0,0.534003617986606,97.1665008385878,255.265619518787,51.3542451430885,0.875,0.929653707525908,398.78503162166,51.88726299490447 +6000.0,0.35,49300.0,0.590090920144534,79.6211174648268,255.265619518787,51.3542451430885,0.85,0.903092173025168,398.78503162166,46.98369846775567 +6000.0,0.35,47850.0,0.691344390788991,60.9981721557301,255.265619518787,51.3542451430885,0.825,0.876530638524428,398.78503162166,42.17074416824522 +6000.0,0.35,46400.0,0.856586290593151,44.4067433965466,255.265619518787,51.3542451430885,0.8,0.849969104023688,398.78503162166,38.038207603369756 +6000.0,0.35,44950.0,1.07852868216672,32.6532715537887,255.265619518787,51.3542451430885,0.775,0.823407569522947,398.78503162166,35.21748993733977 +6000.0,0.35,43500.0,1.33152325107151,25.1885397904928,255.265619518787,51.3542451430885,0.75,0.796846035022207,398.78503162166,33.539126391581064 +6000.0,0.35,42050.0,1.64510575006291,19.7877084172638,255.265619518787,51.3542451430885,0.725,0.770284500521467,398.78503162166,32.552872897808925 +6000.0,0.35,40600.0,2.07601315096264,15.3242670915128,255.265619518787,51.3542451430885,0.7,0.743722966020726,398.78503162166,31.813380010844575 +6000.0,0.35,0.0,0.0,0.0,255.265619518787,51.3542451430885,0.0,0.0,398.78503162166,0.0 diff --git a/Model/data/engine_gpr_model.pth b/Model/data/engine_gpr_model.pth new file mode 100644 index 0000000..e9dc524 Binary files /dev/null and b/Model/data/engine_gpr_model.pth differ diff --git a/Model/src/battery_sim.py b/Model/src/battery_sim.py new file mode 100644 index 0000000..cbd4b8d --- /dev/null +++ b/Model/src/battery_sim.py @@ -0,0 +1,168 @@ +import numpy as np +import matplotlib.pyplot as plt + +class BatterySim: + """ + 混电飞机高压电池模型 + """ + def __init__(self, capacity_kwh=50.0, nom_voltage=500.0, initial_soc=0.5): + """ + 初始化电池参数 + :param capacity_kwh: 电池总能量 (kWh),默认 50 kWh + :param nom_voltage: 额定电压 (V),默认 500 V + :param initial_soc: 初始荷电状态 (0.0 到 1.0) + """ + # --- 基本物理参数 --- + # 单体电池为 3.7V,根据额定电压计算串联数 + self.cells_in_series = int(nom_voltage / 3.7) + + # 电池组电压安全极限 (工程极限) + self.V_min = self.cells_in_series * 2.7 # 绝对放电截止电压 (约 364.5V) + self.V_max = self.cells_in_series * 4.2 # 绝对充电截止电压 (约 567.0V) + + # 容量与内阻标定 + self.capacity_Ah = (capacity_kwh * 1000) / nom_voltage # 安时容量 (约 100Ah) + + # 电池内阻为 0.15 欧姆。 + # 在 SOC=50% 时,此内阻可将最大放电/充电安全功率限制在 300kW 左右。 + self.R_in = 0.15 + + # --- 状态变量 --- + self.SOC = initial_soc + self.V_t = 0.0 # 端电压 (V) + self.I = 0.0 # 实际电流 (A),放电为正,充电为负 + + # --- OCV-SOC 查表曲线 Voc = f(SOC) --- + self.soc_table = np.array([0.0, 0.1, 0.2, 0.5, 0.8, 0.9, 1.0]) + self.cell_ocv_table = np.array([2.8, 3.3, 3.4, 3.6, 3.9, 4.0, 4.15]) + self.Voc_table = self.cell_ocv_table * self.cells_in_series + + def _get_ocv(self, soc): + """根据当前 SOC 线性插值获取开路电压""" + return np.interp(soc, self.soc_table, self.Voc_table) + + def step(self, dt, P_req_kw): + """ + 单步执行电池仿真,包含过充/过放保护(功率限幅) + :param dt: 仿真步长 (秒) + :param P_req_kw: 外部请求功率 (kW)。正数表示放电,负数表示充电 + :return: (实际输出/吸收功率 kW, 端电压 V, 实际电流 A, 当前 SOC) + """ + # 1. 获取当前开路电压 + V_oc = self._get_ocv(self.SOC) + + # 2. 计算工程安全极限 (基于电压边界) + # 2.1 最大放电极限 (限制 V_t >= V_min) + I_dis_max = (V_oc - self.V_min) / self.R_in + P_dis_max_W = self.V_min * I_dis_max # 瓦特 + + # 2.2 最大充电极限 (限制 V_t <= V_max, 电流和功率为负数) + I_cha_max = (V_oc - self.V_max) / self.R_in + P_cha_max_W = self.V_max * I_cha_max # 瓦特 + + # SOC 保护限制 (防止 SOC 突破 0% 和 100%) + if self.SOC <= 0.05: + P_dis_max_W = 0.0 # 电量极低,禁止放电 + if self.SOC >= 0.98: + P_cha_max_W = 0.0 # 电量极高,禁止充电 + + # 3. 保护逻辑:功率限幅 (Clipping) + P_req_W = P_req_kw * 1000.0 + # 强制将需求功率限制在安全充放电区间内 + P_actual_W = max(P_cha_max_W, min(P_req_W, P_dis_max_W)) + + # 4. 根据实际功率求解电流 (一元二次方程) + # R * I^2 - Voc * I + P_actual = 0 + discriminant = V_oc**2 - 4 * self.R_in * P_actual_W + + if discriminant < 0: + self.I = V_oc / (2 * self.R_in) + P_actual_W = V_oc**2 / (4 * self.R_in) + else: + self.I = (V_oc - np.sqrt(discriminant)) / (2 * self.R_in) + + # 5. 计算端电压 + self.V_t = V_oc - self.I * self.R_in + + # 6. 安时积分更新 SOC + delta_soc = (self.I * (dt / 3600.0)) / self.capacity_Ah + self.SOC = self.SOC - delta_soc + self.SOC = max(0.0, min(1.0, self.SOC)) + + P_actual_kw = P_actual_W / 1000.0 + return P_actual_kw, self.V_t, self.I, self.SOC + +if __name__ == "__main__": + import matplotlib + matplotlib.use('Agg') + + # ========================================== + # 【测试示例】展示完整的充放电循环与边界保护 + # ========================================== + plt.rcParams['font.family'] = 'serif' + plt.rcParams['font.serif'] = ['DejaVu Serif', 'Times New Roman'] + plt.rcParams['axes.unicode_minus'] = True + + battery = BatterySim(initial_soc=0.5) + + dt = 0.5 + # 仿真总时长 1 小时,包含一个完整的充放电循环,且在边界处持续请求以验证保护机制 + time_array = np.arange(0, 3600, dt) + + req_power_log = [] + act_power_log = [] + soc_log = [] + vt_log = [] + + for t in time_array: + if t < 100: + P_req = 0.0 + elif t < 1200: + # 持续放电 150kW,将SOC从50%消耗至最低限制(5%) + # 在触发限制后继续请求,以验证禁止放电保护生效 + P_req = 150.0 + elif t < 3300: + # 持续充电 150kW,将SOC从5%一直充满至最高限制(98%) + # 同样在触发满电后继续请求,验证禁止充电保护生效 + P_req = -150.0 + else: + P_req = 0.0 + + P_act, V_t, I_act, soc = battery.step(dt, P_req) + + req_power_log.append(P_req) + act_power_log.append(P_act) + vt_log.append(V_t) + soc_log.append(soc * 100) + + # 绘图展示 + fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(10, 8), sharex=True) + + ax1.plot(time_array, req_power_log, 'k--', linewidth=2, label='Requested Power (kW)') + ax1.plot(time_array, act_power_log, 'r-', linewidth=2, label='Actual Power (kW)') + ax1.set_ylabel('Power [kW]') + ax1.set_title('Battery Power: Complete Cycle Protection Demo', fontweight='bold') + ax1.legend() + ax1.grid(True) + + ax2.plot(time_array, vt_log, 'b-', linewidth=2) + ax2.set_ylabel('Terminal Voltage [V]') + ax2.axhline(battery.V_min, color='r', linestyle=':', label='V_min limit') + ax2.axhline(battery.V_max, color='g', linestyle=':', label='V_max limit') + ax2.set_title('Voltage Dynamics with Physical Limits', fontweight='bold') + ax2.legend() + ax2.grid(True) + + ax3.plot(time_array, soc_log, 'g-', linewidth=2) + ax3.axhline(5, color='r', linestyle=':', alpha=0.8, label='SOC Lower Limit (5%)') + ax3.axhline(98, color='g', linestyle=':', alpha=0.8, label='SOC Upper Limit (98%)') + ax3.set_ylabel('SOC [%]') + ax3.set_xlabel('Time [s]') + ax3.set_title('State of Charge (SOC) Evolution', fontweight='bold') + ax3.legend() + ax3.grid(True) + + plt.tight_layout() + plt.savefig('figures/battery_sim_output.png') + print('Plot saved to figures/battery_sim_output.png') + # plt.show() diff --git a/Model/src/engine_dynamic_sim.py b/Model/src/engine_dynamic_sim.py new file mode 100644 index 0000000..d2e52a7 --- /dev/null +++ b/Model/src/engine_dynamic_sim.py @@ -0,0 +1,358 @@ +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +import numpy as np +import matplotlib.pyplot as plt +from src.engine_gpr_class import EngineGPRModel +from src.increPID import IncrementalPIDController + +class TurboshaftDynamicSim: + """ + 涡轴发动机动态仿真类 + 包含一阶燃油执行机构和转子动力学模型 + """ + def __init__(self, gpr_csv_path="data/Cleaned_Engine_Data_Full.csv", gpr_pth_path="data/engine_gpr_model.pth", + tau_fuel=0.15, K_inertia=100.0, + kp=4.652, ki=7.078, kd=0.222, min_fuel=10.0, max_fuel=600.0, + verbose=False): + """ + 初始化仿真环境和代理模型 + :param gpr_csv_path: GPR模型使用的数据集路径 + :param gpr_pth_path: 预训练的模型参数路径 + :param tau_fuel: 燃油执行机构时间常数 (s) + :param K_inertia: 转子惯性增益 (RPM / (kg/h)) + :param kp: PID比例系数 (用于功率跟随控制,归一化域) + :param ki: PID积分系数 (归一化域) + :param kd: PID微分系数 (归一化域) + :param min_fuel: 燃油流量下限 (kg/h) + :param max_fuel: 燃油流量上限 (kg/h) + :param verbose: 是否打印详细信息 + """ + import os + self.verbose = verbose + + if verbose: + print("-> 正在加载 GPR 稳态代理模型...") + self.engine_model = EngineGPRModel(gpr_csv_path) + + # 检查模型文件是否存在,不存在则训练 + if not os.path.exists(gpr_pth_path): + if verbose: + print(f"-> 模型文件 {gpr_pth_path} 不存在,正在训练模型...") + self.engine_model.train(save_path=gpr_pth_path) + else: + success = self.engine_model.load_model(gpr_pth_path) + if not success: + if verbose: + print(f"-> 模型加载失败,正在重新训练...") + self.engine_model.train(save_path=gpr_pth_path) + + # 动态参数 + self.tau_fuel = tau_fuel + self.K_inertia = K_inertia + + # 归一化基准 (用于PID计算) + self.max_fuel = max_fuel + self.max_power_ref = 300.0 # 300kw为功率归一化基准,根据实际数据调整 + + # 控制器初始化 (使用归一化参数,通过 scaling 自动处理) + self.pid = IncrementalPIDController( + kp=kp, ki=ki, kd=kd, dt=0.01, + output_min=min_fuel, output_max=max_fuel, + input_scale=self.max_power_ref, output_scale=self.max_fuel + ) + + # 环境与状态变量 + self.H_env = 0.0 + self.Ma_env = 0.0 + self.N_current = 0.0 + self.Wf_act_current = 0.0 + self.power_generated = 0.0 + + # 控制指令 + self.Wf_cmd = 0.0 + + def _solve_steady_rpm(self, target_val, target_type='power'): + """ + 内部方法:反解稳态转速 (RPM) + :param target_val: 目标值 (Power[kW] 或 Fuel[kg/h]) + :param target_type: 'power' 或 'fuel' + :return: 对应的稳态转速 + """ + from scipy.optimize import brentq + + # 搜索范围 [RPM_min, RPM_max],根据经验或数据范围设定 + low_bound, high_bound = 0.0, 60000.0 + + def objective(n): + current_input = np.array([[self.H_env, self.Ma_env, n]]) + pred_mean, _ = self.engine_model.predict(current_input) + + # index 0: Fuel Flow (kg/h), index 1: Power (kW) + val = pred_mean[0, 1] if target_type == 'power' else pred_mean[0, 0] + return val - target_val + + try: + # 简单的边界检查,防止报错 + f_low = objective(low_bound) + f_high = objective(high_bound) + if f_low * f_high > 0: + print(f"[Warn] 目标值超出模型范围 [{low_bound}, {high_bound}] RPM 对应的输出。将使用最接近的边界。") + return low_bound if abs(f_low) < abs(f_high) else high_bound + + n_solution = brentq(objective, low_bound, high_bound) + return n_solution + except Exception as e: + print(f"[Error] 稳态求解失败: {e}") + return (low_bound + high_bound) / 2.0 + + def set_steady_state_by_power(self, H_env, Ma_env, Power_target): + """ + 通过目标功率初始化稳态 + :param Power_target: 目标轴功率 (kW) + :return: 对应的稳态转速 (RPM) + """ + self.H_env = H_env + self.Ma_env = Ma_env + + # 反解转速 + self.N_current = self._solve_steady_rpm(Power_target, target_type='power') + + # 计算该转速下的稳态燃油 + current_input = np.array([[self.H_env, self.Ma_env, self.N_current]]) + pred_mean, _ = self.engine_model.predict(current_input) + + self.power_generated = pred_mean[0, 1] + self.Wf_act_current = pred_mean[0, 0] + self.Wf_cmd = self.Wf_act_current + + print(f"-> 稳态(Power)已配置: H={H_env}, Ma={Ma_env}, Target_P={Power_target:.1f} kW => N={self.N_current:.1f} RPM, Wf={self.Wf_cmd:.2f} kg/h") if self.verbose else None + + # 重置PID控制器至当前稳态输出 (自动处理归一化) + self.pid.reset(initial_output=self.Wf_cmd) + + return self.N_current + + def set_steady_state_by_fuel(self, H_env, Ma_env, Wf_target): + """ + 通过目标燃油流量初始化稳态 + :param Wf_target: 目标燃油流量 (kg/h) + :return: 对应的稳态转速 (RPM) + """ + self.H_env = H_env + self.Ma_env = Ma_env + + # 反解转速 + self.N_current = self._solve_steady_rpm(Wf_target, target_type='fuel') + + # 确认该状态下的功率 + current_input = np.array([[self.H_env, self.Ma_env, self.N_current]]) + pred_mean, _ = self.engine_model.predict(current_input) + + self.power_generated = pred_mean[0, 1] + self.Wf_act_current = pred_mean[0, 0] # 理论上应该非常接近 Wf_target + self.Wf_cmd = self.Wf_act_current + + print(f"-> 稳态(Fuel)已配置: H={H_env}, Ma={Ma_env}, Target_Wf={Wf_target:.1f} kg/h => N={self.N_current:.1f} RPM, Power={self.power_generated:.1f} kW") if self.verbose else None + + # 重置PID控制器至当前稳态输出 (自动处理归一化) + self.pid.reset(initial_output=self.Wf_cmd) + + return self.N_current + + def set_fuel_command(self, Wf_cmd): + """ + 更改燃油流量指令 + :param Wf_cmd: 目标燃油流量指令 + """ + self.Wf_cmd = Wf_cmd + + def set_flight_condition(self, H_env=None, Ma_env=None): + """ + 在运行过程中更改当前的飞行条件 (高度和马赫数) + :param H_env: 新的飞行高度 (m)。如果为 None,则保持不变。 + :param Ma_env: 新的飞行马赫数。如果为 None,则保持不变。 + """ + if H_env is not None: + self.H_env = H_env + if Ma_env is not None: + self.Ma_env = Ma_env + + def compute_control_law(self, dt, target_power): + """ + 计算控制律 (PID控制: Power -> Wf) + :param dt: 控制周期 (s) + :param target_power: 期望功率 (kW) + :return: 计算出的燃油指令 + """ + self.pid.dt = dt + # 1. 计算控制增量 (PID内部会自动处理归一化) + self.Wf_cmd = self.pid.compute(setpoint=target_power, measurement=self.power_generated) + return self.Wf_cmd + + def step(self, dt, target_power=None): + """ + 执行单步动态仿真 + :param dt: 积分步长 (s) + :param target_power: 目标轴功率 (kW),若不为 None 则执行一次PID控制 + :return: (当前转速, 实际供油量, 当前需要的平衡供油量, 当前功率) + """ + # 0. 闭环控制计算 + if target_power is not None: + self.compute_control_law(dt, target_power) + + # 1. 燃油执行机构动态 (一阶惯性) + dWf_act_dt = (self.Wf_cmd - self.Wf_act_current) / self.tau_fuel + Wf_act_next = self.Wf_act_current + dWf_act_dt * dt + + # 2. 调用GPR代理模型计算当前转速下的阻力矩(需求燃油) + current_input = np.array([[self.H_env, self.Ma_env, self.N_current]]) + pred_mean, _ = self.engine_model.predict(current_input) + + # GPR 输出: [0]: Fuel Flow, [1]: Shaft Power + Wf_req_current = pred_mean[0, 0] #维持当前转速所需的稳态燃油 + Power_current = pred_mean[0, 1] + self.power_generated = Power_current # 更新当前功率状态 + + # 3. 转子动力学积分 (燃料差额 -> 转速加速度) + dN_dt = self.K_inertia * (self.Wf_act_current - Wf_req_current) + N_next = self.N_current + dN_dt * dt + + # 4. 状态更新 + self.Wf_act_current = Wf_act_next + self.N_current = N_next + + return self.N_current, self.Wf_act_current, Wf_req_current, Power_current + + +if __name__ == "__main__": + # ========================================== + # 【测试示例】利用类运行功率闭环控制仿真 + # ========================================== + import matplotlib + matplotlib.use('Agg') + import matplotlib.pyplot as plt + + plt.rcParams['font.family'] = 'serif' + plt.rcParams['font.serif'] = ['DejaVu Serif', 'Times New Roman'] + plt.rcParams['axes.unicode_minus'] = True + + # 初始化仿真 (优化后的PID参数) + # kp: 比例系数 - 增大以加快响应速度 + # ki: 积分系数 - 适中以消除稳态误差 + # kd: 微分系数 - 设为0避免控制振荡 + sim = TurboshaftDynamicSim() + + # 1. 设置初始稳态 (通过目标功率设定) + P_initial_target = 100.0 # kW + sim.set_steady_state_by_power(H_env=0.0, Ma_env=0.0, Power_target=P_initial_target) + + # 仿真参数 + dt = 0.02 + t_end = 30.0 # 增加仿真时间以展示更多指令变化 + time_array = np.arange(0, t_end, dt) + + # 数据记录 + N_log = [] + Wf_act_log = [] + Wf_cmd_log = [] + Power_log = [] + Power_target_log = [] + + # 定义多段功率指令 (时间[s], 目标功率[kW]) + power_profile = [ + (0.0, 100.0), # 初始稳态 + (3.0, 200.0), # 阶跃上升 + (8.0, 150.0), # 阶跃下降 + (13.0, 250.0), # 阶跃上升至高功率 + (18.0, 100.0), # 快速下降 + (23.0, 180.0), # 再次上升 + ] + + # 斜坡指令测试:从18kW开始以一定速率上升 + ramp_start_time = 25.0 + ramp_rate = 10.0 # kW/s + + # 设定飞行条件改变的时间 + flight_change_time = 28.0 + + def get_target_power(t, profile, ramp_start, ramp_rate, default_power): + """根据时间获取当前目标功率""" + for i, (time, _) in enumerate(profile): + if t < time: + return profile[i-1][1] if i > 0 else default_power + # 如果在斜坡区间 + if t >= ramp_start: + last_static_power = profile[-1][1] + ramp_power = last_static_power + ramp_rate * (t - ramp_start) + return min(ramp_power, 300.0) # 限制最大300kW + return profile[-1][1] + + print("-> 开始仿真步进 (闭环控制)...") + print("-> 功率指令配置文件:") + for time, power in power_profile: + print(f" t={time:.1f}s -> {power:.0f} kW") + print(f" t={ramp_start_time:.1f}s -> 斜坡上升 (速率 {ramp_rate} kW/s)") + print() + + for t in time_array: + # 确定当前的目标功率 + current_target_P = get_target_power(t, power_profile, ramp_start_time, ramp_rate, P_initial_target) + + # 触发飞行条件变化 (确保仅触发一次以免重复打印) + if flight_change_time <= t < flight_change_time + dt: + print(f"\n[!] 时间 t={t:.2f}s, 模拟飞行条件跃变...") + sim.set_flight_condition(H_env=3000.0, Ma_env=0.2) + + # 执行闭环仿真步进 + N_cur, Wf_act_cur, Wf_req, Power_cur = sim.step(dt, target_power=current_target_P) + + # 记录数据 + N_log.append(N_cur) + Wf_act_log.append(Wf_act_cur) + Wf_cmd_log.append(sim.Wf_cmd) + Power_log.append(Power_cur) + Power_target_log.append(current_target_P) + + # 绘图 + fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(12, 10)) + fig.suptitle(f'Turboshaft Engine Dynamic Simulation\nPID Parameters: Kp={sim.pid.kp}, Ki={sim.pid.ki}, Kd={sim.pid.kd}', + fontsize=12, fontweight='bold') + + # Plot 1: Power Tracking + ax1.plot(time_array, Power_target_log, 'k--', linewidth=2, label='Target Power') + ax1.plot(time_array, Power_log, 'g-', linewidth=2, label='Actual Power') + ax1.set_ylabel('Shaft Power [kW]') + ax1.set_title('Closed-Loop Control: Power Tracking', fontweight='bold') + ax1.grid(True, linestyle=':', alpha=0.7) + ax1.legend() + + # Plot 2: Rotor Speed + ax2.plot(time_array, N_log, 'b-', linewidth=2, label='Engine Speed (N)') + ax2.set_ylabel('Rotor Speed [RPM]') + ax2.set_title('Engine Response: Rotor Speed', fontweight='bold') + ax2.grid(True, linestyle=':', alpha=0.7) + ax2.legend() + + # Plot 3: Fuel Flow (Control Input) + ax3.plot(time_array, Wf_cmd_log, 'k--', linewidth=1.5, label='Fuel Command') + ax3.plot(time_array, Wf_act_log, 'r-', linewidth=2, label='Actual Fuel') + ax3.set_xlabel('Time [s]') + ax3.set_ylabel('Fuel Flow [kg/h]') + ax3.set_title('Control Effort: Fuel Flow', fontweight='bold') + ax3.grid(True, linestyle=':', alpha=0.7) + ax3.legend() + + plt.tight_layout(rect=[0, 0, 1, 0.96]) + plt.savefig('figures/engine_dynamic_sim_plot.png') + print('Plot saved to figures/engine_dynamic_sim_plot.png') + + # 保存数据到 .dat 文件 + dat_file = 'data/pid_tuning_data.dat' + with open(dat_file, 'w') as f: + f.write('# Time[s]\tTarget_Power[kW]\tActual_Power[kW]\tRotor_Speed[RPM]\tFuel_Command[kg/h]\tActual_Fuel[kg/h]\n') + for i in range(len(time_array)): + f.write(f'{time_array[i]:.4f}\t{Power_target_log[i]:.2f}\t{Power_log[i]:.2f}\t{N_log[i]:.2f}\t{Wf_cmd_log[i]:.2f}\t{Wf_act_log[i]:.2f}\n') + print(f'Data saved to {dat_file}') + # plt.show() diff --git a/Model/src/engine_gpr_class.py b/Model/src/engine_gpr_class.py new file mode 100644 index 0000000..ab18054 --- /dev/null +++ b/Model/src/engine_gpr_class.py @@ -0,0 +1,283 @@ +import torch +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.colors import LogNorm +from botorch.models import SingleTaskGP +from botorch.fit import fit_gpytorch_mll +from gpytorch.mlls import ExactMarginalLogLikelihood +from gpytorch.means import LinearMean +from gpytorch.priors import GammaPrior +from sklearn.preprocessing import StandardScaler +import warnings +import os + +warnings.filterwarnings("ignore") + +# ========================================== +# 【全局绘图设置】学术规范 +# ========================================== +plt.rcParams['font.family'] = 'serif' +plt.rcParams['font.serif'] = ['DejaVu Serif', 'Times New Roman'] +plt.rcParams['mathtext.fontset'] = 'stix' +plt.rcParams['axes.unicode_minus'] = True + +class EngineGPRModel: + """ + 涡轴发动机 GPR 代理模型类 + 支持: 训练、加载已有模型、预测推断、单马赫数切面可视化 + """ + def __init__(self, csv_path="data/Cleaned_Engine_Data_Full.csv"): + self.csv_path = csv_path + self.df = None + self.valid_X_cols = [] + self.scaler_X = StandardScaler() + self.scaler_Y = StandardScaler() + self.model = None + + def _prepare_data(self): + """数据预处理:读取、筛选、Log变换、标准化""" + self.df = pd.read_csv(self.csv_path) + X_df = self.df[['Altitude_m', 'Mach', 'RPM']] + + # 剔除无效特征 + self.valid_X_cols = [col for col in X_df.columns if X_df[col].nunique() > 1] + X_numpy = self.df[self.valid_X_cols].values + + if 'WF_kg_h' not in self.df.columns: + raise ValueError("Column 'WF_kg_h' not found.") + + Y_numpy = self.df[['WF_kg_h', 'Power_kW']].values + + # Log1p 变换:保证非负性,并线性化指数规律 + Y_numpy = np.log1p(Y_numpy) + + # Z-Score 归一化 + X_scaled = self.scaler_X.fit_transform(X_numpy) + Y_scaled = self.scaler_Y.fit_transform(Y_numpy) + + return torch.tensor(X_scaled, dtype=torch.double), torch.tensor(Y_scaled, dtype=torch.double) + + def _init_model(self, train_X, train_Y): + """内部方法:统一初始化模型结构(包含 Mean 和 Prior 设置)""" + mean_module = LinearMean(input_size=train_X.shape[-1], batch_shape=torch.Size([train_Y.shape[-1]])) + model = SingleTaskGP(train_X, train_Y, mean_module=mean_module) + + # 统一施加 GammaPrior 防止结构不匹配 + # 这一步非常关键:加载模型时,模型结构必须与训练时完全一致,包括 Prior + if hasattr(model.covar_module, 'base_kernel'): + kernel = model.covar_module.base_kernel + else: + kernel = model.covar_module + + if hasattr(kernel, 'lengthscale'): + kernel.lengthscale_prior = GammaPrior(4.0, 1.0) + + return model + + def train(self, save_path=None): + """训练 GPR 模型 (Log-Space + 平滑约束)""" + print(f"{'='*30}\n🚀 GP Training (Log-Space)\n{'='*30}") + + train_X, train_Y = self._prepare_data() + + # 使用统一初始化方法 + self.model = self._init_model(train_X, train_Y) + + # 仅在训练开始前设定初始值,引导优化方向 + if hasattr(self.model.covar_module, 'base_kernel'): + kernel = self.model.covar_module.base_kernel + else: + kernel = self.model.covar_module + + if hasattr(kernel, 'lengthscale'): + kernel.lengthscale = 2.0 + + print("-> Optimizing hyperparameters...") + mll = ExactMarginalLogLikelihood(self.model.likelihood, self.model) + fit_gpytorch_mll(mll) + print("-> Training completed.") + + if save_path: + torch.save(self.model.state_dict(), save_path) + print(f"-> Model saved to {save_path}") + + def load_model(self, pth_path="data/engine_gpr_model.pth"): + """加载已训练的模型""" + print(f"Loading model from {pth_path}...") + try: + train_X, train_Y = self._prepare_data() + # 必须使用完全相同的结构初始化,否则 load_state_dict 会报错 + self.model = self._init_model(train_X, train_Y) + + # 使用 strict=False 忽略 Prior 缓冲区的差异(例如 _transformed_loc 等内部参数) + # 这些参数通常不影响模型预测,只影响后续继续训练时的约束 + self.model.load_state_dict(torch.load(pth_path), strict=True) + self.model.eval() + print("-> Model loaded successfully.") + return True + except Exception as e: + print(f"-> Load failed: {e}") + return False + + def _predict_log_space(self, test_X_real: np.ndarray): + """预测 Log 空间下的均值和标准差""" + if self.model is None: raise ValueError("Model not initialized.") + + self.model.eval() + test_X_scaled = torch.tensor(self.scaler_X.transform(test_X_real), dtype=torch.double) + + with torch.no_grad(): + posterior = self.model.posterior(test_X_scaled) + mu_scaled = posterior.mean.numpy() + var_scaled = posterior.variance.numpy() + + # 反归一化 + mu_log_real = self.scaler_Y.inverse_transform(mu_scaled) + var_log_real = var_scaled * self.scaler_Y.var_ + return mu_log_real, np.sqrt(var_log_real) + + def predict(self, test_X_real: np.ndarray): + """预测物理值 (expm1 还原)""" + mu_log, std_log = self._predict_log_space(test_X_real) + + # 中位数点估计 (Median of LogNormal) + pred_mean = np.expm1(mu_log) + # 近似方差 + var_log = std_log ** 2 + pred_var = (np.expm1(var_log)) * np.exp(2*mu_log + var_log) + + return pred_mean, pred_var + + def visualize(self, target_mach=0.0): + """可视化:生成方差热力图、切面曲线、均值云图""" + if self.model is None: raise ValueError("Model not initialized.") + print(f"Generating Plots for Mach = {target_mach}") + + # 确定绘图范围 (训练数据 Range) + H_min, H_max = self.df['Altitude_m'].min(), self.df['Altitude_m'].max() + RPM_min, RPM_max = self.df['RPM'].min(), self.df['RPM'].max() + + if H_min == H_max: H_min, H_max = H_min-1, H_max+1 + if RPM_min == RPM_max: RPM_min, RPM_max = RPM_min-100, RPM_max+100 + + H_grid, RPM_grid = np.meshgrid(np.linspace(H_min, H_max, 60), np.linspace(RPM_min, RPM_max, 60), indexing='ij') + + test_X_dict = {'Altitude_m': H_grid.flatten(), 'RPM': RPM_grid.flatten()} + if 'Mach' in self.valid_X_cols: + test_X_dict['Mach'] = np.full_like(H_grid.flatten(), target_mach) + + test_X_real = np.column_stack([test_X_dict[col] for col in self.valid_X_cols]) + + # 预测并重塑 (60x60) + pred_mean, pred_var = self.predict(test_X_real) + wf_mean, pow_mean = pred_mean[:, 0].reshape(60, 60), pred_mean[:, 1].reshape(60, 60) + wf_var, pow_var = pred_var[:, 0].reshape(60, 60), pred_var[:, 1].reshape(60, 60) + + # 筛选绘图用的真实数据点 + tol = 1e-3 + plot_df = self.df[(self.df['Mach'] >= target_mach - tol) & (self.df['Mach'] <= target_mach + tol)] if 'Mach' in self.valid_X_cols else self.df + + # 1. 方差热力图 (Log Scale) + fig, axes = plt.subplots(1, 2, figsize=(14, 5.5)) + for ax, var_data, title in zip(axes, [wf_var, pow_var], ['Fuel Flow Variance', 'Shaft Power Variance']): + log_var = np.log10(np.maximum(var_data, 1e-16)) + cf = ax.contourf(RPM_grid, H_grid, log_var, levels=50, cmap='jet', alpha=0.9) + if not plot_df.empty: ax.scatter(plot_df['RPM'], plot_df['Altitude_m'], c='white', edgecolors='black', s=25, label='Data') + ax.set_title(f"{title} (Log10)"); ax.set_xlabel('RPM'); ax.set_ylabel('Altitude') + plt.colorbar(cf, ax=ax) + plt.tight_layout() + plt.savefig(f'figures/gpr_mach_{target_mach}_variance.png') + print(f"Saved figures/gpr_mach_{target_mach}_variance.png") + plt.close() + + # 2. 高度切面图 (95% CI) + fig, axes = plt.subplots(1, 2, figsize=(14, 5.5)) + colors = ['#1f77b4', '#ff7f0e', '#2ca02c'] + RPM_1D = np.linspace(RPM_min, RPM_max, 100) + + for idx, alt in enumerate([0.0, 3000.0, 6000.0]): + d_1D = {'Altitude_m': np.full_like(RPM_1D, alt), 'RPM': RPM_1D} + if 'Mach' in self.valid_X_cols: d_1D['Mach'] = np.full_like(RPM_1D, target_mach) + X_1D = np.column_stack([d_1D[c] for c in self.valid_X_cols]) + + # Log空间预测 -> 计算物理置信区间 (保证下界非负) + mu_log, std_log = self._predict_log_space(X_1D) + mean = np.expm1(mu_log) + lower = np.expm1(mu_log - 2*std_log) + upper = np.expm1(mu_log + 2*std_log) + + for ax, i in zip(axes, [0, 1]): + ax.plot(RPM_1D, mean[:, i], color=colors[idx], label=f'Alt={int(alt)}m') + ax.fill_between(RPM_1D, lower[:, i], upper[:, i], color=colors[idx], alpha=0.2) + + for ax, title, ylab in zip(axes, ['Fuel Flow', 'Shaft Power'], ['kg/h', 'kW']): + ax.set_title(title); ax.set_ylabel(ylab); ax.set_xlabel('RPM') + ax.legend(); ax.grid(True, alpha=0.5) + plt.tight_layout() + plt.savefig(f'figures/gpr_mach_{target_mach}_section.png') + print(f"Saved figures/gpr_mach_{target_mach}_section.png") + plt.close() + + # 3. 均值云图 + fig, axes = plt.subplots(1, 2, figsize=(14, 5.5)) + for ax, mean_data, title in zip(axes, [wf_mean, pow_mean], ['Fuel Flow Mean', 'Shaft Power Mean']): + cf = ax.contourf(RPM_grid, H_grid, mean_data, levels=50, cmap='viridis', alpha=0.9) + if not plot_df.empty: ax.scatter(plot_df['RPM'], plot_df['Altitude_m'], c='red', s=20, edgecolors='white', label='Data') + ax.set_title(title); ax.set_xlabel('RPM'); ax.set_ylabel('Altitude') + plt.colorbar(cf, ax=ax) + plt.tight_layout() + plt.savefig(f'figures/gpr_mach_{target_mach}_mean.png') + print(f"Saved figures/gpr_mach_{target_mach}_mean.png") + plt.close() + +if __name__ == "__main__": + import matplotlib + matplotlib.use('Agg') + print("Using Agg backend for plotting.") + + engine_model = EngineGPRModel() + + # 智能选择加载或训练 + model_path = "data/engine_gpr_model.pth" + if os.path.exists(model_path): + success = engine_model.load_model(model_path) + if not success: + # 如果加载失败(结构不匹配),则重新训练 + engine_model.train(save_path=model_path) + else: + # 如果模型不存在,则训练并保存 + engine_model.train(save_path=model_path) + + # ========================================== + # 【使用示例】 + # ========================================== + print("\n" + "="*50) + print("💡 预测使用示例 (Prediction Example)") + print("="*50) + # 假设默认特征组合为: [Altitude_m, Mach, RPM] + sample_inputs = np.array([ + [0.0, 0.0, 15000.0], # 测试点 1: 海平面静止, 15000 RPM + [3000.0, 0.2, 22000.0] # 测试点 2: 3000米, 0.2马赫, 22000 RPM + ]) + + + mean_preds, var_preds = engine_model.predict(sample_inputs) + + for i, (X_in, Y_mean, Y_var) in enumerate(zip(sample_inputs, mean_preds, var_preds)): + # 格式化输出 + x_str = "[" + ", ".join([f"{val:8.2f}" for val in X_in]) + " ]" + mean_str = "[" + ", ".join([f"{val:10.4f}" for val in Y_mean]) + " ]" + var_str = "[" + ", ".join([f"{val:10.4f}" for val in Y_var]) + " ]" + + print(f"[测试点 {i+1}]") + print(f" -> 输入特征 {engine_model.valid_X_cols}: {x_str}") + print(f" -> 预测均值 [WF (kg/h), Power_kW]: {mean_str}") + print(f" -> 预测方差 [WF (kg/h), Power_kW]: {var_str}\n") + + # ========================================== + # 循环调用绘图方法,分别输出所需的马赫数切面图 + # ========================================== + target_machs = [0.0, 0.1, 0.2, 0.3, 0.4] + for m in target_machs: + engine_model.visualize(target_mach=m) diff --git a/Model/src/increPID.py b/Model/src/increPID.py new file mode 100644 index 0000000..a58f5ee --- /dev/null +++ b/Model/src/increPID.py @@ -0,0 +1,88 @@ +class IncrementalPIDController: + """ + 增量式 PID 控制器 (支持自动归一化缩放) + 适用于发动机燃油控制等具有保持特性的执行机构 + """ + def __init__(self, kp, ki, kd, dt, output_min, output_max, input_scale=1.0, output_scale=1.0): + """ + 初始化 PID 控制器 + + 如果提供了 scale 参数,则 kp/ki/kd 被视为归一化域的参数。 + 内部运算逻辑: + norm_error = (setpoint - measurement) / input_scale + norm_output += PID(norm_error, kp, ki, kd) + physical_output = norm_output * output_scale + + :param kp: 比例系数 (建议使用归一化参数) + :param ki: 积分系数 + :param kd: 微分系数 + :param dt: 控制周期 (s) + :param output_min: 执行机构输出下限 (物理量) + :param output_max: 执行机构输出上限 (物理量) + :param input_scale: 输入测量值的量程基准 (例如额定功率 1000.0) + :param output_scale: 输出控制量的量程基准 (例如最大燃油 600.0) + """ + self.kp = kp + self.ki = ki + self.kd = kd + self.dt = dt + + # 记录缩放因子 + self.input_scale = input_scale + self.output_scale = output_scale + + # 将物理限制转换为内部的归一化限制 + self.out_min_norm = output_min / output_scale + self.out_max_norm = output_max / output_scale + + # 历史误差状态 (归一化误差) + self.e_k1 = 0.0 # e(k-1) + self.e_k2 = 0.0 # e(k-2) + + # 当前实际的控制输出 (归一化值 [0~1] 或 [-1~1]) + self.current_output_norm = 0.0 + + def reset(self, initial_output=0.0): + """ + 重置控制器状态,用于初始化或开闭环的无扰切换 + :param initial_output: 当前执行机构的实际位置(物理量,如燃油流量) + """ + self.e_k1 = 0.0 + self.e_k2 = 0.0 + # 将物理初始值转换为归一化内部状态 + self.current_output_norm = initial_output / self.output_scale + + def compute(self, setpoint, measurement): + """ + 计算下一拍的控制量 + :param setpoint: 目标设定值 (物理量) + :param measurement: 当前测量值 (物理量) + :return: 经过限幅的绝对控制指令 (物理量) + """ + # 1. 计算归一化误差 e(k) + # 误差除以输入量程,使得误差在 -1~1 之间 (对于阶跃通常更小) + e_k = (setpoint - measurement) / self.input_scale + + # 2. 计算归一化控制增量 delta_u + p_term = self.kp * (e_k - self.e_k1) + i_term = self.ki * e_k * self.dt + # 微分项除以dt可能会很大,归一化的时间常数有助于平滑 + d_term = self.kd * (e_k - 2 * self.e_k1 + self.e_k2) / self.dt + + delta_u_norm = p_term + i_term + d_term + + # 3. 更新当前归一化输出量 + self.current_output_norm += delta_u_norm + + # 4. 绝对位置限幅 (在归一化域进行) + if self.current_output_norm > self.out_max_norm: + self.current_output_norm = self.out_max_norm + elif self.current_output_norm < self.out_min_norm: + self.current_output_norm = self.out_min_norm + + # 5. 更新历史误差 + self.e_k2 = self.e_k1 + self.e_k1 = e_k + + # 6. 返回物理量输出 + return self.current_output_norm * self.output_scale diff --git a/Model/src/motor_sim.py b/Model/src/motor_sim.py new file mode 100644 index 0000000..122716e --- /dev/null +++ b/Model/src/motor_sim.py @@ -0,0 +1,1225 @@ +# -*- coding: utf-8 -*- +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +""" +混合动力涡轴发动机驱动电机动力学模型 (Motor Dynamics Model) + +模块提供了永磁同步电机 (PMSM) 的离散时间仿真实现,涵盖了闭环转速控制、 +物理级的电磁转矩估算及端电压/损耗模型的动力学计算。 + +系统符号学约定: +- 轴系转矩 (T_motor): 正值表示吸收轴系功率 (发电机/负载响应),负值表示向轴系输出功率 (驱动动力)。 +- 直流母线功率 (P_bus): 正值表示从母线汲取有功功率,负值表示向母线回馈有功功率。 +""" + +from typing import Any, Dict +import sys +import os +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +import numpy as np +from src.increPID import IncrementalPIDController + + +class MotorSim: + """混电飞机驱动电机模型""" + + def __init__( + self, + n_p: int = 3, + R_s: float = 0.05, + L_d: float = 0.001, + L_q: float = 0.001, + psi_f: float = 0.15, + J: float = 0.5, + u_dc: float = 520.0, + P_rate: float = 300e3, + w_rate: float = 575.95, + eta_mot: float = 0.95, + eta_gen: float = 0.93, + B_visc: float = 3e-4, + k_p_w: float = 13.440362, + k_i_w: float = 42.997816, + k_d_w: float = 0.484660, + k_d_w_error: float = 0.05, + p_bus_slew_rate_kw: float = 2000.0, + t_cmd_slew_rate_nm_s: float = 0.0, + tau_i: float = 0.004, + k_mod: float = 1 / np.sqrt(3), + P_const_loss: float = 250.0, + k_fe: float = 3e-4, + k_inv: float = 0.015, + tau_n_ref: float = 0.35, + tau_t_cmd: float = 0.12, + speed_priority_band_rpm: float = 180.0, + tau_v_bus: float = 0.08, + i_s_max: float | None = None, + ): + """ + 初始化电机动力学仿真器参数。 + + :param n_p: 极对数 + :param R_s: 定子等效电阻 (Ohm) + :param L_d: 直轴电感 (H) + :param L_q: 交轴电感 (H) + :param psi_f: 永磁体磁链 (Wb) + :param J: 轴系总等效转动惯量 (kg·m^2) + :param u_dc: 初始化母线侧额定直流电压 (V) + :param P_rate: 额定机械功率 (W) + :param w_rate: 额定机械角速度 (rad/s) + :param eta_mot: 稳态驱动效率参考值 + :param eta_gen: 稳态发电效率参考值 + :param B_visc: 轴系黏性摩擦阻尼系数 (N·m·s) + :param k_p_w: 速度控制环比例增益 + :param k_i_w: 速度控制环积分增益 + :param k_d_w: 速度控制环微分控制增益(闭环阻尼) + :param k_d_w_error: 目标速度微分前馈增益 + :param p_bus_slew_rate_kw: 允许的最大母线请求功率变化率 (kW/s) + :param t_cmd_slew_rate_nm_s: 允许的最大转矩指令变化率 (Nm/s) + :param tau_i: 闭环电流/电磁转矩等效一阶延迟时间常数 (s) + :param k_mod: DC-AC 变换器电压利用系数 + :param P_const_loss: 独立于工况的系统常量损耗 (W) + :param k_fe: 铁耗计算映射系数 + :param k_inv: DC-AC 逆变环节损耗系数 + :param tau_n_ref: 目标转速给定指令一阶低通滤波时间常数 (s) + :param tau_t_cmd: 转矩输出指令一阶低通滤波时间常数 (s) + :param speed_priority_band_rpm: 目标跟随允许容差基准带 (RPM) + :param tau_v_bus: DC侧动态响应一阶滤波时间常数 (s) + :param i_s_max: 定子相电流约束阈值有效值 (A) + """ + self._validate_parameters( + n_p, + R_s, + L_d, + L_q, + psi_f, + J, + u_dc, + P_rate, + w_rate, + eta_mot, + eta_gen, + tau_i, + ) + + self.n_p = n_p + self.R_s = R_s + self.L_d = L_d + self.L_q = L_q + self.psi_f = psi_f + self.J = J + self.u_dc = u_dc + self.P_rate = P_rate + self.w_rate = w_rate + self.eta_mot = eta_mot + self.eta_gen = eta_gen + self.B_visc = B_visc + self.k_p_w = k_p_w + self.k_i_w = k_i_w + self.k_d_w = k_d_w + self.k_d_w_error = k_d_w_error + self.p_bus_slew_rate_kw = p_bus_slew_rate_kw + self.t_cmd_slew_rate_nm_s = max(0.0, float(t_cmd_slew_rate_nm_s)) + self.tau_i = tau_i + self.k_mod = k_mod + self.P_const_loss = P_const_loss + self.k_fe = k_fe + self.k_inv = k_inv + self.tau_n_ref = max(1e-4, float(tau_n_ref)) + self.tau_t_cmd = max(1e-4, float(tau_t_cmd)) + self.speed_priority_band = max(5.0, float(speed_priority_band_rpm)) * 2.0 * np.pi / 60.0 + self.tau_v_bus = max(1e-4, float(tau_v_bus)) + + self.tau_rate = self.P_rate / self.w_rate + if i_s_max is None: + base_current = self.tau_rate / (1.5 * self.n_p * max(abs(self.psi_f), 1e-6)) + self.i_s_max = max(20.0, 1.8 * base_current) + else: + self.i_s_max = float(i_s_max) + + self.u_s_max = self.u_dc * self.k_mod + + + self.w_M = 0.0 + self.t_motor = 0.0 + self.p_bus = 0.0 + self.p_shaft = 0.0 + self.p_loss = 0.0 + self.i_bus = 0.0 + self.v_motor = self.u_dc + self.i_d = 0.0 + self.i_q = 0.0 + self.i_s = 0j + self.u_d = 0.0 + self.u_q = 0.0 + self.u_s = 0.0 + self.theta_e = 0.0 + self.i_a, self.i_b, self.i_c = 0.0, 0.0, 0.0 + self.u_an, self.u_bn, self.u_cn = 0.0, 0.0, 0.0 + self.duty_a, self.duty_b, self.duty_c = 0.5, 0.5, 0.5 + self._sim_t = 0.0 + self._w_error_int = 0.0 + self._w_error_prev = 0.0 + self._dw_error_f = 0.0 + self._p_bus_req_prev = 0.0 + self._w_set_f = 0.0 + self._t_ref_f = 0.0 + self._v_bus_f = float(self.u_dc) + self._t_load_f = 0.0 + self._t_ext_f = 0.0 + + # 系统机械约束约束配置 + self._dw_max = 800.0 + + # 增量式PID控制器 (用于转速环功率控制) + # output_scale: 额定功率300kW,input_scale: 额定转速575.95 rad/s + self.speed_pid = IncrementalPIDController( + kp=k_p_w, ki=k_i_w, kd=k_d_w, + dt=0.02, # 将在step中动态更新 + output_min=-self.P_rate/1000.0 * 1.2, # 允许放电 + output_max=self.P_rate/1000.0 * 1.2, # 允许充电 + input_scale=self.w_rate, + output_scale=self.P_rate/1000.0 + ) + + self._log = { + 't': [], + 'w_M': [], + 'n_rpm': [], + 't_motor': [], + 't_load': [], + 't_ext': [], + 'p_bus_req_kw': [], + 'p_bus_kw': [], + 'p_shaft_kw': [], + 'p_loss_kw': [], + 'i_bus_a': [], + 'v_bus': [], + 'v_motor': [], + 'mode': [], + 'i_a': [], + 'i_b': [], + 'i_c': [], + 'u_an': [], + 'u_bn': [], + 'u_cn': [], + } + + # 滤波系数缓存 (用于优化: 避免每步重复计算 exp(-dt/tau)) + self._last_dt: float | None = None + self._a_v: float = 0.0 # 母线电压滤波系数 + self._a_n: float = 0.0 # 转速参考滤波系数 + self._a_t_load: float = 0.0 # 负载转矩滤波系数 + self._a_t: float = 0.0 # 转矩指令滤波系数 + self._alpha_i: float = 0.0 # 电流环滤波系数 + + # Magic Numbers 提取为常量 (提高可读性和可维护性) + self._W_MIN_RAD: float = 50.0 # 最小转速阈值 (rad/s),用于避免除零和数值不稳定 + self._EPSILON: float = 1e-6 # 数值 epsilon,用于避免除零 + self._TAU_LOAD_FILTER: float = 0.05 # 负载转矩滤波时间常数 (s) + self._TORQUE_OVERRATE: float = 1.35 # 转矩过载系数 + self._W_ERROR_DEADBAND: float = 0.05 # 转速误差死区 (rad/s) + self._DW_ERROR_FILTER: float = 0.15 # 微分误差滤波系数 + + # 日志记录配置:可选的最大日志长度限制 (None 表示无限制) + self._log_maxlen: int | None = None # 可设置为如 100000 来限制内存使用 + + def _update_filter_coefficients(self, dt: float) -> None: + """更新滤波系数缓存 (当 dt 变化时调用)""" + if self._last_dt == dt: + return + self._last_dt = dt + self._a_v = 1.0 - np.exp(-dt / self.tau_v_bus) + self._a_n = 1.0 - np.exp(-dt / self.tau_n_ref) + self._a_t_load = 1.0 - np.exp(-dt / self._TAU_LOAD_FILTER) + self._a_t = 1.0 - np.exp(-dt / self.tau_t_cmd) + self._alpha_i = 1.0 - np.exp(-dt / self.tau_i) + + def _validate_parameters( + self, + n_p: int, + R_s: float, + L_d: float, + L_q: float, + psi_f: float, + J: float, + u_dc: float, + P_rate: float, + w_rate: float, + eta_mot: float, + eta_gen: float, + tau_i: float, + ) -> None: + """校验主要参数是否满足物理与数值稳定边界。""" + if n_p <= 0: + raise ValueError('n_p must be positive') + if R_s <= 0 or L_d <= 0 or L_q <= 0: + raise ValueError('R_s, L_d and L_q must be positive') + if psi_f <= 0: + raise ValueError('psi_f must be positive') + if J <= 0: + raise ValueError('J must be positive') + if u_dc <= 0 or P_rate <= 0 or w_rate <= 0: + raise ValueError('u_dc, P_rate and w_rate must be positive') + if not (0.0 < eta_mot <= 1.0) or not (0.0 < eta_gen <= 1.0): + raise ValueError('eta_mot and eta_gen must be in (0, 1]') + if tau_i <= 0: + raise ValueError('tau_i must be positive') + + @staticmethod + def clarke_transform(x_a: float, x_b: float, x_c: float) -> tuple[float, float]: + """等幅值 Clarke 变换 (abc -> alpha beta)""" + x_alpha = (2.0/3.0) * (x_a - 0.5 * x_b - 0.5 * x_c) + x_beta = (2.0/3.0) * ((np.sqrt(3.0) / 2.0) * x_b - (np.sqrt(3.0) / 2.0) * x_c) + return float(x_alpha), float(x_beta) + + @staticmethod + def inv_clarke_transform(x_alpha: float, x_beta: float) -> tuple[float, float, float]: + """等幅值逆 Clarke 变换 (alpha beta -> abc)""" + x_a = x_alpha + x_b = -0.5 * x_alpha + (np.sqrt(3.0) / 2.0) * x_beta + x_c = -0.5 * x_alpha - (np.sqrt(3.0) / 2.0) * x_beta + return float(x_a), float(x_b), float(x_c) + + @staticmethod + def park_transform(x_alpha: float, x_beta: float, theta: float) -> tuple[float, float]: + """Park 变换 (alpha beta -> dq)""" + cos_t = np.cos(theta) + sin_t = np.sin(theta) + x_d = x_alpha * cos_t + x_beta * sin_t + x_q = -x_alpha * sin_t + x_beta * cos_t + return float(x_d), float(x_q) + + @staticmethod + def inv_park_transform(x_d: float, x_q: float, theta: float) -> tuple[float, float]: + """逆 Park 变换 (dq -> alpha beta)""" + cos_t = np.cos(theta) + sin_t = np.sin(theta) + x_alpha = x_d * cos_t - x_q * sin_t + x_beta = x_d * sin_t + x_q * cos_t + return float(x_alpha), float(x_beta) + + @staticmethod + def svpwm(u_a: float, u_b: float, u_c: float, u_dc: float) -> tuple[float, float, float, float, float, float]: + """ + 基于共模电压注入的连续 SVPWM 调制 (Min-Max 注入法) + 返回:占空比 d_a, d_b, d_c (0~1) 和实际向电机施加的相电压 u_an, u_bn, u_cn + """ + v_max = max(u_a, u_b, u_c) + v_min = min(u_a, u_b, u_c) + u_zero = -0.5 * (v_max + v_min) # 生成马鞍波零序偏置 + + # 调制后的相电压(相对于参考中点) + u_an = u_a + u_zero + u_bn = u_b + u_zero + u_cn = u_c + u_zero + + # 计算占空比:在 +/- u_dc/2 之间波动映射到 0~1 的占空比 + # 设全桥中点为基准电压 0V,则半桥输出可达 +/- u_dc/2 + d_a = float(np.clip(0.5 + u_an / max(u_dc, 1e-6), 0.0, 1.0)) + d_b = float(np.clip(0.5 + u_bn / max(u_dc, 1e-6), 0.0, 1.0)) + d_c = float(np.clip(0.5 + u_cn / max(u_dc, 1e-6), 0.0, 1.0)) + + return d_a, d_b, d_c, float(u_an), float(u_bn), float(u_cn) + + def _torque_from_currents(self, i_d: float, i_q: float) -> float: + """ + 基于 PMSM 电磁转矩方程计算电机转矩。 + + 注意:正转矩代表吸收轴功率,负转矩代表向轴输出功率。 + + :param i_d: d轴电流 (A) + :param i_q: q轴电流 (A) + :return: 电磁转矩 (Nm) + """ + return 1.5 * self.n_p * (self.psi_f + (self.L_d - self.L_q) * i_d) * i_q + + def _compute_voltage(self, i_d: float, i_q: float, w_M: float, v_bus: float) -> tuple[float, float, float]: + """ + 按 dq 轴稳态方程估算定子电压,并考虑母线电压约束。 + + :param i_d: d轴电流 (A) + :param i_q: q轴电流 (A) + :param w_M: 机械角速度 (rad/s) + :param v_bus: 当前母线电压 (V) + :return: `(u_d, u_q, |u_s|)`,单位均为 V + """ + w_e = self.n_p * abs(w_M) + u_d = self.R_s * i_d - w_e * self.L_q * i_q + u_q = self.R_s * i_q + w_e * (self.L_d * i_d + self.psi_f) + u_s = float(np.hypot(u_d, u_q)) + return u_d, u_q, min(u_s, v_bus * self.k_mod) + + def _max_iq_given_id(self, i_d: float, w_e: float, v_bus: float) -> float: + """计算给定 `i_d` 下受电流圆和电压椭圆约束的 `|i_q|` 上限。""" + if abs(i_d) > self.i_s_max: + return 0.0 + + iq_i = np.sqrt(max(0.0, self.i_s_max**2 - i_d**2)) + if w_e < 1e-6: + return iq_i + + psi_v_max = (v_bus * self.k_mod) / w_e + flux_term = psi_v_max**2 - (self.psi_f + self.L_d * i_d) ** 2 + if flux_term <= 0: + return 0.0 + + iq_v = np.sqrt(flux_term) / max(abs(self.L_q), 1e-9) + return max(0.0, min(iq_i, iq_v)) + + def _compute_tau_limit(self, w_M: float, v_bus: float) -> float: + """ + 计算当前工况下电机可实现的转矩幅值上限。 + + :param w_M: 机械角速度 (rad/s) + :param v_bus: 母线电压 (V) + :return: 转矩幅值上限 (Nm) + """ + w_abs = abs(w_M) + w_e = self.n_p * w_abs + + if w_e < self._EPSILON: + return float(max(0.0, abs(self._torque_from_currents(0.0, self.i_s_max)))) + + # 优化: 减少网格点数从40到12,使用更智能的搜索策略 + i_d_estimate = max(-self.i_s_max, min(0.0, -0.5 * (self.psi_f / (self.L_q - self.L_d)) if self.L_q != self.L_d else 0.0)) + i_d_grid = np.array([ + i_d_estimate - 0.3 * self.i_s_max, + i_d_estimate - 0.2 * self.i_s_max, + i_d_estimate - 0.1 * self.i_s_max, + i_d_estimate, + i_d_estimate + 0.1 * self.i_s_max, + -0.8 * self.i_s_max, + -0.6 * self.i_s_max, + -0.4 * self.i_s_max, + -0.2 * self.i_s_max, + -0.1 * self.i_s_max, + 0.0, + -self.i_s_max, + ]) + i_d_grid = np.clip(i_d_grid, -self.i_s_max, 0.0) + + tau_best = 0.0 + for i_d in i_d_grid: + i_q = self._max_iq_given_id(i_d, w_e, v_bus) + tau_candidate = abs(self._torque_from_currents(i_d, i_q)) + if tau_candidate > tau_best: + tau_best = tau_candidate + if i_d < -0.01 * self.i_s_max: + continue + + tau_p_max = self.P_rate / max(w_abs, self._W_MIN_RAD) + return float(max(0.0, min(tau_best, tau_p_max, self._TORQUE_OVERRATE * self.tau_rate))) + + def _apply_power_slew(self, p_bus_req_kw: float, dt: float) -> float: + """对母线请求功率施加斜率限制。""" + if self.p_bus_slew_rate_kw <= 0: + self._p_bus_req_prev = float(p_bus_req_kw) + return float(p_bus_req_kw) + + delta = self.p_bus_slew_rate_kw * dt + self._p_bus_req_prev = float(p_bus_req_kw) + return float(p_bus_req_kw) + + def _power_to_torque_ref(self, p_bus_w: float, w_M: float) -> float: + """ + 将母线侧实际电气功率转换为物理电磁转矩。 + + :param p_bus_w: 实际输入给电机的电功率 (W) + :param w_M: 当前机械角速度 (rad/s) + :return: 转化为的轴向电磁阻力/推力 (Nm) + """ + if abs(p_bus_w) < 1e-9: + return 0.0 + + w_eff = max(abs(w_M), 50.0) + if p_bus_w >= 0: + # 取电模式:从母线取有功,经过内部热量/电磁损耗后,输出转动推力(负转矩) + return -(p_bus_w * self.eta_mot) / w_eff + else: + # 发电模式:电机受到负负载强推,需要输出极大的正机械阻力(查表吸收电能) + return -p_bus_w / (w_eff * max(self.eta_gen, 1e-6)) + + def _current_ref_from_torque(self, t_motor_ref: float, w_M: float, v_bus: float) -> tuple[float, float]: + """ + 将转矩参考值转换为 d/q 轴电流参考值。 + + :param t_motor_ref: 目标电机转矩 (Nm) + :param w_M: 当前机械角速度 (rad/s) + :param v_bus: 当前母线电压 (V) + :return: `(i_d_ref, i_q_ref)`,单位 A + """ + if abs(self.psi_f) < 1e-9: + return 0.0, 0.0 + + w_e = self.n_p * abs(w_M) + i_q_ref = t_motor_ref / (1.5 * self.n_p * self.psi_f) + i_q_ref = float(np.clip(i_q_ref, -self.i_s_max, self.i_s_max)) + i_d_ref = 0.0 + + if w_e < 1e-6: + return i_d_ref, i_q_ref + + _, _, u_mag = self._compute_voltage(i_d_ref, i_q_ref, w_M, v_bus) + if u_mag <= v_bus * self.k_mod: + return i_d_ref, i_q_ref + + iq_sign = 1.0 if i_q_ref >= 0 else -1.0 + iq_abs_target = abs(i_q_ref) + # 优化: 减少网格点数从80到20 + for i_d in np.linspace(-self.i_s_max, 0.0, 20): + iq_max = self._max_iq_given_id(i_d, w_e, v_bus) + if iq_max >= iq_abs_target: + return float(i_d), float(iq_sign * iq_abs_target) + + i_d_fw = -self.i_s_max + i_q_fw = iq_sign * self._max_iq_given_id(i_d_fw, w_e, v_bus) + return float(i_d_fw), float(i_q_fw) + + def _compute_loss_terms(self, w_M: float) -> tuple[float, float, float, float]: + """计算铜耗、铁耗、逆变器损耗和总损耗。""" + w_e = self.n_p * abs(w_M) + p_cu = 1.5 * self.R_s * (self.i_d**2 + self.i_q**2) + flux_ratio = ((self.psi_f + self.L_d * self.i_d) ** 2 + (self.L_q * self.i_q) ** 2) / max(self.psi_f**2, 1e-9) + p_fe = self.k_fe * (w_e**2) * flux_ratio + p_inv = 40.0 + self.k_inv * abs(self.u_d * self.i_d + self.u_q * self.i_q) + p_total = p_cu + p_fe + self.P_const_loss + p_inv + return float(p_cu), float(p_fe), float(p_inv), float(p_total) + + def _compute_bus_quantities(self, t_motor: float, w_M: float, v_bus: float) -> tuple[float, float, float, float, float]: + """ + 执行电机接口侧电气边界计算及内模功率流映射。 + + 遵循系统全生命周期能量守恒定理进行功率平衡演算是仿真有效性的核心判据。 + + :param t_motor: 瞬时电磁转矩工作点指令值 (Nm) + :param w_M: 工作侧机械角速度反馈量 (rad/s) + :param v_bus: 回环观测的母线直流电压极限 (V) + :return: 跨域功率流核心元组 `(p_shaft, p_bus, i_bus, v_motor, p_loss)` + """ + p_shaft = t_motor * w_M + + # 电磁边界与核心拓扑节点分布损耗推算 + p_cu, p_fe, p_inv, p_loss_model = self._compute_loss_terms(w_M) + p_loss = max(0.0, float(p_loss_model)) + + # 根据能量守恒计算母线功率(包含了真实的各类损耗,取代了定效率查表) + p_bus = -p_shaft + p_loss + + # 真实的有向母线电流(正:从母线流入,负:流出母线) + i_bus_real = p_bus / max(v_bus, 1e-6) + + # 遵循原有接口要求,i_bus 仅输出量级 + i_bus = abs(i_bus_real) + + # 等效电机端电势:引入合理的直流侧等效内阻(如线缆、逆变器直流侧等效压降) + # R_dc 表征母线到真正电机控制端口的线路电阻 + R_dc = 0.05 + + # 基于基尔霍夫电压定律: + # V_bus = V_motor + I_bus_real * R_dc => V_motor = V_bus - I_bus_real * R_dc + v_motor = v_bus - i_bus_real * R_dc + + # 防止系统极端情况产生非物理结果 + v_motor = float(np.clip(v_motor, 0.0, 2.0 * v_bus)) + + return float(p_shaft), float(p_bus), float(i_bus), float(v_motor), float(p_loss) + + def step( + self, + dt: float, + n_setpoint: float, + p_bus_actual_kw: float, + v_bus: float, + t_load: float, + t_ext: float, + ) -> dict: + """ + 执行电机系统单步动力学仿真。 + + 该方法基于功率流架构,根据转速控制闭环计算母线功率需求,并根据实际获得的母线功率 + 反算电磁转矩,进而更新机械状态。 + + 能量流向说明 (Sign Convention): + - 功率 (Power): + - p > 0: 电机从母线吸收电能 (电动模式 Motor Mode) + - p < 0: 电机向母线回馈电能 (发电模式 Generator Mode) + - 转矩 (Torque): + - t < 0: 驱动转矩 (助推,使转速增加) + - t > 0: 负载转矩 (阻碍,使转速衰减) + + :param dt: 仿真步长 (s) + :param n_setpoint: 目标转速指令 (RPM) + :param p_bus_actual_kw: 实际分配给电机的母线功率 (kW)。若为正,表示电池放电供电机;若为负,表示电机发电充电池。 + :param v_bus: 当前直流母线电压 (V) + :param t_load: 轴系负载转矩 (Nm)。通常为正值,表示螺旋桨/风扇的气动阻力。 + :param t_ext: 外部施加转矩 (Nm)。如涡轴发动机并联扭矩。遵循上述符号约定 (负为助推,正为阻碍)。 + :return: 包含当前仿真步所有状态变量的字典。 + """ + if dt <= 0: + raise ValueError('dt must be positive') + if v_bus <= self._EPSILON: + raise ValueError('v_bus must be positive') + + # 更新滤波系数缓存 + self._update_filter_coefficients(dt) + + self._v_bus_f += (float(v_bus) - self._v_bus_f) * self._a_v + self.u_dc = float(self._v_bus_f) + self.u_s_max = self.u_dc * self.k_mod + + t_lim = self._compute_tau_limit(self.w_M, self.u_dc) + + w_set_cmd = n_setpoint * 2 * np.pi / 60.0 + self._w_set_f += (w_set_cmd - self._w_set_f) * self._a_n + w_set = self._w_set_f + + w_error = w_set - self.w_M + if abs(w_error) < self._W_ERROR_DEADBAND: + w_error = 0.0 + + dw_error = (w_error - self._w_error_prev) / max(dt, self._EPSILON) + self._w_error_prev = w_error + self._dw_error_f = self._dw_error_f * (1 - self._DW_ERROR_FILTER) + dw_error * self._DW_ERROR_FILTER + + self._w_error_int += w_error * dt + p_lim_kw = (t_lim * max(self.w_M, self._W_MIN_RAD)) / 1000.0 / max(self.eta_mot, self._EPSILON) + int_limit = 1.2 * p_lim_kw / max(self.k_i_w, self._EPSILON) if self.k_i_w > 0 else 0.0 + self._w_error_int = np.clip(self._w_error_int, -int_limit, int_limit) + + self._t_load_f += (float(t_load) - self._t_load_f) * self._a_t_load + self._t_ext_f += (float(t_ext) - self._t_ext_f) * self._a_t_load + + # 阻力前馈折算为补偿所需电功率(kW) + t_ff = self._t_load_f + self._t_ext_f + self.B_visc * self.w_M + p_mech_ff_kw = (t_ff * max(self.w_M, 1e-3)) / 1000.0 + if p_mech_ff_kw > 0: + p_elec_ff_kw = p_mech_ff_kw / max(self.eta_mot, self._EPSILON) + else: + p_elec_ff_kw = p_mech_ff_kw * self.eta_gen + + # 阻力前馈折算为补偿所需电功率(kW) + t_ff = self._t_load_f + self._t_ext_f + self.B_visc * self.w_M + p_mech_ff_kw = (t_ff * max(self.w_M, 1e-3)) / 1000.0 + if p_mech_ff_kw > 0: + p_elec_ff_kw = p_mech_ff_kw / max(self.eta_mot, 1e-6) + else: + p_elec_ff_kw = p_mech_ff_kw * self.eta_gen + + # ------------------------------------------------------------- + # A) 需求生成层: 以转速环计算下一拍应向电池索取的 P_bus_req_kw + # ------------------------------------------------------------- + # 使用增量式PID计算控制量 + self.speed_pid.dt = dt + p_pid = self.speed_pid.compute(setpoint=w_set, measurement=self.w_M) + + # 添加微分前馈和阻力前馈 + p_d_ff = self.k_d_w_error * self._dw_error_f + + p_cmd_raw = p_pid + p_d_ff + p_elec_ff_kw + p_bus_req_kw = float(np.clip(p_cmd_raw, -p_lim_kw, p_lim_kw)) + p_bus_req_kw = self._apply_power_slew(p_bus_req_kw, dt) + + self.p_bus_req_kw = p_bus_req_kw + + # ------------------------------------------------------------- + # B) 实施层: 以外部传进来的实际被满足电能,硬算电磁反抗力和扭矩 + # ------------------------------------------------------------- + t_motor_ref = self._power_to_torque_ref(p_bus_actual_kw * 1000.0, self.w_M) + t_motor_ref = float(np.clip(t_motor_ref, -t_lim, t_lim)) + + self._t_ref_f += (t_motor_ref - self._t_ref_f) * self._a_t + t_motor_ref_filtered = float(self._t_ref_f) + + i_d_ref, i_q_ref = self._current_ref_from_torque(t_motor_ref_filtered, self.w_M, self.u_dc) + self.i_d += (i_d_ref - self.i_d) * self._alpha_i + self.i_q += (i_q_ref - self.i_q) * self._alpha_i + i_abs = np.hypot(self.i_d, self.i_q) + if i_abs > self.i_s_max > 0: + self.i_d *= self.i_s_max / i_abs + self.i_q *= self.i_s_max / i_abs + + self.t_motor = self._torque_from_currents(self.i_d, self.i_q) + self.i_s = complex(self.i_d, self.i_q) + self.u_d, self.u_q, self.u_s = self._compute_voltage(self.i_d, self.i_q, self.w_M, self.u_dc) + + d_w = -(self.t_motor + t_ext + t_load + self.B_visc * self.w_M) / max(self.J, 1e-9) + d_w = float(np.clip(d_w, -self._dw_max, self._dw_max)) + + w_prev = self.w_M + self.w_M += d_w * dt + self.w_M = max(0.0, self.w_M) + + self.p_shaft, self.p_bus, self.i_bus, self.v_motor, self.p_loss = self._compute_bus_quantities( + self.t_motor, self.w_M, self.u_dc + ) + self.theta_e += self.n_p * self.w_M * dt + self._sim_t += dt + + # =========== 逆变换与 SVPWM (提高物理级仿真保真度) =========== + # DQ -> Alpha Beta + u_alpha, u_beta = self.inv_park_transform(self.u_d, self.u_q, self.theta_e) + i_alpha, i_beta = self.inv_park_transform(self.i_d, self.i_q, self.theta_e) + + # Alpha Beta -> ABC + u_a_ideal, u_b_ideal, u_c_ideal = self.inv_clarke_transform(u_alpha, u_beta) + self.i_a, self.i_b, self.i_c = self.inv_clarke_transform(i_alpha, i_beta) + + # 实际占空比及共模注入调制的相电压 + self.duty_a, self.duty_b, self.duty_c, self.u_an, self.u_bn, self.u_cn = self.svpwm( + u_a_ideal, u_b_ideal, u_c_ideal, self.u_dc + ) + # ============================================================== + + # 添加诊断级平衡校核 + self._torque_balance_error = self.t_motor + t_ext + t_load + self.B_visc * w_prev + self.J * d_w + self._power_balance_error = self.p_bus + self.p_shaft - self.p_loss + + mode = 'idle' + if self.t_motor < -1e-9: + mode = 'motor' + elif self.t_motor > 1e-9: + mode = 'generator' + + # 内存管理:如果设置了最大日志长度,超出时删除最早的记录 + if self._log_maxlen is not None and len(self._log['t']) >= self._log_maxlen: + for key in self._log: + if len(self._log[key]) > 0: + self._log[key].pop(0) + + self._log['t'].append(self._sim_t) + self._log['w_M'].append(self.w_M) + self._log['n_rpm'].append(self.w_M * 60.0 / (2 * np.pi)) + self._log['t_motor'].append(self.t_motor) + self._log['t_load'].append(t_load) + self._log['t_ext'].append(t_ext) + self._log['p_bus_req_kw'].append(self.p_bus_req_kw) + self._log['p_bus_kw'].append(self.p_bus / 1000.0) + self._log['p_shaft_kw'].append(self.p_shaft / 1000.0) + self._log['p_loss_kw'].append(self.p_loss / 1000.0) + self._log['i_bus_a'].append(self.i_bus) + self._log['v_bus'].append(self.u_dc) + self._log['v_motor'].append(self.v_motor) + self._log['mode'].append(mode) + self._log['i_a'].append(self.i_a) + self._log['i_b'].append(self.i_b) + self._log['i_c'].append(self.i_c) + self._log['u_an'].append(self.u_an) + self._log['u_bn'].append(self.u_bn) + self._log['u_cn'].append(self.u_cn) + + return self.get_state() + + def get_state(self) -> dict: + """获取当前瞬时状态量。""" + return { + 't': self._sim_t, + 'w_rad_s': self.w_M, + 'n_rpm': self.w_M * 60.0 / (2 * np.pi), + 't_motor': self.t_motor, + 'p_bus_req_kw': getattr(self, 'p_bus_req_kw', 0.0), + 'torque_balance_error': getattr(self, '_torque_balance_error', 0.0), + 'power_balance_error': getattr(self, '_power_balance_error', 0.0), + 'p_bus_w': self.p_bus, + 'p_bus_kw': self.p_bus / 1000.0, + 'p_shaft_w': self.p_shaft, + 'p_shaft_kw': self.p_shaft / 1000.0, + 'p_loss_w': self.p_loss, + 'p_loss_kw': self.p_loss / 1000.0, + 'i_bus_a': self.i_bus, + 'v_bus': self.u_dc, + 'v_motor': self.v_motor, + 'u_s': self.u_s, + 'mode': 'motor' if self.t_motor < -1e-9 else 'generator' if self.t_motor > 1e-9 else 'idle', + 'i_a': self.i_a, 'i_b': self.i_b, 'i_c': self.i_c, + 'u_an': self.u_an, 'u_bn': self.u_bn, 'u_cn': self.u_cn, + 'duty_a': self.duty_a, 'duty_b': self.duty_b, 'duty_c': self.duty_c, + } + + def reset_log(self) -> None: + """清空日志并重置内部动态状态。""" + for key in self._log: + self._log[key] = [] + self.w_M = 0.0 + self.t_motor = 0.0 + self.p_bus = 0.0 + self.p_shaft = 0.0 + self.p_loss = 0.0 + self.i_bus = 0.0 + self.v_motor = self.u_dc + self.i_d = 0.0 + self.i_q = 0.0 + self.i_s = 0j + self.u_d = 0.0 + self.u_q = 0.0 + self.u_s = 0.0 + self.theta_e = 0.0 + self.i_a, self.i_b, self.i_c = 0.0, 0.0, 0.0 + self.u_an, self.u_bn, self.u_cn = 0.0, 0.0, 0.0 + self.duty_a, self.duty_b, self.duty_c = 0.5, 0.5, 0.5 + self._sim_t = 0.0 + # 增量式PID控制器重置 + self.speed_pid.reset(initial_output=0.0) + self._w_error_int = 0.0 + self._w_error_prev = 0.0 + self._dw_error_f = 0.0 + self._p_bus_req_prev = 0.0 + self._w_set_f = 0.0 + self._t_ref_f = 0.0 + self._v_bus_f = float(self.u_dc) + # 负载转矩前馈相关状态变量 + self._t_load_f = 0.0 + self._t_ext_f = 0.0 + + +def run_motor_test() -> Dict[str, Any]: + """基于接口的独立电机测试 - 复杂测试用例""" + import matplotlib.pyplot as plt + + print('=' * 60) + print('Motor Dynamic Test - Complex Profile') + print('=' * 60) + + # 使用优化后的PID参数 + motor = MotorSim( + P_rate=300e3, + w_rate=575.95, + J=0.8, + k_p_w=13.440362, + k_i_w=42.997816, + k_d_w=0.484660, + P_const_loss=300.0, + k_fe=4e-4, + ) + + dt = 0.02 + t_end = 100.0 + time_array = np.arange(0.0, t_end, dt) + + # 存储关键诊断数据 + torque_balance = [] + power_balance = [] + + p_actual_kw = 0.0 + for t in time_array: + # 复杂测试工况 - 多段转速变化 + 多种扰动 + # 目标转速曲线 + if t < 3.0: + n_setpoint = 0.0 + elif t < 8.0: + n_setpoint = 2000.0 + elif t < 15.0: + n_setpoint = 2800.0 + elif t < 22.0: + n_setpoint = 2200.0 + elif t < 32.0: + n_setpoint = 3500.0 + elif t < 42.0: + n_setpoint = 3800.0 + elif t < 52.0: + n_setpoint = 2800.0 + elif t < 62.0: + n_setpoint = 3000.0 + elif t < 72.0: + n_setpoint = 4000.0 + elif t < 82.0: + n_setpoint = 4200.0 + elif t < 92.0: + n_setpoint = 3200.0 + else: + n_setpoint = 3000.0 + + # 外部转矩扰动 + if t < 5.0: + t_ext = 25.0 + elif t < 12.0: + t_ext = 10.0 + elif t < 18.0: + t_ext = -30.0 + elif t < 25.0: + t_ext = 15.0 + elif t < 35.0: + t_ext = -50.0 + elif t < 45.0: + t_ext = 8.0 + elif t < 55.0: + t_ext = -20.0 + elif t < 65.0: + t_ext = 25.0 + elif t < 75.0: + t_ext = -60.0 + elif t < 85.0: + t_ext = 20.0 + else: + t_ext = 0.0 + + # 负载转矩 - 变化因子 + if t < 10.0: + t_load_factor = 1.0 + elif t < 22.0: + t_load_factor = 1.5 + elif t < 32.0: + t_load_factor = 0.8 + elif t < 42.0: + t_load_factor = 1.8 + elif t < 52.0: + t_load_factor = 1.0 + elif t < 62.0: + t_load_factor = 1.4 + elif t < 72.0: + t_load_factor = 0.9 + elif t < 82.0: + t_load_factor = 1.6 + else: + t_load_factor = 1.1 + + base_t_load = 16.0 + 0.020 * motor.w_M + 1.2e-5 * motor.w_M**2 + t_load = base_t_load * t_load_factor + + # 母线电压波动 + v_bus = 520.0 + 15.0 * np.sin(2 * np.pi * t / 8.0) + 5.0 * np.sin(2 * np.pi * t / 3.0) + + state = motor.step(dt, n_setpoint, p_actual_kw, v_bus, t_load, t_ext) + p_actual_kw = state['p_bus_req_kw'] + + torque_balance.append(state['torque_balance_error']) + power_balance.append(state['power_balance_error']) + + state = motor.get_state() + p_bus_kw = np.array(motor._log['p_bus_kw']) + p_req_kw = np.array(motor._log['p_bus_req_kw']) + p_shaft_kw = np.array(motor._log['p_shaft_kw']) + p_loss_kw = np.array(motor._log['p_loss_kw']) + n_log = np.array(motor._log['n_rpm']) + t_motor_log = np.array(motor._log['t_motor']) + t_load_log = np.array(motor._log['t_load']) + t_ext_log = np.array(motor._log['t_ext']) + v_bus_log = np.array(motor._log['v_bus']) + v_motor_log = np.array(motor._log['v_motor']) + i_bus_log = np.array(motor._log['i_bus_a']) + + # 计算性能指标 + n_setpoints = [] + for t in time_array: + if t < 3.0: + n_setpoints.append(0.0) + elif t < 8.0: + n_setpoints.append(2000.0) + elif t < 15.0: + n_setpoints.append(2800.0) + elif t < 22.0: + n_setpoints.append(2200.0) + elif t < 32.0: + n_setpoints.append(3500.0) + elif t < 42.0: + n_setpoints.append(3800.0) + elif t < 52.0: + n_setpoints.append(2800.0) + elif t < 62.0: + n_setpoints.append(3000.0) + elif t < 72.0: + n_setpoints.append(4000.0) + elif t < 82.0: + n_setpoints.append(4200.0) + elif t < 92.0: + n_setpoints.append(3200.0) + else: + n_setpoints.append(3000.0) + n_setpoints = np.array(n_setpoints) + + error = n_setpoints - n_log + ise = np.sum(error**2) * dt + iae = np.sum(np.abs(error)) * dt + + print(f"Final: speed={state['n_rpm']:.0f} RPM ({state['w_rad_s']:.1f} rad/s)") + print(f" t_motor={state['t_motor']:.2f} Nm, p_bus={state['p_bus_kw']:.2f} kW, v_motor={state['v_motor']:.1f} V") + print(f"Performance - ISE: {ise:.2f}, IAE: {iae:.2f}") + + # 诊断结果 + torque_balance = np.array(torque_balance) + power_balance = np.array(power_balance) + print(f"Diagnostic - Torque balance error (mean): {np.mean(np.abs(torque_balance)):.4f} Nm") + print(f"Diagnostic - Power balance error (mean): {np.mean(np.abs(power_balance)):.4f} W") + + fig, axes = plt.subplots(5, 1, figsize=(14, 14), sharex=True) + + axes[0].plot(time_array, n_setpoints, 'r--', lw=1.0, alpha=0.7, label='Setpoint') + axes[0].plot(time_array, n_log, 'b-', lw=1.6, label='Actual') + axes[0].set_ylabel('Speed [RPM]') + axes[0].set_title('Motor Speed - Complex Profile Test (100s)') + axes[0].grid(True, linestyle=':') + axes[0].legend() + + axes[1].plot(time_array, t_motor_log, 'r-', lw=1.6, label='Motor Torque') + axes[1].plot(time_array, t_load_log, 'k--', lw=1.0, label='Load Torque') + axes[1].plot(time_array, t_ext_log, color='tab:purple', lw=1.0, label='External Torque') + axes[1].set_ylabel('Torque [Nm]') + axes[1].set_title('Torque Balance') + axes[1].axhline(0.0, color='k', lw=0.6) + axes[1].grid(True, linestyle=':') + axes[1].legend() + + axes[2].plot(time_array, p_req_kw, color='tab:gray', lw=1.2, label='Requested Bus Power') + axes[2].plot(time_array, p_bus_kw, color='m', lw=1.4, label='Actual Bus Power') + axes[2].plot(time_array, p_shaft_kw, 'g-', lw=1.2, label='Shaft Power') + axes[2].plot(time_array, p_loss_kw, color='tab:orange', lw=1.0, label='Loss Power') + axes[2].set_ylabel('Power [kW]') + axes[2].set_title('Bus / Shaft / Loss Power') + axes[2].axhline(0.0, color='k', lw=0.6) + axes[2].grid(True, linestyle=':') + axes[2].legend() + + axes[3].plot(time_array, v_bus_log, color='tab:cyan', lw=1.4, label='Bus Voltage') + axes[3].plot(time_array, v_motor_log, color='tab:red', lw=1.2, label='Motor Potential') + axes[3].set_ylabel('Voltage [V]') + axes[3].set_title('Bus Voltage and Motor Equivalent Potential') + axes[3].grid(True, linestyle=':') + axes[3].legend() + + axes[4].plot(time_array, i_bus_log, color='tab:brown', lw=1.4, label='Bus Current') + axes[4].set_ylabel('Current [A]') + axes[4].set_xlabel('Time [s]') + axes[4].set_title('Bus Current') + axes[4].grid(True, linestyle=':') + axes[4].legend() + + plt.tight_layout() + plt.savefig("figures/test_complex_motor_output.png") + + return { + 'final_state': state, + 'peak_speed_rpm': float(np.max(n_log)), + 'peak_bus_current_a': float(np.max(i_bus_log)), + 'torque_balance_error_mean': float(np.mean(np.abs(torque_balance))), + 'power_balance_error_mean': float(np.mean(np.abs(power_balance))), + 'ise': ise, + 'iae': iae, + } + + +def run_motor_battery_coupled_test() -> Dict[str, Any]: + """执行混合动力电机与电池协同闭环抗扰动验证例程 - 复杂测试用例""" + import matplotlib + matplotlib.use('Agg') # 强制使用非交互后端 + import matplotlib.pyplot as plt + import numpy as np + + from src.battery_sim import BatterySim + + print('=' * 60) + print('Motor + Battery Co-Simulation Test (100s) - Complex Profile') + print('=' * 60) + + battery = BatterySim(capacity_kwh=50.0, nom_voltage=520.0, initial_soc=0.65) + battery.V_t = float(battery._get_ocv(battery.SOC)) + + motor = MotorSim( + P_rate=300e3, + w_rate=575.95, + J=0.8, + k_p_w=13.440362, + k_i_w=42.997816, + k_d_w=0.484660, + P_const_loss=300.0, + k_fe=4e-4, + u_dc=battery.V_t, + ) + + dt = 0.02 + t_end = 100.0 + time_array = np.arange(0.0, t_end, dt) + + soc_log = [] + p_req_log = [] + p_bus_log = [] + p_ext_elec_log = [] + p_net_log = [] + v_bus_log = [] + n_setpoints = [] + t_ext_log = [] + t_load_log = [] + + p_actual_kw = 0.0 + for t in time_array: + # 复杂测试工况 - 多段转速变化 + 多种扰动 + p_ext_elec = 0.0 # 外部电功率扰动 (kW) + + # 目标转速曲线 - 复杂多段变化 + if t < 3.0: + n_setpoint = 0.0 + elif t < 8.0: + n_setpoint = 2000.0 + elif t < 15.0: + n_setpoint = 2800.0 + elif t < 22.0: + n_setpoint = 2200.0 + elif t < 32.0: + n_setpoint = 3500.0 + elif t < 42.0: + n_setpoint = 3800.0 + elif t < 52.0: + n_setpoint = 2800.0 + elif t < 62.0: + n_setpoint = 3000.0 + elif t < 72.0: + n_setpoint = 4000.0 + elif t < 82.0: + n_setpoint = 4200.0 + elif t < 92.0: + n_setpoint = 3200.0 + else: + n_setpoint = 3000.0 + + # 外部转矩扰动 - 模拟发动机并联/涡轴输出变化 + if t < 5.0: + t_ext = 25.0 + elif t < 12.0: + t_ext = 10.0 + elif t < 18.0: + t_ext = -30.0 + elif t < 25.0: + t_ext = 15.0 + elif t < 35.0: + t_ext = -50.0 + elif t < 45.0: + t_ext = 8.0 + elif t < 55.0: + t_ext = -20.0 + elif t < 65.0: + t_ext = 25.0 + elif t < 75.0: + t_ext = -60.0 + elif t < 85.0: + t_ext = 20.0 + else: + t_ext = 0.0 + + # 负载转矩 - 模拟风速/气压变化 + if t < 10.0: + t_load = 20.0 + elif t < 22.0: + t_load = 80.0 + elif t < 32.0: + t_load = 40.0 + elif t < 42.0: + t_load = 120.0 + elif t < 52.0: + t_load = 50.0 + elif t < 62.0: + t_load = 90.0 + elif t < 72.0: + t_load = 60.0 + elif t < 82.0: + t_load = 130.0 + else: + t_load = 70.0 + + # 外部电功率扰动 + if 35.0 < t < 40.0: + p_ext_elec = 80.0 # 涡轴发电机注入 80kW + elif 55.0 < t < 60.0: + p_ext_elec = -100.0 # 其他设备用电 100kW + elif 75.0 < t < 80.0: + p_ext_elec = 60.0 # 涡轴发电机注入 60kW + + # 母线电压波动 + v_bus = battery.V_t + 15.0 * np.sin(2 * np.pi * t / 8.0) + 5.0 * np.sin(2 * np.pi * t / 3.0) + + # 延迟一拍的实际电能参与当前动态步,进而PID在内环打出对下一拍的请求 + state = motor.step(dt, n_setpoint, p_actual_kw, v_bus, t_load, t_ext) + p_req_kw = state['p_bus_req_kw'] + + # 计算汇流排给电池真实指派的载荷 = 电机需求 - 其他设备并网干扰 + p_net_req_kw = p_req_kw - p_ext_elec + + # 电池响应,输出真正被释放出来的电功率 + p_net_actual_kw, _, _, soc = battery.step(dt, p_net_req_kw) + + # 回算到电机引脚真正获得的被供应功率,送给下个脉冲周期 + p_actual_kw = p_net_actual_kw + p_ext_elec + + n_setpoints.append(n_setpoint) + soc_log.append(soc) + p_req_log.append(p_req_kw) + p_ext_elec_log.append(p_ext_elec) + p_net_log.append(p_net_req_kw) + p_bus_log.append(p_net_actual_kw) + v_bus_log.append(v_bus) + t_ext_log.append(t_ext) + t_load_log.append(t_load) + + n_log = np.array(motor._log['n_rpm']) + t_motor_log = np.array(motor._log['t_motor']) + v_motor_log = np.array(motor._log['v_motor']) + + # 计算性能指标 + n_setpoints = np.array(n_setpoints) + error = n_setpoints - n_log + ise = np.sum(error**2) * dt + iae = np.sum(np.abs(error)) * dt + + print(f"Final: speed={motor.get_state()['n_rpm']:.0f} RPM, SOC={soc_log[-1]*100:.3f}%") + print(f"Performance - ISE: {ise:.2f}, IAE: {iae:.2f}") + + fig, axes = plt.subplots(5, 1, figsize=(14, 14), sharex=True) + + # 1. 速度响应 + axes[0].plot(time_array, n_setpoints, 'r--', lw=1.2, label='Speed Ref (Setpoint)') + axes[0].plot(time_array, n_log, 'b-', lw=1.6, label='Actual Speed') + axes[0].set_ylabel('Speed [RPM]') + axes[0].set_title('Motor Speed Tracking - Complex Profile') + axes[0].grid(True, linestyle=':') + axes[0].legend() + + # 2. 转矩响应 + axes[1].plot(time_array, t_motor_log, 'r-', lw=1.6, label='Motor Torque (PID Output)') + axes[1].plot(time_array, np.array(t_load_log), 'k--', lw=1.2, label='Propeller Load Torque') + axes[1].plot(time_array, np.array(t_ext_log), color='tab:purple', lw=1.2, label='External Torque') + axes[1].axhline(0.0, color='k', lw=0.6) + axes[1].set_ylabel('Torque [Nm]') + axes[1].set_title('Torque Balance') + axes[1].grid(True, linestyle=':') + axes[1].legend() + + # 3. 功率响应 + axes[2].plot(time_array, np.array(p_req_log), 'm-', lw=1.6, label='Motor Requested Bus Power') + axes[2].plot(time_array, np.array(p_ext_elec_log), 'g--', lw=1.2, label='Engine Gen Power') + axes[2].plot(time_array, np.array(p_net_log), 'k-', lw=1.2, label='Battery Net Output Power') + axes[2].axhline(0.0, color='k', lw=0.6) + axes[2].set_ylabel('Power [kW]') + axes[2].set_title('Bus Power Balance & Electrical Source Injection') + axes[2].grid(True, linestyle=':') + axes[2].legend() + + # 4. 电压响应 + axes[3].plot(time_array, np.array(v_bus_log), color='tab:cyan', lw=1.4, label='Bus Voltage') + axes[3].plot(time_array, v_motor_log, color='tab:red', lw=1.2, label='Motor Potential') + axes[3].set_ylabel('Voltage [V]') + axes[3].set_title('Bus Voltage & Motor Potential') + axes[3].grid(True, linestyle=':') + axes[3].legend() + + # 5. SOC响应 + axes[4].plot(time_array, np.array(soc_log) * 100, color='tab:green', lw=1.4, label='Battery SOC') + axes[4].set_ylabel('SOC [%]') + axes[4].set_xlabel('Time [s]') + axes[4].set_title('Battery State of Charge') + axes[4].grid(True, linestyle=':') + axes[4].legend() + + plt.tight_layout() + plt.savefig("figures/test_complex_output.png") + print("Plot saved to figures/test_complex_output.png") + + return { + 'final_state': motor.get_state(), + 'final_soc': float(soc_log[-1]), + 'peak_speed_rpm': float(np.max(n_log)), + 'ise': ise, + 'iae': iae, + } + +if __name__ == '__main__': + run_motor_battery_coupled_test() diff --git a/Model/src/series_hybrid_sim.py b/Model/src/series_hybrid_sim.py new file mode 100644 index 0000000..7071cd1 --- /dev/null +++ b/Model/src/series_hybrid_sim.py @@ -0,0 +1,261 @@ +import os +import numpy as np +import matplotlib.pyplot as plt + +from engine_dynamic_sim import TurboshaftDynamicSim +from motor_sim import MotorSim +from battery_sim import BatterySim + +class SeriesHybridSystem: + """ + 串联式混合动力系统总成 + """ + def __init__(self): + # ===== 新增:按Model目录定位GPR数据与权重,避免从主项目调用时路径错误 ===== + model_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + gpr_csv_path = os.path.join(model_root, "data", "Cleaned_Engine_Data_Full.csv") + gpr_pth_path = os.path.join(model_root, "data", "engine_gpr_model.pth") + self.genset = TurboshaftDynamicSim( + gpr_csv_path=gpr_csv_path, + gpr_pth_path=gpr_pth_path, + kp=0.5, + ki=0.5, + kd=0.0 + ) + self.drive_motor = MotorSim( + P_rate=300e3, + w_rate=575.95, + k_p_w=5.0, # 增大比例增益 + k_i_w=2.0, # 增大积分增益 + k_d_w=0.5, # 适度微分 + J=1.0, + ) + self.battery = BatterySim(capacity_kwh=50.0, initial_soc=0.6) + + self.bus_voltage = self.battery._get_ocv(self.battery.SOC) + self.motor_actual_power_kw = 0.0 + + # 滞环控制状态 + self._genset_low_power_mode = False # 发动机低功率模式标志 + self._hysteresis_rpm = 100 # 滞环带宽 RPM + + def energy_management_strategy(self, p_drive_req_kw, soc, speed_error_rpm=0.0): + """ + 功率跟随策略 (Power Following Control) - 增强版 + 核心思想: + - 使用滞环控制避免频繁切换 + - 当转速持续高于目标时,降低发动机功率 + - 当转速持续低于目标时,增加发动机功率 + """ + P_eng_max = 300.0 + P_eng_min = 20.0 + SOC_TARGET = 0.60 + K_soc = 30.0 # kW / ΔSOC + K_speed = 1.5 # kW / RPM + p_dyn_reserve = P_eng_max * 0.3 # 90 kW 基础储备 + + # 滞环控制逻辑 + # 进入低功率模式:转速高于目标 + 电机发电 + if speed_error_rpm < -self._hysteresis_rpm and p_drive_req_kw < 0: + self._genset_low_power_mode = True + # 退出低功率模式:转速低于目标 - 滞环带宽 + elif speed_error_rpm > self._hysteresis_rpm: + self._genset_low_power_mode = False + + # 根据模式计算目标功率 + if self._genset_low_power_mode: + # 低功率模式:发动机降到最低 + target_engine_power = P_eng_min + elif speed_error_rpm > 0: + # 加速模式 + p_speed_comp = min(speed_error_rpm * K_speed, 250.0) + target_engine_power = p_drive_req_kw + p_dyn_reserve + p_speed_comp + else: + # 减速/稳态模式 + p_speed_comp = max(speed_error_rpm * K_speed, -250.0) + target_engine_power = p_drive_req_kw + p_dyn_reserve + p_speed_comp + + # SOC补偿 + soc_error = SOC_TARGET - soc + if soc < 0.2 or soc > 0.85: + K_soc_effective = 0 + else: + K_soc_effective = K_soc + p_charge_req = soc_error * K_soc_effective + target_engine_power += p_charge_req + + # 极限状态越界保护 + if soc < 0.15: + target_engine_power = P_eng_max + elif soc > 0.95: + target_engine_power = P_eng_min + + # 限制输出范围 + target_engine_power = max(P_eng_min, min(P_eng_max, target_engine_power)) + + return target_engine_power + + def step(self, dt, target_prop_speed, prop_load_torque): + """ + 全系统单步动力学仿真 + """ + # 1. 需求端:驱动电机电功率请求 + motor_state = self.drive_motor.step( + dt=dt, + n_setpoint=target_prop_speed, + p_bus_actual_kw=self.motor_actual_power_kw, + v_bus=self.bus_voltage, + t_load=prop_load_torque, + t_ext=0.0 + ) + p_drive_req = motor_state['p_bus_req_kw'] + actual_rpm = motor_state['n_rpm'] + + # 计算转速误差(用于EMS) + speed_error_rpm = target_prop_speed - actual_rpm + + # 2. 决策端:EMS 目标功率计算(加入转速误差反馈) + target_engine_pwr = self.energy_management_strategy(p_drive_req, self.battery.SOC, speed_error_rpm) + + # 3. 发电端:涡轴发动机响应并输出电能 + N_eng, Wf_act, Wf_req, P_eng_out = self.genset.step(dt, target_power=target_engine_pwr) + # GPR模型输出的 P_eng_out > 0 表示发动机输出功率(发电) + p_gen_elec = P_eng_out # 正值表示发电功率 + + # 4. 汇流端:电池功率补偿与直流母线状态更新 + # 功率平衡:电机需求 = 发动机发电 + 电池补充 + # p_batt_req > 0 表示电池放电,p_batt_req < 0 表示电池充电 + p_batt_req = p_drive_req - p_gen_elec + p_batt_actual, v_bus, i_batt, soc = self.battery.step(dt, p_batt_req) + + # 5. 状态记忆:为打破代数环,保留关键变量至下一拍 + self.bus_voltage = v_bus + + # 电机实际获得的功率 = 发电功率 + 电池放电功率 + # 注意:允许负值存在,表示电机在发电模式(制动) + # 这样电机控制器才能正确产生制动转矩 + self.motor_actual_power_kw = p_gen_elec + p_batt_actual + + return { + 'soc': soc * 100.0, + 'bus_voltage': v_bus, + 'prop_speed_rpm': motor_state['n_rpm'], + 'target_engine_pwr': target_engine_pwr, + 'p_engine_out_kw': P_eng_out, + 'p_drive_req_kw': p_drive_req, + 'p_motor_actual_kw': self.motor_actual_power_kw, + 'p_batt_actual_kw': p_batt_actual, + 'wf_kg_h': Wf_act, + 'engine_rpm': N_eng + } + + +if __name__ == "__main__": + import os + import matplotlib + matplotlib.use('Agg') # 非交互后端 + import matplotlib.pyplot as plt + + plt.rcParams['font.family'] = 'serif' + plt.rcParams['axes.unicode_minus'] = True + + print("-> 初始化串联混电系统...") + system = SeriesHybridSystem() + system.genset.set_steady_state_by_power(H_env=0.0, Ma_env=0.0, Power_target=50.0) + + dt = 0.02 + t_end = 180.0 + time_array = np.arange(0, t_end, dt) + + log = {k: [] for k in ['soc', 'bus_voltage', 'prop_speed_rpm', 'target_prop_rpm', 'target_engine_pwr', + 'p_engine_out_kw', 'p_drive_req_kw', 'p_motor_actual_kw', + 'p_batt_actual_kw', 'wf_kg_h']} + + print("-> 开始全系统闭环步进仿真 (总时长 3 分钟)...") + for t in time_array: + # 3分钟测试剖面 + if t < 15.0: + target_rpm, load_torque = 1500.0, 50.0 # 地面滑行 + elif t < 60.0: + target_rpm, load_torque = 3000.0, 200.0 # 暴力拉升 + elif t < 120.0: + target_rpm, load_torque = 2800.0, 150.0 # 重载巡航 + else: + target_rpm, load_torque = 1800.0, 60.0 # 降落滑行 + + res = system.step(dt, target_rpm, load_torque) + res['target_prop_rpm'] = target_rpm + for k in log.keys(): + log[k].append(res[k]) + + print("-> 仿真完成,正在绘制系统响应曲线...") + + # 绘图逻辑 + fig, axes = plt.subplots(4, 1, figsize=(14, 12), sharex=True) + fig.suptitle('Series Hybrid Electric System Dynamics (Load Following EMS)', fontweight='bold', fontsize=14) + + # 1. 转速响应 + axes[0].plot(time_array, log['target_prop_rpm'], 'k--', lw=1.5, label='Target Speed') + axes[0].plot(time_array, log['prop_speed_rpm'], 'b-', lw=1.5, label='Actual Speed') + axes[0].set_ylabel('Speed [RPM]') + axes[0].set_title('Drive Motor Speed Response') + axes[0].grid(True, linestyle=':', alpha=0.7) + axes[0].legend() + + # 2. 功率分配流向 + axes[1].plot(time_array, log['p_drive_req_kw'], 'k--', lw=1.5, label='Drive Motor Request') + axes[1].plot(time_array, log['p_engine_out_kw'], 'r-', lw=1.5, label='Engine Output (APU)') + axes[1].plot(time_array, log['p_batt_actual_kw'], 'g-', lw=1.5, label='Battery Output') + axes[1].set_ylabel('Power [kW]') + axes[1].set_title('System Power Flow (Energy Management)') + axes[1].axhline(0, color='gray', lw=1) + axes[1].grid(True, linestyle=':', alpha=0.7) + axes[1].legend() + + # 3. 电池状态 + axes[2].plot(time_array, log['bus_voltage'], 'm-', lw=1.5, label='DC Bus Voltage') + axes[2].set_ylabel('Voltage [V]') + axes[2].set_title('DC Bus Electrical State') + axes[2].grid(True, linestyle=':', alpha=0.7) + axes[2].legend(loc='upper left') + + ax2_soc = axes[2].twinx() + ax2_soc.plot(time_array, log['soc'], 'c--', lw=2, label='Battery SOC') + ax2_soc.set_ylabel('SOC [%]') + ax2_soc.legend(loc='upper right') + + # 4. 燃油消耗 + axes[3].plot(time_array, log['wf_kg_h'], 'tab:orange', lw=1.5, label='Engine Fuel Flow') + axes[3].set_ylabel('Fuel Flow [kg/h]') + axes[3].set_xlabel('Time [s]') + axes[3].set_title('Turboshaft Engine Fuel Consumption') + axes[3].grid(True, linestyle=':', alpha=0.7) + axes[3].legend() + + plt.tight_layout(rect=[0, 0, 1, 0.96]) + + # 保存到 ../figures 目录 + figures_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'figures') + if not os.path.exists(figures_dir): + os.makedirs(figures_dir) + save_path = os.path.join(figures_dir, 'series_hybrid_system_3min_test.png') + + plt.savefig(save_path, dpi=300) + print(f"-> 绘图已保存: {save_path}") + + # 保存数据到dat文件 + data_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'data') + if not os.path.exists(data_dir): + os.makedirs(data_dir) + dat_path = os.path.join(data_dir, 'series_hybrid_data.dat') + + with open(dat_path, 'w') as f: + f.write('# Time(s)\tTarget_RPM\tActual_RPM\tError_RPM\tSOC\tEngine_Power\tDrive_Req\tBatt_Power\n') + for i in range(len(time_array)): + err = log['target_prop_rpm'][i] - log['prop_speed_rpm'][i] + f.write(f'{time_array[i]:.3f}\t{log["target_prop_rpm"][i]:.1f}\t' + f'{log["prop_speed_rpm"][i]:.1f}\t{err:.1f}\t{log["soc"][i]:.2f}\t' + f'{log["p_engine_out_kw"][i]:.2f}\t{log["p_drive_req_kw"][i]:.2f}\t' + f'{log["p_batt_actual_kw"][i]:.2f}\n') + print(f"-> 数据已保存: {dat_path}") + # plt.show() diff --git a/README.md b/README.md index ae60e2b..a97c476 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # 🎛️ 自动控制原理AI+数智平台 -> 交互式控制系统分析与设计工具 | 时域·频域·根轨迹·AI问答 +> 交互式控制系统分析与设计工具 | 时域·频域·根轨迹·算例演示·AI问答 -一个基于 Gradio 构建的现代化自动控制原理学习平台,集成了系统分析工具和 AI 智能问答功能。 +一个基于 Gradio 构建的现代化自动控制原理学习平台,集成了系统分析工具、完整混动模型算例演示与 AI 智能问答功能。 ## ✨ 核心功能 @@ -54,7 +54,14 @@ - s 平面稳定性区域 - 阻尼比等值线 -### 🤖 4. AI 智能问答 (Q&A) +### 🧪 4. 算例演示 (Case Demo) + +- **完整混动模型**:调用 `Model/src/series_hybrid_sim.py` 进行系统级仿真 +- **参数化工况**:支持工况模板、仿真时长、步长、SOC、初始发动机功率与缩放系数 +- **图文结果**:输出三联图(转速响应/功率分配/电气状态)与关键数据表 +- **教学解读**:自动生成指标摘要(最大转速误差、SOC变化、平均功率与燃油流量) + +### 🤖 5. AI 智能问答 (Q&A) - **专业教学助手**:精通自动控制原理的 AI 教授 - **流式响应**:实时显示 AI 回复过程 @@ -62,14 +69,13 @@ - **上下文记忆**:支持多轮对话 **支持的 API**: -- DeepSeek API(推荐,国内网络友好) -- Google Gemini API +- DeepSeek API ## 🚀 快速开始 ### 环境要求 -- Python 3.8+ +- Python 3.10+ - pip 包管理器 ### 安装步骤 @@ -84,20 +90,20 @@ cd AutoControl 2. **安装依赖** ```bash -pip install gradio numpy control matplotlib aiohttp +pip install -r requirements.txt ``` 或使用 conda: ```bash -conda create -n autocontrol python=3.9 +conda create -n autocontrol python=3.10 conda activate autocontrol -pip install gradio numpy control matplotlib aiohttp +pip install -r requirements.txt ``` 3. **配置 API 密钥** -编辑 `app.py` 文件开头的配置区域: +编辑 `config.py` 文件中的配置区域: ```python # ==================== API 配置 ==================== @@ -240,27 +246,28 @@ AI 回复中的数学公式会自动渲染,支持以下格式: ## 📁 项目结构 -``` -AutoControl/ -├── app.py # 主应用程序 -├── README.md # 项目文档 -├── API_CONFIG.md # API 配置详细说明(可选) -├── QUICK_START.md # 快速入门指南(可选) -└── requirements.txt # 依赖列表(可选) +```text +AutoControlCourse/ +├── app.py # Gradio 入口与事件绑定 +├── ui_components.py # 各标签页 UI 组件 +├── analysis_functions.py # 时域/频域/根轨迹计算 +├── case_demo_functions.py # 算例演示模块(调用 Model) +├── chatbot.py # AI 问答 +├── user_stats.py # 在线人数统计 +├── config.py # API 与运行配置 +├── Model/ +│ ├── src/ # 混动模型核心代码 +│ └── data/ # 运行所需模型权重与数据 +└── requirements.txt # 依赖列表 ``` ## 🔧 高级配置 -### 切换到 Gemini API +### 算例演示说明 -如果您想使用 Google Gemini API: - -```python -API_KEY = "your-gemini-api-key" -API_BASE_URL = "https://generativelanguage.googleapis.com/v1beta" -API_MODEL = "gemini-1.5-flash" -API_TYPE = "gemini" -``` +- 仿真时长是模型时间,不等于程序实际等待时间 +- 电池功率符号定义:正值放电,负值充电 +- 若参数超限,程序会在安全范围内自动裁剪 ### 自定义系统提示词 @@ -333,4 +340,4 @@ ax.grid(True, alpha=0.3, linestyle='--') **⭐ 如果这个项目对您有帮助,请给它一个 Star!** -最后更新:2025年10月15日 +最后更新:2026年4月7日 diff --git a/app.py b/app.py index dcd143f..976d8ef 100644 --- a/app.py +++ b/app.py @@ -10,6 +10,8 @@ from analysis_functions import ( frequency_domain_analysis, root_locus_analysis ) +# ===== 新增:算例演示模块函数导入 ===== +from case_demo_functions import run_case_demo from chatbot import chat_with_ai from user_stats import get_online_status_html, update_user_activity from ui_components import ( @@ -17,6 +19,7 @@ from ui_components import ( create_time_domain_tab, create_frequency_domain_tab, create_root_locus_tab, + create_case_demo_tab, create_chatbot_tab ) @@ -59,7 +62,10 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus freq_domain_ui = create_frequency_domain_tab() with gr.TabItem("🎯 根轨迹 (Root Locus)", id=2): root_locus_ui = create_root_locus_tab() - with gr.TabItem("🤖 智能问答 (Q&A)", id=3): + # ===== 新增:算例演示 Tab(位于根轨迹与智能问答之间) ===== + with gr.TabItem("🧪 算例演示 (Case Demo)", id=3): + case_demo_ui = create_case_demo_tab() + with gr.TabItem("🤖 智能问答 (Q&A)", id=4): chatbot_ui = create_chatbot_tab() # 2. 绑定事件逻辑 @@ -144,6 +150,41 @@ with gr.Blocks(title="自动控制理论学习网站 - AI+数智平台", css=cus num_input.change(fn=update_all_on_tf_change, inputs=tf_change_inputs, outputs=tf_change_outputs) den_input.change(fn=update_all_on_tf_change, inputs=tf_change_inputs, outputs=tf_change_outputs) + # ===== 新增:算例演示事件包装器 ===== + def run_case_demo_wrapper(sim_time, dt, initial_soc, initial_engine_power, profile, rpm_scale, load_scale, sid): + update_user_activity(sid) + fig, summary, table_data = run_case_demo( + sim_time_s=sim_time, + dt=dt, + initial_soc_pct=initial_soc, + initial_engine_power_kw=initial_engine_power, + profile_name=profile, + rpm_scale=rpm_scale, + load_scale=load_scale + ) + return fig, summary, table_data, get_online_status_html() + + # ===== 新增:算例演示按钮事件绑定 ===== + case_demo_ui["run_button"].click( + fn=run_case_demo_wrapper, + inputs=[ + case_demo_ui["sim_time"], + case_demo_ui["dt"], + case_demo_ui["initial_soc"], + case_demo_ui["initial_engine_power"], + case_demo_ui["profile"], + case_demo_ui["rpm_scale"], + case_demo_ui["load_scale"], + session_id + ], + outputs=[ + case_demo_ui["plot"], + case_demo_ui["summary"], + case_demo_ui["table"], + online_counter + ] + ) + # --- 聊天机器人事件 --- async def chat_wrapper(message, history, sid): update_user_activity(sid) diff --git a/case_demo_functions.py b/case_demo_functions.py new file mode 100644 index 0000000..7301670 --- /dev/null +++ b/case_demo_functions.py @@ -0,0 +1,145 @@ +import os +import sys +# ===== 新增:OpenMP冲突兼容设置,避免PyTorch初始化报错 ===== +os.environ.setdefault("KMP_DUPLICATE_LIB_OK", "TRUE") +import numpy as np +import matplotlib +matplotlib.use('Agg') +import matplotlib.pyplot as plt + +MODEL_SRC_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Model", "src") +if MODEL_SRC_PATH not in sys.path: + # ===== 新增:将混动模型源码路径加入导入搜索路径 ===== + sys.path.insert(0, MODEL_SRC_PATH) + + +def _profile_points(profile_name): + if profile_name == "高机动阶跃": + return [ + (0.0, 1600.0, 70.0), + (8.0, 3200.0, 220.0), + (20.0, 2500.0, 130.0), + (35.0, 3400.0, 250.0), + (50.0, 1800.0, 80.0), + ] + if profile_name == "经济巡航": + return [ + (0.0, 1500.0, 60.0), + (15.0, 2100.0, 95.0), + (35.0, 2300.0, 105.0), + (55.0, 2000.0, 90.0), + ] + return [ + (0.0, 1500.0, 50.0), + (10.0, 3000.0, 200.0), + (30.0, 2800.0, 150.0), + (50.0, 1800.0, 60.0), + ] + + +def _target_from_profile(t, points, rpm_scale, load_scale): + rpm, torque = points[0][1], points[0][2] + for p_t, p_rpm, p_torque in points: + if t >= p_t: + rpm, torque = p_rpm, p_torque + else: + break + return rpm * rpm_scale, torque * load_scale + + +def run_case_demo(sim_time_s, dt, initial_soc_pct, initial_engine_power_kw, profile_name, rpm_scale, load_scale): + try: + try: + # ===== 新增:懒加载混动系统模型,便于捕获缺失依赖 ===== + from series_hybrid_sim import SeriesHybridSystem + except ModuleNotFoundError as e: + if getattr(e, "name", "") == "torch": + return None, "算例仿真失败:缺少依赖 torch,请先在当前环境安装 PyTorch。", [] + return None, f"算例仿真失败:缺少依赖 {e.name}。", [] + + sim_time_s = float(np.clip(sim_time_s, 10.0, 240.0)) + dt = float(np.clip(dt, 0.01, 0.2)) + initial_soc_pct = float(np.clip(initial_soc_pct, 10.0, 95.0)) + initial_engine_power_kw = float(np.clip(initial_engine_power_kw, 20.0, 260.0)) + rpm_scale = float(np.clip(rpm_scale, 0.5, 1.6)) + load_scale = float(np.clip(load_scale, 0.5, 1.6)) + + points = _profile_points(profile_name) + system = SeriesHybridSystem() + system.battery.SOC = initial_soc_pct / 100.0 + system.bus_voltage = system.battery._get_ocv(system.battery.SOC) + system.genset.set_steady_state_by_power(H_env=0.0, Ma_env=0.0, Power_target=initial_engine_power_kw) + + time_array = np.arange(0.0, sim_time_s, dt) + log = {k: [] for k in [ + "soc", "bus_voltage", "prop_speed_rpm", "target_prop_rpm", + "target_engine_pwr", "p_engine_out_kw", "p_drive_req_kw", + "p_batt_actual_kw", "wf_kg_h" + ]} + + for t in time_array: + target_rpm, load_torque = _target_from_profile(t, points, rpm_scale, load_scale) + res = system.step(dt, target_rpm, load_torque) + res["target_prop_rpm"] = target_rpm + for k in log: + log[k].append(res[k]) + + speed_error = np.array(log["target_prop_rpm"]) - np.array(log["prop_speed_rpm"]) + soc_arr = np.array(log["soc"]) + fuel_arr = np.array(log["wf_kg_h"]) + engine_pwr_arr = np.array(log["p_engine_out_kw"]) + batt_pwr_arr = np.array(log["p_batt_actual_kw"]) + + fig, axes = plt.subplots(3, 1, figsize=(12, 10), sharex=True) + axes[0].plot(time_array, log["target_prop_rpm"], "k--", lw=1.5, label="目标转速") + axes[0].plot(time_array, log["prop_speed_rpm"], "b-", lw=1.5, label="实际转速") + axes[0].set_ylabel("RPM") + axes[0].set_title("推进轴转速响应") + axes[0].grid(True, linestyle=":") + axes[0].legend() + + axes[1].plot(time_array, log["p_drive_req_kw"], "k--", lw=1.2, label="电机需求") + axes[1].plot(time_array, log["p_engine_out_kw"], "r-", lw=1.2, label="发动机输出") + axes[1].plot(time_array, log["p_batt_actual_kw"], "g-", lw=1.2, label="电池功率") + axes[1].axhline(0, color="gray", lw=1) + axes[1].set_ylabel("kW") + axes[1].set_title("功率分配") + axes[1].grid(True, linestyle=":") + axes[1].legend() + + axes[2].plot(time_array, log["bus_voltage"], "m-", lw=1.2, label="母线电压") + axes[2].set_ylabel("V") + axes[2].set_xlabel("时间 (s)") + axes[2].set_title("电气状态") + axes[2].grid(True, linestyle=":") + ax_soc = axes[2].twinx() + ax_soc.plot(time_array, log["soc"], "c--", lw=1.6, label="SOC") + ax_soc.set_ylabel("SOC (%)") + + fig.tight_layout() + + summary = ( + f"### 算例结果解读\n" + f"- 仿真时长:{sim_time_s:.1f} s,步长:{dt:.3f} s\n" + f"- 最大转速误差:{np.max(np.abs(speed_error)):.1f} RPM\n" + f"- SOC 变化:{soc_arr[0]:.2f}% → {soc_arr[-1]:.2f}%(最小 {np.min(soc_arr):.2f}%)\n" + f"- 平均发动机输出:{np.mean(engine_pwr_arr):.2f} kW\n" + f"- 平均电池功率:{np.mean(batt_pwr_arr):.2f} kW\n" + f"- 平均燃油流量:{np.mean(fuel_arr):.2f} kg/h" + ) + + pick_idx = np.linspace(0, len(time_array) - 1, 8, dtype=int) + table_data = [] + for idx in pick_idx: + table_data.append([ + round(float(time_array[idx]), 2), + round(float(log["target_prop_rpm"][idx]), 1), + round(float(log["prop_speed_rpm"][idx]), 1), + round(float(log["p_engine_out_kw"][idx]), 2), + round(float(log["p_batt_actual_kw"][idx]), 2), + round(float(log["soc"][idx]), 2), + ]) + + return fig, summary, table_data + except Exception as e: + return None, f"算例仿真失败:{e}", [] diff --git a/config.py b/config.py index 1b2e024..c1129f7 100644 --- a/config.py +++ b/config.py @@ -16,4 +16,4 @@ API_TYPE = "deepseek" # 当前支持 "deepseek" # ==================== Gradio 应用启动配置 ==================== SERVER_NAME = "0.0.0.0" # 监听所有网络接口 SERVER_PORT = 7860 # 指定一个端口 -SHARE = False # 是否创建Gradio的公开分享链接 +SHARE = True # 是否创建Gradio的公开分享链接 diff --git a/data_usage/case_demo_test_results.json b/data_usage/case_demo_test_results.json new file mode 100644 index 0000000..2b11413 --- /dev/null +++ b/data_usage/case_demo_test_results.json @@ -0,0 +1,70 @@ +[ + { + "name": "常规-起飞巡航", + "figure_ok": true, + "summary_ok": true, + "table_len": 8, + "summary_head": "### 算例结果解读", + "soc_min": 60.0, + "soc_max": 62.05, + "first_row": [ + 0.0, + 1500.0, + 0.0, + 50.0, + -0.65, + 60.0 + ] + }, + { + "name": "高机动-高负载", + "figure_ok": true, + "summary_ok": true, + "table_len": 8, + "summary_head": "### 算例结果解读", + "soc_min": 55.0, + "soc_max": 61.41, + "first_row": [ + 0.0, + 1920.0, + 0.0, + 80.0, + -30.65, + 55.0 + ] + }, + { + "name": "经济巡航-低负载", + "figure_ok": true, + "summary_ok": true, + "table_len": 8, + "summary_head": "### 算例结果解读", + "soc_min": 70.0, + "soc_max": 76.3, + "first_row": [ + 0.0, + 1275.0, + 0.0, + 40.0, + 9.35, + 70.0 + ] + }, + { + "name": "边界输入-自动裁剪", + "figure_ok": true, + "summary_ok": true, + "table_len": 8, + "summary_head": "### 算例结果解读", + "soc_min": 10.0, + "soc_max": 26.51, + "first_row": [ + 0.0, + 2400.0, + 0.0, + 260.0, + -210.65, + 10.0 + ] + } +] \ No newline at end of file diff --git a/data_usage/usage_stats.json b/data_usage/usage_stats.json index 1b02c3f..47c26cf 100644 --- a/data_usage/usage_stats.json +++ b/data_usage/usage_stats.json @@ -1,4 +1,4 @@ { - "total_users": 15, - "last_saved_at": 1760890996.5595384 + "total_users": 22, + "last_saved_at": 1775496284.1673155 } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e2e56e8..a36ea6f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,23 @@ # requirements.txt -gradio -numpy -control -matplotlib -aiohttp +# ===== 新增:PyTorch CPU 轮子下载源 ===== +--extra-index-url https://download.pytorch.org/whl/cpu + +gradio==4.44.1 +gradio-client==1.3.0 +pydantic==2.10.6 +pydantic-core==2.27.2 +huggingface_hub==0.23.0 +numpy==1.26.4 +control==0.9.4 +matplotlib==3.9.4 +aiohttp==3.13.5 +pillow==10.4.0 +# ===== 新增:混动模型(Model)运行依赖 ===== +torch==2.4.1 +botorch==0.14.0 +gpytorch==1.14 +pyro-ppl==1.9.1 +pandas==2.3.3 +scipy==1.15.3 +scikit-learn==1.7.1 diff --git a/ui_components.py b/ui_components.py index da0af4f..25af302 100644 --- a/ui_components.py +++ b/ui_components.py @@ -200,6 +200,37 @@ def create_root_locus_tab(): """) return ui_dict +def create_case_demo_tab(): + """创建算例演示选项卡的UI组件""" + ui_dict = {} + with gr.Row(): + with gr.Column(scale=1): + with gr.Group(): + gr.HTML("
🧪 算例参数设置
") + ui_dict["profile"] = gr.Dropdown( + choices=["起飞-巡航-降落", "高机动阶跃", "经济巡航"], + value="起飞-巡航-降落", + label="工况模板" + ) + ui_dict["sim_time"] = gr.Slider(minimum=20, maximum=180, value=60, step=5, label="仿真时长 (s)") + ui_dict["dt"] = gr.Dropdown(choices=[0.02, 0.05, 0.1], value=0.02, label="仿真步长 (s)") + ui_dict["initial_soc"] = gr.Slider(minimum=20, maximum=90, value=60, step=1, label="初始SOC (%)") + ui_dict["initial_engine_power"] = gr.Slider(minimum=20, maximum=250, value=50, step=5, label="初始发动机功率 (kW)") + ui_dict["rpm_scale"] = gr.Slider(minimum=0.6, maximum=1.4, value=1.0, step=0.05, label="目标转速缩放系数") + ui_dict["load_scale"] = gr.Slider(minimum=0.6, maximum=1.4, value=1.0, step=0.05, label="负载转矩缩放系数") + ui_dict["run_button"] = gr.Button("🚀 运行混动算例", variant="primary", elem_classes="primary-btn") + with gr.Group(): + gr.HTML("
📝 结果解读
") + ui_dict["summary"] = gr.Markdown() + with gr.Column(scale=2): + ui_dict["plot"] = gr.Plot(label="混动系统响应图") + ui_dict["table"] = gr.Dataframe( + headers=["时间(s)", "目标转速", "实际转速", "发动机功率(kW)", "电池功率(kW)", "SOC(%)"], + label="关键时刻数据", + interactive=False + ) + return ui_dict + def create_chatbot_tab(): """创建AI问答选项卡的UI组件""" ui_dict = {}