Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
| <title>API Pump Design Calculator based on Swab Analysis</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet"/> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); | |
| body { | |
| font-family: 'Poppins', sans-serif; | |
| } | |
| .card { | |
| transition: all 0.3s ease; | |
| } | |
| .card:hover { | |
| box-shadow: 0 10px 20px rgba(0,0,0,0.1); | |
| transform: translateY(-5px); | |
| } | |
| .select2-container { | |
| width: 100% ; | |
| } | |
| .loading { | |
| border-top-color: #ffffff; | |
| animation: spin 1s linear infinite; | |
| } | |
| .form-group { | |
| @apply mb-6; | |
| } | |
| .form-group label { | |
| @apply block text-sm font-medium text-gray-700 mb-2; | |
| } | |
| .help-text { | |
| @apply text-xs text-gray-500 mt-1; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8 max-w-6xl"> | |
| <!-- Header --> | |
| <div class="text-center mb-8"> | |
| <h1 class="text-4xl font-bold text-indigo-800 flex justify-center items-center gap-3"> | |
| <i class="fas fa-cogs text-yellow-500"></i> | |
| API Pump Design Calculator | |
| </h1> | |
| <p class="text-gray-600 mt-2">Based on Swab Analysis & API 11E Standard</p> | |
| </div> | |
| <!-- Main Calculator Card --> | |
| <div class="bg-white rounded-2xl shadow-xl p-8 mb-6 card"> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> | |
| <!-- Input Section --> | |
| <div> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> | |
| <i class="fas fa-calculator text-blue-500 mr-2"></i> | |
| Input Parameters | |
| </h2> | |
| <div class="space-y-6"> | |
| <!-- Depth --> | |
| <div class="form-group"> | |
| <label for="depth">Well Depth (ft)</label> | |
| <input type="number" id="depth" placeholder="e.g. 8000" | |
| class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> | |
| <div class="help-text">Measured depth of the well from surface to bottom hole</div> | |
| </div> | |
| <!-- Swab Result --> | |
| <div class="form-group"> | |
| <label for="swabResult">Swab Result (Barrels per Day - B/D)</label> | |
| <input type="number" id="swabResult" placeholder="e.g. 500" | |
| class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> | |
| <div class="help-text">Production rate achieved during swabbing operation</div> | |
| </div> | |
| <!-- Fluid Levels --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div class="form-group"> | |
| <label for="wfl">Working Fluid Level - WFL (ft)</label> | |
| <input type="number" id="wfl" placeholder="e.g. 6000" | |
| class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> | |
| <div class="help-text">Fluid level during production</div> | |
| </div> | |
| <div class="form-group"> | |
| <label for="sfl">Static Fluid Level - SFL (ft)</label> | |
| <input type="number" id="sfl" placeholder="e.g. 3000" | |
| class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> | |
| <div class="help-text">Fluid level at static conditions</div> | |
| </div> | |
| </div> | |
| <!-- Tubing Size --> | |
| <div class="form-group"> | |
| <label for="tubingSize">Tubing Size (inches)</label> | |
| <select id="tubingSize" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all bg-white"> | |
| <option value="">Select Tubing Size</option> | |
| <option value="1.9">1.900" (40 ft³/1000 ft)</option> | |
| <option value="2.375">2.375" (60 ft³/1000 ft)</option> | |
| <option value="2.875">2.875" (80 ft³/1000 ft)</option> | |
| <option value="3.5">3.500" (120 ft³/1000 ft)</option> | |
| <option value="4.5">4.500" (180 ft³/1000 ft)</option> | |
| </select> | |
| <div class="help-text">Inside diameter of production tubing</div> | |
| </div> | |
| <!-- Casing Size --> | |
| <div class="form-group"> | |
| <label for="casingSize">Casing Size (inches)</label> | |
| <select id="casingSize" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all bg-white"> | |
| <option value="">Select Casing Size</option> | |
| <option value="4.5">4.500" (Normal)</option> | |
| <option value="5.5">5.500" (Common)</option> | |
| <option value="7">7.000" (Large)</option> | |
| <option value="9.625">9.625" (Surface)</option> | |
| <option value="13.375">13.375" (Conductor)</option> | |
| </select> | |
| <div class="help-text">Inside diameter of the casing string</div> | |
| </div> | |
| <!-- Pump Type --> | |
| <div class="form-group"> | |
| <label for="pumpType">Pump Type</label> | |
| <select id="pumpType" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all bg-white"> | |
| <option value="">Select Pump Type</option> | |
| <option value="D">Class D - Heavy Duty</option> | |
| <option value="H">Class H - Heavy Duty</option> | |
| <option value="K">Class K - Extra Heavy Duty</option> | |
| </select> | |
| <div class="help-text">API pump class based on load requirements</div> | |
| </div> | |
| <!-- Power Fluid Specific Gravity --> | |
| <div class="form-group"> | |
| <label for="specificGravity">Power Fluid Specific Gravity</label> | |
| <input type="number" step="0.01" id="specificGravity" placeholder="e.g. 0.87" value="0.87" | |
| class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"> | |
| <div class="help-text">Typically 0.85-0.90 for crude oil</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Output Section --> | |
| <div> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> | |
| <i class="fas fa-chart-line text-green-500 mr-2"></i> | |
| Design Results | |
| </h2> | |
| <div class="bg-gray-50 rounded-xl p-6 h-full flex flex-col"> | |
| <div id="resultsContainer" class="space-y-4 flex-grow"> | |
| <!-- Enhanced result display with icons --> | |
| <div class="result-item flex justify-between py-2 border-b border-gray-200"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-tint mr-2 text-blue-500"></i> | |
| Recommended Pump Size: | |
| </span> | |
| <span id="pumpSize" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| <div class="result-item flex justify-between py-2 border-b border-gray-200"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-ruler-vertical mr-2 text-green-500"></i> | |
| Plunger Size (in): | |
| </span> | |
| <span id="plungerSize" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| <div class="result-item flex justify-between py-2 border-b border-gray-200"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-water mr-2 text-purple-500"></i> | |
| Barrels per Stroke: | |
| </span> | |
| <span id="barrelsPerStroke" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| <div class="result-item flex justify-between py-2 border-b border-gray-200"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-sync-alt mr-2 text-orange-500"></i> | |
| Required Strokes/min: | |
| </span> | |
| <span id="strokesPerMin" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| <div class="result-item flex justify-between py-2 border-b border-gray-200"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-chart-area mr-2 text-teal-500"></i> | |
| Fluid Capacity (BPD): | |
| </span> | |
| <span id="fluidCapacity" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| <div class="result-item flex justify-between py-2 border-b border-gray-200"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-compress-arrows-alt mr-2 text-red-500"></i> | |
| Pump Submergence: | |
| </span> | |
| <span id="submergence" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| <div class="result-item flex justify-between py-2 border-b border-gray-200"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-temperature-low mr-2 text-indigo-500"></i> | |
| Pump Setting Depth: | |
| </span> | |
| <span id="pumpDepth" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| <div class="result-item flex justify-between py-2"> | |
| <span class="text-gray-600 flex items-center"> | |
| <i class="fas fa-file-code mr-2 text-gray-500"></i> | |
| API Design Code: | |
| </span> | |
| <span id="apiCode" class="font-semibold text-indigo-700">-</span> | |
| </div> | |
| </div> | |
| <div class="mt-6 space-y-4"> | |
| <button id="calculateBtn" | |
| class="w-full bg-gradient-to-r from-blue-600 to-indigo-600 text-white font-semibold py-3 px-6 rounded-lg hover:from-blue-700 hover:to-indigo-700 transition-all duration-300 flex items-center justify-center"> | |
| <i class="fas fa-cog mr-2"></i> | |
| Calculate Pump Design | |
| </button> | |
| <button id="resetBtn" | |
| class="w-full bg-gradient-to-r from-gray-500 to-gray-600 text-white font-semibold py-3 px-6 rounded-lg hover:from-gray-600 hover:to-gray-700 transition-all duration-300 flex items-center justify-center"> | |
| <i class="fas fa-redo mr-2"></i> | |
| Reset Form | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Charts and Analysis Section --> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6"> | |
| <!-- Performance Chart --> | |
| <div class="bg-white rounded-2xl shadow-xl p-6 lg:col-span-2"> | |
| <h3 class="text-xl font-semibold text-gray-800 mb-4">Pump Performance Analysis</h3> | |
| <div class="relative"> | |
| <canvas id="performanceChart" height="300"></canvas> | |
| <div id="chartLegend" class="absolute top-0 right-0 bg-white p-2 rounded shadow-md text-xs"> | |
| <div class="flex items-center mb-1"> | |
| <div class="w-3 h-3 bg-blue-500 mr-1"></div> | |
| <span>Max Capacity</span> | |
| </div> | |
| <div class="flex items-center"> | |
| <div class="w-3 h-3 bg-green-500 mr-1"></div> | |
| <span>Required Rate</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Tubing Capacity Chart --> | |
| <div class="bg-white rounded-2xl shadow-xl p-6"> | |
| <h3 class="text-xl font-semibold text-gray-800 mb-4">Wellbore Configuration</h3> | |
| <canvas id="tubingChart" height="300"></canvas> | |
| <div class="mt-4 text-sm"> | |
| <div class="flex justify-between mb-2"> | |
| <span class="text-gray-600">Tubing ID:</span> | |
| <span id="displayTubing" class="font-medium">-</span> | |
| </div> | |
| <div class="flex justify-between mb-2"> | |
| <span class="text-gray-600">Casing ID:</span> | |
| <span id="displayCasing" class="font-medium">-</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-600">Annular Volume:</span> | |
| <span id="annularVol" class="font-medium">-</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- API Standard Reference and Recommendations --> | |
| <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6"> | |
| <div class="bg-white rounded-2xl shadow-xl p-6"> | |
| <h3 class="text-xl font-semibold text-gray-800 mb-4 flex items-center"> | |
| <i class="fas fa-lightbulb text-yellow-500 mr-2"></i> | |
| Design Recommendations | |
| </h3> | |
| <div id="recommendations" class="space-y-3 text-gray-700"> | |
| <p>Enter well parameters and click "Calculate" to view design recommendations.</p> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-2xl shadow-xl p-6"> | |
| <h3 class="text-xl font-semibold text-gray-800 mb-4 flex items-center"> | |
| <i class="fas fa-book text-purple-500 mr-2"></i> | |
| API 11E Standard | |
| </h3> | |
| <div class="bg-blue-50 border-l-4 border-blue-400 p-4 rounded-r-lg"> | |
| <p class="text-gray-700 text-sm"> | |
| <strong>API Specification 11E</strong> covers design requirements for sucker rod pumping units and accessories. | |
| This calculator uses standard formulas for pump displacement, fluid load calculations, and proper pump selection | |
| based on well parameters. Always verify with local engineering standards and manufacturer specifications. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Sample tubing data for chart | |
| const tubingSizes = ['1.9"', '2.375"', '2.875"', '3.5"', '4.5"']; | |
| const tubingCapacity = [40, 60, 80, 120, 180]; // ft³ per 1000 ft | |
| // Casing data | |
| const casingSizes = ['4.5"', '5.5"', '7"', '9.625"', '13.375"']; | |
| const casingCapacity = [50, 80, 150, 280, 500]; // ft³ per 1000 ft | |
| // Initialize charts | |
| let performanceChart, tubingChart; | |
| window.onload = function() { | |
| initCharts(); | |
| setupEventListeners(); | |
| }; | |
| function initCharts() { | |
| // Performance Chart | |
| const perfCtx = document.getElementById('performanceChart').getContext('2d'); | |
| performanceChart = new Chart(perfCtx, { | |
| type: 'line', | |
| data: { | |
| labels: Array.from({length: 21}, (_, i) => i * 2), | |
| datasets: [{ | |
| label: 'Maximum Capacity (BPD)', | |
| data: Array.from({length: 21}, () => 0), | |
| borderColor: '#3B82F6', | |
| backgroundColor: 'rgba(59, 130, 246, 0.1)', | |
| tension: 0.3, | |
| fill: true | |
| }, | |
| { | |
| label: 'Required Production Rate', | |
| data: Array.from({length: 21}, () => 0), | |
| borderColor: '#10B981', | |
| borderDash: [5, 5], | |
| pointRadius: 0 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| display: false | |
| }, | |
| tooltip: { | |
| mode: 'index', | |
| intersect: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| title: { | |
| display: true, | |
| text: 'Capacity (BPD)' | |
| } | |
| }, | |
| x: { | |
| title: { | |
| display: true, | |
| text: 'Strokes per Minute' | |
| }, | |
| ticks: { | |
| stepSize: 2 | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| // Tubing and Casing Chart | |
| const tubeCtx = document.getElementById('tubingChart').getContext('2d'); | |
| tubingChart = new Chart(tubeCtx, { | |
| type: 'bar', | |
| data: { | |
| labels: ['Tubing', 'Casing'], | |
| datasets: [{ | |
| label: 'Wellbore Capacity (ft³ per 1000 ft)', | |
| data: [0, 0], | |
| backgroundColor: [ | |
| '#8B5CF6', '#4F46E5' | |
| ], | |
| borderColor: [ | |
| '#7C3AED', '#4338CA' | |
| ], | |
| borderWidth: 1 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| title: { | |
| display: true, | |
| text: 'Volume (ft³)' | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| function setupEventListeners() { | |
| document.getElementById('calculateBtn').addEventListener('click', calculateDesign); | |
| document.getElementById('resetBtn').addEventListener('click', resetForm); | |
| // Auto-calculate when pressing Enter in any input field | |
| document.querySelectorAll('input').forEach(input => { | |
| input.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') { | |
| calculateDesign(); | |
| } | |
| }); | |
| }); | |
| // Update display when selecting tubing or casing | |
| document.getElementById('tubingSize').addEventListener('change', updateTubingDisplay); | |
| document.getElementById('casingSize').addEventListener('change', updateCasingDisplay); | |
| } | |
| function updateTubingDisplay() { | |
| const tubingSelect = document.getElementById('tubingSize'); | |
| const selectedValue = tubingSelect.value; | |
| const displayTubing = document.getElementById('displayTubing'); | |
| if (selectedValue) { | |
| // Find the corresponding tubing capacity | |
| const index = ['1.9', '2.375', '2.875', '3.5', '4.5'].indexOf(selectedValue); | |
| const capacity = index >= 0 ? tubingCapacity[index] : 0; | |
| displayTubing.textContent = `${selectedValue}" (${capacity} ft³/kft)`; | |
| // Update chart | |
| tubingChart.data.datasets[0].data[0] = capacity; | |
| tubingChart.update(); | |
| } | |
| } | |
| function updateCasingDisplay() { | |
| const casingSelect = document.getElementById('casingSize'); | |
| const selectedValue = casingSelect.value; | |
| const displayCasing = document.getElementById('displayCasing'); | |
| if (selectedValue) { | |
| // Find the corresponding casing capacity | |
| const index = ['4.5', '5.5', '7', '9.625', '13.375'].indexOf(selectedValue); | |
| const capacity = index >= 0 ? casingCapacity[index] : 0; | |
| displayCasing.textContent = `${selectedValue}" (${capacity} ft³/kft)`; | |
| // Update chart | |
| tubingChart.data.datasets[0].data[1] = capacity; | |
| tubingChart.update(); | |
| // Calculate and display annular volume | |
| const tubingSelect = document.getElementById('tubingSize'); | |
| const tubingValue = tubingSelect.value; | |
| if (tubingValue) { | |
| const tubingIndex = ['1.9', '2.375', '2.875', '3.5', '4.5'].indexOf(tubingValue); | |
| const tubingCap = tubingIndex >= 0 ? tubingCapacity[tubingIndex] : 0; | |
| // Annular volume is the difference between casing and tubing capacity | |
| const annularVol = capacity - tubingCap; | |
| document.getElementById('annularVol').textContent = `${annularVol.toFixed(1)} ft³/kft`; | |
| } | |
| } | |
| } | |
| function calculateDesign() { | |
| // Get input values | |
| const depth = parseFloat(document.getElementById('depth').value); | |
| const swabResult = parseFloat(document.getElementById('swabResult').value); | |
| const wfl = parseFloat(document.getElementById('wfl').value); | |
| const sfl = parseFloat(document.getElementById('sfl').value); | |
| const tubingSize = document.getElementById('tubingSize').value; | |
| const casingSize = document.getElementById('casingSize').value; | |
| const pumpType = document.getElementById('pumpType').value; | |
| const sg = parseFloat(document.getElementById('specificGravity').value); | |
| // Validate inputs | |
| if (!depth || !swabResult || !wfl || !tubingSize || !casingSize || !pumpType) { | |
| alert('Please fill in all required fields'); | |
| return; | |
| } | |
| // Validate that WFL is less than depth | |
| if (wfl >= depth) { | |
| alert('Working Fluid Level must be less than Well Depth'); | |
| return; | |
| } | |
| // Validate SFL if provided (should be less than or equal to WFL) | |
| if (sfl && (sfl > wfl || sfl >= depth)) { | |
| alert('Static Fluid Level must be less than or equal to Working Fluid Level and less than Well Depth'); | |
| return; | |
| } | |
| // Show loading state | |
| const calcBtn = document.getElementById('calculateBtn'); | |
| const originalText = calcBtn.innerHTML; | |
| calcBtn.innerHTML = '<i class="fas fa-spinner loading mr-2"></i>Calculating...'; | |
| calcBtn.disabled = true; | |
| // Simulate calculation delay | |
| setTimeout(() => { | |
| // Calculate pump parameters based on API formulas and rules | |
| const depthInThousandFt = depth / 1000; | |
| // Determine plunger size based on depth and production rate | |
| let plungerSize, pumpSize; | |
| // Decision matrix for pump selection based on depth and production rate | |
| if (depth < 6000) { | |
| if (swabResult < 300) { | |
| plungerSize = "1.25"; | |
| pumpSize = "16"; | |
| } else if (swabResult < 600) { | |
| plungerSize = "1.5"; | |
| pumpSize = "20"; | |
| } else { | |
| plungerSize = "1.75"; | |
| pumpSize = "25"; | |
| } | |
| } else if (depth < 9000) { | |
| if (swabResult < 400) { | |
| plungerSize = "1.0"; | |
| pumpSize = "13"; | |
| } else if (swabResult < 700) { | |
| plungerSize = "1.25"; | |
| pumpSize = "16"; | |
| } else { | |
| plungerSize = "1.5"; | |
| pumpSize = "20"; | |
| } | |
| } else { | |
| if (swabResult < 500) { | |
| plungerSize = "0.875"; | |
| pumpSize = "10"; | |
| } else if (swabResult < 800) { | |
| plungerSize = "1.0"; | |
| pumpSize = "13"; | |
| } else { | |
| plungerSize = "1.25"; | |
| pumpSize = "16"; | |
| } | |
| } | |
| // Calculate barrels per stroke (API formula) | |
| const barrelsPerStroke = (0.1166 * Math.pow(parseFloat(plungerSize), 2) * depthInThousandFt).toFixed(3); | |
| // Calculate required strokes per minute | |
| const strokesPerMin = (swabResult / (parseFloat(barrelsPerStroke) * 24)).toFixed(2); | |
| // Calculate fluid capacity at 15 SPM | |
| const fluidCapacity = (parseFloat(barrelsPerStroke) * 24 * 15).toFixed(0); | |
| // Calculate submergence - more accurate calculation | |
| const submergence = ((wfl / depth) * 100).toFixed(1) + "%"; | |
| // Calculate optimal pump setting depth (typically 100-200 ft above fluid level) | |
| const pumpSettingDepth = wfl + 150; // 150 ft above fluid level | |
| const maxPumpDepth = depth - 100; // At least 100 ft from bottom | |
| const actualPumpDepth = Math.min(pumpSettingDepth, maxPumpDepth); | |
| // Generate API code | |
| const apiCode = `API ${pumpType}-${pumpSize}(${plungerSize}")-${Math.round(depth)}`; | |
| // Update results | |
| document.getElementById('pumpSize').textContent = pumpSize + " Series"; | |
| document.getElementById('plungerSize').textContent = plungerSize + '"'; | |
| document.getElementById('barrelsPerStroke').textContent = barrelsPerStroke + " B/Stroke"; | |
| document.getElementById('strokesPerMin').textContent = strokesPerMin + " SPM"; | |
| document.getElementById('fluidCapacity').textContent = fluidCapacity + " BPD"; | |
| document.getElementById('submergence').textContent = submergence; | |
| document.getElementById('pumpDepth').textContent = `${Math.round(actualPumpDepth)} ft`; | |
| document.getElementById('apiCode').textContent = apiCode; | |
| // Update charts with relevant data | |
| updateCharts(parseFloat(strokesPerMin), swabResult, barrelsPerStroke); | |
| // Update recommendations | |
| updateRecommendations(depth, swabResult, wfl, sfl, pumpSize, plungerSize, parseFloat(strokesPerMin), casingSize, tubingSize); | |
| // Restore button | |
| calcBtn.innerHTML = originalText; | |
| calcBtn.disabled = false; | |
| }, 800); | |
| } | |
| function updateCharts(spm, targetProduction, barrelsPerStroke) { | |
| // Generate performance data based on pump characteristics | |
| const strokes = Array.from({length: 21}, (_, i) => i * 2); | |
| const maxCapacity = strokes.map(s => parseFloat(barrelsPerStroke) * s * 24); | |
| // Fill the required production rate array | |
| const requiredRate = Array(21).fill(targetProduction); | |
| // Update performance chart | |
| performanceChart.data.labels = strokes; | |
| performanceChart.data.datasets[0].data = maxCapacity; | |
| performanceChart.data.datasets[1].data = requiredRate; | |
| performanceChart.update(); | |
| } | |
| function updateRecommendations(depth, production, wfl, sfl, pumpSize, plungerSize, spm, casing, tubing) { | |
| const recContainer = document.getElementById('recommendations'); | |
| // Calculate some key parameters | |
| const submergence = (wfl / depth) * 100; | |
| const drawDown = sfl ? sfl - wfl : 0; | |
| let recommendations = []; | |
| // Pump size recommendation | |
| recommendations.push(`<strong>Pump Selection:</strong> API Class ${pumpSize} series with ${plungerSize}" plunger is appropriate for your well conditions.`); | |
| // Operating range | |
| if (spm < 6) { | |
| recommendations.push(`<strong>Low Stroke Speed:</strong> At ${spm} SPM, consider a larger pump or increasing stroke length to improve efficiency.`); | |
| } else if (spm > 20) { | |
| recommendations.push(`<strong>High Stroke Speed:</strong> At ${spm} SPM, consider a larger pump or reducing stroke length to minimize wear.`); | |
| } else { | |
| recommendations.push(`<strong>Optimal Operation:</strong> At ${spm} SPM, your pump will operate within the recommended range of 6-20 SPM.`); | |
| } | |
| // Submergence analysis | |
| if (submergence > 85) { | |
| recommendations.push(`<strong>Deep Submergence:</strong> With ${submergence.toFixed(1)}% submergence, gas interference should be minimal.`); | |
| } else if (submergence > 60) { | |
| recommendations.push(`<strong>Moderate Submergence:</strong> At ${submergence.toFixed(1)}% submergence, monitor for potential gas interference.`); | |
| } else { | |
| recommendations.push(`<strong>Shallow Submergence:</strong> With only ${submergence.toFixed(1)}% submergence, gas interference is likely. Consider deeper setting or gas separator.`); | |
| } | |
| // Drawdown analysis if SFL is provided | |
| if (sfl && drawDown > 0) { | |
| recommendations.push(`<strong>Drawdown Analysis:</strong> The ${drawDown.toFixed(0)} ft drawdown indicates good well productivity.`); | |
| if (drawDown / depth > 0.2) { | |
| recommendations.push(`<strong>High Drawdown:</strong> The drawdown represents ${(drawDown/depth*100).toFixed(1)}% of total depth, indicating good reservoir pressure.`); | |
| } | |
| } | |
| // Casing and tubing compatibility | |
| const casingVal = parseFloat(casing); | |
| const tubingVal = parseFloat(tubing); | |
| if (casingVal - tubingVal < 1) { | |
| recommendations.push(`<strong>Clearance Check:</strong> With only ${(casingVal-tubingVal).toFixed(2)}" radial clearance, verify all equipment will pass.`); | |
| } | |
| // Generate recommendations HTML | |
| recContainer.innerHTML = recommendations.map(rec => `<p class="flex items-start"><i class="fas fa-check-circle text-green-500 mr-2 mt-1"></i>${rec}</p>`).join(''); | |
| // Add a final note | |
| recContainer.innerHTML += `<p class="text-xs text-gray-500 mt-3">Note: These are general recommendations. Always consult with a pumping unit engineer for final design approval.</p>`; | |
| } | |
| function resetForm() { | |
| // Reset all form fields | |
| document.getElementById('depth').value = ''; | |
| document.getElementById('swabResult').value = ''; | |
| document.getElementById('wfl').value = ''; | |
| document.getElementById('sfl').value = ''; | |
| document.getElementById('tubingSize').value = ''; | |
| document.getElementById('casingSize').value = ''; | |
| document.getElementById('pumpType').value = ''; | |
| document.getElementById('specificGravity').value = '0.87'; | |
| // Reset results | |
| document.querySelectorAll('#resultsContainer span[id]').forEach(span => { | |
| span.textContent = '-'; | |
| }); | |
| // Reset charts | |
| performanceChart.data.datasets[0].data = Array(21).fill(0); | |
| performanceChart.data.datasets[1].data = Array(21).fill(0); | |
| performanceChart.update(); | |
| tubingChart.data.datasets[0].data = [0, 0]; | |
| tubingChart.update(); | |
| // Reset displays | |
| document.getElementById('displayTubing').textContent = '-'; | |
| document.getElementById('displayCasing').textContent = '-'; | |
| document.getElementById('annularVol').textContent = '-'; | |
| // Reset recommendations | |
| document.getElementById('recommendations').innerHTML = '<p class="text-gray-700">Enter well parameters and click "Calculate" to view design recommendations.</p>'; | |
| } | |
| // Add some sample data to inputs for easier testing | |
| document.getElementById('depth').value = '8500'; | |
| document.getElementById('swabResult').value = '650'; | |
| document.getElementById('wfl').value = '6700'; | |
| document.getElementById('sfl').value = '4500'; | |
| document.getElementById('tubingSize').value = '2.875'; | |
| document.getElementById('casingSize').value = '5.5'; | |
| document.getElementById('pumpType').value = 'D'; | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-qwensite.hf.space/logo.svg" alt="qwensite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-qwensite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >QwenSite</a> - 🧬 <a href="https://enzostvs-qwensite.hf.space?remix=alterzick/api-pump-design" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |