### Build Documentation with uv sync and mkdocs serve Source: https://marlim3.readthedocs.io/en/latest Commands to install documentation dependencies and serve the documentation locally using uv and mkdocs. ```bash uv sync --group docs uv run mkdocs serve ``` -------------------------------- ### Verify Marlim3 installation Source: https://marlim3.readthedocs.io/en/latest/getting-started Runs a Python one-liner to print the installed Marlim3 version. Use this after the initial setup to confirm the package is importable. ```bash uv run --locked python -c "import marlim3; print(marlim3.__version__)" ``` -------------------------------- ### Setup and imports for Marlim3 nodal analysis Source: https://marlim3.readthedocs.io/en/latest/tutorials/2-nodal_analysis Loads autoreload extensions and imports matplotlib, numpy, marlim3, and copy for the tutorial. This is the initial setup cell for the notebook. ```python %load_ext autoreload %autoreload 2 import matplotlib.pyplot as plt import numpy as np import marlim3 import copy ``` -------------------------------- ### Load Marlim3 and dependencies Source: https://marlim3.readthedocs.io/en/latest/tutorials/1-horizontal_vertical_comparison Sets up the notebook environment by loading the autoreload extension and importing numpy, marlim3, and copy. This is the initial setup for the tutorial. ```python %load_ext autoreload %autoreload 2 import numpy as np import marlim3 import copy ``` -------------------------------- ### Install dependencies and Python package with uv Source: https://marlim3.readthedocs.io/en/latest/getting-started Creates a .venv with Python 3.12+, installs dev tools (pytest, flake8, jupyter, etc.), and installs marlim3 in editable mode. After this step, you can use 'import marlim3' in your scripts. ```bash uv sync --locked --group dev ``` -------------------------------- ### Build Desktop Application with uv Source: https://marlim3.readthedocs.io/en/latest/getting-started Build the standalone desktop application for the current operating system. The script detects the platform, builds the native engine, installs desktop dependencies, and writes a release-named artifact to dist/. ```bash uv run python -m marlim3_desktop.build ``` -------------------------------- ### Example initialConfig JSON for Marlim3 Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/general Shows a complete initialConfig JSON object for the Marlim3 simulator. It includes system, transient, slip, drift, flow pattern, mass transfer, and advanced settings. The tip advises keeping advanced and optional features at defaults until baseline results are validated. ```json { "system": "PROD", "initialConfig": { "transient": false, "initialCondition": 1, "steadyStateSlip": true, "transientSlip": true, "driftModel": true, "flowPatternMap": 0, "massTransfer": 0, "steadyStateOrder": 1, "checkValve": 0, "geometryFollowsFlow": true, "gasLine": false, "pressureTable": true, "correlationsByPattern": { "stratified": 1, "slugBubble": 1, "annularChurn": 1 }, "advanced": { "threads": 1, "massTransferLimit": 10.0, "simplePressureFrontier": true, "accelerateSteadyConvergence": true } } } ``` -------------------------------- ### Run Marlim3 Desktop Application on Linux Source: https://marlim3.readthedocs.io/en/latest/getting-started Make the Linux desktop executable runnable and start it. The executable is a self-contained ELF binary requiring glibc 2.34 or newer. ```bash chmod +x Marlim3-desktop-linux-x64 ./Marlim3-desktop-linux-x64 ``` -------------------------------- ### XY Mode with Correction Factors Configuration (PT keys) Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/pipes Example JSON configuration for XY mode with correction factors, using Portuguese keys. The initial config disables gas line and enables XY mode with starting coordinates. Two production pipes are defined with coordinates, cell counts, and correction factors for friction and temperature. ```json { "configuracaoInicial": { "linhaGas": false, "modoXY": true, "xProdInicio": 0.0, "yProdInicio": -2000.0 }, "dutosProducao": [ { "id": 0, "ativo": true, "idCorte": 0, "idFormacao": 0, "xCoor": 500.0, "yCoor": -1800.0, "nCelulas_XY": 25, "dPdLFric": 0, "dTdL": 0 }, { "id": 1, "ativo": true, "idCorte": 0, "idFormacao": 0, "xCoor": 1000.0, "yCoor": -1500.0, "nCelulas_XY": 50, "dPdLFric": 1, "dTdL": 1 } ] } ``` -------------------------------- ### Coupled Production/Service Segments Configuration (EN keys) Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/pipes Example JSON configuration for a coupled production and service pipe setup. Uses English keys. The initial config enables gas line and geometry follows flow, with XY mode disabled. Production and service pipes are defined with discretization cells. ```json { "initialConfig": { "gasLine": true, "xyMode": false, "geometryFollowsFlow": true }, "productionPipe": [ { "id": 0, "active": true, "crossSectionId": 0, "angle": -1.57079632679, "formationId": 0, "thermalCoupling": 1, "grouping": true, "discretization": [ {"numCells": 40, "length": 10.0} ] } ], "servicePipe": [ { "id": 0, "active": true, "crossSectionId": 1, "angle": -1.57079632679, "grouping": true, "discretization": [ {"numCells": 40, "length": 10.0} ] } ] } ``` -------------------------------- ### Launch Marlim3 Streamlit GUI Source: https://marlim3.readthedocs.io/en/latest/getting-started Synchronize the GUI dependencies and start the Streamlit-based graphical interface. The GUI auto-detects an executable from build/ or marlim3/ under the repository root; otherwise, provide the executable path manually in the app. ```bash uv sync --group gui uv run streamlit run gui/app.py ``` -------------------------------- ### Install Marlim3 via pip Source: https://marlim3.readthedocs.io/en/latest/getting-started Installs the Marlim3 Python package. On supported platforms, the first import downloads the matching native executable from GitHub Releases if not already present. ```bash pip install marlim3 ``` -------------------------------- ### Install and test with uv sync and pytest Source: https://marlim3.readthedocs.io/en/latest/dev-guide/dependencies Use these commands to install dependencies and run tests in a public development environment. The --locked flag prevents automatic lock updates during normal development. ```bash uv sync --locked --group dev uv run --locked python -m pytest ``` -------------------------------- ### Example JSON configuration for gas fluid Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/fluids Shows a complete JSON object with initialConfig, productionFluid, and compTable settings. The productionFluid array includes gasDensity, CO2Fraction, criticalCorrelation, and other fluid properties. The compTable defines a pressure-temperature table with 50 points. ```json { "initialConfig": { "flashTableFluidModel": false, "compositionalFluidModel": false, "fluidType": 0, "cpModel": 0, "jtlModel": 0, "pressureTable": true, "pvtFile": "PVT_CASE.tab" }, "productionFluid": [ { "id": 0, "active": true, "api": 28.0, "gasDensity": 0.65, "gor": 150.0, "bsw": 0.10, "waterDensity": 1.02, "CO2Fraction": 0.03, "deadOilModel": 3, "liveOilModel": 0, "undersaturatedOilModel": 0, "criticalCorrelation": 1, "RsPbModel": 0, "emulsionType": 0 } ], "compTable": { "active": true, "numPoints": 50, "minPressure": 1.0, "maxPressure": 500.0, "minTemperature": 4.0, "maxTemperature": 120.0 } } ``` -------------------------------- ### Install Homebrew GCC and CMake, then build on macOS Source: https://marlim3.readthedocs.io/en/latest/getting-started Install GCC and CMake via Homebrew, then configure and build Marlim3 using the gcc-release preset. The -j$(sysctl -n hw.ncpu) flag uses the number of hardware CPU cores for parallel compilation. ```bash brew install gcc cmake cmake --preset gcc-release cmake --build --preset gcc-release -j$(sysctl -n hw.ncpu) ``` -------------------------------- ### Two Formation IDs JSON Example Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/rock-formation Shows a formation configuration with two rock property sets, each with a distinct id. The productionTime is 180 days, and the two rocks have different thermal properties. ```json { "initialConfig": { "formation": { "productionTime": 180, "properties": [ { "id": 0, "conductivity": 3.0, "specificHeat": 900.0, "density": 2400.0 }, { "id": 1, "conductivity": 1.5, "specificHeat": 950.0, "density": 2500.0 } ] } } } ``` -------------------------------- ### Python bilingual API example with marlim3.Tramo Source: https://marlim3.readthedocs.io/en/latest/dev-guide/translations Shows how to create a Tramo (alias for Branch), set attributes and nested data using Portuguese keys, access nested values in both languages, write nested values in Portuguese, and export to JSON in Portuguese or English. ```python import marlim3 tramo = marlim3.Tramo() tramo.sistema = "PROD" tramo.fluidosProducao = [{"id": 0, "api": 30, "rgo": 100, "densidadeGas": 0.7, "bsw": 0.0}] tramo.secaoTransversal = [{ "id": 0, "diametroInterno": 0.254, "rugosidade": 1.83e-4, "camadas": [{"idMaterial": 0, "tipoMedicaoCamada": "ESPESSURA", "espessura": 0.0254}], }] # Nested access in both languages tramo.fluidosProducao[0]["densidadeGas"] # → 0.7 tramo.productionFluid[0]["gasDensity"] # → 0.7 # Nested write in Portuguese persists tramo.fonteLiquido[0]["vazaoLiquido"] = [2000] assert tramo.liquidSource[0]["liquidFlowRate"] == [2000] # Export in Portuguese tramo.to_json("modelo", language='pt') # Export in English (default) tramo.to_json("model") ``` -------------------------------- ### Preview dependency changes locally Source: https://marlim3.readthedocs.io/en/latest/dev-guide/dependencies Use these commands to test a changed manifest or pending upgrade locally while waiting for Actions. This uses a separate, ignored .venv-preview and temporary lock. Inside Petrobras, all preliminary resolution/downloads use JFrog. Preview results are provisional: the final public lock must be installed and tested again. ```python python scripts/dependencies.py preview --group dev --group docs python scripts/dependencies.py run --preview -- python -m pytest ``` -------------------------------- ### Single Rock Definition JSON Example Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/rock-formation Shows a minimal formation configuration with one rock property set. The productionTime is 365 days, and the rock has conductivity 2.5 W/(m·°C), specificHeat 850.0 J/(kg·°C), and density 2500.0 kg/m³. ```json { "initialConfig": { "formation": { "productionTime": 365, "properties": [ { "id": 0, "conductivity": 2.5, "specificHeat": 850.0, "density": 2500.0 } ] } } } ``` -------------------------------- ### translations.json structure example Source: https://marlim3.readthedocs.io/en/latest/dev-guide/translations Shows the JSON structure of translations.json with 'keys' and 'values' sections. The 'keys' section maps English key names to Portuguese, and 'values' maps English string values to Portuguese for specific keys. ```json { "keys": { "englishKeyName": "nomeChavePortugues", ... }, "values": { "keyName": { "ENGLISH_VALUE": "VALOR_PORTUGUES", ... } } } ``` -------------------------------- ### Initialize Marlim3 branch and configure simulation Source: https://marlim3.readthedocs.io/en/latest/tutorials/5_temperature_pulse Sets up the main Marlim3 object with initial settings, time control, production fluid, separator, and liquid source to simulate a thermal pulse. ```python case = marlim3.Branch() case.initialConfig = { "transient": True, "initialCondition": 0, "initialFluidId": 0 } case.time = { "finalTime": 3000.0, "times": [0.0], "maxDT": [0.4] } case.productionFluid = [{ "id": 0, "api": 35.95, "gor": 0.0, "gasDensity": 0.845, "bsw": 0.0 }] case.separator = { "time": [0], "pressure": [15.0] } case.liquidSource = [{ "id": 0, "prodFluidId": 0, "measuredLength": 0.0, "time": [0, 999, 1000, 1499, 1500, 3000], "temperature": [20.0, 20.0, 80.0, 80.0, 20.0, 20.0], "liquidFlowRate": [3000, 3000, 3000, 3000, 3000, 3000] }] ``` -------------------------------- ### Simulate base case with gas lift (base_case_vgl.simulate()) Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Runs the simulation for the base case with gas lift using the %%time magic to measure execution time. The output includes a log file named 'simulacao.log' and CPU/wall time. ```python %%time base_case_vgl.simulate() ``` ```text ******************************************************************************* UFA!!!!!!!! Quem vive de navegar, o vento e quem lhe comanda Seu Pereira na feira de artesanatos numericos ******************************************************************************* ARQUIVO DE LOG: simulacao.log CPU times: total: 31.2 ms Wall time: 2.51 s ``` -------------------------------- ### Simulate strong coupling case (strong_coupling_case.simulate()) Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Runs the simulation for the strong coupling case using the %%time magic. The output includes a log file named 'simulacao.log' and CPU/wall time. ```python %%time strong_coupling_case.simulate() ``` ```text ******************************************************************************* UFA!!!!!!!! Infeliz e o espirito ansioso pelo futuro. Seneca do Mindfulness ******************************************************************************* ARQUIVO DE LOG: simulacao.log CPU times: total: 31.2 ms Wall time: 2.75 s ``` -------------------------------- ### Run Marlim3 on Windows Source: https://marlim3.readthedocs.io/en/latest/getting-started Run the Marlim3 executable on Windows with a flow network simulation. Use .\ as the directory name to export results to the current working directory. ```bash # Windows Marlim3.exe -d .\output -i simulation.json -s REDE ``` -------------------------------- ### Set up Category III comparison case with gas-oil ratio 500 Sm³/Sm³ Source: https://marlim3.readthedocs.io/en/latest/tutorials/4_black_box_correlations Creates a deep copy of the base case, sets the gas-oil ratio (rgo) to 500 Sm³/Sm³, and runs the compare_correlations function with correlation IDs [4, 5, 6, 7, 8, 12] corresponding to Duns & Ros, Orkiszewski, Beggs & Brill, Mukherjee & Brill, Aziz, Govier & Fogarasi, and Beggs & Brill with Palmer correction. The output includes log messages from the simulation. ```python cat3_case = copy.deepcopy(base_case) cat3_case.productionFluid[0]['rgo'] = 500 #Sm3/Sm3 cat3_scenarios = compare_correlations(cat3_case, [4, 5, 6, 7, 8, 12]) ``` -------------------------------- ### Define well duct with geothermal gradient Source: https://marlim3.readthedocs.io/en/latest/tutorials/2-nodal_analysis Defines the well duct with 10 cells over 1000 m, specifying formation temperatures at three points (90°C at start, 50°C at 80%, 4°C at end) to represent the geothermal gradient. ```python n_cells = 10 total_length = 1000 # m discretization = { "numCells": n_cells, "length": total_length / n_cells # m } formation_conditions = { "measuredPosition": [0, 0.8, 1], "ambientTemp": [90, 50, 4], # degC } tubing = { "id": 0, "label": "Well", "crossSectionId": 0, "formationId": 0, "angle": np.pi / 2, # rad "discretization": [discretization], "initialConditions": formation_conditions } ``` -------------------------------- ### Build Marlim3 on Windows with MinGW Source: https://marlim3.readthedocs.io/en/latest/getting-started Configure and build Marlim3 on Windows using the mingw-release preset. The -j%NUMBER_OF_PROCESSORS% flag parallelizes the build. The resulting build/Marlim3.exe is fully statically linked and does not require external DLLs. ```bash cmake --preset mingw-release cmake --build --preset mingw-release -j%NUMBER_OF_PROCESSORS% ``` -------------------------------- ### Build and run optional C++ unit tests for Marlim3 Source: https://marlim3.readthedocs.io/en/latest/getting-started Opt-in verification tests for the numerical core. Configure with -DMARLIM_BUILD_TESTS=ON, build the test_friction_factor target, and run ctest with --output-on-failure to see detailed failures. ```bash cmake -S . -B build -DMARLIM_BUILD_TESTS=ON cmake --build build --target test_friction_factor ctest --test-dir build --output-on-failure ``` -------------------------------- ### Run comparative simulation for insulation scenarios Source: https://marlim3.readthedocs.io/en/latest/tutorials/5_temperature_pulse Sets up a production pipe with initial thermo-fluid-dynamic conditions, defines two study cases (no insulation and with insulation), and runs the Marlim3 simulation for each. The output folder is renamed to 'results_' after each run, removing any existing folder with that name. ```python # Base pipe configuration case.productionPipe = [{"id": 0, "label": "PIPE-1", "crossSectionId": 0, # This ID will be dynamically changed in the loop "angle": 0.0, "environment": 0, "discretization": [{"numCells": 100, "length": 5.0}], "initialConditions": { "measuredPosition": [0, 1], "temp": [20.0, 20.0], "pressure": [15.0, 15.0], "holdup": [1.0, 1.0], "complementaryFluidFraction": [0.0, 0.0], "usl": [1.9, 1.9], "usg": [0.0, 0.0], "ambientTemp": [4.0, 4.0], "ambientVel": [0.3, 0.3], "ambientConductivity": [0.6, 0.6], "ambientSpecificHeat": [3990.0, 3990.0], "ambientDensity": [1025.0, 1025.0], "ambientVisc": [1.5, 1.5]} }] # Defining scenarios for the loop study_cases = [ {"name": "no_insulation", "cross_section_id": 0, "title": "Bare Steel (No Insulation)"}, {"name": "with_insulation", "cross_section_id": 1, "title": "With Polyethylene Foam"} ] default_folder = "marlim3_resultados" for c in study_cases: # 1. Changes which cross-section the pipe will use case.productionPipe[0]["crossSectionId"] = c["cross_section_id"] # 2. Runs the simulation case.simulate() # 3. Renames the output folder destination_folder = f"results_{c['name']}" if os.path.exists(destination_folder): shutil.rmtree(destination_folder) os.rename(default_folder, destination_folder) ``` -------------------------------- ### Activate Marlim3 Python package locally with MARLIM3_SKIP_BUILD Source: https://marlim3.readthedocs.io/en/latest/getting-started After building, activate the Python package locally while skipping recompilation by setting MARLIM3_SKIP_BUILD=1 and running uv sync --locked. This ensures the package picks up the latest binary without rebuilding. ```bash MARLIM3_SKIP_BUILD=1 uv sync --locked ``` -------------------------------- ### Run base simulation with base_case.simulate() Source: https://marlim3.readthedocs.io/en/latest/tutorials/2-nodal_analysis Executes the base case simulation. The output includes a log message and the simulation log file 'simulacao.log'. ```python base_case.simulate() ``` -------------------------------- ### Set Venturi valve type and simulate comparison Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Creates deep copies of the base case, sets the Venturi valve type (valveType = 2) for one case, simulates both, and creates a Scenarios object for comparison. The simulation log output is shown. ```python orifice_case = copy.deepcopy(base_case_vgl) venturi_case = copy.deepcopy(base_case_vgl) venturi_case.gasLiftSource[0]['valveType'] = 2 # venturi venturi_case.simulate() orifice_venturi_comparison = marlim3.Scenarios({'orifice': orifice_case, 'venturi': venturi_case}) ``` ```text ******************************************************************************* UFA!!!!!!!! Uma vez me perguntaram o que achava da passagem do tempo, e eu disse: sou contra Luis Fernando Verissimo das Simulacoes Permanentes ******************************************************************************* ARQUIVO DE LOG: simulacao.log ``` -------------------------------- ### Add, remove, or upgrade dependencies Source: https://marlim3.readthedocs.io/en/latest/dev-guide/dependencies Run these commands to add, remove, or upgrade a package. Add/remove operations edit a temporary manifest and resolve it using your mode's index. Upgrade operations resolve against that index and write dependency-update.toml with explicit version requests. The official lock is preserved. A failed preliminary resolution leaves the official manifest, request and lock unchanged. ```python python scripts/dependencies.py add package-name --group docs python scripts/dependencies.py remove package-name --group docs python scripts/dependencies.py upgrade package-name python scripts/dependencies.py upgrade package-name==desired-version ``` -------------------------------- ### Access production profile with base_case.resultados['productionProfile'] Source: https://marlim3.readthedocs.io/en/latest/tutorials/2-nodal_analysis Retrieves the production profile data as a table with columns for pressure, temperature, liquid holdup, flow rates, and more. The output shows a sample of the data over time. ```python base_case.resultados['productionProfile'] ``` -------------------------------- ### Sync dependencies after building executable Source: https://marlim3.readthedocs.io/en/latest/getting-started Runs uv sync with MARLIM3_SKIP_BUILD=1 to skip local CMake compilation. This is required after building the C++/Fortran executable, as the CMake build copies the executable into marlim3/ automatically. ```bash MARLIM3_SKIP_BUILD=1 uv sync --locked ``` -------------------------------- ### Restart from Snapshot Configuration Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/time JSON configuration for restarting a transient simulation from a snapshot file. Sets initialCondition to 2 and specifies the snapshot file 'shutdown_3600s.snp'. Defines a new time schedule with finalTime 7200 and adaptive timesteps. ```json { "initialConfig": { "transient": true, "initialCondition": 2, "snapshotFile": "shutdown_3600s.snp" }, "time": { "finalTime": 7200, "times": [0, 100], "maxDT": [1.0, 5.0] } } ``` -------------------------------- ### Run Marlim3 on Linux/macOS Source: https://marlim3.readthedocs.io/en/latest/getting-started Run the Marlim3 executable on Linux or macOS with a flow network simulation. Use ./ as the directory name to export results to the current working directory. ```bash # Linux/macOS ./Marlim3 -d ./output -i simulation.json -s REDE ``` -------------------------------- ### Create uncoupled production duct and insert at position 0 Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Builds a dictionary for the uncoupled well section (0-200 m) with id 3, label 'Well - uncoupled section', crossSectionId 2, formationId 0, angle pi/2, and discretization of 2 cells of 100 m. Sets initial conditions using well_ambient_temperature at 0 and 200 m, then inserts the duct at the beginning of the productionPipe list. ```python uncoupled_production_duct = { 'id': 3, 'label': 'Well - uncoupled section', 'crossSectionId': 2, # new cross-section defined above, containing only the inner steel layer 'formationId': 0, # original formation 'angle': np.pi/2, 'discretization': [{'numCells': 2, 'length': 100}]} uncoupled_production_duct['initialConditions'] = {'measuredPosition': [0,1], 'ambientTemp': [well_ambient_temperature(0), well_ambient_temperature(200)]} base_case_vgl.productionPipe.insert(0, uncoupled_production_duct) ``` -------------------------------- ### Run Marlim3 Command-Line Simulations Source: https://marlim3.readthedocs.io/en/latest/getting-started Run the compiled Marlim3 executable with the four simulation types: simple production system, simple injection system, flow network, and natural convection in cross-section. The -d flag sets the output directory, -i specifies the input JSON file, and -s selects the simulation type. ```bash # 1. Simple production system ./Marlim3 -d output_directory -i input_file # 2. Simple injection system ./Marlim3 -d output_directory -i input_file -s INJETOR # 3. Flow network ./Marlim3 -d output_directory -i input_file -s REDE # 4. Natural convection in cross-section ./Marlim3 -d output_directory -i input_file -s CONVECNAT ``` -------------------------------- ### Configure global settings and boundary conditions for thermal pulse Source: https://marlim3.readthedocs.io/en/latest/tutorials/5_temperature_pulse Initializes the Marlim3 Branch object, sets transient simulation parameters, defines the production fluid, outlet separator pressure, and inlet liquid source with a thermal pulse (20°C to 80°C between 1000s and 1500s). ```python # Initializes the main Marlim3 object case = marlim3.Branch() # Initial settings case.initialConfig = { "transient": True, "initialCondition": 0, "initialFluidId": 0 } # Simulation time control case.time = { "finalTime": 3000.0, "times": [0.0], "maxDT": [0.4] } # Production fluid definition (35.95 API Oil, no free gas or initial water) case.productionFluid = [{ "id": 0, "api": 35.95, "gor": 0.0, "gasDensity": 0.845, "bsw": 0.0 }] # Outlet boundary condition case.separator = { "time": [0], "pressure": [15.0] } # Inlet boundary condition # We simulate a thermal pulse: fluid enters at 20°C, rises to 80°C between 1000s and 1500s, then returns to 20°C. case.liquidSource = [{ "id": 0, "prodFluidId": 0, "measuredLength": 0.0, "time": [0, 999, 1000, 1499, 1500, 3000], "temperature": [20.0, 20.0, 80.0, 80.0, 20.0, 20.0], "liquidFlowRate": [3000, 3000, 3000, 3000, 3000, 3000] }] ``` -------------------------------- ### Run Marlim3 Regression Tool Source: https://marlim3.readthedocs.io/en/latest/getting-started Synchronize the regression tool dependencies and run the regression and native coverage tool. See regression_tool/README.md for toolchain requirements and workflow details. ```bash uv sync --group regression_tool uv run regression_tool/run.py ``` -------------------------------- ### Create Scenarios object for comparison Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Creates a marlim3.Scenarios object to compare three cases: using gasSource, using gasLiftSource, and using gasLiftSource strong coupling. ```python source_comparison = marlim3.Scenarios({'using gasSource': base_case, 'using gasLiftSource': base_case_vgl, 'using gasLiftSource strong coupling': strong_coupling_case}) ``` -------------------------------- ### Standard Transient Configuration Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/time JSON configuration for a standard transient simulation with adaptive timesteps. Sets transient mode, initial condition 1, and defines time points with corresponding maximum timesteps. Includes saveSnapshot at 1800 and 3600 seconds for checkpoint writes. ```json { "initialConfig": { "transient": true, "initialCondition": 1, "initialFluidId": 0 }, "time": { "finalTime": 3600, "times": [0, 10, 100], "maxDT": [0.1, 1.0, 5.0], "saveSnapshot": [1800, 3600] } } ``` -------------------------------- ### Compute inlet pressure for correlations across flow rates Source: https://marlim3.readthedocs.io/en/latest/tutorials/4_black_box_correlations Loops over a range of liquid flow rates, simulating a drift-flux reference case and several black-box correlations. For each case, it sets the flow model and flow rate, disables classic output, and captures the inlet pressure from the production profile. Exceptions are caught and recorded as NaN. The results are stored in dictionaries for later plotting. ```python %%time selected_corrs = [0, 3, 6, 4, 5] flow_rates = np.linspace(500, 6000, 12) flow_rate_results = {corr_id: [] for corr_id in selected_corrs} drift_results = [] for flow_rate in flow_rates: # Drift-flux reference drift_case = copy.deepcopy(base_case) drift_case.initialConfig['driftModel'] = True drift_case.liquidSource[0]['liquidFlowRate'] = [flow_rate] drift_case.initialConfig['classicOutput'] = False try: drift_case.simulate() drift_results.append(drift_case.results['productionProfile'].iloc[:,2][0,0]) except Exception: drift_results.append(np.nan) # Black-box correlations for corr_id in selected_corrs: case = copy.deepcopy(base_case) case.productionPipe[0]['ssFlowModel'] = corr_id case.liquidSource[0]['liquidFlowRate'] = [flow_rate] case.initialConfig['classicOutput'] = False try: case.simulate() inlet_pressure = case.results['productionProfile'].iloc[:,2][0,0] except Exception: inlet_pressure = np.nan flow_rate_results[corr_id].append(inlet_pressure) ``` -------------------------------- ### Run the Marlim3 Python test suite Source: https://marlim3.readthedocs.io/en/latest/getting-started Run the Python test suite with pytest in verbose mode. See tests/README.md for markers, regression references, and how to update them. ```bash uv run pytest tests/ -v ``` -------------------------------- ### Set strongAnnularColCoupling in initialConfig.advanced Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Creates a deep copy of the base case and sets the strongAnnularColCoupling field to 20 in initialConfig.advanced to enable pseudo-transient marching for thermal coupling. ```python strong_coupling_case = copy.deepcopy(base_case_vgl) strong_coupling_case.initialConfig['advanced'] = {} strong_coupling_case.initialConfig['advanced']['strongAnnularColCoupling'] = 20 ``` -------------------------------- ### Create Marlim3 Scenarios for Horizontal and Vertical Cases Source: https://marlim3.readthedocs.io/en/latest/tutorials/1-horizontal_vertical_comparison Creates two Scenarios objects, scenarios_h and scenarios_v, using dictionary comprehensions that map flow rate legends to case objects. The legend format is 'Q = {flow_rate} sm3/d'. ```python scenarios_h = marlim3.Scenarios({f'Q = {flow_rate} sm3/d': cases_h[i] for i, flow_rate in enumerate(flow_rates)}) scenarios_v = marlim3.Scenarios({f'Q = {flow_rate} sm3/d': cases_v[i] for i, flow_rate in enumerate(flow_rates)}) ``` -------------------------------- ### Activate gas line in initialConfig Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Sets the 'gasLine' key to True in the base_case_vgl.initialConfig dictionary to enable the service line. This is the first step before defining service cross-sections. ```python base_case_vgl.initialConfig['gasLine'] = True ``` -------------------------------- ### Segregation Window Configuration Source: https://marlim3.readthedocs.io/en/latest/single-branch-model-reference/time JSON configuration for a transient simulation with a segregation window. Defines a time schedule with finalTime 86400 and segregationTime [0, 600] with segregation [0, 1] to control step size and convergence during sensitive transitions. ```json { "time": { "finalTime": 86400, "times": [0, 60, 600, 3600], "maxDT": [0.5, 2.0, 10.0, 30.0], "segregationTime": [0, 600], "segregation": [0, 1] } } ``` -------------------------------- ### Plot profiles with injection and master valve markers Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Plots the profiles from the source_comparison Scenarios object and adds vertical lines for the injection point and master valve position. ```python fig, axes = source_comparison.plot_profiles() for ax in axes: injection = ax.axvline(base_case.gasSource[0]['measuredLength'], c='r', label='injection point', ls='-.') anm = ax.axvline(base_case.masterValve['measuredLength'], c='k', label='master valve position', ls='--') fig.legend([injection, anm], ['injection point', 'master valve position'], loc='upper right'); ``` -------------------------------- ### Optimize gas flow rate and plot gas lift performance curve Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Uses scipy.optimize.minimize_scalar with the bounded method over the interval (1e5, 1e6) Sm3/d to find the optimal gas flow rate. It then generates 20 points across the interval, simulates each, and plots the produced liquid flow rate against injected gas flow rate, marking the optimal point. The cell uses %%time to measure execution time. ```python %%time # importing optimizer from scipy.optimize import minimize_scalar # gas flow rate search interval interval = (1e5, 1e6) #sm3/d # optimizing result = minimize_scalar(objective_function, bounds=interval, method='bounded') # optimal result optimal_gas_flow_rate = result.x optimal_liquid_flow_rate = -result.fun # generating points for the plot gas_flow_rates = np.linspace(interval[0], interval[1], 20) liquid_flow_rates = [] for gas_flow_rate in gas_flow_rates: optimization_case.gasSource[0]['gasFlowRate'] = [gas_flow_rate] optimization_case.simulate() produced_liquid_flow_rate = optimization_case.results['productionProfile'].loc[0, 'Standard dead oil volumetric flow rate (Sm3/d) F'].iloc[-1] liquid_flow_rates.append(produced_liquid_flow_rate) # plotting the objective function and the optimal point plt.figure(figsize=(10, 6)) plt.plot(gas_flow_rates, liquid_flow_rates, color='#39C0E0') plt.scatter(optimal_gas_flow_rate, optimal_liquid_flow_rate, color='#FFA933', label=f"Optimal Point\nQgi: {optimal_gas_flow_rate:.2f} Sm3/d\nQl: {optimal_liquid_flow_rate:.2f} Sm3/d") plt.xlabel("Injected Gas Flow Rate (Sm3/d)") plt.ylabel("Produced Liquid Flow Rate (Sm3/d)") plt.title("Gas Lift Performance Curve") plt.legend() plt.grid() ``` -------------------------------- ### Plot profiles from comparison results Source: https://marlim3.readthedocs.io/en/latest/tutorials/4_black_box_correlations Plots the profiles from the cat1_scenarios object returned by compare_correlations. The resulting plot shows pressure, temperature, holdup, and hydrostatic term profiles. ```python cat1_scenarios.plot_profiles(); ``` -------------------------------- ### Define monitored sections and production trend Source: https://marlim3.readthedocs.io/en/latest/tutorials/5_temperature_pulse Creates a list of positions from 0m to 1000m in 100m increments and assigns a production trend with temperature and external heat coefficient enabled for each position. ```python monitored_sections = [100 * i for i in range(0, 11)] case.productionTrend = [{"active": True, "measuredLength": pos, "dt": 1.0, "label": f"PIPE-1_Sec_{int(pos)}m", "temperature": True, "externalHeatCoef": True } for pos in monitored_sections] ``` -------------------------------- ### Import base case from JSON Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Creates a Branch object and loads the base case from 'base_case1_tutorials.mr3'. ```python base_case = marlim3.Branch() base_case.from_json('base_case1_tutorials.mr3') ``` -------------------------------- ### Create Marlim3 Branch object for base case Source: https://marlim3.readthedocs.io/en/latest/tutorials/2-nodal_analysis Initializes a new Branch object from the Marlim3 library, which serves as the base case for the nodal analysis workflow. ```python base_case = marlim3.Branch() ``` -------------------------------- ### Register materials and cross-sections in Marlim3 case database Source: https://marlim3.readthedocs.io/en/latest/tutorials/5_temperature_pulse Defines two materials (Carbon Steel and Poly_Ethylene_Foam) and two pipe cross-sections (no insulation and with 25mm PE insulation) in the Marlim3 case database. The sections reference the materials by ID and specify layer thickness and discretization. ```python case.material = [{"id": 0, "label": "Carbon Steel", "type": 0, "conductivity": 45.0, "specificHeat": 470.0, "rho": 7850.0}, {"id": 1, "label": "Poly_Ethylene_Foam", "type": 0, "conductivity": 0.04, "specificHeat": 2300.0, "rho": 32.0} ] # Section 1: Pipe with carbon steel only section_no_insulation = {"id": 0, "label": "Section_No_Insulation", "innerDiameter": 0.1524, "roughness": 5e-05, "layers": [{"label": "Tube Wall - Steel", "materialId": 0, "layerMeasurementType": "THICKNESS", "thickness": 0.0071, "discretization": 3}] } # Section 2: Carbon steel pipe coated with 25mm of Polyethylene Foam section_with_insulation = {"id": 1, "label": "Section_With_PE_Insulation", "innerDiameter": 0.1524, "roughness": 5e-05, "layers": [{"label": "Tube Wall - Steel", "materialId": 0, "layerMeasurementType": "THICKNESS", "thickness": 0.0071, "discretization": 3}, {"label": "Insulation - Foam", "materialId": 1, "layerMeasurementType": "THICKNESS", "thickness": 0.025, "discretization": 10}] } # Assigns both options to the model case.crossSection = [section_no_insulation, section_with_insulation] ``` -------------------------------- ### Simulation output Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Output from base_case.simulate() showing a log file message. ```text ******************************************************************************* UFA!!!!!!!! O sucesso nao e uma linha reta, e um jogo de resistencia, e cada tropeco e apenas um degrau a mais para a vitoria! Mario Pascal do Insta ******************************************************************************* ARQUIVO DE LOG: simulacao.log ``` -------------------------------- ### Build Marlim3 on Linux with GCC Source: https://marlim3.readthedocs.io/en/latest/getting-started Use the gcc-release CMake preset to configure and build Marlim3 on Linux. The -j$(nproc) flag parallelizes the build across all available CPU cores. ```bash cmake --preset gcc-release cmake --build --preset gcc-release -j$(nproc) ``` -------------------------------- ### Set corporate mode environment variables Source: https://marlim3.readthedocs.io/en/latest/dev-guide/dependencies Enable corporate mode for Petrobras by setting these environment variables. The values shown are placeholders, not a verified Petrobras endpoint. Do not put credentials in an index URL or commit local configuration. ```bash export MARLIM_DEPENDENCY_MODE=corporate export MARLIM_JFROG_INDEX='https://registry.example/artifactory/api/pypi/repository/simple' export UV_INDEX_JFROG_USERNAME='your-user' export UV_INDEX_JFROG_PASSWORD='your-token' ``` -------------------------------- ### Configure data acquisition sensors along pipeline Source: https://marlim3.readthedocs.io/en/latest/tutorials/5_temperature_pulse Defines sensor positions every 100 meters from 0 to 1000 meters and sets up production trends to monitor temperature and external heat coefficient. ```python monitored_sections = [100 * i for i in range(0, 11)] case.productionTrend = [{"active": True, "measuredLength": pos, "dt": 1.0, "label": f"PIPE-1_Sec_{int(pos)}m", "temperature": True, "externalHeatCoef": True } for pos in monitored_sections] ``` -------------------------------- ### Define output variables Source: https://marlim3.readthedocs.io/en/latest/tutorials/4_black_box_correlations Specifies the output variables to be recorded in the production profile, including pressure, temperature, holdup, and pressure gradients. ```python out_vars_list = ["pressure", "temperature", "holdup", "frictionPressureGradient", "hydrostaticPressureGradient"] output_vars = {"time": [0]} | {var: True for var in out_vars_list} base_case.productionProfile = output_vars ``` -------------------------------- ### Run Simulations for TPR Curve Source: https://marlim3.readthedocs.io/en/latest/tutorials/2-nodal_analysis Runs thirty simulations with flow rates from 10 to 8000 sm3/d, extracting bottom hole pressures from the results. After the loop, re-enables the IPR boundary condition and deactivates the liquid source. The execution time is shown as CPU times: total: 609 ms, Wall time: 1min 10s. ```python %%time flow_rates = np.linspace(10, 8000, 30) # sm3/d cases = [] # running a simulation for each flow rate for flow_rate in flow_rates: cases.append(copy.deepcopy(base_case)) cases[-1].initialConfig['classicOutput'] = False cases[-1].liquidSource[0]['liquidFlowRate'] = [flow_rate] cases[-1].simulate() # extracting bottom hole pressures from the results tpr_bottom_pressures = np.array([cases[i].resultados['productionProfile'].iloc[:, 2][0, 0] for i in range(len(cases))]) # re-enabling the IPR BC for the base case base_case.ipr[0]['active'] = True base_case.liquidSource[0]['active'] = False ``` -------------------------------- ### Plot inlet pressure vs. flow rate for correlations Source: https://marlim3.readthedocs.io/en/latest/tutorials/4_black_box_correlations Creates a plot of inlet pressure versus liquid flow rate for the drift-flux reference and each selected correlation. Uses markers for correlations and a dashed line for the reference. Labels axes, adds a title, legend, grid, and tight layout. ```python plt.figure(figsize=(10, 6)) plt.plot(flow_rates, drift_results, 'k--', linewidth=2, label='Drift-flux (ref.)') for corr_id in selected_corrs: plt.plot(flow_rates, flow_rate_results[corr_id], marker='o', label=corr_names[corr_id]) plt.xlabel('Liquid flow rate (Sm³/d)') plt.ylabel('Inlet pressure (kgf/cm²)') plt.title('Inlet pressure vs. flow rate — Vertical pipe') plt.legend() plt.grid() plt.tight_layout() ``` -------------------------------- ### Import required libraries for Marlim3 simulation Source: https://marlim3.readthedocs.io/en/latest/tutorials/5_temperature_pulse Imports Marlim3 and standard Python libraries (os, shutil, pandas, matplotlib) needed for the simulation and plotting. ```python import marlim3 import os import shutil import pandas as pd import matplotlib.pyplot as plt import matplotlib.cm as cm ``` -------------------------------- ### Access production profile Source: https://marlim3.readthedocs.io/en/latest/tutorials/3-gas_lift Retrieves the production profile from the simulation results. ```python base_case.results['productionProfile'] ```