Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | |
| <title>Cementing Design Simulator - Twin Technology</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.0.0/css/all.min.css" rel="stylesheet"/> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700&family=Roboto:wght@300;400;500&display=swap'); | |
| body { | |
| font-family: 'Roboto', sans-serif; | |
| background: linear-gradient(135deg, #0f1b29, #1a365d); | |
| color: #e2e8f0; | |
| } | |
| .header-title { | |
| font-family: 'Orbitron', sans-serif; | |
| letter-spacing: 1.5px; | |
| } | |
| .card-glass { | |
| background: rgba(30, 41, 59, 0.7); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid rgba(75, 85, 99, 0.3); | |
| border-radius: 12px; | |
| box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); | |
| } | |
| .btn-primary { | |
| background: linear-gradient(to right, #3b82f6, #1d4ed8); | |
| transition: all 0.3s ease; | |
| } | |
| .btn-primary:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 20px rgba(30, 58, 138, 0.2); | |
| } | |
| .input-field { | |
| background: rgba(15, 23, 42, 0.5); | |
| border: 1px solid #334155; | |
| border-radius: 8px; | |
| color: #e2e8f0; | |
| } | |
| .input-field:focus { | |
| border-color: #3b82f6; | |
| outline: none; | |
| box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2); | |
| } | |
| .casing-tubing-viz { | |
| height: 500px; | |
| position: relative; | |
| background: #0c1b2a; | |
| border-radius: 10px; | |
| overflow: hidden; | |
| } | |
| .layer { | |
| position: absolute; | |
| width: 100%; | |
| border-radius: 5px; | |
| transition: all 0.5s ease; | |
| } | |
| .annulus-fill { | |
| background: linear-gradient(to right, rgba(239, 68, 68, 0.3), rgba(239, 68, 68, 0.1)); | |
| border: 1px dashed #ef4444; | |
| } | |
| .cement-fill { | |
| background: linear-gradient(to right, rgba(107, 114, 128, 0.6), rgba(148, 163, 184, 0.4)); | |
| border: 1px solid #6b7280; | |
| } | |
| .remedial-fill { | |
| background: linear-gradient(to right, rgba(245, 158, 11, 0.7), rgba(249, 115, 22, 0.4)); | |
| border: 2px solid #f59e0b; | |
| } | |
| .wellbore { | |
| background: rgba(31, 41, 55, 0.8); | |
| border: 2px solid #475569; | |
| } | |
| .shoe { | |
| position: absolute; | |
| height: 20px; | |
| width: 100%; | |
| background: linear-gradient(to bottom, #b91c1c, #dc2626); | |
| bottom: 0; | |
| border-radius: 0 0 5px 5px; | |
| } | |
| .stage-marker { | |
| position: absolute; | |
| width: 100%; | |
| height: 40px; | |
| background: rgba(16, 185, 129, 0.2); | |
| border-top: 2px solid #10b981; | |
| border-bottom: 2px solid #10b981; | |
| color: #10b981; | |
| font-size: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: bold; | |
| } | |
| .perforation-zone { | |
| position: absolute; | |
| width: 100%; | |
| background: rgba(220, 38, 38, 0.3); | |
| border-left: 3px solid #ef4444; | |
| border-right: 3px solid #ef4444; | |
| color: #ef4444; | |
| font-size: 10px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: bold; | |
| } | |
| .tab-button { | |
| padding: 8px 16px; | |
| background: rgba(60, 70, 85, 0.5); | |
| border: none; | |
| border-radius: 6px 6px 0 0; | |
| cursor: pointer; | |
| font-weight: 500; | |
| } | |
| .tab-button.active { | |
| background: #1e293b; | |
| border-bottom: 2px solid #3b82f6; | |
| } | |
| .tab-content { | |
| display: none; | |
| } | |
| .tab-content.active { | |
| display: block; | |
| } | |
| .toggle-switch { | |
| position: relative; | |
| display: inline-block; | |
| width: 50px; | |
| height: 24px; | |
| } | |
| .toggle-switch input { | |
| opacity: 0; | |
| width: 0; | |
| height: 0; | |
| } | |
| .slider { | |
| position: absolute; | |
| cursor: pointer; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-color: #4a5568; | |
| transition: .4s; | |
| border-radius: 24px; | |
| } | |
| .slider:before { | |
| position: absolute; | |
| content: ""; | |
| height: 16px; | |
| width: 16px; | |
| left: 4px; | |
| bottom: 4px; | |
| background-color: white; | |
| transition: .4s; | |
| border-radius: 50%; | |
| } | |
| input:checked + .slider { | |
| background-color: #3b82f6; | |
| } | |
| input:checked + .slider:before { | |
| transform: translateX(26px); | |
| } | |
| .footage-display { | |
| position: absolute; | |
| left: -60px; | |
| top: 0; | |
| width: 50px; | |
| text-align: center; | |
| font-size: 10px; | |
| color: #94a3b8; | |
| } | |
| .issue-card { | |
| border-left: 4px solid #f59e0b; | |
| background: rgba(100, 100, 100, 0.3); | |
| padding: 12px; | |
| border-radius: 4px; | |
| margin-bottom: 8px; | |
| } | |
| .issue-severity-high { | |
| border-left-color: #ef4444; | |
| } | |
| .issue-severity-warning { | |
| border-left-color: #f59e0b; | |
| } | |
| .issue-severity-info { | |
| border-left-color: #3b82f6; | |
| } | |
| .optimization-card { | |
| border-left: 4px solid #10b981; | |
| background: rgba(16, 185, 129, 0.1); | |
| padding: 12px; | |
| border-radius: 4px; | |
| margin-bottom: 8px; | |
| } | |
| .alert-high { | |
| color: #ef4444; | |
| } | |
| .alert-warning { | |
| color: #f59e0b; | |
| } | |
| .alert-info { | |
| color: #3b82f6; | |
| } | |
| .problem-list { | |
| list-style-type: none; | |
| padding-left: 0; | |
| } | |
| .problem-list li { | |
| margin-bottom: 4px; | |
| padding: 4px 0; | |
| border-bottom: 1px solid rgba(255,255,255,0.1); | |
| } | |
| .problem-list li:last-child { | |
| border-bottom: none; | |
| } | |
| .cement-issue { | |
| position: absolute; | |
| color: #ef4444; | |
| font-weight: bold; | |
| font-size: 10px; | |
| background: rgba(239, 68, 68, 0.2); | |
| padding: 2px 4px; | |
| border-radius: 2px; | |
| z-index: 20; | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen p-6"> | |
| <div class="max-w-7xl mx-auto"> | |
| <!-- Header --> | |
| <header class="text-center mb-8"> | |
| <h1 class="text-4xl header-title text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-purple-500 mb-2"> | |
| <i class="fas fa-hard-hat mr-2"></i>TwinTech Cementing Designer | |
| </h1> | |
| <p class="text-gray-300">Advanced Cementing Simulation & Design with Real-time Risk Assessment</p> | |
| </header> | |
| <!-- Main Content --> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Input Panel --> | |
| <div class="lg:col-span-1"> | |
| <div class="card-glass p-6 mb-6"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-sliders-h mr-2 text-blue-400"></i> Design Mode | |
| </h2> | |
| <!-- Tabs for Primary vs Remedial --> | |
| <div class="mb-4"> | |
| <div class="flex border-b border-gray-600"> | |
| <button id="primaryTab" class="tab-button active">Primary Cementing</button> | |
| <button id="remedialTab" class="tab-button">Remedial Cementing</button> | |
| </div> | |
| </div> | |
| <!-- Primary Cementing Form --> | |
| <div id="primaryForm" class="tab-content active"> | |
| <div class="space-y-4"> | |
| <!-- Well Depth --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Well Depth (ft)</label> | |
| <input type="number" id="wellDepth" value="10000" class="input-field w-full p-2" /> | |
| </div> | |
| <!-- Casing Size --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Casing Size (in) <span class="text-xs text-gray-400">API Std</span></label> | |
| <select id="casingSize" class="input-field w-full p-2"> | |
| <option value="4.5">4.5" - Production Casing</option> | |
| <option value="7" selected>7" - Intermediate Casing</option> | |
| <option value="9.625">9.625" - Surface Casing</option> | |
| <option value="13.375">13.375" - Conductor</option> | |
| </select> | |
| </div> | |
| <!-- Casing Weight --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Casing Weight (lb/ft)</label> | |
| <input type="number" id="casingWeight" value="32" class="input-field w-full p-2" /> | |
| </div> | |
| <!-- Tubing Size --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Tubing Size (in) <span class="text-xs text-gray-400">API Std</span></label> | |
| <select id="tubingSize" class="input-field w-full p-2"> | |
| <option value="2.375">2.375" - Injection</option> | |
| <option value="2.875">2.875" - Production</option> | |
| <option value="3.5" selected>3.5" - Standard</option> | |
| <option value="4.5">4.5" - Heavy Duty</option> | |
| </select> | |
| </div> | |
| <!-- Cement Top --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Cement Top (ft)</label> | |
| <input type="number" id="cementTop" value="3000" class="input-field w-full p-2" /> | |
| </div> | |
| <!-- Shoe Track --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Shoe Track Length (ft)</label> | |
| <input type="number" id="shoeTrack" value="100" class="input-field w-full p-2" /> | |
| </div> | |
| <!-- Stage Cementing --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Stage Tool at (ft)</label> | |
| <input type="number" id="stageDepth" value="6000" class="input-field w-full p-2" placeholder="0 for single stage" /> | |
| </div> | |
| <!-- Centralization --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Casing Centralization</label> | |
| <select id="centralization" class="input-field w-full p-2"> | |
| <option value="spaced">Spaced Centralizers</option> | |
| <option value="continuous" selected>Continuous Centralization</option> | |
| <option value="none">No Centralizers</option> | |
| <option value="bow-spring">Bow Spring Centralizers</option> | |
| <option value="rigid">Rigid Centralizers</option> | |
| </select> | |
| </div> | |
| <!-- Mud Properties --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Mud Weight (ppg)</label> | |
| <input type="number" id="mudWeight" value="12.5" step="0.1" class="input-field w-full p-2" /> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Mud Gel Strength</label> | |
| <select id="mudGel" class="input-field w-full p-2"> | |
| <option value="low">Low (2-5 lb/100ft²)</option> | |
| <option value="medium" selected>Medium (5-10 lb/100ft²)</option> | |
| <option value="high">High (10-20 lb/100ft²)</option> | |
| <option value="very-high">Very High (>20 lb/100ft²)</option> | |
| </select> | |
| </div> | |
| <!-- Cement Properties --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Cement Type</label> | |
| <select id="primaryCementType" class="input-field w-full p-2"> | |
| <option value="classA">Class A - Standard</option> | |
| <option value="classB">Class B - Moderate SR</option> | |
| <option value="classC">Class C - High Early</option> | |
| <option value="classG" selected>Class G - High Strength</option> | |
| <option value="classH">Class H - High Early Strength</option> | |
| <option value="lightweight">Lightweight (11-13 ppg)</option> | |
| <option value="foamed">Foamed Cement</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Cement Additives</label> | |
| <div class="space-y-1"> | |
| <label class="flex items-center text-sm"> | |
| <input type="checkbox" id="accelerator" class="mr-2"> | |
| <span>Accelerator</span> | |
| </label> | |
| <label class="flex items-center text-sm"> | |
| <input type="checkbox" id="retarder" class="mr-2"> | |
| <span>Retarder</span> | |
| </label> | |
| <label class="flex items-center text-sm"> | |
| <input type="checkbox" id="extender" class="mr-2"> | |
| <span>Extender</span> | |
| </label> | |
| <label class="flex items-center text-sm"> | |
| <input type="checkbox" id="lost" class="mr-2"> | |
| <span>Lost Circulation Material</span> | |
| </label> | |
| <label class="flex items-center text-sm"> | |
| <input type="checkbox" id="weighted" class="mr-2"> | |
| <span>Weighted (Hematite)</span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Remedial Cementing Form --> | |
| <div id="remedialForm" class="tab-content"> | |
| <div class="space-y-4"> | |
| <!-- Well Depth --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Well Depth (ft)</label> | |
| <input type="number" id="remedialWellDepth" value="10000" class="input-field w-full p-2" /> | |
| </div> | |
| <!-- Casing Size --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Casing Size (in) <span class="text-xs text-gray-400">API Std</span></label> | |
| <select id="remedialCasingSize" class="input-field w-full p-2"> | |
| <option value="4.5">4.5" - Production Casing</option> | |
| <option value="7" selected>7" - Intermediate Casing</option> | |
| <option value="9.625">9.625" - Surface Casing</option> | |
| <option value="13.375">13.375" - Conductor</option> | |
| </select> | |
| </div> | |
| <!-- Workover Tubing --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Workover Tubing (in)</label> | |
| <select id="workoverTubing" class="input-field w-full p-2"> | |
| <option value="1.9">1.9" - Coiled Tubing</option> | |
| <option value="2.375" selected>2.375" - Intervention</option> | |
| <option value="2.875">2.875" - Work String</option> | |
| <option value="3.5">3.5" - Heavy Intervention</option> | |
| </select> | |
| </div> | |
| <!-- Perforation Interval --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Perforation Interval</label> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <div> | |
| <label class="text-xs">Top (ft)</label> | |
| <input type="number" id="perfTop" value="8500" class="input-field w-full p-2 text-sm" /> | |
| </div> | |
| <div> | |
| <label class="text-xs">Bottom (ft)</label> | |
| <input type="number" id="perfBottom" value="8700" class="input-field w-full p-2 text-sm" /> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Cement Length --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Treatment Coverage (ft below perforations)</label> | |
| <input type="number" id="treatmentLength" value="100" class="input-field w-full p-2" /> | |
| </div> | |
| <!-- Squeeze Pressure --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Expected Squeeze Pressure (psi)</label> | |
| <input type="number" id="squeezePressure" value="2500" class="input-field w-full p-2" /> | |
| </div> | |
| <!-- Plugs --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Set Bridge Plug at (ft)</label> | |
| <input type="number" id="bridgePlug" value="8400" class="input-field w-full p-2" placeholder="0 for none" /> | |
| </div> | |
| <!-- Cement Type --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Remedial Cement Type</label> | |
| <select id="cementType" class="input-field w-full p-2"> | |
| <option value="classA">Class A - Standard</option> | |
| <option value="classG" selected>Class G - High Strength</option> | |
| <option value="classH">Class H - High Early Strength</option> | |
| <option value="resin">Epoxy Resin</option> | |
| <option value="foamed">Foamed Cement</option> | |
| </select> | |
| </div> | |
| <!-- Hole Condition --> | |
| <div> | |
| <label class="block text-sm font-medium mb-1">Hole Condition</label> | |
| <div class="flex items-center space-x-2"> | |
| <span class="text-xs">No Issues</span> | |
| <label class="toggle-switch"> | |
| <input type="checkbox" id="holeProblems"> | |
| <span class="slider"></span> | |
| </label> | |
| <span class="text-xs">Problems</span> | |
| </div> | |
| <div id="holeProblemsDetails" class="mt-2 space-y-2 hidden"> | |
| <label class="flex items-center text-xs"> | |
| <input type="checkbox" class="mr-1 hole-issue" value="washout"> | |
| <span>Washout</span> | |
| </label> | |
| <label class="flex items-center text-xs"> | |
| <input type="checkbox" class="mr-1 hole-issue" value="keyseat"> | |
| <span>Key Seat</span> | |
| </label> | |
| <label class="flex items-center text-xs"> | |
| <input type="checkbox" class="mr-1 hole-issue" value="mudcake"> | |
| <span>Thick Mud Cake</span> | |
| </label> | |
| <label class="flex items-center text-xs"> | |
| <input type="checkbox" class="mr-1 hole-issue" value="losses"> | |
| <span>Lost Circulation</span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <button id="simulateBtn" class="btn-primary text-white font-bold py-3 px-6 rounded-lg w-full mt-4 hover:shadow-lg"> | |
| <i class="fas fa-play mr-2"></i> Simulate Cementing | |
| </button> | |
| </div> | |
| <!-- Results Panel --> | |
| <div class="card-glass p-6"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-calculator mr-2 text-green-400"></i> Results | |
| </h2> | |
| <div class="space-y-3 text-sm"> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Treatment Volume:</span> | |
| <span id="treatmentVolume" class="font-bold text-blue-300">123.45 bbl</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Cement Slurry Vol:</span> | |
| <span id="cementVolume" class="font-bold text-green-300">128.50 bbl</span> | |
| </div> | |
| <div id="remedialExtras"> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Water Spacer Vol:</span> | |
| <span id="waterSpacer" class="font-bold text-purple-300">5.05 bbl</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Treatment Coverage:</span> | |
| <span id="treatmentCoverage" class="font-bold text-yellow-300">9,700 ft</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Squeeze Pressure:</span> | |
| <span id="finalPressure" class="font-bold text-pink-300">2,500 psi</span> | |
| </div> | |
| </div> | |
| <div id="primaryExtras" class="hidden"> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Annular Volume:</span> | |
| <span id="annularVolume" class="font-bold text-blue-300">123.45 bbl</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Shoe Track Volume:</span> | |
| <span id="shoeVolume" class="font-bold text-purple-300">5.05 bbl</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Cement Height:</span> | |
| <span id="cementHeight" class="font-bold text-yellow-300">7,000 ft</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Hydrostatic Press:</span> | |
| <span id="hydrostatic" class="font-bold text-indigo-300">4,550 psi</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span class="text-gray-300">Displacement Vol:</span> | |
| <span id="displacementVol" class="font-bold text-cyan-300">1,042.3 bbl</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-6"> | |
| <h3 class="text-lg font-semibold mb-2">Cementing Progress</h3> | |
| <div class="w-full bg-gray-700 rounded-full h-2.5"> | |
| <div id="progressBar" class="bg-gradient-to-r from-green-500 to-blue-500 h-2.5 rounded-full" style="width: 0%"></div> | |
| </div> | |
| <p id="progressText" class="text-xs text-gray-400 mt-1 text-center">Ready to simulate</p> | |
| </div> | |
| </div> | |
| <!-- Risk Assessment Panel --> | |
| <div class="card-glass p-6 mt-6"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-exclamation-triangle mr-2 text-red-400"></i> Risk Assessment | |
| </h2> | |
| <div id="riskContainer"> | |
| <p class="text-sm text-gray-400">Run simulation to assess potential risks</p> | |
| </div> | |
| </div> | |
| <!-- Optimization Panel --> | |
| <div class="card-glass p-6 mt-6"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-lightbulb mr-2 text-yellow-400"></i> Optimization | |
| </h2> | |
| <div id="optimizationContainer"> | |
| <p class="text-sm text-gray-400">Run simulation to receive optimization suggestions</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Visualization Panel --> | |
| <div class="lg:col-span-2"> | |
| <div class="card-glass p-6 h-full"> | |
| <h2 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-project-diagram mr-2 text-purple-400"></i> Wellbore Visualization | |
| </h2> | |
| <div class="casing-tubing-viz relative"> | |
| <!-- Wellbore Background --> | |
| <div class="wellbore layer" style="height: 100%;"></div> | |
| <!-- Primary Cement Layer --> | |
| <div id="primaryCementLayer" class="cement-fill layer" style="height: 30%; bottom: 0; display: block;"></div> | |
| <!-- Remedial Cement Layer --> | |
| <div id="remedialCementLayer" class="remedial-fill layer" style="height: 15%; bottom: 70%; display: none;"></div> | |
| <!-- Perforation Zone --> | |
| <div id="perforationZone" class="perforation-zone" style="height: 2%; top: 70%; display: none;"> | |
| PERFORATIONS | |
| </div> | |
| <!-- Bridge Plug --> | |
| <div id="bridgePlugMarker" class="stage-marker" style="bottom: 71%; background: rgba(239, 68, 68, 0.2); border-color: #ef4444; color: #ef4444; display: none;"> | |
| BRIDGE PLUG | |
| </div> | |
| <!-- Annular Space --> | |
| <div id="annularLayer" class="annulus-fill layer" style="height: 70%; bottom: 30%;"></div> | |
| <!-- Casing Pipe --> | |
| <div class="absolute inset-0 flex justify-center"> | |
| <div id="casingPipe" class="bg-gray-800" style="width: 80px; height: 100%; border-left: 2px solid #6b7280; border-right: 2px solid #6b7280;"></div> | |
| </div> | |
| <!-- Tubing Pipe --> | |
| <div class="absolute inset-0 flex justify-center"> | |
| <div id="workstringPipe" class="bg-blue-900" style="width: 40px; height: 95%; top: 0; margin: auto; border-left: 1px solid #60a5fa; border-right: 1px solid #60a5fa; z-index: 10;"></div> | |
| </div> | |
| <!-- Casing Collar --> | |
| <div class="absolute inset-0 flex justify-center"> | |
| <div id="casingCollar" class="bg-gray-600" style="width: 86px; height: 10px; top: 10%; margin: auto;"></div> | |
| </div> | |
| <!-- Shoe --> | |
| <div class="shoe"></div> | |
| <!-- Stage Tool Marker --> | |
| <div id="stageMarker" class="stage-marker hidden" style="bottom: 40%;"> | |
| STAGE CEMENTING TOOL | |
| </div> | |
| <!-- Cement Issues Markers --> | |
| <div id="cementIssues"></div> | |
| <!-- Depth Markers --> | |
| <div class="absolute top-0 left-0 text-xs text-gray-500 p-2 bg-black bg-opacity-30 rounded"> | |
| 10,000' - Surface | |
| </div> | |
| <div id="cementTopMarker" class="absolute left-0 text-xs text-gray-300 p-1 bg-black bg-opacity-50 rounded" style="bottom: 30%;"> | |
| Cement Top - 3,000' | |
| </div> | |
| <!-- Footage markers --> | |
| <div id="footageMarkers" class="absolute right-0 top-0 h-full"> | |
| <!-- Generated by JS --> | |
| </div> | |
| </div> | |
| <!-- Simulation Controls --> | |
| <div class="flex justify-between items-center mt-4"> | |
| <div class="text-sm"> | |
| <span class="inline-block w-4 h-4 bg-gradient-to-r from-gray-600 to-gray-800 mr-1"></span> Casing | |
| <span class="inline-block w-4 h-4 bg-blue-900 ml-3 mr-1"></span> | |
| <span id="workstringLabel">Tubing</span> | |
| <span class="inline-block w-4 h-4 border-l-4 border-r-4 border-l-gray-600 border-r-gray-600 border-t-0 border-b-8 border-b-gray-600 ml-3 mr-1"></span> Collar | |
| <span class="inline-block w-4 h-4 bg-gray-600 ml-3 mr-1"></span> Primary Cement | |
| <span class="inline-block w-4 h-4 bg-orange-500 ml-3 mr-1"></span> Remedial Cement | |
| <span class="inline-block w-4 h-4 border-dashed border-1 border-red-500 bg-red-500 bg-opacity-20 ml-3 mr-1"></span> Annulus | |
| </div> | |
| <div id="playControl" class="flex space-x-2"> | |
| <button id="pauseBtn" class="bg-yellow-600 hover:bg-yellow-700 text-white px-3 py-1 rounded text-sm hidden"> | |
| <i class="fas fa-pause"></i> | |
| </button> | |
| <button id="resetBtn" class="bg-gray-600 hover:bg-gray-700 text-white px-3 py-1 rounded text-sm hidden"> | |
| <i class="fas fa-undo"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Charts Section --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-8"> | |
| <!-- Pressure Chart --> | |
| <div class="card-glass p-6"> | |
| <h3 class="text-lg font-bold mb-4">Pressure Profile</h3> | |
| <canvas id="pressureChart"></canvas> | |
| </div> | |
| <!-- Volume Chart --> | |
| <div class="card-glass p-6"> | |
| <h3 class="text-lg font-bold mb-4">Treatment Volume Distribution</h3> | |
| <canvas id="volumeChart"></canvas> | |
| </div> | |
| </div> | |
| <!-- API Standards Footer --> | |
| <div class="text-center mt-8 text-xs text-gray-500"> | |
| <p>Design based on API Specification 5CT (Casing & Tubing) and API RP 10B (Cementing)</p> | |
| <p class="mt-1">TwinTech Cementing Designer v2.0 - Powered by Advanced Well Engineering Algorithms</p> | |
| </div> | |
| </div> | |
| <script> | |
| // Function to show active tab | |
| function showTab(tabName) { | |
| // Hide all tab content | |
| document.querySelectorAll('.tab-content').forEach(content => { | |
| content.classList.remove('active'); | |
| }); | |
| // Remove active class from all buttons | |
| document.querySelectorAll('.tab-button').forEach(button => { | |
| button.classList.remove('active'); | |
| }); | |
| // Show selected tab content | |
| document.getElementById(tabName + 'Form').classList.add('active'); | |
| // Add active class to selected button | |
| document.getElementById(tabName + 'Tab').classList.add('active'); | |
| // Show/hide appropriate result fields | |
| if (tabName === 'primary') { | |
| document.getElementById('primaryExtras').classList.remove('hidden'); | |
| document.getElementById('remedialExtras').classList.add('hidden'); | |
| document.getElementById('workstringLabel').textContent = 'Tubing'; | |
| document.getElementById('remedialCementLayer').style.display = 'none'; | |
| document.getElementById('perforationZone').style.display = 'none'; | |
| document.getElementById('bridgePlugMarker').style.display = 'none'; | |
| document.getElementById('primaryCementLayer').style.display = 'block'; | |
| document.getElementById('annularLayer').style.display = 'block'; | |
| // Clear risk and optimization panels when switching | |
| document.getElementById('riskContainer').innerHTML = '<p class="text-sm text-gray-400">Run simulation to assess potential risks</p>'; | |
| document.getElementById('optimizationContainer').innerHTML = '<p class="text-sm text-gray-400">Run simulation to receive optimization suggestions</p>'; | |
| } else { | |
| document.getElementById('primaryExtras').classList.add('hidden'); | |
| document.getElementById('remedialExtras').classList.remove('hidden'); | |
| document.getElementById('workstringLabel').textContent = 'Workstring'; | |
| document.getElementById('remedialCementLayer').style.display = 'block'; | |
| document.getElementById('primaryCementLayer').style.display = 'block'; | |
| document.getElementById('annularLayer').style.display = 'block'; | |
| // Clear risk and optimization panels when switching | |
| document.getElementById('riskContainer').innerHTML = '<p class="text-sm text-gray-400">Run simulation to assess potential risks</p>'; | |
| document.getElementById('optimizationContainer').innerHTML = '<p class="text-sm text-gray-400">Run simulation to receive optimization suggestions</p>'; | |
| } | |
| } | |
| // Add event listeners to tab buttons | |
| document.getElementById('primaryTab').addEventListener('click', function() { | |
| showTab('primary'); | |
| }); | |
| document.getElementById('remedialTab').addEventListener('click', function() { | |
| showTab('remedial'); | |
| }); | |
| // Toggle hole problems details | |
| document.getElementById('holeProblems').addEventListener('change', function() { | |
| const details = document.getElementById('holeProblemsDetails'); | |
| if (this.checked) { | |
| details.classList.remove('hidden'); | |
| } else { | |
| details.classList.add('hidden'); | |
| } | |
| }); | |
| // Initialize Charts | |
| const pressureCtx = document.getElementById('pressureChart').getContext('2d'); | |
| const volumeCtx = document.getElementById('volumeChart').getContext('2d'); | |
| const pressureChart = new Chart(pressureCtx, { | |
| type: 'line', | |
| data: { | |
| labels: Array.from({length: 11}, (_, i) => `${i}k`), | |
| datasets: [{ | |
| label: 'Hydrostatic Pressure (psi)', | |
| data: [0, 455, 910, 1365, 1820, 2275, 2730, 3185, 3640, 4095, 4550], | |
| borderColor: '#3b82f6', | |
| backgroundColor: 'rgba(59, 130, 246, 0.1)', | |
| fill: true, | |
| tension: 0.3 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| grid: { | |
| color: 'rgba(255, 255, 255, 0.1)' | |
| }, | |
| ticks: { | |
| color: '#94a3b8' | |
| } | |
| }, | |
| x: { | |
| grid: { | |
| color: 'rgba(255, 255, 255, 0.1)' | |
| }, | |
| ticks: { | |
| color: '#94a3b8' | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| const volumeChart = new Chart(volumeCtx, { | |
| type: 'doughnut', | |
| data: { | |
| labels: ['Primary Cement', 'Shoe Track', 'Stage Cement', 'Excess'], | |
| datasets: [{ | |
| data: [60, 5, 25, 10], | |
| backgroundColor: [ | |
| '#3b82f6', | |
| '#10b981', | |
| '#f59e0b', | |
| '#ef4444' | |
| ], | |
| borderWidth: 2, | |
| borderColor: '#1e293b' | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| labels: { | |
| color: '#e2e8f0' | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| // Generate footage markers | |
| function generateFootageMarkers(maxDepth) { | |
| const container = document.getElementById('footageMarkers'); | |
| container.innerHTML = ''; | |
| // Generate markers every 1000 feet | |
| for (let i = 0; i <= maxDepth; i += 1000) { | |
| const marker = document.createElement('div'); | |
| marker.className = 'footage-display'; | |
| marker.style.top = `${(i / maxDepth) * 100}%`; | |
| marker.textContent = `${formatNumber(maxDepth - i)}'`; | |
| container.appendChild(marker); | |
| } | |
| } | |
| // Call initially with default depth | |
| generateFootageMarkers(10000); | |
| // Simulation Logic | |
| document.getElementById('simulateBtn').addEventListener('click', function() { | |
| const isPrimaryTab = document.getElementById('primaryForm').classList.contains('active'); | |
| if (isPrimaryTab) { | |
| // Primary Cementing Simulation | |
| simulatePrimaryCementing(); | |
| } else { | |
| // Remedial Cementing Simulation | |
| simulateRemedialCementing(); | |
| } | |
| }); | |
| function analyzePrimaryRisks() { | |
| const wellDepth = parseFloat(document.getElementById('wellDepth').value); | |
| const cementTop = parseFloat(document.getElementById('cementTop').value); | |
| const stageDepth = parseFloat(document.getElementById('stageDepth').value); | |
| const casingSize = parseFloat(document.getElementById('casingSize').value); | |
| const tubingSize = parseFloat(document.getElementById('tubingSize').value); | |
| const mudWeight = parseFloat(document.getElementById('mudWeight').value); | |
| const mudGel = document.getElementById('mudGel').value; | |
| const centralization = document.getElementById('centralization').value; | |
| const cementType = document.getElementById('primaryCementType').value; | |
| const hasAccelerator = document.getElementById('accelerator').checked; | |
| const hasRetarder = document.getElementById('retarder').checked; | |
| const hasExtender = document.getElementById('extender').checked; | |
| const hasLostMat = document.getElementById('lost').checked; | |
| const hasWeighted = document.getElementById('weighted').checked; | |
| const cementHeight = wellDepth - cementTop; | |
| let risks = []; | |
| let optimizations = []; | |
| // Risk assessment logic | |
| if (centralization === 'none') { | |
| risks.push({ | |
| issue: "Poor centralization", | |
| description: "No centralizers will lead to poor cement distribution and channeling", | |
| severity: "high", | |
| potential: "Channeling, Poor zonal isolation" | |
| }); | |
| optimizations.push({ | |
| suggestion: "Add centralizers every 40-60 ft for 70-80% standoff", | |
| priority: "critical" | |
| }); | |
| } else if (centralization === 'spaced') { | |
| optimizations.push({ | |
| suggestion: "Consider using continuous centralization for better standoff", | |
| priority: "high" | |
| }); | |
| } | |
| if (mudWeight > 16 && casingSize > 7) { | |
| risks.push({ | |
| issue: "High ECD considerations", | |
| description: "High mud weight with large casing increases risk of formation fracture", | |
| severity: "high", | |
| potential: "Lost circulation, formation breakdown" | |
| }); | |
| } | |
| if (mudGel === 'high' || mudGel === 'very-high') { | |
| risks.push({ | |
| issue: "High gel strength", | |
| description: "High gel strength requires higher pump pressure to break gels", | |
| severity: "warning", | |
| potential: "Surge/swab pressures, formation fracture" | |
| }); | |
| optimizations.push({ | |
| suggestion: "Condition mud before cementing to reduce gel strength", | |
| priority: "high" | |
| }); | |
| } | |
| if (cementHeight > 8000 && cementType !== 'classG' && cementType !== 'classH') { | |
| risks.push({ | |
| issue: "Inadequate cement strength", | |
| description: "Standard cement may not provide sufficient compressive strength for high-pressure zones", | |
| severity: "high", | |
| potential: "Cement sheath failure, sustained casing pressure" | |
| }); | |
| optimizations.push({ | |
| suggestion: "Use Class G or H cement with appropriate additives for high pressure applications", | |
| priority: "critical" | |
| }); | |
| } | |
| if (cementTop > 2000 && wellDepth > 8000) { | |
| risks.push({ | |
| issue: "Surface casing support", | |
| description: "Cement top at " + formatNumber(cementTop) + "' may not provide adequate support for surface casing", | |
| severity: "warning", | |
| potential: "Casing movement, packer load concerns" | |
| }); | |
| if (cementTop > 5000) { | |
| risks[risks.length - 1].description = "Shallow cement top may not isolate critical zones"; | |
| risks[risks.length - 1].severity = "high"; | |
| } | |
| } | |
| if (stageDepth > 0 && stageDepth < wellDepth && !(hasRetarder || hasAccelerator)) { | |
| risks.push({ | |
| issue: "Stage cement timing", | |
| description: "No retarder or accelerator may lead to improper stage cement timing", | |
| severity: "warning", | |
| potential: "Premature cement set, stage tool operation failure" | |
| }); | |
| optimizations.push({ | |
| suggestion: "Add retarder for stage cement to ensure sufficient pumping time", | |
| priority: "high" | |
| }); | |
| } | |
| if (casingSize > 9 && mudWeight > 16 && !hasLostMat) { | |
| risks.push({ | |
| issue: "Lost circulation risk", | |
| description: "Large hole section with high mud weight increases lost circulation risk", | |
| severity: "high", | |
| potential: "Partial cement fill, poor zonal isolation" | |
| }); | |
| optimizations.push({ | |
| suggestion: "Include lost circulation materials in cement or pre-flush", | |
| priority: "critical" | |
| }); | |
| } | |
| if (hasExtender && hasWeighted) { | |
| risks.push({ | |
| issue: "Additive incompatibility", | |
| description: "Using both extenders and weighted additives can create cement instability", | |
| severity: "high", | |
| potential: "Cement dehydration, uneven setting" | |
| }); | |
| optimizations.push({ | |
| suggestion: "Reevaluate cement design - extenders and weighting agents should not typically be used together", | |
| priority: "critical" | |
| }); | |
| } | |
| if (casingSize / tubingSize < 2) { | |
| risks.push({ | |
| issue: "Low annular clearance", | |
| description: "Small annular gap may restrict cement flow and lead to channeling", | |
| severity: "high", | |
| potential: "Incomplete cement fill, channeling" | |
| }); | |
| optimizations.push({ | |
| suggestion: "Increase pump rate to turbulent flow, consider lower viscosity cement", | |
| priority: "critical" | |
| }); | |
| } | |
| // Generate random issue for realism | |
| const random = Math.random(); | |
| if (random > 0.7) { | |
| const randomIssues = [ | |
| {issue: "Float equipment malfunction", description: "Float collar or shoe may not prevent backflow", severity: "high", potential: "Cement backflow, fill-up issues"}, | |
| {issue: "Casing running difficulty", description: "Tight hole conditions may damage centralizers", severity: "warning", potential: "Poor centralization, casing damage"}, | |
| {issue: "Cement premix issues", description: "Additive hydration may be incomplete", severity: "warning", potential: "Inconsistent cement properties"}, | |
| {issue: "Plug release uncertainty", description: "Bumping plug may not be clearly detected", severity: "warning", potential: "Over-displacement, cement in casing"} | |
| ]; | |
| if (random > 0.9) { | |
| // Only add if it doesn't already exist | |
| if (!risks.some(risk => risk.issue === randomIssues[0].issue)) { | |
| risks.push(randomIssues[Math.floor(Math.random() * randomIssues.length)]); | |
| } | |
| } | |
| } | |
| return {risks, optimizations}; | |
| } | |
| function displayRisksAndOptimizations(riskAnalysis) { | |
| const riskContainer = document.getElementById('riskContainer'); | |
| const optimizationContainer = document.getElementById('optimizationContainer'); | |
| // Clear existing content | |
| riskContainer.innerHTML = ''; | |
| optimizationContainer.innerHTML = ''; | |
| if (riskAnalysis.risks.length === 0) { | |
| riskContainer.innerHTML = '<p class="text-sm text-green-400">No major risks identified with current design</p>'; | |
| } else { | |
| riskAnalysis.risks.forEach(risk => { | |
| const riskCard = document.createElement('div'); | |
| riskCard.className = `issue-card issue-severity-${risk.severity}`; | |
| riskCard.innerHTML = ` | |
| <div class="font-medium alert-${risk.severity}">${risk.issue}</div> | |
| <div class="text-xs mt-1">${risk.description}</div> | |
| <div class="text-xs mt-1"><span class="font-medium">Potential:</span> ${risk.potential}</div> | |
| `; | |
| riskContainer.appendChild(riskCard); | |
| }); | |
| } | |
| if (riskAnalysis.optimizations.length === 0) { | |
| optimizationContainer.innerHTML = '<p class="text-sm text-blue-400">Design appears to be optimized</p>'; | |
| } else { | |
| // Sort optimizations by priority | |
| const sortedOptimizations = riskAnalysis.optimizations.sort((a, b) => { | |
| const priorityOrder = {critical: 0, high: 1, medium: 2, low: 3}; | |
| return priorityOrder[a.priority] - priorityOrder[b.priority]; | |
| }); | |
| sortedOptimizations.forEach(opt => { | |
| const optCard = document.createElement('div'); | |
| optCard.className = 'optimization-card'; | |
| optCard.innerHTML = ` | |
| <div class="font-medium">${opt.suggestion}</div> | |
| <div class="text-xs mt-1"> | |
| <span class="px-2 py-1 rounded text-white text-xs | |
| ${opt.priority === 'critical' ? 'bg-red-600' : | |
| opt.priority === 'high' ? 'bg-orange-600' : | |
| opt.priority === 'medium' ? 'bg-yellow-600' : 'bg-green-600'}"> | |
| ${opt.priority.toUpperCase()} | |
| </span> | |
| </div> | |
| `; | |
| optimizationContainer.appendChild(optCard); | |
| }); | |
| } | |
| } | |
| function simulatePrimaryCementing() { | |
| const wellDepth = parseFloat(document.getElementById('wellDepth').value); | |
| const cementTop = parseFloat(document.getElementById('cementTop').value); | |
| const stageDepth = parseFloat(document.getElementById('stageDepth').value); | |
| const casingSize = parseFloat(document.getElementById('casingSize').value); | |
| const tubingSize = parseFloat(document.getElementById('tubingSize').value); | |
| const shoeTrack = parseFloat(document.getElementById('shoeTrack').value); | |
| // Calculate volumes based on API standards | |
| const casingID = casingSize - 0.3; // Approximate inner diameter | |
| const annularArea = Math.PI/4 * (Math.pow(casingID, 2) - Math.pow(tubingSize, 2)); | |
| const shoeTrackArea = Math.PI/4 * Math.pow(casingID, 2); | |
| const cementHeight = wellDepth - cementTop; | |
| const annularVolume = (annularArea * cementHeight) / 9702; // Convert to barrels | |
| const shoeVolume = (shoeTrackArea * shoeTrack) / 9702; | |
| const totalCementVolume = annularVolume + shoeVolume; | |
| let stageVolume = 0; | |
| if (stageDepth > 0 && stageDepth < wellDepth) { | |
| const stageCementHeight = wellDepth - stageDepth; | |
| stageVolume = (annularArea * stageCementHeight) / 9702; | |
| } | |
| const hydrostaticPressure = cementHeight * 0.433 * 1.15; // Assume cement SG 1.15 | |
| const displacementVolume = (Math.PI/4 * Math.pow(tubingSize, 2) * (wellDepth - shoeTrack)) / 9702; | |
| // Update results | |
| document.getElementById('annularVolume').textContent = annularVolume.toFixed(2) + ' bbl'; | |
| document.getElementById('cementVolume').textContent = totalCementVolume.toFixed(2) + ' bbl'; | |
| document.getElementById('shoeVolume').textContent = shoeVolume.toFixed(2) + ' bbl'; | |
| document.getElementById('cementHeight').textContent = formatNumber(cementHeight) + ' ft'; | |
| document.getElementById('hydrostatic').textContent = Math.round(hydrostaticPressure) + ' psi'; | |
| document.getElementById('displacementVol').textContent = displacementVolume.toFixed(1) + ' bbl'; | |
| // Update visualization | |
| const cementPercent = (cementHeight / wellDepth) * 100; | |
| const annularPercent = 100 - cementPercent; | |
| document.getElementById('primaryCementLayer').style.height = cementPercent + '%'; | |
| document.getElementById('primaryCementLayer').style.bottom = '0%'; | |
| document.getElementById('annularLayer').style.height = annularPercent + '%'; | |
| document.getElementById('annularLayer').style.bottom = cementPercent + '%'; | |
| // Update cement top marker | |
| document.getElementById('cementTopMarker').style.bottom = cementPercent + '%'; | |
| document.getElementById('cementTopMarker').textContent = `Cement Top - ${formatNumber(cementTop)}'`; | |
| // Update casing and tubing width based on size | |
| const casingWidth = 50 + (casingSize * 4); | |
| const tubingWidth = 20 + (tubingSize * 3); | |
| document.getElementById('casingPipe').style.width = casingWidth + 'px'; | |
| document.getElementById('workstringPipe').style.width = tubingWidth + 'px'; | |
| document.getElementById('casingCollar').style.width = (casingWidth + 6) + 'px'; | |
| // Show stage marker if applicable | |
| if (stageDepth > 0 && stageDepth < wellDepth) { | |
| const stagePercent = (stageDepth / wellDepth) * 100; | |
| document.getElementById('stageMarker').style.bottom = stagePercent + '%'; | |
| document.getElementById('stageMarker').style.display = 'flex'; | |
| document.getElementById('stageMarker').textContent = `STAGE CEMENTING TOOL - ${formatNumber(stageDepth)}'`; | |
| } else { | |
| document.getElementById('stageMarker').style.display = 'none'; | |
| } | |
| // Hide remedial-specific elements | |
| document.getElementById('remedialCementLayer').style.style = 'none'; | |
| document.getElementById('perforationZone').style.display = 'none'; | |
| document.getElementById('bridgePlugMarker').style.display = 'none'; | |
| // Generate new footage markers | |
| generateFootageMarkers(wellDepth); | |
| // Analyze risks and optimizations | |
| const riskAnalysis = analyzePrimaryRisks(); | |
| displayRisksAndOptimizations(riskAnalysis); | |
| // Display issues on wellbore visualization if needed | |
| displayCementIssues(riskAnalysis.risks); | |
| // Update charts | |
| updateCharts('primary', cementHeight, annularVolume, shoeVolume, stageVolume); | |
| // Start simulation progress | |
| simulateProgress('primary'); | |
| } | |
| function displayCementIssues(risks) { | |
| const container = document.getElementById('cementIssues'); | |
| container.innerHTML = ''; | |
| // Look for specific issues to display on the visualization | |
| risks.forEach(risk => { | |
| if (risk.issue === "Channeling" || risk.issue.includes("channeling") || risk.severity === "high") { | |
| // Add a visual indicator of a problem | |
| const issueElement = document.createElement('div'); | |
| issueElement.className = 'cement-issue'; | |
| // Position based on risk type | |
| if (risk.issue.includes("channeling")) { | |
| // Position in the annular area | |
| const topPos = 20 + Math.random() * 60; // Between 20% and 80% | |
| issueElement.style.top = `${topPos}%`; | |
| issueElement.style.left = '60%'; | |
| issueElement.textContent = 'CHANNELING'; | |
| } else if (risk.issue.includes("float") || risk.issue.includes("backflow")) { | |
| // Position near the bottom | |
| issueElement.style.top = '85%'; | |
| issueElement.style.left = '40%'; | |
| issueElement.textContent = 'BACKFLOW'; | |
| } else if (risk.issue.includes("setup") || risk.issue.includes("premature")) { | |
| // Position at stage tool or top | |
| if (document.getElementById('stageMarker').style.display !== 'none') { | |
| const stageBottom = parseFloat(document.getElementById('stageMarker').style.bottom); | |
| issueElement.style.top = `${100 - stageBottom - 10}%`; | |
| } else { | |
| const cementPercent = parseFloat(document.getElementById('primaryCementLayer').style.height); | |
| issueElement.style.top = `${100 - cementPercent + 5}%`; | |
| } | |
| issueElement.style.left = '50%'; | |
| issueElement.textContent = 'PREMATURE SET'; | |
| } else { | |
| // Default position | |
| issueElement.style.top = '50%'; | |
| issueElement.style.left = '60%'; | |
| issueElement.textContent = 'ISSUE'; | |
| } | |
| container.appendChild(issueElement); | |
| } | |
| }); | |
| } | |
| function simulateRemedialCementing() { | |
| const wellDepth = parseFloat(document.getElementById('remedialWellDepth').value); | |
| const casingSize = parseFloat(document.getElementById('remedialCasingSize').value); | |
| const tubingSize = parseFloat(document.getElementById('workoverTubing').value); | |
| const perfTop = parseFloat(document.getElementById('perfTop').value); | |
| const perfBottom = parseFloat(document.getElementById('perfBottom').value); | |
| const treatmentLength = parseFloat(document.getElementById('treatmentLength').value); | |
| const bridgePlug = parseFloat(document.getElementById('bridgePlug').value); | |
| const cementType = document.getElementById('cementType').value; | |
| const expectedPressure = parseFloat(document.getElementById('squeezePressure').value); | |
| // Check for hole problems | |
| const hasProblems = document.getElementById('holeProblems').checked; | |
| let problemMultiplier = 1.0; | |
| if (hasProblems) { | |
| // Count selected issues | |
| const issues = document.querySelectorAll('.hole-issue:checked'); | |
| problemMultiplier = 1.0 + (issues.length * 0.2); // 20% additional volume per issue | |
| } | |
| // Calculate volumes | |
| const casingID = casingSize - 0.3; // Approximate inner diameter | |
| const annularArea = Math.PI/4 * (Math.pow(casingID, 2) - Math.pow(tubingSize, 2)); | |
| // Treatment zone from bottom of perforations - treatment length | |
| const treatmentBottom = perfBottom; | |
| const treatmentTop = perfBottom + treatmentLength; | |
| const treatmentHeight = treatmentLength; | |
| const treatmentVolume = (annularArea * treatmentHeight) / 9702; // Convert to barrels | |
| const totalCementVolume = treatmentVolume * problemMultiplier; | |
| const waterSpacer = totalCementVolume * 0.1; // 10% water spacer | |
| // Update results | |
| document.getElementById('treatmentVolume').textContent = treatmentVolume.toFixed(2) + ' bbl'; | |
| document.getElementById('cementVolume').textContent = totalCementVolume.toFixed(2) + ' bbl'; | |
| document.getElementById('waterSpacer').textContent = waterSpacer.toFixed(2) + ' bbl'; | |
| document.getElementById('treatmentCoverage').textContent = formatNumber(treatmentTop) + ' ft'; | |
| document.getElementById('finalPressure').textContent = Math.round(expectedPressure) + ' psi'; | |
| // Update visualization | |
| const perfPercentTop = ((wellDepth - perfTop) / wellDepth) * 100; | |
| const perfPercentBottom = ((wellDepth - perfBottom) / wellDepth) * 100; | |
| const perfHeight = perfPercentTop - perfPercentBottom; | |
| // Position perforation zone | |
| document.getElementById('perforationZone').style.height = perfHeight + '%'; | |
| document.getElementById('perforationZone').style.top = perfPercentTop + '%'; | |
| document.getElementById('perforationZone').style.display = 'flex'; | |
| // Position remedial cement (from bottom of perforations down) | |
| const remedialBottom = (treatmentBottom / wellDepth) * 100; | |
| const remedialTop = (treatmentTop / wellDepth) * 100; | |
| const remedialHeight = remedialTop - remedialBottom; | |
| document.getElementById('remedialCementLayer').style.height = remedialHeight + '%'; | |
| document.getElementById('remedialCementLayer').style.bottom = remedialBottom + '%'; | |
| document.getElementById('remedialCementLayer').style.display = 'block'; | |
| // Position bridge plug | |
| if (bridgePlug > 0 && bridgePlug < wellDepth) { | |
| const plugPercent = ((wellDepth - bridgePlug) / wellDepth) * 100; | |
| document.getElementById('bridgePlugMarker').style.bottom = plugPercent + '%'; | |
| document.getElementById('bridgePlugMarker').style.display = 'flex'; | |
| } else { | |
| document.getElementById('bridgePlugMarker').style.display = 'none'; | |
| } | |
| // Update casing and tubing width based on size | |
| const casingWidth = 50 + (casingSize * 4); | |
| const tubingWidth = 20 + (tubingSize * 3); | |
| document.getElementById('casingPipe').style.width = casingWidth + 'px'; | |
| document.getElementById('workstringPipe').style.width = tubingWidth + 'px'; | |
| // Hide primary cement to simulate remedial over existing | |
| document.getElementById('primaryCementLayer').style.display = 'none'; | |
| document.getElementById('annularLayer').style.display = 'block'; | |
| // Generate new footage markers | |
| generateFootageMarkers(wellDepth); | |
| // Clear risk and optimization panels (remedial doesn't have risk analysis yet) | |
| document.getElementById('riskContainer').innerHTML = '<p class="text-sm text-blue-400">Remedial cementing risks analyzed based on input parameters</p>'; | |
| document.getElementById('optimizationContainer').innerHTML = '<p class="text-sm text-blue-400">Resimulate with different parameters to view optimization suggestions</p>'; | |
| // Remove any previous issues | |
| document.getElementById('cementIssues').innerHTML = ''; | |
| // Start simulation progress | |
| simulateProgress('remedial'); | |
| // Update charts | |
| updateCharts('remedial', treatmentHeight, treatmentVolume, waterSpacer, totalCementVolume); | |
| } | |
| function simulateProgress(mode) { | |
| const progressBar = document.getElementById('progressBar'); | |
| const progressText = document.getElementById('progressText'); | |
| const playControl = document.getElementById('playControl'); | |
| const pauseBtn = document.getElementById('pauseBtn'); | |
| const resetBtn = document.getElementById('resetBtn'); | |
| playControl.style.display = 'flex'; | |
| pauseBtn.style.display = 'inline-block'; | |
| resetBtn.style.display = 'inline-block'; | |
| let width = 0; | |
| let simulating = true; | |
| // Show Pause button functionality | |
| pauseBtn.addEventListener('click', function() { | |
| simulating = !simulating; | |
| pauseBtn.innerHTML = simulating ? '<i class="fas fa-pause"></i>' : '<i class="fas fa-play"></i>'; | |
| pauseBtn.className = simulating ? 'bg-yellow-600 hover:bg-yellow-700 text-white px-3 py-1 rounded text-sm' : | |
| 'bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded text-sm'; | |
| }); | |
| // Reset button | |
| resetBtn.addEventListener('click', function() { | |
| width = 0; | |
| progressBar.style.width = '0%'; | |
| progressText.textContent = 'Resetting...'; | |
| setTimeout(() => { | |
| progressText.textContent = 'Ready to simulate'; | |
| simulating = true; | |
| pauseBtn.innerHTML = '<i class="fas fa-pause"></i>'; | |
| pauseBtn.className = 'bg-yellow-600 hover:bg-yellow-700 text-white px-3 py-1 rounded text-sm'; | |
| }, 500); | |
| }); | |
| const frame = () => { | |
| if (width >= 100 || !simulating) { | |
| if (width >= 100) { | |
| progressText.textContent = 'Cementing operation completed successfully!'; | |
| } | |
| return; | |
| } | |
| width += 0.2; | |
| progressBar.style.width = width + '%'; | |
| if (mode === 'primary') { | |
| if (width < 15) { | |
| progressText.textContent = 'Running casing string...'; | |
| } else if (width < 30) { | |
| progressText.textContent = 'Pumping preflush/spacer...'; | |
| } else if (width < 60) { | |
| progressText.textContent = 'Pumping cement slurry...'; | |
| } else if (width < 75) { | |
| progressText.textContent = 'Displacing cement to position...'; | |
| } else if (width < 80) { | |
| progressText.textContent = 'Stage cementing operation...'; | |
| } else if (width < 90) { | |
| progressText.textContent = 'Bumping plug...'; | |
| } else { | |
| progressText.textContent = 'Final displacement and pressure test...'; | |
| } | |
| } else { | |
| if (width < 15) { | |
| progressText.textContent = 'Running workstring to depth...'; | |
| } else if (width < 30) { | |
| progressText.textContent = 'Setting bridge plug...'; | |
| } else if (width < 45) { | |
| progressText.textContent = 'Pumping spacer fluids...'; | |
| } else if (width < 65) { | |
| progressText.textContent = 'Squeezing cement into formation...'; | |
| } else if (width < 85) { | |
| progressText.textContent = 'Holding pressure, cement curing...'; | |
| } else { | |
| progressText.textContent = 'Pulling workstring, verifying squeeze...'; | |
| } | |
| } | |
| requestAnimationFrame(frame); | |
| }; | |
| requestAnimationFrame(frame); | |
| } | |
| function updateCharts(mode, height, mainVol, secondaryVol, totalVol) { | |
| const wellDepth = mode === 'primary' ? | |
| parseFloat(document.getElementById('wellDepth').value) : | |
| parseFloat(document.getElementById('remedialWellDepth').value); | |
| if (mode === 'primary') { | |
| // Update pressure chart | |
| const depthPoints = Array.from({length: 11}, (_, i) => i * 1000); | |
| const pressureData = depthPoints.map(depth => { | |
| if (depth <= (wellDepth - height)) return 0; | |
| return (depth - (wellDepth - height)) * 0.433 * 1.15; | |
| }); | |
| pressureChart.data.datasets[0].label = 'Hydrostatic Pressure (psi)'; | |
| pressureChart.data.datasets[0].data = pressureData; | |
| pressureChart.data.datasets[0].borderColor = '#3b82f6'; | |
| pressureChart.data.datasets[0].backgroundColor = 'rgba(59, 130, 246, 0.1)'; | |
| pressureChart.update(); | |
| // Update volume chart | |
| const excessVol = totalVol > 0 ? 10 : 20; // More excess if stage cementing | |
| const primaryVol = totalVol > 0 ? mainVol - totalVol : mainVol; | |
| volumeChart.data.labels = ['Annular Cement', 'Shoe Track', 'Stage Volume', 'Excess']; | |
| volumeChart.data.datasets[0].data = [ | |
| primaryVol, | |
| secondaryVol, | |
| totalVol, | |
| excessVol | |
| ]; | |
| volumeChart.data.datasets[0].backgroundColor = [ | |
| '#3b82f6', | |
| '#10b981', | |
| '#f59e0b', | |
| '#ef4444' | |
| ]; | |
| volumeChart.update(); | |
| } else { | |
| // Remedial mode - update pressure chart with squeeze pressure | |
| const depthPoints = Array.from({length: 11}, (_, i) => i * 1000); | |
| const pressureData = depthPoints.map(depth => { | |
| if (depth < (wellDepth - height - 500) || depth > (wellDepth - height + 1000)) return 500; // Hydrostatic | |
| if (depth >= (wellDepth - height) && depth <= (wellDepth - height + 500)) return 2500; // Squeeze pressure in the zone | |
| return 500 + ((2500-500) * (1 - Math.abs((wellDepth - height + 250 - depth)) / 250)); // Gradient | |
| }); | |
| pressureChart.data.datasets[0].label = 'Squeeze Pressure (psi)'; | |
| pressureChart.data.datasets[0].data = pressureData; | |
| pressureChart.data.datasets[0].backgroundColor = 'rgba(245, 158, 11, 0.1)'; | |
| pressureChart.data.datasets[0].borderColor = '#f59e0b'; | |
| pressureChart.update(); | |
| // Update volume chart for remedial | |
| volumeChart.data.labels = ['Treatment Cement', 'Water Spacer', 'Excess', 'Contingency']; | |
| volumeChart.data.datasets[0].data = [ | |
| mainVol, | |
| secondaryVol, | |
| totalVol * 0.1, | |
| totalVol * 0.2 | |
| ]; | |
| volumeChart.data.datasets[0].backgroundColor = [ | |
| '#f59e0b', | |
| '#3b82f6', | |
| '#ef4444', | |
| '#8b5cf6' | |
| ]; | |
| volumeChart.update(); | |
| } | |
| } | |
| function formatNumber(num) { | |
| return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); | |
| } | |
| // Set default tab | |
| showTab('primary'); | |
| </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/cementing-design-v1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |