{"id":24966,"date":"2026-10-23T03:33:55","date_gmt":"2026-10-23T03:33:55","guid":{"rendered":"https:\/\/www.mechstream.com\/?p=24966"},"modified":"2026-10-23T03:33:58","modified_gmt":"2026-10-23T03:33:58","slug":"stress-concentration-fatigue-correction-calculator","status":"publish","type":"post","link":"https:\/\/www.mechstream.com\/ar\/stress-concentration-fatigue-correction-calculator\/","title":{"rendered":"Stress Concentration Fatigue Correction Calculator"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The Stress Concentration Fatigue Correction Calculator is a practical engineering tool designed to evaluate how geometric discontinuities affect fatigue performance under cyclic loading. Using established fatigue analysis equations, this calculator helps engineers determine the fatigue stress concentration factor (Kf), notch sensitivity factor (q), corrected alternating stress, and stress amplification percentage. It also supports Peterson notch sensitivity calculations and Modified Goodman fatigue safety factor assessments. Ideal for mechanical engineers, structural designers, and manufacturing professionals, the Stress Concentration Fatigue Correction Calculator simplifies preliminary fatigue analysis of shafts, fillets, grooves, holes, and notched components. Improve mechanical design reliability, evaluate potential fatigue risks, and optimize component geometry with accurate, formula-based engineering calculations.<\/p>\n\n\n\n<div id=\"scf-calculator\" class=\"scf-root\" data-scf-widget=\"stress-concentration-fatigue-correction\">\n<style>\n#scf-calculator,#scf-calculator *,#scf-calculator *::before,#scf-calculator *::after{box-sizing:border-box}\n#scf-calculator{\n  --scf-bg:#ffffff;--scf-card:#ffffff;--scf-text:#1f2937;--scf-head:#111827;--scf-muted:#4b5563;--scf-soft:#6b7280;\n  --scf-line:#d1d5db;--scf-line-soft:#e5e7eb;--scf-panel:#f8fafc;--scf-accent:#1d64c8;--scf-accent-dark:#154c9a;--scf-accent-soft:#eaf1fb;\n  --scf-err:#b42318;--scf-err-soft:#fdecea;--scf-warn:#7a4b00;--scf-warn-soft:#fff6e0;--scf-ok:#146c43;--scf-ok-soft:#e8f6ee;\n  display:block;width:100%;max-width:1180px;margin:24px auto;padding:28px;background:var(--scf-bg);color:var(--scf-text);\n  border:1px solid var(--scf-line-soft);border-radius:20px;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;\n  font-size:16px;line-height:1.55;font-weight:400;letter-spacing:normal;text-transform:none;text-indent:0;word-spacing:normal;-webkit-font-smoothing:antialiased;text-align:left;position:relative\n}\n#scf-calculator .scf-wrap{container-type:inline-size;container-name:scf;width:100%}\n#scf-calculator h1,#scf-calculator h2,#scf-calculator h3,#scf-calculator h4,#scf-calculator p,#scf-calculator ul,#scf-calculator ol,#scf-calculator li,#scf-calculator figure,#scf-calculator figcaption,#scf-calculator table,#scf-calculator details,#scf-calculator summary,#scf-calculator fieldset,#scf-calculator legend,#scf-calculator label,#scf-calculator section,#scf-calculator article,#scf-calculator aside{\n  margin:0;padding:0;border:0;background:none;color:inherit;font-family:inherit;font-size:inherit;font-weight:inherit;font-style:normal;line-height:inherit;text-indent:0;text-transform:none;letter-spacing:normal;text-shadow:none;box-shadow:none;float:none;width:auto;max-width:none\n}\n#scf-calculator ul,#scf-calculator ol{list-style:none}\n#scf-calculator a{color:var(--scf-accent);text-decoration:underline}\n#scf-calculator sub,#scf-calculator sup{font-size:.72em;line-height:0;position:relative;vertical-align:baseline}\n#scf-calculator sub{bottom:-.25em}\n#scf-calculator sup{top:-.5em}\n#scf-calculator [hidden]{display:none!important}\n#scf-calculator svg{display:block;max-width:100%;height:auto;overflow:visible}\n#scf-calculator .scf-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;align-items:start}\n#scf-calculator .scf-col{min-width:0}\n#scf-calculator .scf-card{background:var(--scf-card);border:1px solid var(--scf-line-soft);border-radius:14px;padding:20px;box-shadow:0 1px 2px rgba(17,24,39,.04),0 4px 14px rgba(17,24,39,.04);min-width:0}\n#scf-calculator .scf-card+.scf-card{margin-top:16px}\n#scf-calculator .scf-card-title{margin:0 0 4px;color:var(--scf-head);font-size:17px;font-weight:650;line-height:1.3;display:flex;align-items:center;gap:10px}\n#scf-calculator .scf-step{display:inline-flex;align-items:center;justify-content:center;flex:0 0 24px;width:24px;height:24px;border-radius:50%;background:var(--scf-accent-soft);color:var(--scf-accent);font-size:12.5px;font-weight:700}\n#scf-calculator .scf-card-note{color:var(--scf-muted);font-size:14px;margin:0 0 14px}\n#scf-calculator .scf-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:14px 16px}\n#scf-calculator .scf-field{min-width:0}\n#scf-calculator .scf-span{grid-column:1\/-1}\n#scf-calculator .scf-label{display:block;font-size:14px;font-weight:600;color:var(--scf-head);margin:0 0 6px;line-height:1.3}\n#scf-calculator .scf-opt{color:var(--scf-soft);font-weight:400;font-size:12.5px;margin-left:4px}\n#scf-calculator .scf-hint{display:block;color:var(--scf-soft);font-size:12.6px;margin-top:5px;line-height:1.45}\n#scf-calculator .scf-hint:empty{display:none}\n#scf-calculator .scf-error{display:block;color:var(--scf-err);font-size:13px;margin-top:4px;line-height:1.4}\n#scf-calculator .scf-error:empty{display:none}\n#scf-calculator .scf-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:stretch}\n#scf-calculator .scf-unit{display:inline-flex;align-items:center;justify-content:center;min-width:56px;min-height:44px;padding:0 10px;border-radius:10px;background:#f1f4f8;color:var(--scf-muted);font-size:14px;font-weight:600;white-space:nowrap}\n#scf-calculator input[type=number],#scf-calculator select{\n  -webkit-appearance:none;appearance:none;display:block;width:100%;min-height:44px;height:auto;margin:0;padding:9px 13px;font:inherit;font-size:16px;line-height:1.3;\n  color:var(--scf-text);background-color:#fff;border:1px solid var(--scf-line);border-radius:10px;box-shadow:none;outline:none;max-width:none;transition:border-color .15s ease,box-shadow .15s ease\n}\n#scf-calculator select{padding-right:34px;background-image:linear-gradient(45deg,transparent 50%,#4b5563 50%),linear-gradient(135deg,#4b5563 50%,transparent 50%);background-position:calc(100% - 18px) 19px,calc(100% - 13px) 19px;background-size:5px 5px,5px 5px;background-repeat:no-repeat;cursor:pointer}\n#scf-calculator input[type=number]:focus,#scf-calculator select:focus{border-color:var(--scf-accent);box-shadow:0 0 0 4px rgba(29,100,200,.16)}\n#scf-calculator input[type=number]::placeholder{color:#9ca3af;opacity:1}\n#scf-calculator .scf-invalid{border-color:var(--scf-err)!important;box-shadow:0 0 0 3px rgba(180,35,24,.12)!important}\n#scf-calculator .scf-seg{display:grid;grid-template-columns:minmax(0,1fr);gap:4px;padding:4px;background:#eef1f5;border-radius:12px;border:0;margin:0;position:relative;min-width:0;width:100%}\n#scf-calculator .scf-seg legend{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n#scf-calculator .scf-seg input{position:absolute;opacity:0;width:1px;height:1px;margin:0;pointer-events:none}\n#scf-calculator .scf-seg label{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:42px;padding:6px 8px;border-radius:9px;font-size:14px;font-weight:600;color:var(--scf-muted);cursor:pointer;text-align:center;line-height:1.25;transition:background .15s,color .15s,box-shadow .15s;margin:0}\n#scf-calculator .scf-seg label small{display:block;font-size:11.8px;font-weight:500;color:var(--scf-soft);margin-top:1px}\n#scf-calculator .scf-seg input:checked+label{background:#fff;color:var(--scf-accent-dark);box-shadow:0 1px 3px rgba(17,24,39,.15)}\n#scf-calculator .scf-seg input:focus-visible+label{outline:3px solid rgba(29,100,200,.4);outline-offset:1px}\n#scf-calculator .scf-seg-label{display:block;font-size:14px;font-weight:600;color:var(--scf-head);margin:0 0 6px}\n#scf-calculator .scf-info{padding:12px 14px;border-radius:10px;background:var(--scf-panel);border:1px solid var(--scf-line-soft);font-size:13.4px;color:var(--scf-muted);line-height:1.5}\n#scf-calculator .scf-info strong{color:var(--scf-head);font-weight:600}\n#scf-calculator .scf-derived{padding:10px 13px;border-radius:10px;background:var(--scf-accent-soft);border:1px solid #cddcf2;font-size:13.6px;color:var(--scf-accent-dark);line-height:1.45;overflow-wrap:anywhere}\n#scf-calculator .scf-derived:empty{display:none}\n#scf-calculator .scf-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px;justify-content:center}\n#scf-calculator .scf-btn{-webkit-appearance:none;appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:46px;margin:0;padding:10px 18px;border-radius:999px;border:1px solid var(--scf-line);background:#fff;color:var(--scf-head);font:inherit;font-size:15px;font-weight:600;line-height:1.2;cursor:pointer;text-decoration:none;text-transform:none;letter-spacing:normal;box-shadow:none;width:auto;height:auto;flex:1 1 auto;transition:background .15s,border-color .15s,color .15s}\n#scf-calculator .scf-btn:hover{background:#f3f6fa;border-color:#b9c3d0;color:var(--scf-head)}\n#scf-calculator .scf-btn-primary{background:var(--scf-accent);border-color:var(--scf-accent);color:#fff;flex:0 0 auto;width:auto;min-width:200px;padding:10px 36px}\n#scf-calculator .scf-btn-primary:hover{background:var(--scf-accent-dark);border-color:var(--scf-accent-dark);color:#fff}\n#scf-calculator .scf-btn:disabled{opacity:.5;cursor:not-allowed}\n#scf-calculator .scf-btn:focus-visible{outline:3px solid rgba(29,100,200,.4);outline-offset:2px}\n#scf-calculator .scf-form-msg{text-align:center;color:var(--scf-err);font-size:13.6px;margin-top:10px;min-height:1.3em}\n#scf-calculator .scf-form-msg.scf-ok{color:var(--scf-ok)}\n#scf-calculator .scf-empty{padding:26px 16px;text-align:center;color:var(--scf-soft);font-size:14.2px;border:1px dashed var(--scf-line);border-radius:12px;background:var(--scf-panel)}\n#scf-calculator .scf-stale{margin:0 0 12px;padding:10px 13px;border-radius:10px;background:var(--scf-warn-soft);color:#5c3a00;font-size:13.2px;border:1px solid #f0dca6}\n#scf-calculator .scf-is-stale .scf-dim{opacity:.45;transition:opacity .2s}\n#scf-calculator .scf-hero{display:grid;grid-template-columns:minmax(0,1fr);gap:10px}\n#scf-calculator .scf-hero-card{border-radius:12px;padding:14px 16px;border:1px solid #cddcf2;background:var(--scf-accent-soft);min-width:0}\n#scf-calculator .scf-hero-label{font-size:13px;font-weight:600;color:var(--scf-muted);line-height:1.35}\n#scf-calculator .scf-hero-value{font-size:clamp(24px,3.2vw,30px);font-weight:700;color:var(--scf-head);letter-spacing:-.01em;line-height:1.2;margin-top:3px;overflow-wrap:anywhere}\n#scf-calculator .scf-hero-sub{font-size:12.6px;color:var(--scf-muted);margin-top:3px;line-height:1.45;overflow-wrap:anywhere}\n#scf-calculator .scf-kpis{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:10px}\n#scf-calculator .scf-kpi{background:var(--scf-panel);border:1px solid var(--scf-line-soft);border-radius:12px;padding:11px 13px;min-width:0}\n#scf-calculator .scf-kpi-label{font-size:12.6px;font-weight:600;color:var(--scf-muted);line-height:1.3}\n#scf-calculator .scf-kpi-value{font-size:clamp(17px,2.1vw,20px);font-weight:700;color:var(--scf-head);letter-spacing:-.01em;margin-top:2px;line-height:1.25;overflow-wrap:anywhere}\n#scf-calculator .scf-kpi-value.scf-na{color:var(--scf-soft);font-size:15px}\n#scf-calculator .scf-kpi-sub{font-size:12.1px;color:var(--scf-soft);margin-top:2px;line-height:1.4;overflow-wrap:anywhere}\n#scf-calculator .scf-formula{margin-top:12px;padding:10px 13px;border-radius:10px;background:var(--scf-panel);border:1px dashed var(--scf-line);font-size:13.5px;color:var(--scf-text);overflow-wrap:anywhere;line-height:1.6;font-variant-numeric:tabular-nums}\n#scf-calculator .scf-formula div+div{margin-top:2px}\n#scf-calculator .scf-status{display:inline-block;padding:2px 10px;border-radius:999px;font-size:12px;font-weight:700;letter-spacing:.02em;line-height:1.6;vertical-align:middle;white-space:nowrap}\n#scf-calculator .scf-st-ok{background:var(--scf-ok-soft);color:var(--scf-ok)}\n#scf-calculator .scf-st-bad{background:var(--scf-err-soft);color:var(--scf-err)}\n#scf-calculator .scf-st-na{background:#eef1f5;color:var(--scf-soft)}\n#scf-calculator .scf-hero-card.scf-hero-ok{background:var(--scf-ok-soft);border-color:#b9e2cb}\n#scf-calculator .scf-hero-card.scf-hero-bad{background:var(--scf-err-soft);border-color:#f3c3bd}\n#scf-calculator .scf-hero-card.scf-hero-na{background:var(--scf-panel);border-color:var(--scf-line-soft)}\n#scf-calculator .scf-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n@container scf (min-width:520px){\n  #scf-calculator .scf-grid{grid-template-columns:repeat(2,minmax(0,1fr))}\n  #scf-calculator .scf-hero{grid-template-columns:repeat(2,minmax(0,1fr))}\n  #scf-calculator .scf-kpis{grid-template-columns:repeat(3,minmax(0,1fr))}\n  #scf-calculator .scf-seg.scf-seg-3{grid-template-columns:repeat(3,minmax(0,1fr))}\n  #scf-calculator .scf-seg.scf-seg-2{grid-template-columns:repeat(2,minmax(0,1fr))}\n}\n@media (max-width:700px){\n  #scf-calculator{padding:16px 12px;border-radius:14px;margin:12px auto}\n  #scf-calculator .scf-card{padding:16px 14px;border-radius:12px}\n  #scf-calculator .scf-seg label{font-size:13.4px}\n}\n@media (max-width:360px){\n  #scf-calculator .scf-kpis{grid-template-columns:minmax(0,1fr)}\n}\n@media (prefers-reduced-motion:reduce){#scf-calculator *{transition:none!important}}\n@media print{#scf-calculator .scf-actions{display:none!important}}\n<\/style>\n<div class=\"scf-wrap\">\n<div class=\"scf-layout\">\n<div class=\"scf-col scf-col-in\">\n<form class=\"scf-form\" id=\"scf-form\" novalidate onsubmit=\"return false;\">\n<section class=\"scf-card\" aria-labelledby=\"scf-h-mode\">\n<h2 class=\"scf-card-title\" id=\"scf-h-mode\"><span class=\"scf-step\" aria-hidden=\"true\">1<\/span>Calculation mode and units<\/h2>\n<p class=\"scf-card-note\">Choose how the notch sensitivity is obtained and whether a Modified Goodman fatigue safety factor is required.<\/p>\n<fieldset class=\"scf-seg scf-seg-3\">\n<legend>Calculation mode<\/legend>\n<input type=\"radio\" id=\"scf-m-a\" name=\"scf-mode\" value=\"A\" checked><label for=\"scf-m-a\">Mode A<small>Direct K<sub>t<\/sub> and q<\/small><\/label>\n<input type=\"radio\" id=\"scf-m-b\" name=\"scf-mode\" value=\"B\"><label for=\"scf-m-b\">Mode B<small>Peterson q<\/small><\/label>\n<input type=\"radio\" id=\"scf-m-c\" name=\"scf-mode\" value=\"C\"><label for=\"scf-m-c\">Mode C<small>Fatigue safety factor<\/small><\/label>\n<\/fieldset>\n<p class=\"scf-hint\" id=\"scf-mode-hint\"><\/p>\n<div class=\"scf-grid\" style=\"margin-top:14px\">\n<div class=\"scf-field\">\n<label class=\"scf-label\" for=\"scf-su\">Stress unit<\/label>\n<select id=\"scf-su\" name=\"stressUnit\" aria-describedby=\"scf-su-hint\">\n<option value=\"MPa\" selected>MPa<\/option>\n<option value=\"Pa\">Pa<\/option>\n<option value=\"psi\">psi<\/option>\n<option value=\"ksi\">ksi<\/option>\n<\/select>\n<span class=\"scf-hint\" id=\"scf-su-hint\">Values are converted internally to MPa. Changing the unit converts values already entered.<\/span>\n<\/div>\n<div class=\"scf-field\">\n<label class=\"scf-label\" for=\"scf-lu\">Length unit (r and a)<\/label>\n<select id=\"scf-lu\" name=\"lengthUnit\" aria-describedby=\"scf-lu-hint\">\n<option value=\"mm\" selected>mm<\/option>\n<option value=\"in\">inches<\/option>\n<\/select>\n<span class=\"scf-hint\" id=\"scf-lu-hint\">Notch radius and Peterson parameter always share this unit.<\/span>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"scf-card\" aria-labelledby=\"scf-h-mat\">\n<h2 class=\"scf-card-title\" id=\"scf-h-mat\"><span class=\"scf-step\" aria-hidden=\"true\">2<\/span>Material properties<\/h2>\n<p class=\"scf-card-note\" id=\"scf-mat-note\">Material selection is informational. No property is filled in automatically.<\/p>\n<div class=\"scf-grid\">\n<div class=\"scf-field scf-span\">\n<label class=\"scf-label\" for=\"scf-material\">Material<\/label>\n<select id=\"scf-material\" name=\"material\">\n<option value=\"carbon\" selected>Carbon Steel<\/option>\n<option value=\"alloy\">Alloy Steel<\/option>\n<option value=\"stainless\">Stainless Steel<\/option>\n<option value=\"aluminum\">Aluminum Alloy<\/option>\n<option value=\"custom\">Custom Material<\/option>\n<\/select>\n<\/div>\n<div class=\"scf-info scf-span\" id=\"scf-mat-info\" aria-live=\"polite\"><\/div>\n<div class=\"scf-field\">\n<label class=\"scf-label\" for=\"scf-sut\">Ultimate Tensile Strength (S<sub>ut<\/sub>) <span class=\"scf-opt\" id=\"scf-sut-opt\">(Mode C)<\/span><\/label>\n<div class=\"scf-row\"><input id=\"scf-sut\" name=\"sut\" type=\"number\" inputmode=\"decimal\" step=\"any\" placeholder=\"e.g. 600\" aria-describedby=\"scf-sut-err\"><span class=\"scf-unit scf-su-l\" aria-hidden=\"true\">MPa<\/span><\/div>\n<span class=\"scf-error\" id=\"scf-sut-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field\">\n<label class=\"scf-label\" for=\"scf-se\">Endurance Limit (S<sub>e<\/sub>) <span class=\"scf-opt\" id=\"scf-se-opt\">(Mode C)<\/span><\/label>\n<div class=\"scf-row\"><input id=\"scf-se\" name=\"se\" type=\"number\" inputmode=\"decimal\" step=\"any\" placeholder=\"validated value\" aria-describedby=\"scf-se-hint scf-se-err\"><span class=\"scf-unit scf-su-l\" aria-hidden=\"true\">MPa<\/span><\/div>\n<span class=\"scf-hint\" id=\"scf-se-hint\">Validated, corrected component endurance limit (surface, size, load, temperature and reliability effects). It is never assigned automatically.<\/span>\n<span class=\"scf-error\" id=\"scf-se-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field scf-span\" id=\"scf-sebasis-field\">\n<label class=\"scf-label\" for=\"scf-sebasis\">What does the entered S<sub>e<\/sub> already include?<\/label>\n<select id=\"scf-sebasis\" name=\"seBasis\" aria-describedby=\"scf-sebasis-hint\">\n<option value=\"unnotched\" selected>Unnotched component value: this notch is NOT included (apply Kf to alternating stress)<\/option>\n<option value=\"notched\">Notched component or notched-specimen value: this notch IS already included (do not apply Kf again)<\/option>\n<\/select>\n<span class=\"scf-hint\" id=\"scf-sebasis-hint\">Prevents the notch effect from being counted twice.<\/span>\n<\/div>\n<div class=\"scf-field scf-span\">\n<label class=\"scf-label\" for=\"scf-sy\">Yield Strength (S<sub>y<\/sub>) <span class=\"scf-opt\" id=\"scf-sy-opt\">(optional)<\/span><\/label>\n<div class=\"scf-row\"><input id=\"scf-sy\" name=\"sy\" type=\"number\" inputmode=\"decimal\" step=\"any\" placeholder=\"optional\" aria-describedby=\"scf-sy-hint scf-sy-err\"><span class=\"scf-unit scf-su-l\" aria-hidden=\"true\">MPa<\/span><\/div>\n<span class=\"scf-hint\" id=\"scf-sy-hint\">Used only to check for local yielding at the notch root and for the first-cycle yield check. Required for the yield-adjusted mean stress method.<\/span>\n<span class=\"scf-error\" id=\"scf-sy-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"scf-card\" aria-labelledby=\"scf-h-sc\">\n<h2 class=\"scf-card-title\" id=\"scf-h-sc\"><span class=\"scf-step\" aria-hidden=\"true\">3<\/span>Stress concentration<\/h2>\n<p class=\"scf-card-note\">K<sub>t<\/sub> must come from a geometry-specific chart, FEA, measurement or validated reference, based on the same nominal stress definition used below.<\/p>\n<div class=\"scf-grid\">\n<div class=\"scf-field scf-span\">\n<label class=\"scf-label\" for=\"scf-kt\">Theoretical Stress Concentration Factor (K<sub>t<\/sub>)<\/label>\n<input id=\"scf-kt\" name=\"kt\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"1\" placeholder=\"e.g. 2.5\" aria-describedby=\"scf-kt-hint scf-kt-err\">\n<span class=\"scf-hint\" id=\"scf-kt-hint\">Elastic factor, K<sub>t<\/sub> \u2265 1.<\/span>\n<span class=\"scf-error\" id=\"scf-kt-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field scf-span\" id=\"scf-qsrc-field\" hidden>\n<span class=\"scf-seg-label\" aria-hidden=\"true\">Notch sensitivity input<\/span>\n<fieldset class=\"scf-seg scf-seg-2\">\n<legend>Notch sensitivity input<\/legend>\n<input type=\"radio\" id=\"scf-qs-d\" name=\"scf-qsrc\" value=\"direct\" checked><label for=\"scf-qs-d\">Enter q directly<\/label>\n<input type=\"radio\" id=\"scf-qs-p\" name=\"scf-qsrc\" value=\"peterson\"><label for=\"scf-qs-p\">Peterson q = 1\/(1 + a\/r)<\/label>\n<\/fieldset>\n<\/div>\n<div class=\"scf-field scf-span\" id=\"scf-q-field\">\n<label class=\"scf-label\" for=\"scf-q\">Notch Sensitivity Factor (q)<\/label>\n<input id=\"scf-q\" name=\"q\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" max=\"1\" placeholder=\"0 to 1, e.g. 0.8\" aria-describedby=\"scf-q-hint scf-q-err\">\n<span class=\"scf-hint\" id=\"scf-q-hint\">0 = notch-insensitive within the model, 1 = fully notch-sensitive (K<sub>f<\/sub> = K<sub>t<\/sub>). Take from notch-sensitivity charts or test data.<\/span>\n<span class=\"scf-error\" id=\"scf-q-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field\" id=\"scf-r-field\" hidden>\n<label class=\"scf-label\" for=\"scf-r\">Notch Root Radius (r)<\/label>\n<div class=\"scf-row\"><input id=\"scf-r\" name=\"r\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" placeholder=\"e.g. 1.5\" aria-describedby=\"scf-r-err\"><span class=\"scf-unit scf-lu-l\" aria-hidden=\"true\">mm<\/span><\/div>\n<span class=\"scf-error\" id=\"scf-r-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field\" id=\"scf-a-field\" hidden>\n<label class=\"scf-label\" for=\"scf-a\">Peterson Material Parameter (a)<\/label>\n<div class=\"scf-row\"><input id=\"scf-a\" name=\"a\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" placeholder=\"from validated data\" aria-describedby=\"scf-a-hint scf-a-err\"><span class=\"scf-unit scf-lu-l\" aria-hidden=\"true\">mm<\/span><\/div>\n<span class=\"scf-error\" id=\"scf-a-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<p class=\"scf-hint scf-span\" id=\"scf-a-hint\" hidden>The Peterson characteristic length a depends on the material and its strength. Take it from validated material data or an engineering reference; this calculator does not supply default values.<\/p>\n<div class=\"scf-derived scf-span\" id=\"scf-q-derived\" aria-live=\"polite\"><\/div>\n<\/div>\n<\/section>\n<section class=\"scf-card\" aria-labelledby=\"scf-h-load\">\n<h2 class=\"scf-card-title\" id=\"scf-h-load\"><span class=\"scf-step\" aria-hidden=\"true\">4<\/span>Loading parameters<\/h2>\n<p class=\"scf-card-note\">Nominal stresses at the notched section. Tension is positive, compression negative.<\/p>\n<span class=\"scf-seg-label\" aria-hidden=\"true\">Stress input method<\/span>\n<fieldset class=\"scf-seg scf-seg-2\">\n<legend>Stress input method<\/legend>\n<input type=\"radio\" id=\"scf-lm-d\" name=\"scf-lm\" value=\"direct\" checked><label for=\"scf-lm-d\">Alternating (and mean) stress<\/label>\n<input type=\"radio\" id=\"scf-lm-m\" name=\"scf-lm\" value=\"maxmin\"><label for=\"scf-lm-m\">Maximum and minimum stress<\/label>\n<\/fieldset>\n<div class=\"scf-grid\" style=\"margin-top:14px\">\n<div class=\"scf-field\" id=\"scf-sa-field\">\n<label class=\"scf-label\" for=\"scf-sa\">Nominal Alternating Stress (\u03c3<sub>a<\/sub>)<\/label>\n<div class=\"scf-row\"><input id=\"scf-sa\" name=\"sa\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" placeholder=\"e.g. 100\" aria-describedby=\"scf-sa-err\"><span class=\"scf-unit scf-su-l\" aria-hidden=\"true\">MPa<\/span><\/div>\n<span class=\"scf-error\" id=\"scf-sa-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field\" id=\"scf-sm-field\">\n<label class=\"scf-label\" for=\"scf-sm\">Nominal Mean Stress (\u03c3<sub>m<\/sub>) <span class=\"scf-opt\" id=\"scf-sm-opt\">(optional)<\/span><\/label>\n<div class=\"scf-row\"><input id=\"scf-sm\" name=\"sm\" type=\"number\" inputmode=\"decimal\" step=\"any\" placeholder=\"e.g. 0\" aria-describedby=\"scf-sm-err\"><span class=\"scf-unit scf-su-l\" aria-hidden=\"true\">MPa<\/span><\/div>\n<span class=\"scf-error\" id=\"scf-sm-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field\" id=\"scf-smax-field\" hidden>\n<label class=\"scf-label\" for=\"scf-smax\">Maximum Nominal Stress (\u03c3<sub>max<\/sub>)<\/label>\n<div class=\"scf-row\"><input id=\"scf-smax\" name=\"smax\" type=\"number\" inputmode=\"decimal\" step=\"any\" placeholder=\"e.g. 150\" aria-describedby=\"scf-smax-err\"><span class=\"scf-unit scf-su-l\" aria-hidden=\"true\">MPa<\/span><\/div>\n<span class=\"scf-error\" id=\"scf-smax-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field\" id=\"scf-smin-field\" hidden>\n<label class=\"scf-label\" for=\"scf-smin\">Minimum Nominal Stress (\u03c3<sub>min<\/sub>)<\/label>\n<div class=\"scf-row\"><input id=\"scf-smin\" name=\"smin\" type=\"number\" inputmode=\"decimal\" step=\"any\" placeholder=\"e.g. -50\" aria-describedby=\"scf-smin-err\"><span class=\"scf-unit scf-su-l\" aria-hidden=\"true\">MPa<\/span><\/div>\n<span class=\"scf-error\" id=\"scf-smin-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-derived scf-span\" id=\"scf-load-derived\" aria-live=\"polite\"><\/div>\n<div class=\"scf-field scf-span\" id=\"scf-mt-field\" hidden>\n<label class=\"scf-label\" for=\"scf-mt\">Mean stress concentration treatment (K<sub>m<\/sub>)<\/label>\n<select id=\"scf-mt\" name=\"meanTreatment\" aria-describedby=\"scf-mt-hint scf-mt-err\">\n<option value=\"\" selected>Select a treatment<\/option>\n<option value=\"kf\">Km = Kf (conservative, notch remains elastic)<\/option>\n<option value=\"nominal\">Km = 1 (nominal mean stress, no concentration)<\/option>\n<option value=\"norton\">Yield-adjusted Kfm (Norton method, requires Sy)<\/option>\n<option value=\"user\">User-defined Km (validated value)<\/option>\n<\/select>\n<span class=\"scf-hint\" id=\"scf-mt-hint\">K<sub>f<\/sub> is not assumed to apply to the mean stress. Local yielding at the notch root can relax the local mean stress, so the mean stress concentration depends on the material, peak stress and loading history. Choose the treatment that matches your data.<\/span>\n<span class=\"scf-error\" id=\"scf-mt-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"scf-field\" id=\"scf-km-field\" hidden>\n<label class=\"scf-label\" for=\"scf-km\">Mean Stress Concentration Factor (K<sub>m<\/sub>)<\/label>\n<input id=\"scf-km\" name=\"km\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" placeholder=\"e.g. 1.6\" aria-describedby=\"scf-km-err\">\n<span class=\"scf-error\" id=\"scf-km-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<\/div>\n<div class=\"scf-actions\">\n<button type=\"button\" class=\"scf-btn scf-btn-primary\" id=\"scf-calc\">Calculate<\/button>\n<\/div>\n<p class=\"scf-form-msg\" id=\"scf-form-msg\" role=\"status\" aria-live=\"polite\"><\/p>\n<\/section>\n<\/form>\n<\/div>\n<div class=\"scf-col scf-col-out\">\n<section class=\"scf-card\" id=\"scf-results\" aria-labelledby=\"scf-h-res\" tabindex=\"-1\" hidden>\n<h2 class=\"scf-card-title\" id=\"scf-h-res\"><span class=\"scf-step\" aria-hidden=\"true\">5<\/span>Calculation results<\/h2>\n<div class=\"scf-empty\" id=\"scf-res-empty\">Enter K<sub>t<\/sub>, the notch sensitivity and the nominal stress, then press Calculate.<\/div>\n<div id=\"scf-res-body\" hidden>\n<p class=\"scf-stale\" id=\"scf-stale\" role=\"status\" hidden>Some inputs are invalid. The results below are from the last valid calculation.<\/p>\n<div class=\"scf-dim\">\n<div class=\"scf-hero\" style=\"margin-top:10px\">\n<div class=\"scf-hero-card\"><div class=\"scf-hero-label\">Fatigue Stress Concentration Factor K<sub>f<\/sub><\/div><div class=\"scf-hero-value\" id=\"scf-r-kf\"><\/div><div class=\"scf-hero-sub\" id=\"scf-r-kf-sub\"><\/div><\/div>\n<div class=\"scf-hero-card\"><div class=\"scf-hero-label\">Corrected Alternating Stress \u03c3<sub>a,corrected<\/sub><\/div><div class=\"scf-hero-value\" id=\"scf-r-sac\"><\/div><div class=\"scf-hero-sub\" id=\"scf-r-sac-sub\"><\/div><\/div>\n<\/div>\n<div class=\"scf-kpis\" id=\"scf-r-kpis\"><\/div>\n<div class=\"scf-formula\" id=\"scf-r-formula\"><\/div>\n<\/div>\n<\/div>\n<\/section>\n<\/div>\n<\/div>\n<\/div>\n<script>\n(function () {\n  \"use strict\";\n  \/* =====================================================================\n     CONSTANTS\n     Stress units are converted to MPa internally; lengths to mm.\n     ===================================================================== *\/\n  var STRESS = { MPa: 1, Pa: 1e-6, psi: 0.006894757, ksi: 6.894757 };\n  var LEN = { mm: 1, \"in\": 25.4 };\n  var MAX_STRESS_MPA = 100000; \/* sanity cap to catch unit mistakes *\/\n  var MAT_INFO = {\n    carbon: \"Carbon steel. Informational only. Notch sensitivity of steels generally rises with tensile strength, so take q or the Peterson parameter a, as well as Se and Sut, from validated data for the grade and heat treatment.\",\n    alloy: \"Alloy steel. Informational only. High-strength alloy steels are typically highly notch-sensitive (q close to 1 except for very small radii). Use validated data for the specific grade and condition.\",\n    stainless: \"Stainless steel. Informational only. Fatigue and notch behaviour differ between austenitic, ferritic, martensitic and duplex grades; use grade-specific data.\",\n    aluminum: \"Aluminum alloy. Informational only. Aluminum alloys have no true endurance limit: in Mode C enter a fatigue strength at a stated life (published values are often quoted at 5\u00d710\u2078 cycles) as Se. The safety factor then applies only at that life.\",\n    custom: \"Custom material. Enter all properties from validated test data or an applicable standard.\"\n  };\n  var MAT_NAME = { carbon: \"Carbon Steel\", alloy: \"Alloy Steel\", stainless: \"Stainless Steel\", aluminum: \"Aluminum Alloy\", custom: \"Custom Material\" };\n  var MODE_HINT = {\n    A: \"Mode A: enter Kt and q directly to obtain Kf and the corrected alternating stress.\",\n    B: \"Mode B: q is calculated from the notch root radius r and the Peterson parameter a, then Kf and the corrected alternating stress follow.\",\n    C: \"Mode C: Kf plus a Modified Goodman fatigue safety factor. Requires Sut, a validated Se, the mean stress and a mean stress treatment.\"\n  };\n  var MT_LABEL = { kf: \"Km = Kf (conservative, notch remains elastic)\", nominal: \"Km = 1 (nominal mean stress)\", norton: \"Yield-adjusted Kfm (Norton method)\", user: \"User-defined Km\" };\n  \/* =====================================================================\n     FORMATTING HELPERS\n     ===================================================================== *\/\n  function isNum(v) { return typeof v === \"number\" ? isFinite(v) : false; }\n  function fix(v, d) { var r = Number(v.toFixed(d)); return r === 0 ? 0 : r; }\n  function fmtNum(v, minD, maxD) {\n    if (!isNum(v)) { return \"\u2014\"; }\n    var r = fix(v, maxD);\n    return (r < 0 ? \"\u2212\" : \"\") + Math.abs(r).toLocaleString(\"en-US\", { minimumFractionDigits: minD, maximumFractionDigits: maxD });\n  }\n  function fmtF(v) { return fmtNum(v, 2, 3); }            \/* factors: 2.20, 0.833 *\/\n  function fmtPct(v) { return fmtNum(v, 0, 1) + \"%\"; }\n  function fmtSF(v) { return fmtNum(v, 2, 2); }\n  function toU(mpa, u) { return mpa \/ STRESS[u]; }\n  function fromU(v, u) { return v * STRESS[u]; }\n  function stressDec(v) { var a = Math.abs(v); return a >= 1000 ? 0 : (a >= 100 ? 1 : 2); }\n  function fmtS(mpa, u) { if (!isNum(mpa)) { return \"\u2014\"; } var v = toU(mpa, u); return fmtNum(v, 0, stressDec(v)) + \" \" + u; }\n  function fmtSnum(mpa, u) { var v = toU(mpa, u); return fmtNum(v, 0, stressDec(v)); }\n  function fmtL(mm, u) { if (!isNum(mm)) { return \"\u2014\"; } var v = mm \/ LEN[u]; return fmtNum(v, 0, u === \"in\" ? 5 : 4) + \" \" + (u === \"in\" ? \"in\" : \"mm\"); }\n  \/* =====================================================================\n     ENGINE (pure functions, no DOM). Stresses in MPa, lengths in mm.\n     ===================================================================== *\/\n  \/* Modified Goodman assessment (Mode C) *\/\n  function fatigue(inp, r) {\n    var f = { Se: inp.se, Sut: inp.sut, Sy: inp.sy, notched: inp.seBasis === \"notched\" };\n    \/* Alternating stress used against Se: Kf is not applied again if Se already contains this notch *\/\n    f.KfA = f.notched ? 1 : r.Kf;\n    f.saL = f.KfA * r.saNom;\n    \/* Mean stress concentration factor Km *\/\n    if (inp.meanTreat === \"kf\") { f.Km = r.Kf; f.KmBasis = \"Km = Kf: the full fatigue concentration is applied to the mean stress (conservative while the notch root remains elastic).\"; }\n    else if (inp.meanTreat === \"nominal\") { f.Km = 1; f.KmBasis = \"Km = 1: nominal mean stress used without concentration.\"; }\n    else if (inp.meanTreat === \"user\") { f.Km = inp.km; f.KmBasis = \"User-defined Km = \" + fmtF(inp.km) + \".\"; }\n    else {\n      \/* Norton (Machine Design): yield-adjusted mean stress concentration factor\n         if Kf|smax| <= Sy              -> Kfm = Kf\n         if Kf|smax| >  Sy              -> Kfm = (Sy - Kf*sa)\/|sm|\n         if Kf|smax - smin| > 2Sy       -> Kfm = 0 (local stress fully reversed after yielding) *\/\n      var Kf = r.Kf, Sy = inp.sy;\n      if (Kf * r.peakNom <= Sy) { f.Km = Kf; f.KmBasis = \"Norton method: Kf\u00b7|\u03c3max| = \" + fmtS(Kf * r.peakNom, inp.su) + \" \u2264 Sy, notch stays elastic, so Kfm = Kf.\"; }\n      else if (Kf * r.saNom > Sy) { f.Km = 0; f.KmBasis = \"Norton method: Kf\u00b7|\u03c3max \u2212 \u03c3min| > 2Sy, the notch yields in both directions and the local mean stress is relaxed, so Kfm = 0.\"; }\n      else if (r.smNom === 0) { f.Km = Kf; f.KmBasis = \"Norton method: nominal mean stress is zero, so Kfm has no effect.\"; }\n      else { f.Km = (Sy - Kf * r.saNom) \/ Math.abs(r.smNom); f.KmBasis = \"Norton method: Kf\u00b7|\u03c3max| > Sy, local yielding reduces the mean stress concentration: Kfm = (Sy \u2212 Kf\u00b7\u03c3a)\/|\u03c3m| = \" + fmtF((Sy - Kf * r.saNom) \/ Math.abs(r.smNom)) + \".\"; }\n    }\n    f.smL = f.Km * r.smNom;\n    if (f.smL === 0) { f.smL = 0; }\n    \/* Safety factor *\/\n    f.n = null; f.case = \"\";\n    if (f.saL === 0) {\n      if (f.smL > 0) { f.n = f.Sut \/ f.smL; f.case = \"static\"; }\n      else { f.case = \"none\"; f.why = f.smL < 0 ? \"Static compressive stress only: a fatigue criterion is not applicable.\" : \"No cyclic or mean stress: the safety factor is undefined.\"; }\n    } else if (f.smL < 0) {\n      \/* Conservative treatment of compressive mean stress: beneficial effect neglected, n = Se\/sa *\/\n      f.n = f.Se \/ f.saL; f.case = \"compressive\";\n    } else {\n      \/* Modified Goodman: sa\/Se + sm\/Sut = 1\/n *\/\n      f.n = 1 \/ (f.saL \/ f.Se + f.smL \/ f.Sut); f.case = \"goodman\";\n    }\n    \/* First-cycle yield check (Langer): ny = Sy \/ (Kf*sa + |sm,local|) *\/\n    f.ny = null;\n    if (f.Sy !== null) {\n      var peak = r.Kf * r.saNom + Math.abs(f.smL);\n      if (peak > 0) { f.ny = f.Sy \/ peak; f.peakLanger = peak; }\n    }\n    return f;\n  }\n  function compute(inp) {\n    var r = { inp: inp, warn: [], assume: [] };\n    function W(level, text) { r.warn.push({ level: level, text: text }); }\n    function A(text) { r.assume.push(text); }\n    var u = inp.su;\n    r.Kt = inp.kt;\n    \/* Notch sensitivity *\/\n    if (inp.qSource === \"peterson\") {\n      r.q = 1 \/ (1 + inp.a \/ inp.r);                       \/* Peterson: q = 1\/(1 + a\/r) *\/\n      r.qBasis = \"Peterson: q = 1\/(1 + a\/r) = 1\/(1 + \" + fmtL(inp.a, inp.lu) + \" \/ \" + fmtL(inp.r, inp.lu) + \")\";\n    } else { r.q = inp.q; r.qBasis = \"User-entered notch sensitivity\"; }\n    r.Kf = 1 + r.q * (r.Kt - 1);                           \/* Kf = 1 + q(Kt - 1) *\/\n    r.amp = (r.Kf - 1) * 100;                              \/* amplification (%) *\/\n    \/* Nominal stresses *\/\n    if (inp.lm === \"maxmin\") {\n      r.saNom = (inp.smax - inp.smin) \/ 2;                 \/* sa = (smax - smin)\/2 *\/\n      r.smNom = (inp.smax + inp.smin) \/ 2;                 \/* sm = (smax + smin)\/2 *\/\n      r.hasMean = true; r.smaxNom = inp.smax; r.sminNom = inp.smin;\n    } else {\n      r.saNom = inp.sa; r.hasMean = inp.sm !== null; r.smNom = r.hasMean ? inp.sm : null;\n      if (r.hasMean) { r.smaxNom = r.smNom + r.saNom; r.sminNom = r.smNom - r.saNom; }\n    }\n    if (r.smNom === 0) { r.smNom = 0; }\n    r.saCorr = r.Kf * r.saNom;                             \/* sa,corrected = Kf * sa,nominal *\/\n    r.peakNom = r.hasMean ? Math.max(Math.abs(r.smaxNom), Math.abs(r.sminNom)) : r.saNom;\n    r.peakKt = r.Kt * r.peakNom;\n    if (r.hasMean) { r.R = r.smaxNom !== 0 ? r.sminNom \/ r.smaxNom : null; }\n    \/* ---- Fatigue (Mode C) ---- *\/\n    r.fat = inp.mode === \"C\" ? fatigue(inp, r) : null;\n    \/* ---- Assumptions ---- *\/\n    A(\"Kf = 1 + q(Kt \u2212 1) with 0 \u2264 q \u2264 1, so 1 \u2264 Kf \u2264 Kt. Notch sensitivity: \" + (inp.qSource === \"peterson\" ? \"Peterson model q = 1\/(1 + a\/r), with a supplied by the user from validated data.\" : \"entered directly by the user.\") );\n    A(\"Kt is a linear-elastic factor supplied by the user and based on the same nominal stress definition as the stresses entered.\");\n    A(\"Uniaxial normal stress, constant-amplitude cyclic loading, high-cycle fatigue. Combined or multiaxial stresses need an equivalent-stress or multiaxial method.\");\n    A(\"Corrected alternating stress \u03c3a,corrected = Kf \u00d7 \u03c3a,nominal\" + (inp.lm === \"maxmin\" ? \", with \u03c3a = (\u03c3max \u2212 \u03c3min)\/2 and \u03c3m = (\u03c3max + \u03c3min)\/2.\" : \".\"));\n    if (r.fat) {\n      var f = r.fat;\n      A(\"Modified Goodman criterion for tensile mean stress: \u03c3a\/Se + \u03c3m\/Sut = 1\/n, using the user-supplied validated Se = \" + fmtS(f.Se, u) + \" and Sut = \" + fmtS(f.Sut, u) + \".\");\n      A(f.notched ? \"Se already includes this notch, so Kf is not applied to the alternating stress again (\u03c3a used = nominal \u03c3a).\" : \"Se is the corrected unnotched component endurance limit; Kf is applied to the nominal alternating stress.\");\n      A(\"Mean stress: \" + f.KmBasis);\n      A(\"Compressive local mean stress is treated conservatively: its beneficial effect is neglected (mean stress contribution set to zero, n = Se\/\u03c3a).\");\n      A(\"Results represent an infinite-life (endurance) check at the notch, not a life prediction.\");\n    }\n    \/* ---- Warnings ---- *\/\n    if (r.q === 0) { W(\"i\", \"q = 0: the material is treated as notch-insensitive within the model, so Kf = 1 and the alternating stress is not amplified.\"); }\n    if (r.q === 1) { W(\"i\", \"q = 1: fully notch-sensitive, Kf = Kt. This is the conservative assumption when no validated notch sensitivity data are available.\"); }\n    if (r.Kt === 1) { W(\"i\", \"Kt = 1 means no geometric stress concentration, so Kf = 1.\"); }\n    if (r.Kt > 6) { W(\"w\", \"Kt = \" + fmtF(r.Kt) + \" is unusually high. Verify the geometry chart or FEA basis; very sharp notches may behave more like cracks, where fracture mechanics is more appropriate.\"); }\n    if (inp.qSource === \"peterson\") {\n      if (inp.r < 0.1) { W(\"w\", \"Very small notch radius (\" + fmtL(inp.r, inp.lu) + \"). Empirical notch sensitivity models are least reliable for crack-like notches; consider q = 1 or a fracture mechanics assessment.\"); }\n      if (inp.a === 0) { W(\"i\", \"Peterson parameter a = 0 gives q = 1 (Kf = Kt).\"); }\n      W(\"i\", \"The Peterson parameter a must come from validated data for this material and strength level. It is not supplied by this calculator.\");\n    }\n    if (r.saNom === 0) { W(\"i\", \"Nominal alternating stress is zero, so there is no alternating stress to correct.\"); }\n    if (inp.sy !== null) {\n      if (r.peakKt > inp.sy) {\n        W(\"w\", \"Local yielding likely: the elastic peak stress Kt\u00b7|\u03c3nom,max| = \" + fmtS(r.peakKt, u) + \" exceeds Sy = \" + fmtS(inp.sy, u) + \". The linear-elastic Kt\/Kf approach may not represent local stresses accurately; consider an elastic-plastic notch method (for example Neuber's rule) or finite element analysis.\");\n      } else {\n        W(\"i\", \"No local yielding predicted: the elastic peak stress Kt\u00b7|\u03c3nom,max| = \" + fmtS(r.peakKt, u) + \" is below Sy = \" + fmtS(inp.sy, u) + (r.hasMean ? \".\" : \" (alternating stress only; no mean stress entered).\"));\n      }\n    } else {\n      W(\"i\", \"Enter the yield strength Sy to check whether local yielding at the notch root could invalidate the linear-elastic approach.\");\n    }\n    if (r.fat) {\n      var g = r.fat;\n      if (inp.mat === \"aluminum\") { W(\"w\", \"Aluminum alloy: Se should be a fatigue strength at a stated number of cycles. The safety factor then applies only at that life, not to unlimited life.\"); }\n      if (g.notched) {\n        W(\"i\", \"Notch correction not applied twice: Se was entered as a notched value, so the alternating stress is used without Kf.\");\n        if (g.Km !== 1) { W(\"w\", \"Se already includes the notch effect. When notched-specimen data are used, nominal stresses are normally used throughout; consider Km = 1 so the mean stress is treated consistently.\"); }\n      }\n      if (inp.meanTreat === \"user\") {\n        if (inp.km > r.Kt) { W(\"w\", \"Km = \" + fmtF(inp.km) + \" exceeds Kt = \" + fmtF(r.Kt) + \". A mean stress concentration above the elastic factor is not physically expected; check the value.\"); }\n      }\n      if (inp.meanTreat === \"kf\") {\n        if (inp.sy !== null) { if (r.Kf * r.peakNom > inp.sy) { W(\"w\", \"Kf\u00b7|\u03c3max| exceeds Sy: local yielding will relax the notch mean stress, so Km = Kf is likely to be overly conservative. The yield-adjusted (Norton) treatment may be more representative.\"); } }\n      }\n      if (g.case === \"compressive\") { W(\"i\", \"The local mean stress is compressive. Its beneficial effect is neglected (conservative), so n = Se\/\u03c3a rather than the tensile Goodman equation.\"); }\n      if (g.case === \"static\") { W(\"i\", \"No alternating stress at the notch: n = Sut\/\u03c3m (static check against the ultimate strength).\"); }\n      if (g.n !== null) {\n        if (g.n < 1) { W(\"e\", \"Modified Goodman n = \" + fmtSF(g.n) + \" < 1: fatigue failure is predicted at these stresses under the stated assumptions.\"); }\n        else if (g.n < 1.5) { W(\"w\", \"Modified Goodman n = \" + fmtSF(g.n) + \" gives a small margin. Typical design practice requires a margin that reflects data scatter and load uncertainty.\"); }\n      }\n      if (g.ny !== null) { if (g.ny < 1) { W(\"e\", \"First-cycle yielding check ny = \" + fmtSF(g.ny) + \" < 1: the notch yields on the first load cycle. The linear Goodman result should not be relied on without an elastic-plastic assessment.\"); } }\n      if (g.Sy === null) { W(\"i\", \"No yield strength entered: the first-cycle yield check (Langer) was not performed. The Goodman line alone does not guard against yielding.\"); }\n    }\n    return r;\n  }\n  function finiteResult(r) {\n    var vals = [r.q, r.Kf, r.amp, r.saNom, r.saCorr, r.peakKt];\n    if (r.hasMean) { vals.push(r.smNom); }\n    if (r.fat) { vals.push(r.fat.saL, r.fat.smL, r.fat.Km); if (r.fat.n !== null) { vals.push(r.fat.n); } if (r.fat.ny !== null) { vals.push(r.fat.ny); } }\n    return vals.every(isNum);\n  }\n  \/* =====================================================================\n     UI\n     ===================================================================== *\/\n  function init() {\n    var root = document.getElementById(\"scf-calculator\");\n    if (!root) { return; }\n    if (root.getAttribute(\"data-scf-init\") === \"1\") { return; }\n    root.setAttribute(\"data-scf-init\", \"1\");\n    root.scfEngine = { compute: compute };\n    function $(id) { return root.querySelector(\"#\" + id); }\n    function mk(tag, cls, text) { var n = document.createElement(tag); if (cls) { n.className = cls; } if (text !== undefined) { n.textContent = text; } return n; }\n    function clear(n) { while (n.firstChild) { n.removeChild(n.firstChild); } }\n    function radioVal(name) { var r = root.querySelector('input[name=\"' + name + '\"]:checked'); return r ? r.value : null; }\n    function setRadio(name, v) { var r = root.querySelector('input[name=\"' + name + '\"][value=\"' + v + '\"]'); if (r) { r.checked = true; } }\n    var el = {};\n    [\"form\", \"su\", \"lu\", \"material\", \"mat-info\", \"sut\", \"se\", \"sebasis\", \"sebasis-field\", \"sy\", \"sy-opt\", \"sut-opt\", \"se-opt\", \"kt\", \"qsrc-field\", \"q\", \"q-field\", \"r\", \"r-field\", \"a\", \"a-field\", \"a-hint\", \"q-derived\",\n     \"sa\", \"sa-field\", \"sm\", \"sm-field\", \"sm-opt\", \"smax\", \"smax-field\", \"smin\", \"smin-field\", \"load-derived\", \"mt\", \"mt-field\", \"km\", \"km-field\", \"mode-hint\",\n     \"calc\", \"form-msg\", \"results\", \"res-empty\", \"res-body\", \"stale\", \"r-kf\", \"r-kf-sub\", \"r-sac\", \"r-sac-sub\", \"r-kpis\", \"r-formula\",\n          ].forEach(function (id) {\n      el[id.replace(\/-([a-z])\/g, function (s, c) { return c.toUpperCase(); })] = $(\"scf-\" + id);\n    });\n    var state = { live: false, last: null, timer: null, su: \"MPa\", lu: \"mm\", rz: null, lastW: 0 };\n    var STRESS_INPUTS = [el.sut, el.se, el.sy, el.sa, el.sm, el.smax, el.smin];\n    var LEN_INPUTS = [el.r, el.a];\n    function mode() { return radioVal(\"scf-mode\") || \"A\"; }\n    function qSource() { var m = mode(); return m === \"A\" ? \"direct\" : (m === \"B\" ? \"peterson\" : (radioVal(\"scf-qsrc\") || \"direct\")); }\n    function lm() { return radioVal(\"scf-lm\") || \"direct\"; }\n    \/* ---------- reading numbers ---------- *\/\n    function readNum(input) {\n      var s = String(input.value).trim();\n      if (s === \"\") { return (input.validity ? input.validity.badInput : false) ? NaN : null; }\n      var v = Number(s);\n      return isFinite(v) ? v : NaN;\n    }\n    function nOrNull(input) { var v = readNum(input); return isNum(v) ? v : null; }\n    function setVal(input, v, d) { input.value = (v === null ? true : v === \"\") ? \"\" : String(fix(Number(v), d === undefined ? 6 : d)); }\n    \/* ---------- validation ---------- *\/\n    function setErr(input, msg) {\n      var e = $(input.id + \"-err\");\n      if (e) { e.textContent = msg || \"\"; }\n      if (msg) { input.classList.add(\"scf-invalid\"); input.setAttribute(\"aria-invalid\", \"true\"); }\n      else { input.classList.remove(\"scf-invalid\"); input.removeAttribute(\"aria-invalid\"); }\n      return !msg;\n    }\n    function check(input, active, required, reqMsg, rule) {\n      if (!active) { return setErr(input, \"\"); }\n      var v = readNum(input);\n      if (v === null) { return required ? setErr(input, reqMsg) : setErr(input, \"\"); }\n      if (isNaN(v)) { return setErr(input, \"Enter a valid number.\"); }\n      return setErr(input, rule(v) || \"\");\n    }\n    function su() { return el.su.value; }\n    function capStress(v) { return Math.abs(fromU(v, su())) > MAX_STRESS_MPA ? \"Magnitude exceeds \" + fmtS(MAX_STRESS_MPA, su()) + \". Check the unit.\" : \"\"; }\n    var isC = function () { return mode() === \"C\"; };\n    function vSut() {\n      return check(el.sut, true, isC(), \"Enter the ultimate tensile strength (required in Mode C).\", function (v) {\n        if (v <= 0) { return \"Ultimate tensile strength must be greater than zero.\"; }\n        return capStress(v);\n      });\n    }\n    function vSe() {\n      return check(el.se, true, isC(), \"Enter a validated endurance limit (required in Mode C).\", function (v) {\n        if (v <= 0) { return \"Endurance limit must be greater than zero.\"; }\n        var sut = nOrNull(el.sut);\n        if (sut !== null) { if (sut > 0) { if (v >= sut) { return \"Endurance limit must be lower than the ultimate tensile strength.\"; } } }\n        return capStress(v);\n      });\n    }\n    function vSy() {\n      var need = isC() ? el.mt.value === \"norton\" : false;\n      return check(el.sy, true, need, \"Enter the yield strength (required for the Norton mean stress method).\", function (v) {\n        if (v <= 0) { return \"Yield strength must be greater than zero, or leave it blank.\"; }\n        var sut = nOrNull(el.sut);\n        if (sut !== null) { if (sut > 0) { if (v > sut) { return \"Yield strength cannot exceed the ultimate tensile strength.\"; } } }\n        return capStress(v);\n      });\n    }\n    function vKt() {\n      return check(el.kt, true, true, \"Enter the theoretical stress concentration factor Kt.\", function (v) {\n        if (v < 1) { return \"Kt must be at least 1.\"; }\n        if (v > 20) { return \"Kt above 20 is outside the range of this calculator.\"; }\n        return \"\";\n      });\n    }\n    function vQ() {\n      return check(el.q, qSource() === \"direct\", true, \"Enter the notch sensitivity q (0 to 1).\", function (v) {\n        if (v < 0) { return \"q must be between 0 and 1.\"; }\n        if (v > 1) { return \"q must be between 0 and 1.\"; }\n        return \"\";\n      });\n    }\n    function lenMM(v) { return v * LEN[el.lu.value]; }\n    function vR() {\n      return check(el.r, qSource() === \"peterson\", true, \"Enter the notch root radius r.\", function (v) {\n        if (v <= 0) { return \"Notch radius must be greater than zero.\"; }\n        if (lenMM(v) > 1000) { return \"Notch radius must not exceed 1,000 mm (39.37 in).\"; }\n        return \"\";\n      });\n    }\n    function vA() {\n      return check(el.a, qSource() === \"peterson\", true, \"Enter the Peterson parameter a from validated material data.\", function (v) {\n        if (v < 0) { return \"The Peterson parameter must be zero or positive.\"; }\n        if (lenMM(v) > 100) { return \"Peterson parameter above 100 mm (3.94 in) is not realistic. Check the unit.\"; }\n        return \"\";\n      });\n    }\n    function vSa() {\n      return check(el.sa, lm() === \"direct\", true, \"Enter the nominal alternating stress.\", function (v) {\n        if (v < 0) { return \"Alternating stress is an amplitude and cannot be negative. Enter a compressive mean stress in the mean stress field.\"; }\n        return capStress(v);\n      });\n    }\n    function vSm() {\n      return check(el.sm, lm() === \"direct\", isC(), \"Enter the nominal mean stress (required in Mode C; use 0 for fully reversed loading).\", capStress);\n    }\n    function vSmax() { return check(el.smax, lm() === \"maxmin\", true, \"Enter the maximum nominal stress.\", capStress); }\n    function vSmin() {\n      var ok = check(el.smin, lm() === \"maxmin\", true, \"Enter the minimum nominal stress.\", capStress);\n      if (!ok) { return false; }\n      if (lm() !== \"maxmin\") { return true; }\n      var a = nOrNull(el.smax), b = nOrNull(el.smin);\n      if (a !== null) { if (b !== null) { if (b > a) { return setErr(el.smin, \"The minimum stress cannot be greater than the maximum stress.\"); } } }\n      return true;\n    }\n    function vMt() {\n      if (!isC()) { return setErr(el.mt, \"\"); }\n      return setErr(el.mt, el.mt.value === \"\" ? \"Select how the mean stress concentration is treated.\" : \"\");\n    }\n    function vKm() {\n      return check(el.km, isC() ? el.mt.value === \"user\" : false, true, \"Enter a validated mean stress concentration factor Km.\", function (v) {\n        if (v < 0) { return \"Km must be zero or positive.\"; }\n        if (v > 20) { return \"Km above 20 is outside the range of this calculator.\"; }\n        return \"\";\n      });\n    }\n    var VALIDATORS = {\n      \"scf-sut\": function () { vSut(); vSe(); return vSy(); }, \"scf-se\": vSe, \"scf-sy\": vSy, \"scf-kt\": vKt, \"scf-q\": vQ, \"scf-r\": vR, \"scf-a\": vA,\n      \"scf-sa\": vSa, \"scf-sm\": vSm, \"scf-smax\": function () { vSmax(); return vSmin(); }, \"scf-smin\": vSmin, \"scf-mt\": function () { vMt(); vSy(); return vKm(); }, \"scf-km\": vKm\n    };\n    function validateAll() {\n      var res = [vSut(), vSe(), vSy(), vKt(), vQ(), vR(), vA(), vSa(), vSm(), vSmax(), vSmin(), vMt(), vKm()];\n      return res.every(Boolean);\n    }\n    function clearErrors() {\n      var all = root.querySelectorAll(\".scf-invalid\"), i;\n      for (i = 0; i < all.length; i++) { all[i].classList.remove(\"scf-invalid\"); all[i].removeAttribute(\"aria-invalid\"); }\n      var errs = root.querySelectorAll(\".scf-error\");\n      for (i = 0; i < errs.length; i++) { errs[i].textContent = \"\"; }\n    }\n    function readInput() {\n      var u = su(), lu = el.lu.value, sy = nOrNull(el.sy), sut = nOrNull(el.sut), se = nOrNull(el.se), sm = nOrNull(el.sm);\n      return {\n        mode: mode(), su: u, lu: lu, mat: el.material.value, qSource: qSource(), lm: lm(),\n        kt: readNum(el.kt), q: nOrNull(el.q), r: nOrNull(el.r) === null ? null : lenMM(nOrNull(el.r)), a: nOrNull(el.a) === null ? null : lenMM(nOrNull(el.a)),\n        sa: nOrNull(el.sa) === null ? null : fromU(nOrNull(el.sa), u), sm: sm === null ? null : fromU(sm, u),\n        smax: nOrNull(el.smax) === null ? null : fromU(nOrNull(el.smax), u), smin: nOrNull(el.smin) === null ? null : fromU(nOrNull(el.smin), u),\n        sut: sut === null ? null : fromU(sut, u), se: se === null ? null : fromU(se, u), sy: sy === null ? null : fromU(sy, u),\n        seBasis: el.sebasis.value, meanTreat: el.mt.value, km: nOrNull(el.km)\n      };\n    }\n    \/* ---------- dependent UI ---------- *\/\n    function updateModeUI() {\n      var m = mode(), qs = qSource(), c = m === \"C\";\n      el.modeHint.textContent = MODE_HINT[m];\n      el.qsrcField.hidden = !c;\n      el.qField.hidden = qs !== \"direct\";\n      el.rField.hidden = qs !== \"peterson\"; el.aField.hidden = qs !== \"peterson\"; el.aHint.hidden = qs !== \"peterson\";\n      el.sebasisField.hidden = !c; el.mtField.hidden = !c;\n      el.kmField.hidden = !(c ? el.mt.value === \"user\" : false);\n      el.sutOpt.textContent = c ? \"(required)\" : \"(used in Mode C)\";\n      el.seOpt.textContent = c ? \"(required)\" : \"(used in Mode C)\";\n      el.syOpt.textContent = (c ? el.mt.value === \"norton\" : false) ? \"(required for Norton method)\" : \"(optional)\";\n      el.smOpt.textContent = c ? \"(required)\" : \"(optional)\";\n      var d = lm() === \"direct\";\n      el.saField.hidden = !d; el.smField.hidden = !d; el.smaxField.hidden = d; el.sminField.hidden = d;\n      updateDerived();\n    }\n    function updateMaterialUI() {\n      clear(el.matInfo);\n      var p = mk(\"p\"); p.appendChild(mk(\"strong\", \"\", MAT_NAME[el.material.value] + \". \")); p.appendChild(document.createTextNode(MAT_INFO[el.material.value].replace(\/^[^.]*\\.\\s*\/, \"\")));\n      el.matInfo.appendChild(p);\n    }\n    function updateUnitLabels() {\n      var a = root.querySelectorAll(\".scf-su-l\"), b = root.querySelectorAll(\".scf-lu-l\"), i;\n      for (i = 0; i < a.length; i++) { a[i].textContent = su(); }\n      for (i = 0; i < b.length; i++) { b[i].textContent = el.lu.value === \"in\" ? \"in\" : \"mm\"; }\n    }\n    \/* Live previews of derived q and nominal stresses *\/\n    function updateDerived() {\n      var u = su(), txt = \"\";\n      if (qSource() === \"peterson\") {\n        var r = nOrNull(el.r), a = nOrNull(el.a);\n        if (r !== null) { if (a !== null) { if (r > 0) { if (a >= 0) { txt = \"Calculated q = 1\/(1 + a\/r) = \" + fmtF(1 \/ (1 + a \/ r)); } } } }\n      }\n      el.qDerived.textContent = txt;\n      var t2 = \"\";\n      if (lm() === \"maxmin\") {\n        var mx = nOrNull(el.smax), mn = nOrNull(el.smin);\n        if (mx !== null) { if (mn !== null) { if (mn <= mx) {\n          t2 = \"Nominal \u03c3a = (\u03c3max \u2212 \u03c3min)\/2 = \" + fmtNum((mx - mn) \/ 2, 0, stressDec((mx - mn) \/ 2)) + \" \" + u + \" \u00b7 Nominal \u03c3m = (\u03c3max + \u03c3min)\/2 = \" + fmtNum((mx + mn) \/ 2, 0, stressDec((mx + mn) \/ 2)) + \" \" + u + (mx !== 0 ? \" \u00b7 R = \" + fmtNum(mn \/ mx, 2, 3) : \"\");\n        } } }\n      }\n      el.loadDerived.textContent = t2;\n    }\n    \/* Unit switching converts values already entered *\/\n    function onStressUnit() {\n      var nu = su(), ou = state.su;\n      if (nu === ou) { return; }\n      STRESS_INPUTS.forEach(function (i) { var v = readNum(i); if (isNum(v)) { var mpa = fromU(v, ou), nv = toU(mpa, nu); setVal(i, nv, nu === \"Pa\" ? 0 : 4); } });\n      state.su = nu; updateUnitLabels();\n    }\n    function onLenUnit() {\n      var nu = el.lu.value, ou = state.lu;\n      if (nu === ou) { return; }\n      LEN_INPUTS.forEach(function (i) { var v = readNum(i); if (isNum(v)) { setVal(i, v * LEN[ou] \/ LEN[nu], 6); } });\n      state.lu = nu; updateUnitLabels();\n    }\n    \/* =====================================================================\n       RENDER\n       ===================================================================== *\/\n    function kpi(label, value, sub, na) {\n      var c = mk(\"div\", \"scf-kpi\");\n      c.appendChild(mk(\"div\", \"scf-kpi-label\", label));\n      c.appendChild(mk(\"div\", \"scf-kpi-value\" + (na ? \" scf-na\" : \"\"), value));\n      if (sub) { c.appendChild(mk(\"div\", \"scf-kpi-sub\", sub)); }\n      return c;\n    }\n    function line(parent, text) { parent.appendChild(mk(\"div\", \"\", text)); }\n    function render(r, scroll) {\n      var inp = r.inp, u = inp.su;\n      root.classList.remove(\"scf-is-stale\"); el.stale.hidden = true;\n      el.results.hidden = false; el.resEmpty.hidden = true; el.resBody.hidden = false;\n      el.rKf.textContent = fmtF(r.Kf);\n      el.rKfSub.textContent = \"1 + q(Kt \u2212 1) = 1 + \" + fmtF(r.q) + \" \u00d7 (\" + fmtF(r.Kt) + \" \u2212 1)\";\n      el.rSac.textContent = fmtS(r.saCorr, u);\n      el.rSacSub.textContent = \"Kf \u00d7 \u03c3a,nominal = \" + fmtF(r.Kf) + \" \u00d7 \" + fmtS(r.saNom, u);\n      clear(el.rKpis);\n      el.rKpis.appendChild(kpi(\"Theoretical factor Kt\", fmtF(r.Kt), \"User input (elastic)\"));\n      el.rKpis.appendChild(kpi(\"Notch sensitivity q\", fmtF(r.q), inp.qSource === \"peterson\" ? \"Peterson, a\/r = \" + fmtNum(inp.a \/ inp.r, 2, 4) : \"User input\"));\n      el.rKpis.appendChild(kpi(\"Stress amplification\", fmtPct(r.amp), \"(Kf \u2212 1) \u00d7 100\"));\n      el.rKpis.appendChild(kpi(\"Nominal alternating \u03c3a\", fmtS(r.saNom, u), inp.lm === \"maxmin\" ? \"(\u03c3max \u2212 \u03c3min)\/2\" : \"User input\"));\n      el.rKpis.appendChild(kpi(\"Nominal mean \u03c3m\", r.hasMean ? fmtS(r.smNom, u) : \"Not entered\", r.hasMean ? (inp.lm === \"maxmin\" ? \"(\u03c3max + \u03c3min)\/2\" : \"User input\") : \"Optional in Modes A and B\", !r.hasMean));\n      el.rKpis.appendChild(kpi(\"Elastic peak Kt\u00b7|\u03c3max|\", fmtS(r.peakKt, u), r.hasMean ? \"For the local yielding check\" + (r.R !== null ? \" \u00b7 R = \" + fmtNum(r.R, 2, 3) : \"\") : \"Alternating stress only\"));\n      clear(el.rFormula);\n      line(el.rFormula, (inp.qSource === \"peterson\" ? \"q = 1\/(1 + a\/r) = 1\/(1 + \" + fmtL(inp.a, inp.lu) + \" \/ \" + fmtL(inp.r, inp.lu) + \") = \" + fmtF(r.q) : \"q = \" + fmtF(r.q) + \" (entered)\"));\n      line(el.rFormula, \"Kf = 1 + q(Kt \u2212 1) = 1 + \" + fmtF(r.q) + \" \u00d7 (\" + fmtF(r.Kt) + \" \u2212 1) = \" + fmtF(r.Kf));\n      line(el.rFormula, \"\u03c3a,corrected = Kf \u00d7 \u03c3a,nominal = \" + fmtF(r.Kf) + \" \u00d7 \" + fmtS(r.saNom, u) + \" = \" + fmtS(r.saCorr, u));\n      line(el.rFormula, \"Amplification = (Kf \u2212 1) \u00d7 100 = \" + fmtPct(r.amp));\n      \/* Mode C: Modified Goodman results shown in the same panel *\/\n      if (r.fat) {\n        var f = r.fat;\n        el.rKpis.appendChild(kpi(\"Mean factor Km\", fmtF(f.Km), MT_LABEL[inp.meanTreat]));\n        el.rKpis.appendChild(kpi(\"Corrected mean \u03c3m\", fmtS(f.smL, u), \"Km \u00d7 \u03c3m,nominal\" + (f.smL < 0 ? \" (compressive)\" : \"\")));\n        el.rKpis.appendChild(kpi(\"Goodman safety factor n\", f.n === null ? \"Not applicable\" : fmtSF(f.n), f.n === null ? f.why : (f.n >= 1 ? \"n \u2265 1, safe under stated assumptions\" : \"n < 1, fatigue failure predicted\"), f.n === null));\n        line(el.rFormula, \"\u03c3m,corrected = Km \u00d7 \u03c3m,nominal = \" + fmtF(f.Km) + \" \u00d7 \" + fmtS(r.smNom, u) + \" = \" + fmtS(f.smL, u));\n        if (f.case === \"goodman\") { line(el.rFormula, \"1\/n = \u03c3a\/Se + \u03c3m\/Sut = \" + fmtSnum(f.saL, u) + \"\/\" + fmtSnum(f.Se, u) + \" + \" + fmtSnum(f.smL, u) + \"\/\" + fmtSnum(f.Sut, u) + \" = \" + fmtNum(1 \/ f.n, 3, 4) + \"  \u2192  n = \" + fmtSF(f.n)); }\n        else if (f.case === \"compressive\") { line(el.rFormula, \"Compressive mean stress neglected (conservative): n = Se\/\u03c3a = \" + fmtSnum(f.Se, u) + \"\/\" + fmtSnum(f.saL, u) + \" = \" + fmtSF(f.n)); }\n        else if (f.case === \"static\") { line(el.rFormula, \"n = Sut\/\u03c3m = \" + fmtSnum(f.Sut, u) + \"\/\" + fmtSnum(f.smL, u) + \" = \" + fmtSF(f.n)); }\n        if (f.notched) { line(el.rFormula, \"Se already includes this notch, so Kf is not applied again: \u03c3a used = \" + fmtS(f.saL, u)); }\n      }\n      if (scroll) { focusResults(); }\n    }\n    function focusResults() {\n      try { el.results.focus({ preventScroll: true }); } catch (e) { \/* ignore *\/ }\n      var rect = el.results.getBoundingClientRect(), vh = window.innerHeight || document.documentElement.clientHeight;\n      if (rect.top < 0 ? true : rect.top > vh * 0.6) { if (el.results.scrollIntoView) { el.results.scrollIntoView({ behavior: \"smooth\", block: \"start\" }); } }\n    }\n    function msg(t, ok) { el.formMsg.textContent = t; el.formMsg.className = \"scf-form-msg\" + (ok ? \" scf-ok\" : \"\"); }\n    \/* =====================================================================\n       CALCULATE \/ LIVE UPDATE\n       ===================================================================== *\/\n    function run(fromButton) {\n      msg(\"\");\n      updateDerived();\n      if (!validateAll()) {\n        if (fromButton) {\n          msg(\"Please correct the highlighted fields.\");\n          var first = root.querySelector(\".scf-invalid\");\n          if (first) { first.focus(); }\n        }\n        if (state.last) { root.classList.add(\"scf-is-stale\"); el.stale.hidden = false; }\n        return;\n      }\n      var r = compute(readInput());\n      if (!finiteResult(r)) {\n        msg(\"The inputs produce a non-finite result. Check the values and units.\");\n        if (state.last) { root.classList.add(\"scf-is-stale\"); el.stale.hidden = false; }\n        return;\n      }\n      state.last = r; state.live = true;\n      render(r, fromButton);\n    }\n    function schedule() { clearTimeout(state.timer); state.timer = setTimeout(function () { if (state.live) { run(false); } }, 200); }\n    function resetAll() {\n      clearTimeout(state.timer);\n      setRadio(\"scf-mode\", \"A\"); setRadio(\"scf-qsrc\", \"direct\"); setRadio(\"scf-lm\", \"direct\");\n      el.su.value = \"MPa\"; el.lu.value = \"mm\"; state.su = \"MPa\"; state.lu = \"mm\";\n      el.material.value = \"carbon\"; el.sebasis.value = \"unnotched\"; el.mt.value = \"\";\n      [el.sut, el.se, el.sy, el.kt, el.q, el.r, el.a, el.sa, el.sm, el.smax, el.smin, el.km].forEach(function (i) { i.value = \"\"; });\n      clearErrors();\n      state.live = false; state.last = null;\n      root.classList.remove(\"scf-is-stale\"); el.stale.hidden = true;\n      el.results.hidden = true; el.resEmpty.hidden = false; el.resBody.hidden = true;\n      msg(\"\");\n      updateUnitLabels(); updateMaterialUI(); updateModeUI();\n    }\n    \/* ---------- events ---------- *\/\n    function onFieldEvent(e) {\n      var t = e.target;\n      if (!t) { return; }\n      if (t.id === \"scf-su\") { onStressUnit(); }\n      if (t.id === \"scf-lu\") { onLenUnit(); }\n      if (t.id === \"scf-material\") { updateMaterialUI(); }\n      if (t.name === \"scf-mode\" ? true : (t.name === \"scf-qsrc\" ? true : (t.name === \"scf-lm\" ? true : t.id === \"scf-mt\"))) {\n        updateModeUI();\n        if (state.live) { validateAll(); } else { clearErrors(); }\n      }\n      if (VALIDATORS[t.id]) { VALIDATORS[t.id](); }\n      updateDerived();\n      schedule();\n    }\n    function isChoice(t) { return !t ? false : (t.tagName === \"SELECT\" ? true : (t.type === \"radio\" ? true : t.type === \"checkbox\")); }\n    el.form.addEventListener(\"input\", function (e) { if (!isChoice(e.target)) { onFieldEvent(e); } });\n    el.form.addEventListener(\"change\", function (e) { if (isChoice(e.target)) { onFieldEvent(e); } });\n    el.form.addEventListener(\"keydown\", function (e) { if (e.key === \"Enter\" ? (e.target ? e.target.tagName === \"INPUT\" : false) : false) { e.preventDefault(); run(true); } });\n    el.calc.addEventListener(\"click\", function () { run(true); });\n    resetAll();\n  }\n  if (document.getElementById(\"scf-calculator\")) { init(); }\n  else if (document.readyState === \"loading\") { document.addEventListener(\"DOMContentLoaded\", init); }\n  else { init(); }\n})();\n<\/script>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The Stress Concentration Fatigue Correction Calculator is a practical engineering tool designed to evaluate how geometric discontinuities affect fatigue performance under cyclic loading. Using established&#8230;<\/p>","protected":false},"author":2,"featured_media":24967,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pmpro_default_level":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[8647],"tags":[8766,8756,8768,8765,8767],"class_list":["post-24966","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-materials-science-and-properties","tag-fatigue-correction-calculator","tag-fatigue-safety-factor","tag-mechanical-fatigue-analysis","tag-notch-sensitivity","tag-stress-concentration-factor","pmpro-has-access"],"acf":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/www.mechstream.com\/wp-content\/uploads\/2026\/10\/Stress-Concentration-Fatigue-Correction-Calculator.png","_links":{"self":[{"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/posts\/24966","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/comments?post=24966"}],"version-history":[{"count":1,"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/posts\/24966\/revisions"}],"predecessor-version":[{"id":24968,"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/posts\/24966\/revisions\/24968"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/media\/24967"}],"wp:attachment":[{"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/media?parent=24966"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/categories?post=24966"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mechstream.com\/ar\/wp-json\/wp\/v2\/tags?post=24966"}],"curies":[{"name":"\u0648\u0648\u0631\u062f\u0628\u0631\u064a\u0633","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}