{"spec_id":"line-stress-strain","library":"echarts","language":"javascript","code":"// anyplot.ai\n// line-stress-strain: Engineering Stress-Strain Curve\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-08-24\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Deterministic noise (small-amplitude, fixed-seed LCG) ------------------\nfunction lcg(seed) {\n  let state = seed >>> 0;\n  return function () {\n    state = (1664525 * state + 1013904223) >>> 0;\n    return state / 4294967296;\n  };\n}\nconst rand = lcg(42);\n\n// --- Piecewise stress-strain curve builder -----------------------------------\n// `knots` are [strain, stress] control points; `segments[i]` describes the leg\n// between knots[i] and knots[i+1]: point count, whether to ease the stress\n// interpolation (smoothstep, for a rounded knee/plateau/necking shape) or keep\n// it linear (Hooke's law elastic region), and noise amplitude in MPa.\nfunction buildCurve(knots, segments) {\n  const strain = [];\n  const stress = [];\n  for (let s = 0; s < segments.length; s++) {\n    const [x0, y0] = knots[s];\n    const [x1, y1] = knots[s + 1];\n    const { n, eased, noise } = segments[s];\n    const start = s === 0 ? 0 : 1;\n    for (let i = start; i <= n; i++) {\n      const tt = i / n;\n      const et = eased ? tt * tt * (3 - 2 * tt) : tt;\n      const strainVal = x0 + (x1 - x0) * tt;\n      let stressVal = y0 + (y1 - y0) * et;\n      if (noise) stressVal += (rand() - 0.5) * noise;\n      strain.push(Number(strainVal.toFixed(5)));\n      stress.push(Number(stressVal.toFixed(1)));\n    }\n  }\n  return strain.map((s, i) => [s, stress[i]]);\n}\n\n// --- Mild steel: sharp yield point + Luders plateau + hardening + necking ---\nconst STEEL_E = 200000; // MPa (Young's modulus, ~200 GPa)\nconst STEEL_YIELD_STRAIN = 0.00125;\nconst STEEL_YIELD_STRESS = STEEL_E * STEEL_YIELD_STRAIN; // 250 MPa\nconst STEEL_UTS_STRAIN = 0.2;\nconst STEEL_UTS_STRESS = 400;\nconst STEEL_FRACTURE_STRAIN = 0.27;\nconst STEEL_FRACTURE_STRESS = 322;\n\nconst steelCurve = buildCurve(\n  [\n    [0, 0],\n    [STEEL_YIELD_STRAIN, STEEL_YIELD_STRESS],\n    [0.02, 251],\n    [STEEL_UTS_STRAIN, STEEL_UTS_STRESS],\n    [STEEL_FRACTURE_STRAIN, STEEL_FRACTURE_STRESS],\n  ],\n  [\n    { n: 20, eased: false, noise: 0 }, // elastic (Hooke's law, no noise)\n    { n: 25, eased: false, noise: 2.5 }, // Luders plateau (serrated yielding)\n    { n: 90, eased: true, noise: 2.5 }, // strain hardening\n    { n: 45, eased: true, noise: 2 }, // necking to fracture\n  ],\n);\n\n// --- Aluminum alloy: gradual rounded knee, lower ductility, comparison series\nconst AL_E = 70000; // MPa (Young's modulus, ~70 GPa)\nconst AL_KNEE_STRAIN = 0.0038;\nconst AL_KNEE_STRESS = AL_E * AL_KNEE_STRAIN;\nconst AL_UTS_STRAIN = 0.1;\nconst AL_UTS_STRESS = 310;\nconst AL_FRACTURE_STRAIN = 0.135;\nconst AL_FRACTURE_STRESS = 296;\n\nconst aluminumCurve = buildCurve(\n  [\n    [0, 0],\n    [AL_KNEE_STRAIN, AL_KNEE_STRESS],\n    [AL_UTS_STRAIN, AL_UTS_STRESS],\n    [AL_FRACTURE_STRAIN, AL_FRACTURE_STRESS],\n  ],\n  [\n    { n: 15, eased: false, noise: 0 }, // elastic (Hooke's law, no noise)\n    { n: 90, eased: true, noise: 1 }, // rounded knee into gradual hardening\n    { n: 30, eased: true, noise: 1 }, // necking to fracture\n  ],\n);\n\n// --- 0.2% offset construction line: parallel to the elastic modulus slope,\n// shifted 0.002 strain — its intersection with the curve is the offset yield\n// point. For steel's flat plateau, that intersection sits at ~250 MPa.\nconst offsetIntersectionStrain = 0.002 + STEEL_YIELD_STRESS / STEEL_E;\nconst offsetLineEndStrain = offsetIntersectionStrain + 0.0011;\nconst offsetLine = [\n  [0.002, 0],\n  [offsetLineEndStrain, STEEL_E * (offsetLineEndStrain - 0.002)],\n];\n\n// --- Init ---------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option ---------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  color: t.palette,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"line-stress-strain · javascript · echarts · anyplot.ai\",\n    left: \"center\",\n    top: 24,\n    textStyle: { color: t.ink, fontSize: 22, fontWeight: 500 },\n  },\n  legend: {\n    data: [\"Mild steel\", \"Aluminum alloy\"],\n    top: 66,\n    right: 70,\n    textStyle: { color: t.inkSoft, fontSize: 15 },\n    itemWidth: 24,\n    itemHeight: 3,\n  },\n  grid: { left: 120, right: 170, top: 150, bottom: 110 },\n  xAxis: {\n    type: \"value\",\n    name: \"Engineering Strain (mm/mm)\",\n    nameLocation: \"middle\",\n    nameGap: 44,\n    min: 0,\n    max: 0.3,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { lineStyle: { color: t.inkSoft } },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n  yAxis: {\n    type: \"value\",\n    name: \"Engineering Stress (MPa)\",\n    nameLocation: \"middle\",\n    nameGap: 68,\n    min: 0,\n    max: 480,\n    nameTextStyle: { color: t.ink, fontSize: 16 },\n    axisLabel: { color: t.inkSoft, fontSize: 14 },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { lineStyle: { color: t.grid } },\n  },\n  series: [\n    {\n      name: \"0.2% Offset\",\n      type: \"line\",\n      data: offsetLine,\n      showSymbol: false,\n      silent: true,\n      lineStyle: { color: t.inkSoft, width: 2, type: \"dashed\" },\n      z: 2,\n    },\n    {\n      name: \"Mild steel\",\n      type: \"line\",\n      data: steelCurve,\n      showSymbol: false,\n      smooth: false,\n      lineStyle: { color: t.palette[0], width: 3.5 },\n      z: 3,\n      markPoint: {\n        symbolSize: 16,\n        itemStyle: { color: t.ink, borderColor: t.pageBg, borderWidth: 2 },\n        label: { color: t.ink, fontSize: 14, fontWeight: 500 },\n        data: [\n          {\n            name: \"Yield\",\n            coord: [offsetIntersectionStrain, STEEL_YIELD_STRESS],\n            symbol: \"circle\",\n            label: {\n              formatter: \"Yield ≈ 250 MPa\\n(0.2% offset)\",\n              position: [28, 44],\n            },\n          },\n          {\n            name: \"UTS\",\n            coord: [STEEL_UTS_STRAIN, STEEL_UTS_STRESS],\n            symbol: \"circle\",\n            label: {\n              formatter: `UTS ≈ ${STEEL_UTS_STRESS} MPa`,\n              position: \"top\",\n              distance: 10,\n            },\n          },\n          {\n            name: \"Fracture\",\n            coord: [STEEL_FRACTURE_STRAIN, STEEL_FRACTURE_STRESS],\n            symbol: \"diamond\",\n            symbolSize: 15,\n            label: {\n              formatter: \"Fracture\",\n              position: \"right\",\n              distance: 12,\n            },\n          },\n          {\n            name: \"Modulus label\",\n            coord: [0.024, 340],\n            symbol: \"circle\",\n            symbolSize: 4,\n            itemStyle: { color: t.pageBg, borderColor: t.pageBg },\n            label: {\n              show: true,\n              formatter: \"E ≈ 200 GPa\",\n              color: t.inkSoft,\n              fontSize: 14,\n              fontStyle: \"italic\",\n              position: \"top\",\n            },\n          },\n          {\n            name: \"Elastic phase\",\n            coord: [0.015, 445],\n            symbol: \"circle\",\n            symbolSize: 4,\n            itemStyle: { color: t.pageBg, borderColor: t.pageBg },\n            label: {\n              show: true,\n              formatter: \"Elastic\",\n              color: t.inkSoft,\n              fontSize: 15,\n              fontWeight: 500,\n              position: \"top\",\n            },\n          },\n          {\n            name: \"Hardening phase\",\n            coord: [0.1, 445],\n            symbol: \"circle\",\n            symbolSize: 4,\n            itemStyle: { color: t.pageBg, borderColor: t.pageBg },\n            label: {\n              show: true,\n              formatter: \"Strain hardening\",\n              color: t.inkSoft,\n              fontSize: 15,\n              fontWeight: 500,\n              position: \"top\",\n            },\n          },\n          {\n            name: \"Necking phase\",\n            coord: [0.235, 445],\n            symbol: \"circle\",\n            symbolSize: 4,\n            itemStyle: { color: t.pageBg, borderColor: t.pageBg },\n            label: {\n              show: true,\n              formatter: \"Necking\",\n              color: t.inkSoft,\n              fontSize: 15,\n              fontWeight: 500,\n              position: \"top\",\n            },\n          },\n        ],\n      },\n    },\n    {\n      name: \"Aluminum alloy\",\n      type: \"line\",\n      data: aluminumCurve,\n      showSymbol: false,\n      smooth: false,\n      lineStyle: { color: t.palette[1], width: 3 },\n      z: 1,\n    },\n  ],\n});\n"}