Forgot password?
LoadMark
SEL Thermal Calculator
🔍 Field
Saved

Jobs

Saved transformer records

Online · Synced
No saved jobs yet. Start a new job above.

Load Loss Calculator

MVA1 / MVA2 / MVA3 are rating fields. ONAN and ONAF are cooling-stage names. This section shows current, CT ratios, efficiency, and voltage regulation.

Rating Fields vs Cooling Stages MVA1, MVA2, and MVA3 are the user-entered rating buckets. The label beside them, such as ONAN 90 or ONAF 120, is the cooling-stage/rating name. Enhanced rows are separate calculated ratings, not new no-load-loss inputs.
⚠ Engineering Warnings
  • No-load loss has not been entered.
  • No load-loss values have been entered.
Voltage Connection Assimilation

Example: 138000D - 34500/19919. For Wye, enter either line-line or line-neutral and the missing value is calculated using √3. Delta uses line-line voltage.

Calculated: HV L-L — V — LV L-L — V / L-N — V
DETC Settings

Configure the de-energized tap changer side, percent per step, tap range, and selected tap. The table calculates effective line-line voltage and transformer ratio for each tap.

PositionTapPercentMultiplierHV L-L (V)LV L-L (V)Ratio
Selected DETC tap: 0 at 0.000%. Effective ratio —
Tap Changer Load Flow ▼ Show
Transformer Inputs
Given no-load/core loss
Used only if all six rating losses are blank
Used for efficiency and voltage regulation
Nameplate transformer impedance
Base and Enhanced MVA Load-Loss Inputs
How scaling works Enter one known load loss or fill any/all six. Blank load-loss rows are calculated from the first entered loss using MVA² scaling.
StageMVALoad Loss (kW) — Optional
ONAN Base
ONAN Enhanced
ONAF Base
ONAF Enhanced
ONAF Base
ONAF Enhanced
Main Results Table
StageSourceConfidenceMVA Nominal HV Current (A)Nominal LV Current (A) Load-Loss RatioTotal Load Loss (kW) Incl. No-Load (kW)Efficiency (%)Voltage Reg. (%)

Formula Reference

HV / LV Current
I = MVA × 1000 / (√3 × kV)
Three-phase line current from rated MVA and line-to-line voltage.
Efficiency
η = (MVA×1000×PF) / (MVA×1000×PF + Load_loss + No-load_loss) × 100
Output power divided by total input power (output + all losses).
Voltage Regulation
Reg = R%×PF ± X%×sin(acos(PF)), where R%=LL/(MVA×1000)×100, X%=√(Z%²−R%²)
+ for lagging PF, − for leading PF. Requires %Z input.
Nominal vs Tap-Adjusted Current
MVA FieldStageMVA Nominal HV (A)Tap HV (A)HV Δ (A) Nominal LV (A)Tap LV (A)LV Δ (A)
CT Ratio Check
CTRatioPrimary Phase A (A) Secondary Phase A (A)Secondary Phase B (A)Secondary Phase C (A)

Selected current: — A per phase. CT secondary current = primary phase current × CT secondary rating ÷ CT primary rating.

Efficiency Table
MVA FieldStageOutput (kW)Total Losses (kW)Efficiency (%)
Voltage Regulation Table
MVA FieldStageZ (%)R (%)X (%)Voltage Reg. (%)
Loss Summary by Stage

Thermal Model Calculations

Temperature rise over oil for ONAN, ONAF1, and ONAF2 stages

Ambient Temperature Correction
IEEE C57.91 Reference Ambient IEEE C57.91 reference ambient is 30°C. Adjust to site conditions. Adjusted hotspot temperatures add the site ambient to all rise values.
IEEE C57.91 reference is 30°C
SEL Guide Thermal-Constant Inputs
55 or 65 rated rise
Default 5 min = 0.083 hr
Shared Losses (from Section 01)
No-Load
— kW
MVA1 (ONAN)
— kW
MVA1E
— kW
MVA2 (ONAF1)
— kW
MVA2E
— kW
MVA3 (ONAF2)
— kW
MVA3E
— kW
ONAN
ONANStage 1 — natural oil, natural air
HV Hotspot over Oil
— °C
LV Hotspot over Oil
— °C
Adj. Top Oil Temp
— °C
Adj. HS Temp (HV)
— °C
Adj. HS Temp (LV)
— °C
ONAF1
ONAF1Stage 2 — first forced-air cooling stage
HV Hotspot over Oil
— °C
LV Hotspot over Oil
— °C
Adj. Top Oil Temp
— °C
Adj. HS Temp (HV)
— °C
Adj. HS Temp (LV)
— °C
ONAF2
ONAF2Stage 3 — second forced-air cooling stage
HV Hotspot over Oil
— °C
LV Hotspot over Oil
— °C
Adj. Top Oil Temp
— °C
Adj. HS Temp (HV)
— °C
Adj. HS Temp (LV)
— °C

T1RATL is load loss divided by no-load loss. T1OTR is the oil thermal time constant: thermal capacity × T1THOR ÷ total watt loss.

SEL Constants Summary
StageCoolingC (thermal cap.)Total Watt Loss (W) T1THORT1THGRT1RATLT1OTR (hr)T1EXPNT1EXPM

Final SEL Settings Summary

Copy/paste-ready relay settings — values update live as inputs change

SEL FieldStageValueUnitsFormula / MeaningCopy
Alarm & Trip Setpoint Recommendations
Engineering Basis These are starting recommendations per IEEE C57.91 and SEL-387/T35 guidance. Adjust based on site ambient history, load profile, and coordination with other protective devices.
SettingStageRecommended Value (°C)IEEE BasisSEL FieldCopy

Final Engineering Review Summary

A one-page review of the selected assumptions, source confidence, warnings, and main outputs.

Summary Metrics
Selected Rating
90.000
MVA
Total Load Loss
kW
Total Loss incl. No-Load
kW
Efficiency
%
Nominal HV Current
A
Tap HV Current
A
Nominal LV Current
A
Tap LV Current
A
Voltage Regulation
%
KVAR Scenario Study

"If" power triangle from collected data. Pick a transformer rating, enter the MW you want to study, and adjust power factor. The triangle shows how apparent power and kVAR grow even when real MW looks reasonable.

"Hidden gem: transformer efficiency tells you how much heat loss you have, but kVAR tells you how much magnetic/reactive burden is riding on the transformer. MW does the work; kVAR builds the field; MVA is what the transformer must carry."
REACTIVE POWER TRIANGLE
ONAN —
PF angle °
Apparent Power (S)
— MVA
Real Power (P)
— MW
Reactive Power (Q)
— MVAR
PF Angle
— °
Apparent Power
MVA
Reactive Power
MVAR
Power Factor
Rating Used (%)
%
MVA Reserve
MVA
Scenario Load Loss
kW
Monetization Readiness Checks
Needs data
Validation
Enter no-load loss, at least one load loss, and both HV/LV voltages before relying on the results.
Needs data
One-load-loss scaling
Enter one known load-loss value to calculate the remaining MVA load losses.
Nominal
Current comparison
Selected DETC tap is nominal or has no measurable current difference from nameplate voltage.
Beta ready
Professional packaging
Autosave, import/export, print, source-confidence labels, engineering warnings, and review notes are present.
Source of Value / Confidence
RatingSourceConfidenceEngineer Note
⚠ Engineering Warnings
  • No-load loss has not been entered.
  • No load-loss values have been entered.

Aging & Loss of Life (IEEE C57.91)

Calculates hotspot temperature, aging acceleration factor (FAA), and percent loss of insulation life per IEEE C57.91. Normal insulation life = 180,000 hr.

IEEE C57.91 Aging Model FAA = exp(15000/383 − 15000/(HS + 273)). Loss of Life (%) = (FAA × hours × days) / 180,000 × 100. Select the thermal stage to pull T1EXPN, T1EXPM, and T1THGR constants.
Hotspot Temperature
°C
Aging Accel. Factor (FAA)
× normal aging
Loss of Life
%
Equiv. Normal Aging Hours
hr

IEEE C57.91 Equations Used

HS Temp
HS = Ambient + T1THOR × Load^(2×T1EXPN) + T1THGR × Load^(2×T1EXPM)
FAA
FAA = exp(15000/383 − 15000/(HS + 273))
Loss of Life
LoL% = (FAA × hours/day × days) / 180,000 × 100

Multi-Transformer Comparison

Compare the current transformer (A) against a second transformer (B) entered manually. Transformer A values are pulled from the current calculator inputs.

Parameter Transformer A (Current) Transformer B (Manual) Difference (B − A)
// ============================================================ // SUPABASE AUTH GATE (Phase 2) // ============================================================ async function _lmLogin() { const email = document.getElementById('lm-email').value.trim(); const pwd = document.getElementById('lm-pass').value; document.getElementById('lm-err').textContent = 'Signing in...'; // Primary auth — local credentials always work const _LM_EMAIL = 'thomaspchance@yahoo.com'; const _LM_PASS = 'IAMAtech12'; if (email.toLowerCase().trim() === _LM_EMAIL && pwd === _LM_PASS) { sessionStorage.setItem('lm_auth_v1','1'); document.getElementById('lm-gate').classList.add('hidden'); document.getElementById('lm-err').textContent = ''; try { _showToast('Welcome back — LoadMark ready', 'success'); } catch(e) {} try { _playSound('chime'); } catch(e) {} return; } // Full Supabase auth for other users try { const { data, error } = await _supa.auth.signInWithPassword({ email, password: pwd }); if (error) { document.getElementById('lm-err').textContent = error.message; } else { _currentUser = data.user; document.getElementById('lm-gate').classList.add('hidden'); document.getElementById('lm-err').textContent = ''; _showToast('Welcome back — LoadMark ready', 'success'); _playSound('chime'); _loadCloudJobs(); } } catch(e) { document.getElementById('lm-err').textContent = 'Connection error. Try again.'; } } async function _lmForgot() { const email = document.getElementById('lm-email').value.trim(); if (!email) { document.getElementById('lm-err').textContent = 'Enter your email first.'; return; } const { error } = await _supa.auth.resetPasswordForEmail(email); document.getElementById('lm-err').textContent = error ? error.message : 'Password reset email sent.'; } async function _lmSignOut() { await _supa.auth.signOut(); _currentUser = null; location.reload(); } // Add Enter key support for gate inputs document.addEventListener('DOMContentLoaded', function() { const lmPass = document.getElementById('lm-pass'); const lmEmail = document.getElementById('lm-email'); if (lmPass) lmPass.addEventListener('keydown', function(e) { if (e.key === 'Enter') _lmLogin(); }); if (lmEmail) lmEmail.addEventListener('keydown', function(e) { if (e.key === 'Enter') lmPass && lmPass.focus(); }); }); // Check session on load — if already logged in, hide gate (async function _checkSession() { // Check local session first if (sessionStorage.getItem('lm_auth_v1') === '1') { const gate = document.getElementById('lm-gate'); if (gate) gate.classList.add('hidden'); return; } // Then check Supabase session try { const { data } = await _supa.auth.getSession(); if (data?.session?.user) { _currentUser = data.session.user; const gate = document.getElementById('lm-gate'); if (gate) gate.classList.add('hidden'); _loadCloudJobs(); } } catch(e) {} })(); // ============================================================ // TOAST NOTIFICATION SYSTEM (Change 3) // ============================================================ function _showToast(msg, type='info', duration=3000) { const container = document.getElementById('toast-container'); if (!container) return; const t = document.createElement('div'); t.className = `toast ${type}`; t.textContent = msg; container.appendChild(t); requestAnimationFrame(() => { requestAnimationFrame(() => t.classList.add('show')); }); setTimeout(() => { t.classList.remove('show'); setTimeout(() => t.remove(), 300); }, duration); } // ============================================================ // SOUND SYSTEM (Change 4) // ============================================================ const _sounds = { enabled: true, volume: 0.5, individual: { chime: true, click: true, upload: true, error: true } }; function _playSound(type) { try { if (!_sounds.enabled || !_sounds.individual[type]) return; const ctx = new (window.AudioContext || window.webkitAudioContext)(); const g = ctx.createGain(); g.gain.value = _sounds.volume; g.connect(ctx.destination); const o = ctx.createOscillator(); o.connect(g); if (type === 'chime') { o.type = 'sine'; o.frequency.setValueAtTime(880, ctx.currentTime); o.frequency.setValueAtTime(1108, ctx.currentTime + 0.15); g.gain.setValueAtTime(0.5, ctx.currentTime); g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.6); o.start(ctx.currentTime); o.stop(ctx.currentTime + 0.6); } else if (type === 'click') { o.type = 'square'; o.frequency.setValueAtTime(200, ctx.currentTime); g.gain.setValueAtTime(0.3, ctx.currentTime); g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.08); o.start(ctx.currentTime); o.stop(ctx.currentTime + 0.08); } else if (type === 'upload') { o.type = 'sine'; o.frequency.setValueAtTime(660, ctx.currentTime); o.frequency.setValueAtTime(880, ctx.currentTime + 0.2); g.gain.setValueAtTime(0.4, ctx.currentTime); g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.5); o.start(ctx.currentTime); o.stop(ctx.currentTime + 0.5); } else if (type === 'error') { o.type = 'sawtooth'; o.frequency.setValueAtTime(220, ctx.currentTime); g.gain.setValueAtTime(0.3, ctx.currentTime); g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.3); o.start(ctx.currentTime); o.stop(ctx.currentTime + 0.3); } } catch(e) {} // fail silently } function _toggleSound() { _sounds.enabled = !_sounds.enabled; const btn = document.getElementById('sound-toggle-btn'); if (btn) btn.textContent = _sounds.enabled ? '🔔' : '🔕'; _showToast(_sounds.enabled ? 'Sound on' : 'Sound off', 'info', 1500); } // ============================================================ // GLOBAL ERROR HANDLER (Change 5) // ============================================================ window.onerror = function(msg, src, line, col, err) { _showToast('App error — refresh if needed', 'error'); console.error('Global error:', msg, err); return true; }; window.onunhandledrejection = function(e) { console.error('Unhandled promise:', e.reason); }; // ============================================================ // CLOUD JOB DASHBOARD (Change 2) // ============================================================ let _jobs = []; let _activeJobId = null; async function _loadCloudJobs() { if (!_currentUser) return; try { _updateSyncStatus('syncing'); const { data, error } = await _supa .from('transformer_jobs') .select('*') .eq('user_id', _currentUser.id) .order('updated_at', { ascending: false }); if (!error && data) { _jobs = data; _renderJobs(data); _updateSyncStatus('online'); } else { _updateSyncStatus('error'); } } catch(e) { _updateSyncStatus('error'); } } function _renderJobs(jobs) { const el = document.getElementById('jobs-list'); if (!el) return; if (!jobs || jobs.length === 0) { el.innerHTML = '
No saved jobs yet. Start a new job above.
'; return; } el.innerHTML = jobs.map(j => { const d = j.job_data || {}; const date = new Date(j.updated_at).toLocaleDateString(); const safeId = j.id.replace(/'/g, "\'"); return `
${j.job_name || 'Untitled Job'}
Updated ${date} · ${d.txName || ''} ${d.mva0 ? d.mva0+' MVA' : (d.mva1 ? d.mva1+' MVA' : '')}
`; }).join(''); } async function _newJob() { _activeJobId = null; if (typeof _doReset === 'function') _doReset(); else if (typeof resetAll === 'function') { const modal = document.getElementById('resetModal'); if (modal) modal.style.display = 'flex'; } _showToast('New job started', 'info'); } async function _openJob(id) { const job = _jobs.find(j => j.id === id); if (!job) return; _activeJobId = id; try { const d = job.job_data; if (d) { Object.keys(d).forEach(k => { const el = document.getElementById(k); if (el && d[k] !== undefined) el.value = d[k]; }); if (typeof calcVoltages === 'function') calcVoltages(); if (typeof calcDETC === 'function') calcDETC(); if (typeof recalcAll === 'function') recalcAll(); if (typeof recalcThermal === 'function') recalcThermal(); if (typeof calcKvar === 'function') calcKvar(); } _showToast('Job loaded: ' + job.job_name, 'success'); _playSound('chime'); } catch(e) { _showToast('Error loading job', 'error'); } } async function _saveJobToCloud() { if (!_currentUser) { _showToast('Sign in to save to cloud', 'warning'); return; } _updateSyncStatus('syncing'); try { const jobName = document.getElementById('txName')?.value || document.getElementById('jobNameInput')?.value || 'Untitled Job'; const fields = ['hvConn','hvLL','hvLN','lvConn','lvLL','lvLN', 'detcWinding','detcStep','detcAbove','detcBelow','detcSelected', 'noLoadLoss','fallbackLL','fallbackStage','llBasis','pf','pfDir','pctZ', 'mva0','mva1','mva2','mva3','mva4','mva5', 'll0','ll1','ll2','ll3','ll4','ll5', 'thwr','t1thsMin','coreCoilWt','tankFitWt','oilVol', 'cool1','cool2','cool3', 'tor0','hvWR0','lvWR0','hvHS0','lvHS0', 'tor1','hvWR1','lvWR1','hvHS1','lvHS1', 'tor2','hvWR2','lvWR2','hvHS2','lvHS2', 'ambientTemp','kvarRating','scenMW','scenPF','scenPFDir']; const jobData = {}; fields.forEach(id => { const el = document.getElementById(id); if (el) jobData[id] = el.value; }); if (_activeJobId) { await _supa.from('transformer_jobs').update({ job_name: jobName, job_data: jobData, updated_at: new Date().toISOString() }).eq('id', _activeJobId); } else { const { data } = await _supa.from('transformer_jobs').insert({ user_id: _currentUser.id, job_name: jobName, job_data: jobData }).select().single(); if (data) _activeJobId = data.id; } _updateSyncStatus('online'); _showToast('✓ Data saved to cloud', 'success'); _playSound('chime'); // Update last-saved line const lst = document.getElementById('last-saved-time'); const lsl = document.getElementById('last-saved-loc'); if (lst) lst.textContent = new Date().toLocaleTimeString(); if (lsl) lsl.textContent = 'Cloud ✓'; _loadCloudJobs(); } catch(e) { _updateSyncStatus('error'); _showToast('Save failed — retrying...', 'error'); _playSound('error'); _queueOfflineSave(); } } async function _deleteJob(id) { if (!_currentUser) return; try { await _supa.from('transformer_jobs').delete().eq('id', id); _showToast('Job deleted', 'info'); _loadCloudJobs(); } catch(e) { _showToast('Delete failed', 'error'); } } function _updateSyncStatus(status) { const bar = document.getElementById('sync-status-bar'); const label = document.getElementById('sync-label'); if (!bar || !label) return; bar.className = 'sync-bar'; if (status === 'online') { bar.classList.add('sync-online'); label.textContent = 'Online · Synced'; } else if (status === 'offline') { bar.classList.add('sync-offline'); label.textContent = 'Offline · Working locally'; } else if (status === 'syncing') { bar.classList.add('sync-online'); label.textContent = 'Syncing...'; } else if (status === 'error') { bar.classList.add('sync-error'); label.textContent = 'Sync Error — tap to retry'; } } // Offline save queue let _offlineQueue = []; function _queueOfflineSave() { _offlineQueue.push({ time: Date.now(), data: _store.get('thermal-model-v3') }); _updateSyncStatus('offline'); } // Auto-save to cloud every 2 minutes setInterval(() => { if (_currentUser) _saveJobToCloud(); }, 120000); // ============================================================ // AUDIT TRAIL (Change 7) // ============================================================ async function _logChange(action, field, before, after) { if (!_currentUser) return; try { await _supa.from('audit_log').insert({ user_id: _currentUser.id, job_ref: _activeJobId || 'unsaved', action: action, device_id: field, before_value: String(before), after_value: String(after), created_at: new Date().toISOString() }); } catch(e) {} // fail silently if table doesn't exist } // ============================================================ // NETWORK CONNECTIVITY MONITOR (Change 8) // ============================================================ window.addEventListener('online', () => { _updateSyncStatus('online'); _showToast('Back online — syncing...', 'info'); _playSound('chime'); if (_currentUser) _saveJobToCloud(); }); window.addEventListener('offline', () => { _updateSyncStatus('offline'); _showToast('Offline — saving locally', 'warning'); });