diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7c73d8d..fba6fd7 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -37,10 +37,11 @@ jobs: sudo apt-get install libopm-simulators-bin sudo apt-get install texlive-fonts-recommended texlive-fonts-extra dvipng cm-super - - name: Install test dependecies + - name: Install dependecies run: | pip install --upgrade pip setuptools wheel pip install -r dev-requirements.txt + pip install opm - name: Install plopm run: | diff --git a/README.md b/README.md index 1eae1d8..5b07150 100755 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ # plopm: Simplified and flexible tool to visualize OPM Flow geological models ## Main feature -Quick generation of PNG figures from a simulation model given any 2D slide. +Quick generation of PNG figures and VTKs from a OPM Flow type model. ## Installation To install the _plopm_ executable in an existing Python environment: @@ -40,7 +40,7 @@ To use the conversion from OPM Flow output files (i.e., .EGRID, .INIT, .UNRST) t ## Running plopm You can run _plopm_ as a single command line: ``` -plopm -i some_input -o some_output_folder +plopm -i name(s)_of_input_file(s) ``` Run `plopm --help` to see all possible command line argument options. @@ -51,4 +51,4 @@ See the [_examples_](https://cssr-tools.github.io/plopm/examples.html) in the [_ The _plopm_ package is being funded by the [_HPC Simulation Software for the Gigatonne Storage Challenge project_](https://www.norceresearch.no/en/projects/hpc-simulation-software-for-the-gigatonne-storage-challenge) [project number 622059] and [_Center for Sustainable Subsurface Resources (CSSR)_](https://cssr.no) [project no. 331841]. This is work in progress. -Contributions are more than welcome using the fork and pull request approach. \ No newline at end of file +Contributions are more than welcome using the fork and pull request approach. For new features, please request them raising an issue. \ No newline at end of file diff --git a/docs/_images/about.png b/docs/_images/about.png index 3a175a9..e47e3f5 100644 Binary files a/docs/_images/about.png and b/docs/_images/about.png differ diff --git a/docs/_images/fgip_spe11b.png b/docs/_images/fgip_spe11b.png index 8cec964..b0bfda7 100644 Binary files a/docs/_images/fgip_spe11b.png and b/docs/_images/fgip_spe11b.png differ diff --git a/docs/_images/fgipm.png b/docs/_images/fgipm.png new file mode 100644 index 0000000..18a8696 Binary files /dev/null and b/docs/_images/fgipm.png differ diff --git a/docs/_images/norne.png b/docs/_images/norne.png new file mode 100644 index 0000000..52212b0 Binary files /dev/null and b/docs/_images/norne.png differ diff --git a/docs/_images/norne_transformed.png b/docs/_images/norne_transformed.png new file mode 100644 index 0000000..9fe06ba Binary files /dev/null and b/docs/_images/norne_transformed.png differ diff --git a/docs/_images/plopm.png b/docs/_images/plopm.png index 76ae289..434af77 100644 Binary files a/docs/_images/plopm.png and b/docs/_images/plopm.png differ diff --git a/docs/_images/spe10.png b/docs/_images/spe10.png index 00e6578..260187f 100644 Binary files a/docs/_images/spe10.png and b/docs/_images/spe10.png differ diff --git a/docs/_images/tcpu.png b/docs/_images/tcpu.png deleted file mode 100644 index f735d80..0000000 Binary files a/docs/_images/tcpu.png and /dev/null differ diff --git a/docs/_images/wells.png b/docs/_images/wells.png index 612d9f3..a02dc14 100644 Binary files a/docs/_images/wells.png and b/docs/_images/wells.png differ diff --git a/docs/_sources/about.rst.txt b/docs/_sources/about.rst.txt index 972aa90..22b4c6c 100644 --- a/docs/_sources/about.rst.txt +++ b/docs/_sources/about.rst.txt @@ -3,9 +3,8 @@ About plopm =========== .. image:: ./figs/about.png - :scale: 25% -This **plopm** package is being funded by the `HPC Simulation Software for the Gigatonne Storage Challenge project `_ +**plopm** is being funded by the `HPC Simulation Software for the Gigatonne Storage Challenge project `_ [project number 622059] and `Center for Sustainable Subsurface Resources (CSSR) `_ [project no. 331841]. This is work in progress. -Contributions are more than welcome using the fork and pull request approach. \ No newline at end of file +Contributions are more than welcome using the fork and pull request approach. For new features, please request them raising an issue. \ No newline at end of file diff --git a/docs/_sources/examples.rst.txt b/docs/_sources/examples.rst.txt index 8d7e4e3..9683b9d 100644 --- a/docs/_sources/examples.rst.txt +++ b/docs/_sources/examples.rst.txt @@ -22,43 +22,26 @@ The default argument options are: .. code-block:: bash - plopm -i SPE11B -o . -s ,1, -f 14 -x '' -y '' -z yes -u resdata -v '' -c '' -n '' -l '' -r -1 -w 0 + plopm -i SPE11B -o . -v '' -m png -s ,1, -p flow -z yes -f 14 -x '' -y '' -u resdata -c '' -e '' -n '' -b '' -d 8,16 -l '' -t '' -r -1 -w 0 -g 0 -a 1 -time s -ylabel '' -xlabel '' -ylnum 4 -xlnum 4 -cnum '' -clabel '' -labels '' -axgrid 1 -dpi 300 -xformat '' -yformat '' -xunits m -yunits m -remove 0,0,0,0 -facecolor w -save '' -log 0 -rotate 0 -translate '[0,0]' -global 0 -ncolor w See the :ref:`overview` or run `plopm -h` for the definition of the argument options. -For example, for the gas saturation at the report step number 4: +For example, for the gas saturation at the report step number 4 using a given colormap (-c): .. code-block:: bash - plopm -i SPE11B -v sgas -c cubehelix -r 4 -n "lambda x, _: f'{x:.2f}'" + plopm -i SPE11B -v sgas -r 4 -c cubehelix .. figure:: figs/sgas_spe11b.png -and for the gas in place summary vector: +and for the gas in place summary vector given a color, line style, font size, dimension of the figure, and using dates for the times: .. code-block:: bash - plopm -i SPE11B -v fgip -c k + plopm -i SPE11B -v fgip -c b -e ':' -f 12 -d 5,5 -time dates .. figure:: figs/fgip_spe11b.png - :scale: 20% - -===== -Norne -===== - -This example relies on the simulation results in `opm-tests `_. If you -download the files in that folder, then by using the **plopm** tool: - -.. code-block:: bash - - plopm -i NORNE_ATW2013 -o . -s ,,1 -x 455600,462200 -y 7319500,7327100 - -these are some of the generated figures: - -.. image:: ./figs/plopm.png - -Here, we plot the top view (xy axis, k=1), and we set the xlim (-x) and ylim (-y) in order to reduce the white space outside the active cells. + :scale: 30% ============ Generic deck @@ -73,16 +56,41 @@ for an example where **plopm** is used to generate figures from the .. code-block:: bash - plopm -i SPE10_MODEL2 -o . -s 4,, + plopm -i SPE10_MODEL2 -v permz -s ,4, -log 1 -xunits km -yunits km -xlnum 6 -yformat .2f -t 'K$_z$ at the forth slide in the xz plane' -b '[1e-7,1e3]' -To plot the location of the wells from the top view, then: +Here, we look at the forth slide in the xz plane and use log scale for the permeability in the z direction, as well as changing the axis units to km, +setting the format to the numbers to two floats in the y axis, and setting manualli the upper and lower bound for the color map. + +To plot information for the grid, and also the location of the wells from the top view, this is achieved by: .. code-block:: bash - plopm -i SPE10_MODEL2 -w 1 + plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -g 1 && plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -w 1 .. image:: ./figs/wells.png - :scale: 20% + +=============================== +Rotation, translation, and zoom +=============================== + +This example relies on the simulation results in `opm-tests `_. If you +download the files in that folder, then by using the **plopm** tool: + +.. code-block:: bash + + plopm -i NORNE_ATW2013 -s ,,1 + +these are some of the generated figures: + +.. image:: ./figs/norne.png + +In order to reduce the white space outside the active cells, as well as to rotate the grid and translate it, this can be ahieved by: + +.. code-block:: bash + + plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 20 + +.. image:: ./figs/norne_transformed.png ===================== Different input files @@ -93,11 +101,12 @@ called spe11b_larger_inj. Then, to plot the summary vector for both runs we can .. code-block:: bash - plopm -i spe11b/SPE11B,/Users/dmar/spe11b_larger_inj/SPE11B -v tcpu -d 5,5 -c r,b -e 'solid;:' -t 'Comparing the simulation times' -f 10 + plopm -i spe11b/SPE11B,/home/user/spe11b_larger_inj/SPE11B -v fgipm -a 1e-6 -time w -d 5,5 -c r,b -e 'solid;:' -t 'Comparing the total mass' -f 10 -.. image:: ./figs/tcpu.png +.. image:: ./figs/fgipm.png + :scale: 30% -Here, we have lower the size of the figure to 5,5 inches, set to use red and blue colors with solid and dotted lines, as well as settting the title and lower the font size to 10. +Here, we plot the injected mass and scaled to kilo tons, and the time is shown in weeks. .. tip:: For any summary variable, one can give the path to more than two different simulation cases, just by separating the folder paths by commas in the -i. @@ -114,7 +123,7 @@ To changue the colormap and setting the clorbar limits manually, this can be ach .. code-block:: bash - plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]' + plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]' -n "lambda x, _: f'{x:.3f}'" .. image:: ./figs/sgas_diff_edit.png @@ -122,12 +131,12 @@ To changue the colormap and setting the clorbar limits manually, this can be ach Convert to VTK ============== Inside the `examples folder `_, then we can create VTKs from the -OPM Flow simulation results (i.e., .EGRID, .INIT, .UNRST). For example, to create VTKS for the temperature from the restart -files from the initial (0) to the number 5 restart, using a OPM Flow build from source in a given path, this can be achieved by: +OPM Flow simulation results (i.e., .EGRID, .INIT, .UNRST). For example, to create VTKS for the temperature, fipnum, and the co2 mass +from the restart files from the initial (0) to the number 5 restart, using a OPM Flow build from source in a given path, this can be achieved by: .. code-block:: bash - plopm -i SPE11B -v temp -r 0,5 -m vtk -p /Users/dmar/build/opm-simulators/bin/flow + plopm -i SPE11B -v temp,fipnum,co2m -r 0,5 -m vtk -p /Users/dmar/build/opm-simulators/bin/flow .. figure:: ./figs/vtk_temp.png @@ -136,4 +145,5 @@ files from the initial (0) to the number 5 restart, using a OPM Flow build from .. note:: It is possible to write directly VTKs from OPM Flow simulations by adding the flag **--enable-vtk-output=true**. - However, there are quantities that are not written (e.g., fipnum, flores). This is when **plopm** can be helpful. \ No newline at end of file + However, there are quantities that are not written (e.g., fipnum, flores), in addition to quantities not supported + such as component mass (e.g., co2, h2o). This is when **plopm** can be helpful. \ No newline at end of file diff --git a/docs/_sources/installation.rst.txt b/docs/_sources/installation.rst.txt index b13688f..f670a5f 100644 --- a/docs/_sources/installation.rst.txt +++ b/docs/_sources/installation.rst.txt @@ -34,6 +34,7 @@ install the Python requirements in a virtual environment with the following comm .. note:: For not macOS users, to install the Python opm package, execute in the terminal **pip install opm**. + In addition, to install the dependencies used for the figure's formatting, execute **sudo apt-get install texlive-fonts-recommended texlive-fonts-extra dvipng cm-super**. For macOS, see :ref:`macOS`. OPM Flow @@ -84,7 +85,7 @@ in the terminal the following lines (which in turn should build flow in the fold You can create a .sh file (e.g., build_opm_mpi.sh), copy the previous lines, and run in the terminal **source build_opm_mpi.sh** Regarding the reading of from OPM Flow output files (i.e., .EGRID, .INIT, .UNRST), it is possible to use the opm python package instead of resdata (e.g., it seems the opm Python package -is faster than resdata to read large simulation files). To use opm, you first need to install it, by executing in the terminal **pip install opm**. +is faster than resdata to read large simulation files). To use opm, you first need to install it, by executing in the terminal **pip install opm** and when executing plopm adding the flag **-u opm**. .. _macOS: diff --git a/docs/_sources/introduction.rst.txt b/docs/_sources/introduction.rst.txt index 0eb2153..61e7db2 100644 --- a/docs/_sources/introduction.rst.txt +++ b/docs/_sources/introduction.rst.txt @@ -4,11 +4,11 @@ Introduction .. image:: ./figs/plopm.png -This documentation describes the content of the **plopm** tool. +This documentation describes the **plopm** tool hosted in `https://github.com/cssr-tools/plopm `_. Concept ------- -Simplified and flexible framework for quick visualization of `OPM Flow `_ geological models. +Simplified and flexible framework for quick visualization of `OPM Flow `_ geological models. The approach is the generation of PNG figures from static (e.g, porosity, pore volume fluid in place numbers) and dynamic (e.g., pressure, fluid saturations) properties given any 2D slide (e.g., the middle part of a reservoir in the xy plane), as well as plotting any given summary vector (e.g., field gas in place a.k.a fgip). @@ -26,29 +26,55 @@ The current implementation supports the following executable with the argument o .. code-block:: bash - plopm -i some_input -o some_output_folder + plopm -i name(s)_of_input_file(s) where -- \-i: The base name of the input files; if more than one is given, separate them by ',' (e.g, 'SPE11B,SPE11B_TUNED') (`SPE11B` by default). -- \-o: The base name of the output folder (`.` by default). -- \-f: The font size (`14` by default). -- \-s: The slide for the 2D maps of the static variables, e.g, `10,,` to plot the xz plane on all cells with i=10 (`,1,` by default, i.e., the xz surface at j=1). -- \-x: Option to set the lower and upper bounds in the 2D map along x ('' by default). -- \-y: Option to set the lower and upper bounds in the 2D map along y ('' by default). -- \-z: The option to scale the axis in the 2D maps (`yes` by default). -- \-u: Use resdata or opm Python libraries (`resdata` by default). -- \-v: Specify the name of the static vairable to plot (e.g., `depth`) ('' by default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum). -- \-c: Specify the colormap (e.g., `jet`) ('' by default, i.e., set by plopm). -- \-n: Specify the format for the numbers in the colormap (e.g., "lambda x, _: f'{x:.0f}'") ('' by default, i.e., set by plopm). -- \-l: Specify the units (e.g., \"[m\\$^2\\$]\") ('' by default, i.e., set by plopm). -- \-r: Restart number to plot the dynamic variable, where 1 corresponds to the initial one ('-1' by default, i.e., the last restart file). -- \-w: Plot the positions of the wells or sources ('0' by default). -- \-g: Plot information about the number of cells in the x, y, and z directions and number of active grid cells ('0' by default). -- \-e: Specify the linestyles separated by ';' (e.g., 'solid;:') ('' by default, i.e., set by plopm). -- \-b: Specify the upper and lower bounds for the color map (e.g., '[-0.1,11]') ('' by default, i.e., set by matplotlib). -- \-d: Specify the dimensions of the Figure (e.g., '5,5') ('8,16' by default). -- \-t: Specify the figure title (e.g., 'Final saturation map') ('' by default, i.e., set by plopm). -- \-r: Restart number to plot the dynamic variable, where 1 corresponds to the initial one ('-1' by default, i.e., the last restart file). -- \-p: Path to flow (e.g., '\home\build\bin\flow'). This is used to generate the grid for the vtk files ('flow' by default). -- \-m: Generate 'png' or 'vtk' files ('png' by default). \ No newline at end of file +-i The base name (or full path) of the input files; if more than one is given, separate them by ',' (e.g, 'SPE11B,\\home\\user\\SPE11B_TUNED') ('SPE11B' by default). +-o The base name (or full path) of the output folder ('.' by default, i.e., the folder where plopm is executed). +-v Specify the name of the vairable to plot, e.g., 'pressure', in addition to special extensive quantities for the mass such as 'gasm', 'dism', 'liqm', 'vapm', 'co2m', 'h2om', 'fwcdm', and 'fgipm' ('' by default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum). +-m Generate 'png' or 'vtk' files ('png' by default). +-s The slide in the 3D model to plot the 2D maps, e.g, '10,,' to plot the xz plane on all cells with i=10 (',1,' by default, i.e., the xz surface at j=1). +-p Path to flow, e.g., '\\home\\build\\bin\\flow'. This is used to generate the grid for the vtk files ('flow' by default). +-z Scale the axis in the 2D maps ('1' by default). +-f The font size ('14' by default). +-x Set the lower and upper bounds along x, e.g., '[-100,200]' ('' by default). +-y Set the lower and upper bounds along y, e.g., '[-10,300]' ('' by default). +-u Use resdata or opm Python libraries ('resdata' by default). +-c Specify the colormap, e.g., 'jet', or color(s) for the summary, e.g., 'b,r' ('' by default, i.e., set by plopm). +-e Specify the linestyles separated by ';', e.g., 'solid;:' ('' by default, i.e., set by plopm). +-n Specify the format for the numbers in the colormap, e.g., "lambda x, _ f'{x:.0f}'" ('' by default, i.e., set by plopm). +-b Specify the upper and lower bounds for the color map, e.g., '[-0.1,11]' ('' by default, i.e., set by plopm). +-d Specify the dimensions in inches generated png, e.g., '5,5' ('8,16' by default). +-l Specify the units of the variable, e.g., \"[m\\$^2\\$]\" ('' by default, i.e., set by plopm). +-t Specify the figure title, e.g., 'Final saturation map' ('' by default, i.e., set by plopm). +-r Restart number to plot the dynamic variable, where 1 corresponds to the initial one ('-1' by default, i.e., the last restart file). +-w Plot the positions of the wells or sources ('0' by default). +-g Plot information about the number of cells in the x, y, and z directions and number of active grid cells ('0' by default). +-a Scale the mass variable, e.g., 1e-9 for the color bar for the CO2 mass to be in Mt ('1' by default). +-time For the x axis in the summary use seconds 's', minutes 'm', hours 'h', days 'd', weeks 'w', years 'y', or dates 'dates' ('s' by default). +-ylabel Text for the y axis ('' by default, i.e., set by plopm). +-xlabel Text for the x axis ('' by default, i.e., set by plopm). +-ylnum Number of y axis labels ('4' by default). +-xlnum Number of x axis labels ('4' by default). +-cnum Number of color labels ('' by default, i.e., set by plopm). +-clabel Text for the colorbar ('' by default, i.e., set by plopm). +-labels Legend in the summary plot, separated by commas if more than one ('' by default, i.e., set by plopm). +-axgrid Set axis.grid to True for the summary plots ('1' by default). +-dpi Dots per inch for the figure ('300' by default). +-xformat Format for the x numbers, e.g., .2e for exponential notation ('' by default, i.e., set by plopm). +-yformat Format for the y numbers, e.g., .1f for one decimal ('' by default, i.e., set by plopm). +-xunits For the x axis in the spatial maps meters 'm', kilometers 'km', centimeters 'cm', or milimeters 'mm' ('m' by default). +-yunits For the y axis in the spatial maps meters 'm', kilometers 'km', centimeters 'cm', or milimeters 'mm' ('m' by default). +-remove Set the entries to 1 to remove in the spatial maps the left axis, bottom axis, colorbar, and title ('0,0,0,0' by default). +-facecolor Color outside the spatial map ('w' by default, i.e., white). +-save Name of the output files ('' by default, i.e., set by plopm). +-log Log scale for the color map ('0' by default). +-rotate Grades to rotate the grid in the 2D maps ('0' by default). +-translate Translate the grid in the 2D maps x,y directions ('[0,0]' by default). +-global Min and max in the colorbars from the current 2D slide values (0) or whole 3D model '1' ('0' by default). +-ncolor Color for the inactive cells in the 2D maps ('w' by default, i.e., white). + +.. tip:: + + Type in the terminal **plopm --help** to show these argument options. \ No newline at end of file diff --git a/docs/_static/basic.css b/docs/_static/basic.css index f316efc..30fee9d 100644 --- a/docs/_static/basic.css +++ b/docs/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/docs/_static/doctools.js b/docs/_static/doctools.js index 4d67807..d06a71d 100644 --- a/docs/_static/doctools.js +++ b/docs/_static/doctools.js @@ -4,7 +4,7 @@ * * Base JavaScript utilities for all Sphinx HTML documentation. * - * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/docs/_static/fipnum_norne.png b/docs/_static/fipnum_norne.png deleted file mode 100644 index f9ff958..0000000 Binary files a/docs/_static/fipnum_norne.png and /dev/null differ diff --git a/docs/_static/language_data.js b/docs/_static/language_data.js index 367b8ed..250f566 100644 --- a/docs/_static/language_data.js +++ b/docs/_static/language_data.js @@ -5,7 +5,7 @@ * This script contains the language-specific data used by searchtools.js, * namely the list of stopwords, stemmer, scorer and splitter. * - * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -13,7 +13,7 @@ var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; -/* Non-minified version is copied as a separate JS file, if available */ +/* Non-minified version is copied as a separate JS file, is available */ /** * Porter Stemmer diff --git a/docs/_static/permx_log.png b/docs/_static/permx_log.png new file mode 100644 index 0000000..b659676 Binary files /dev/null and b/docs/_static/permx_log.png differ diff --git a/docs/_static/searchtools.js b/docs/_static/searchtools.js index b08d58c..7918c3f 100644 --- a/docs/_static/searchtools.js +++ b/docs/_static/searchtools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for the full-text search. * - * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -99,7 +99,7 @@ const _displayItem = (item, searchTerms, highlightTerms) => { .then((data) => { if (data) listItem.appendChild( - Search.makeSearchSummary(data, searchTerms, anchor) + Search.makeSearchSummary(data, searchTerms) ); // highlight search terms in the summary if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js @@ -116,8 +116,8 @@ const _finishSearch = (resultCount) => { ); else Search.status.innerText = _( - "Search finished, found ${resultCount} page(s) matching the search query." - ).replace('${resultCount}', resultCount); + `Search finished, found ${resultCount} page(s) matching the search query.` + ); }; const _displayNextItem = ( results, @@ -137,22 +137,6 @@ const _displayNextItem = ( // search finished, update title and status message else _finishSearch(resultCount); }; -// Helper function used by query() to order search results. -// Each input is an array of [docname, title, anchor, descr, score, filename]. -// Order the results by score (in opposite order of appearance, since the -// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. -const _orderResultsByScoreThenName = (a, b) => { - const leftScore = a[4]; - const rightScore = b[4]; - if (leftScore === rightScore) { - // same score: sort alphabetically - const leftTitle = a[1].toLowerCase(); - const rightTitle = b[1].toLowerCase(); - if (leftTitle === rightTitle) return 0; - return leftTitle > rightTitle ? -1 : 1; // inverted is intentional - } - return leftScore > rightScore ? 1 : -1; -}; /** * Default splitQuery function. Can be overridden in ``sphinx.search`` with a @@ -176,26 +160,13 @@ const Search = { _queued_query: null, _pulse_status: -1, - htmlToText: (htmlString, anchor) => { + htmlToText: (htmlString) => { const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); - for (const removalQuery of [".headerlink", "script", "style"]) { - htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); - } - if (anchor) { - const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); - if (anchorContent) return anchorContent.textContent; - - console.warn( - `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` - ); - } - - // if anchor not specified or not found, fall back to main content + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent) return docContent.textContent; - + if (docContent !== undefined) return docContent.textContent; console.warn( - "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." ); return ""; }, @@ -268,7 +239,16 @@ const Search = { else Search.deferQuery(query); }, - _parseQuery: (query) => { + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + // stem the search terms and add them to the correct list const stemmer = new Stemmer(); const searchTerms = new Set(); @@ -304,38 +284,21 @@ const Search = { // console.info("required: ", [...searchTerms]); // console.info("excluded: ", [...excludedTerms]); - return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; - }, - - /** - * execute search (requires search index to be loaded) - */ - _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - - // Collect multiple result groups to be sorted separately and then ordered. - // Each is an array of [docname, title, anchor, descr, score, filename]. - const normalResults = []; - const nonMainIndexResults = []; - + // array of [docname, title, anchor, descr, score, filename] + let results = []; _removeChildren(document.getElementById("search-progress")); - const queryLower = query.toLowerCase().trim(); + const queryLower = query.toLowerCase(); for (const [title, foundTitles] of Object.entries(allTitles)) { - if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { for (const [file, id] of foundTitles) { - const score = Math.round(Scorer.title * queryLower.length / title.length); - const boost = titles[file] === title ? 1 : 0; // add a boost for document titles - normalResults.push([ + let score = Math.round(100 * queryLower.length / title.length) + results.push([ docNames[file], titles[file] !== title ? `${titles[file]} > ${title}` : title, id !== null ? "#" + id : "", null, - score + boost, + score, filenames[file], ]); } @@ -345,47 +308,46 @@ const Search = { // search for explicit entries in index directives for (const [entry, foundEntries] of Object.entries(indexEntries)) { if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { - for (const [file, id, isMain] of foundEntries) { - const score = Math.round(100 * queryLower.length / entry.length); - const result = [ + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ docNames[file], titles[file], id ? "#" + id : "", null, score, filenames[file], - ]; - if (isMain) { - normalResults.push(result); - } else { - nonMainIndexResults.push(result); - } + ]); } } } // lookup as object objectTerms.forEach((term) => - normalResults.push(...Search.performObjectSearch(term, objectTerms)) + results.push(...Search.performObjectSearch(term, objectTerms)) ); // lookup as search terms in fulltext - normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); // let the scorer override scores with a custom scoring function - if (Scorer.score) { - normalResults.forEach((item) => (item[4] = Scorer.score(item))); - nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); - } - - // Sort each group of results by score and then alphabetically by name. - normalResults.sort(_orderResultsByScoreThenName); - nonMainIndexResults.sort(_orderResultsByScoreThenName); - - // Combine the result groups in (reverse) order. - // Non-main index entries are typically arbitrary cross-references, - // so display them after other results. - let results = [...nonMainIndexResults, ...normalResults]; + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); // remove duplicate search results // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept @@ -399,12 +361,7 @@ const Search = { return acc; }, []); - return results.reverse(); - }, - - query: (query) => { - const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); - const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + results = results.reverse(); // for debugging //Search.lastresults = results.slice(); // a copy @@ -509,18 +466,14 @@ const Search = { // add support for partial matches if (word.length > 2) { const escapedWord = _escapeRegExp(word); - if (!terms.hasOwnProperty(word)) { - Object.keys(terms).forEach((term) => { - if (term.match(escapedWord)) - arr.push({ files: terms[term], score: Scorer.partialTerm }); - }); - } - if (!titleTerms.hasOwnProperty(word)) { - Object.keys(titleTerms).forEach((term) => { - if (term.match(escapedWord)) - arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); - }); - } + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); } // no match but word was a required one @@ -543,8 +496,9 @@ const Search = { // create the mapping files.forEach((file) => { - if (!fileMap.has(file)) fileMap.set(file, [word]); - else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); }); }); @@ -595,8 +549,8 @@ const Search = { * search summary for a given text. keywords is a list * of stemmed words. */ - makeSearchSummary: (htmlText, keywords, anchor) => { - const text = Search.htmlToText(htmlText, anchor); + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); if (text === "") return null; const textLower = text.toLowerCase(); diff --git a/docs/about.html b/docs/about.html index cb60831..92098c7 100644 --- a/docs/about.html +++ b/docs/about.html @@ -16,7 +16,7 @@ - + @@ -35,7 +35,7 @@ - +
@@ -80,11 +80,11 @@

About plopm

-_images/about.png -

This plopm package is being funded by the HPC Simulation Software for the Gigatonne Storage Challenge project +_images/about.png +

plopm is being funded by the HPC Simulation Software for the Gigatonne Storage Challenge project [project number 622059] and Center for Sustainable Subsurface Resources (CSSR) [project no. 331841]. This is work in progress. -Contributions are more than welcome using the fork and pull request approach.

+Contributions are more than welcome using the fork and pull request approach. For new features, please request them raising an issue.

diff --git a/docs/api.html b/docs/api.html index b189412..12b58b1 100644 --- a/docs/api.html +++ b/docs/api.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
diff --git a/docs/examples.html b/docs/examples.html index 3d01005..8a81bf5 100644 --- a/docs/examples.html +++ b/docs/examples.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
@@ -51,8 +51,8 @@
  • Installation
  • Examples @@ -101,36 +101,25 @@

    SPE11B< _images/satnum_spe11b.png

    The default argument options are:

    -
    plopm -i SPE11B -o . -s ,1, -f 14 -x '' -y '' -z yes -u resdata -v '' -c '' -n '' -l '' -r -1 -w 0
    +
    plopm -i SPE11B -o . -v '' -m png -s ,1, -p flow -z yes -f 14 -x '' -y '' -u resdata  -c ''  -e '' -n '' -b '' -d 8,16 -l '' -t '' -r -1 -w 0 -g 0 -a 1 -time s -ylabel '' -xlabel '' -ylnum 4 -xlnum 4 -cnum '' -clabel '' -labels '' -axgrid 1 -dpi 300 -xformat '' -yformat '' -xunits m -yunits m -remove 0,0,0,0 -facecolor w -save '' -log 0 -rotate 0 -translate '[0,0]' -global 0 -ncolor w
     

    See the Overview or run plopm -h for the definition of the argument options.

    -

    For example, for the gas saturation at the report step number 4:

    -
    plopm -i SPE11B -v sgas -c cubehelix -r 4 -n "lambda x, _: f'{x:.2f}'"
    +

    For example, for the gas saturation at the report step number 4 using a given colormap (-c):

    +
    plopm -i SPE11B -v sgas -r 4 -c cubehelix
     
    _images/sgas_spe11b.png
    -

    and for the gas in place summary vector:

    -
    plopm -i SPE11B -v fgip -c k
    +

    and for the gas in place summary vector given a color, line style, font size, dimension of the figure, and using dates for the times:

    +
    plopm -i SPE11B -v fgip -c b -e ':' -f 12 -d 5,5 -time dates
     
    -_images/fgip_spe11b.png +_images/fgip_spe11b.png
    -
    -

    Norne

    -

    This example relies on the simulation results in opm-tests. If you -download the files in that folder, then by using the plopm tool:

    -
    plopm -i NORNE_ATW2013 -o . -s ,,1 -x 455600,462200 -y 7319500,7327100
    -
    -
    -

    these are some of the generated figures:

    -_images/plopm.png -

    Here, we plot the top view (xy axis, k=1), and we set the xlim (-x) and ylim (-y) in order to reduce the white space outside the active cells.

    -

    Generic deck

    See/run the test_generic_deck.py @@ -138,25 +127,42 @@

    Generic deckSPE10_MODEL2 model by downloading the files and using the OPM Flow simulator.

    _images/spe10.png -
    plopm -i SPE10_MODEL2 -o . -s 4,,
    +
    plopm -i SPE10_MODEL2 -v permz -s ,4, -log 1 -xunits km -yunits km -xlnum 6 -yformat .2f -t 'K$_z$ at the forth slide in the xz plane' -b '[1e-7,1e3]'
    +
    +
    +

    Here, we look at the forth slide in the xz plane and use log scale for the permeability in the z direction, as well as changing the axis units to km, +setting the format to the numbers to two floats in the y axis, and setting manualli the upper and lower bound for the color map.

    +

    To plot information for the grid, and also the location of the wells from the top view, this is achieved by:

    +
    plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -g 1 && plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -w 1
     
    -

    To plot the location of the wells from the top view, then:

    -
    plopm -i SPE10_MODEL2 -w 1
    +_images/wells.png
    +

    +
    +

    Rotation, translation, and zoom

    +

    This example relies on the simulation results in opm-tests. If you +download the files in that folder, then by using the plopm tool:

    +
    plopm -i NORNE_ATW2013 -s ,,1
    +
    +
    +

    these are some of the generated figures:

    +_images/norne.png +

    In order to reduce the white space outside the active cells, as well as to rotate the grid and translate it, this can be ahieved by:

    +
    plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 20
     
    -_images/wells.png +_images/norne_transformed.png

    Different input files

    Let us assume we have two different runs in different folders for the spe11b case, where the firsts results are save in a folder called spe11b, and simulation results where the injection rate has been increased are saved in a folder called spe11b_larger_inj. Then, to plot the summary vector for both runs we can execute:

    -
    plopm -i spe11b/SPE11B,/Users/dmar/spe11b_larger_inj/SPE11B -v tcpu -d 5,5 -c r,b -e 'solid;:' -t 'Comparing the simulation times' -f 10
    +
    plopm -i spe11b/SPE11B,/home/user/spe11b_larger_inj/SPE11B -v fgipm -a 1e-6 -time w -d 5,5 -c r,b -e 'solid;:' -t 'Comparing the total mass' -f 10
     
    -_images/tcpu.png -

    Here, we have lower the size of the figure to 5,5 inches, set to use red and blue colors with solid and dotted lines, as well as settting the title and lower the font size to 10.

    +_images/fgipm.png +

    Here, we plot the injected mass and scaled to kilo tons, and the time is shown in weeks.

    Tip

    For any summary variable, one can give the path to more than two different simulation cases, just by separating the folder paths by commas in the -i.

    @@ -167,7 +173,7 @@

    Different input files _images/sgas_diff.png

    To changue the colormap and setting the clorbar limits manually, this can be achieved by:

    -
    plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]'
    +
    plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]' -n "lambda x, _: f'{x:.3f}'"
     
    _images/sgas_diff_edit.png @@ -175,9 +181,9 @@

    Different input files

    Convert to VTK

    Inside the examples folder, then we can create VTKs from the -OPM Flow simulation results (i.e., .EGRID, .INIT, .UNRST). For example, to create VTKS for the temperature from the restart -files from the initial (0) to the number 5 restart, using a OPM Flow build from source in a given path, this can be achieved by:

    -
    plopm -i SPE11B -v temp -r 0,5 -m vtk -p /Users/dmar/build/opm-simulators/bin/flow
    +OPM Flow simulation results (i.e., .EGRID, .INIT, .UNRST). For example, to create VTKS for the temperature, fipnum, and the co2 mass
    +from the restart files from the initial (0) to the number 5 restart, using a OPM Flow build from source in a given path, this can be achieved by:

    +
    plopm -i SPE11B -v temp,fipnum,co2m -r 0,5 -m vtk -p /Users/dmar/build/opm-simulators/bin/flow
     
    @@ -189,7 +195,8 @@

    Convert to VTK

    Note

    It is possible to write directly VTKs from OPM Flow simulations by adding the flag –enable-vtk-output=true. -However, there are quantities that are not written (e.g., fipnum, flores). This is when plopm can be helpful.

    +However, there are quantities that are not written (e.g., fipnum, flores), in addition to quantities not supported +such as component mass (e.g., co2, h2o). This is when plopm can be helpful.

    diff --git a/docs/genindex.html b/docs/genindex.html index 9981b5d..32535d8 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -15,7 +15,7 @@ - + @@ -33,7 +33,7 @@ - +
    diff --git a/docs/index.html b/docs/index.html index c97db15..0d2dfee 100644 --- a/docs/index.html +++ b/docs/index.html @@ -16,7 +16,7 @@ - + @@ -35,7 +35,7 @@ - +
    @@ -98,8 +98,8 @@

    Welcome to plopm’s documentation!Examples diff --git a/docs/installation.html b/docs/installation.html index 0e68c6c..6f9c4bc 100644 --- a/docs/installation.html +++ b/docs/installation.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -164,7 +165,7 @@

    Source build in Linux/Windows

    Source build in macOS

    diff --git a/docs/introduction.html b/docs/introduction.html index 76c516a..5614c7f 100644 --- a/docs/introduction.html +++ b/docs/introduction.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
    @@ -86,10 +86,10 @@

    Introduction

    _images/plopm.png -

    This documentation describes the content of the plopm tool.

    +

    This documentation describes the plopm tool hosted in https://github.com/cssr-tools/plopm.

    Concept

    -

    Simplified and flexible framework for quick visualization of OPM Flow geological models. +

    Simplified and flexible framework for quick visualization of OPM Flow geological models. The approach is the generation of PNG figures from static (e.g, porosity, pore volume fluid in place numbers) and dynamic (e.g., pressure, fluid saturations) properties given any 2D slide (e.g., the middle part of a reservoir in the xy plane), as well as plotting any given summary vector (e.g., field gas in place a.k.a fgip).

    @@ -101,34 +101,148 @@

    Concept

    Overview

    The current implementation supports the following executable with the argument options:

    -
    plopm -i some_input -o some_output_folder
    +
    plopm -i name(s)_of_input_file(s)
     

    where

    -
      -
    • -i: The base name of the input files; if more than one is given, separate them by ‘,’ (e.g, ‘SPE11B,SPE11B_TUNED’) (SPE11B by default).

    • -
    • -o: The base name of the output folder (. by default).

    • -
    • -f: The font size (14 by default).

    • -
    • -s: The slide for the 2D maps of the static variables, e.g, 10,, to plot the xz plane on all cells with i=10 (,1, by default, i.e., the xz surface at j=1).

    • -
    • -x: Option to set the lower and upper bounds in the 2D map along x (’’ by default).

    • -
    • -y: Option to set the lower and upper bounds in the 2D map along y (’’ by default).

    • -
    • -z: The option to scale the axis in the 2D maps (yes by default).

    • -
    • -u: Use resdata or opm Python libraries (resdata by default).

    • -
    • -v: Specify the name of the static vairable to plot (e.g., depth) (’’ by default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum).

    • -
    • -c: Specify the colormap (e.g., jet) (’’ by default, i.e., set by plopm).

    • -
    • -n: Specify the format for the numbers in the colormap (e.g., “lambda x, _: f’{x:.0f}’”) (’’ by default, i.e., set by plopm).

    • -
    • -l: Specify the units (e.g., "[m\$^2\$]") (’’ by default, i.e., set by plopm).

    • -
    • -r: Restart number to plot the dynamic variable, where 1 corresponds to the initial one (‘-1’ by default, i.e., the last restart file).

    • -
    • -w: Plot the positions of the wells or sources (‘0’ by default).

    • -
    • -g: Plot information about the number of cells in the x, y, and z directions and number of active grid cells (‘0’ by default).

    • -
    • -e: Specify the linestyles separated by ‘;’ (e.g., ‘solid;:’) (’’ by default, i.e., set by plopm).

    • -
    • -b: Specify the upper and lower bounds for the color map (e.g., ‘[-0.1,11]’) (’’ by default, i.e., set by matplotlib).

    • -
    • -d: Specify the dimensions of the Figure (e.g., ‘5,5’) (‘8,16’ by default).

    • -
    • -t: Specify the figure title (e.g., ‘Final saturation map’) (’’ by default, i.e., set by plopm).

    • -
    • -r: Restart number to plot the dynamic variable, where 1 corresponds to the initial one (‘-1’ by default, i.e., the last restart file).

    • -
    • -p: Path to flow (e.g., ‘homebuildbinflow’). This is used to generate the grid for the vtk files (‘flow’ by default).

    • -
    • -m: Generate ‘png’ or ‘vtk’ files (‘png’ by default).

    • -
    +
    +
    -i
    +

    The base name (or full path) of the input files; if more than one is given, separate them by ‘,’ (e.g, ‘SPE11B,\home\user\SPE11B_TUNED’) (‘SPE11B’ by default).

    +
    +
    -o
    +

    The base name (or full path) of the output folder (‘.’ by default, i.e., the folder where plopm is executed).

    +
    +
    -v
    +

    Specify the name of the vairable to plot, e.g., ‘pressure’, in addition to special extensive quantities for the mass such as ‘gasm’, ‘dism’, ‘liqm’, ‘vapm’, ‘co2m’, ‘h2om’, ‘fwcdm’, and ‘fgipm’ (’’ by default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum).

    +
    +
    -m
    +

    Generate ‘png’ or ‘vtk’ files (‘png’ by default).

    +
    +
    -s
    +

    The slide in the 3D model to plot the 2D maps, e.g, ‘10,,’ to plot the xz plane on all cells with i=10 (‘,1,’ by default, i.e., the xz surface at j=1).

    +
    +
    -p
    +

    Path to flow, e.g., ‘\home\build\bin\flow’. This is used to generate the grid for the vtk files (‘flow’ by default).

    +
    +
    -z
    +

    Scale the axis in the 2D maps (‘1’ by default).

    +
    +
    -f
    +

    The font size (‘14’ by default).

    +
    +
    -x
    +

    Set the lower and upper bounds along x, e.g., ‘[-100,200]’ (’’ by default).

    +
    +
    -y
    +

    Set the lower and upper bounds along y, e.g., ‘[-10,300]’ (’’ by default).

    +
    +
    -u
    +

    Use resdata or opm Python libraries (‘resdata’ by default).

    +
    +
    -c
    +

    Specify the colormap, e.g., ‘jet’, or color(s) for the summary, e.g., ‘b,r’ (’’ by default, i.e., set by plopm).

    +
    +
    -e
    +

    Specify the linestyles separated by ‘;’, e.g., ‘solid;:’ (’’ by default, i.e., set by plopm).

    +
    +
    -n
    +

    Specify the format for the numbers in the colormap, e.g., “lambda x, _ f’{x:.0f}’” (’’ by default, i.e., set by plopm).

    +
    +
    -b
    +

    Specify the upper and lower bounds for the color map, e.g., ‘[-0.1,11]’ (’’ by default, i.e., set by plopm).

    +
    +
    -d
    +

    Specify the dimensions in inches generated png, e.g., ‘5,5’ (‘8,16’ by default).

    +
    +
    -l
    +

    Specify the units of the variable, e.g., "[m\$^2\$]" (’’ by default, i.e., set by plopm).

    +
    +
    -t
    +

    Specify the figure title, e.g., ‘Final saturation map’ (’’ by default, i.e., set by plopm).

    +
    +
    -r
    +

    Restart number to plot the dynamic variable, where 1 corresponds to the initial one (‘-1’ by default, i.e., the last restart file).

    +
    +
    -w
    +

    Plot the positions of the wells or sources (‘0’ by default).

    +
    +
    -g
    +

    Plot information about the number of cells in the x, y, and z directions and number of active grid cells (‘0’ by default).

    +
    +
    -a
    +

    Scale the mass variable, e.g., 1e-9 for the color bar for the CO2 mass to be in Mt (‘1’ by default).

    +
    +
    -time
    +

    For the x axis in the summary use seconds ‘s’, minutes ‘m’, hours ‘h’, days ‘d’, weeks ‘w’, years ‘y’, or dates ‘dates’ (‘s’ by default).

    +
    +
    -ylabel
    +

    Text for the y axis (’’ by default, i.e., set by plopm).

    +
    +
    -xlabel
    +

    Text for the x axis (’’ by default, i.e., set by plopm).

    +
    +
    -ylnum
    +

    Number of y axis labels (‘4’ by default).

    +
    +
    -xlnum
    +

    Number of x axis labels (‘4’ by default).

    +
    +
    -cnum
    +

    Number of color labels (’’ by default, i.e., set by plopm).

    +
    +
    -clabel
    +

    Text for the colorbar (’’ by default, i.e., set by plopm).

    +
    +
    -labels
    +

    Legend in the summary plot, separated by commas if more than one (’’ by default, i.e., set by plopm).

    +
    +
    -axgrid
    +

    Set axis.grid to True for the summary plots (‘1’ by default).

    +
    +
    -dpi
    +

    Dots per inch for the figure (‘300’ by default).

    +
    +
    -xformat
    +

    Format for the x numbers, e.g., .2e for exponential notation (’’ by default, i.e., set by plopm).

    +
    +
    -yformat
    +

    Format for the y numbers, e.g., .1f for one decimal (’’ by default, i.e., set by plopm).

    +
    +
    -xunits
    +

    For the x axis in the spatial maps meters ‘m’, kilometers ‘km’, centimeters ‘cm’, or milimeters ‘mm’ (‘m’ by default).

    +
    +
    -yunits
    +

    For the y axis in the spatial maps meters ‘m’, kilometers ‘km’, centimeters ‘cm’, or milimeters ‘mm’ (‘m’ by default).

    +
    +
    -remove
    +

    Set the entries to 1 to remove in the spatial maps the left axis, bottom axis, colorbar, and title (‘0,0,0,0’ by default).

    +
    +
    -facecolor
    +

    Color outside the spatial map (‘w’ by default, i.e., white).

    +
    +
    -save
    +

    Name of the output files (’’ by default, i.e., set by plopm).

    +
    +
    -log
    +

    Log scale for the color map (‘0’ by default).

    +
    +
    -rotate
    +

    Grades to rotate the grid in the 2D maps (‘0’ by default).

    +
    +
    -translate
    +

    Translate the grid in the 2D maps x,y directions (‘[0,0]’ by default).

    +
    +
    -global
    +

    Min and max in the colorbars from the current 2D slide values (0) or whole 3D model ‘1’ (‘0’ by default).

    +
    +
    -ncolor
    +

    Color for the inactive cells in the 2D maps (‘w’ by default, i.e., white).

    +
    +
    +
    +

    Tip

    +

    Type in the terminal plopm –help to show these argument options.

    +

    diff --git a/docs/modules.html b/docs/modules.html index a01a666..8570715 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -16,7 +16,7 @@ - + @@ -34,7 +34,7 @@ - +
    diff --git a/docs/plopm.core.html b/docs/plopm.core.html index 24fe2b7..8e39969 100644 --- a/docs/plopm.core.html +++ b/docs/plopm.core.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
    diff --git a/docs/plopm.core.plopm.html b/docs/plopm.core.plopm.html index 4bf0194..ffc9b62 100644 --- a/docs/plopm.core.plopm.html +++ b/docs/plopm.core.plopm.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
    diff --git a/docs/plopm.html b/docs/plopm.html index 6b72715..98ca84b 100644 --- a/docs/plopm.html +++ b/docs/plopm.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
    diff --git a/docs/py-modindex.html b/docs/py-modindex.html index 20ec3f7..96c054e 100644 --- a/docs/py-modindex.html +++ b/docs/py-modindex.html @@ -15,7 +15,7 @@ - + @@ -36,7 +36,7 @@ - +
    diff --git a/docs/related.html b/docs/related.html index 99f8574..d6c0a97 100644 --- a/docs/related.html +++ b/docs/related.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
    diff --git a/docs/search.html b/docs/search.html index c624103..c785728 100644 --- a/docs/search.html +++ b/docs/search.html @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - +
    diff --git a/docs/searchindex.js b/docs/searchindex.js index 4b7ecdd..5f9d4a5 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles": {"About plopm": [[0, null]], "Concept": [[5, "concept"]], "Convert to VTK": [[2, "convert-to-vtk"]], "Different input files": [[2, "different-input-files"]], "Examples": [[2, null]], "Generic deck": [[2, "generic-deck"]], "Indices and tables": [[3, "indices-and-tables"]], "Installation": [[4, null]], "Introduction": [[5, null]], "Module contents": [[7, "module-plopm"], [8, "module-plopm.core"]], "Norne": [[2, "norne"]], "OPM Flow": [[4, "opm-flow"]], "Overview": [[5, "overview"]], "Python package": [[4, "python-package"]], "Related": [[10, null]], "SPE11B": [[2, "spe11b"]], "Source build in Linux/Windows": [[4, "source-build-in-linux-windows"]], "Source build in macOS": [[4, "source-build-in-macos"]], "Submodules": [[8, "submodules"]], "Subpackages": [[7, "subpackages"]], "Welcome to plopm\u2019s documentation!": [[3, null]], "ad-micp": [[10, "ad-micp"]], "expreccs": [[10, "expreccs"]], "plopm": [[1, "plopm"], [6, null]], "plopm Python API": [[1, null]], "plopm package": [[7, null]], "plopm.core package": [[8, null]], "plopm.core.plopm module": [[9, null]], "pycopm": [[10, "pycopm"]], "pymm": [[10, "pymm"]], "pyopmnearwell": [[10, "pyopmnearwell"]], "pyopmspe11": [[10, "pyopmspe11"]]}, "docnames": ["about", "api", "examples", "index", "installation", "introduction", "modules", "plopm", "plopm.core", "plopm.core.plopm", "related"], "envversion": {"sphinx": 62, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["about.rst", "api.rst", "examples.rst", "index.rst", "installation.rst", "introduction.rst", "modules.rst", "plopm.rst", "plopm.core.rst", "plopm.core.plopm.rst", "related.rst"], "indexentries": {}, "objects": {"": [[7, 0, 0, "-", "plopm"]], "plopm": [[8, 0, 0, "-", "core"]], "plopm.core": [[9, 0, 0, "-", "plopm"]], "plopm.core.plopm": [[9, 1, 1, "", "handle_slide_x"], [9, 1, 1, "", "handle_slide_y"], [9, 1, 1, "", "handle_slide_z"], [9, 1, 1, "", "load_parser"], [9, 1, 1, "", "main"], [9, 1, 1, "", "plopm"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"]}, "objtypes": {"0": "py:module", "1": "py:function"}, "terms": {"": [2, 5], "0": [2, 4, 5], "04": 4, "0f": 5, "1": [2, 4, 5], "10": [2, 4, 5], "11": 5, "14": [2, 5], "16": 5, "2": 5, "2024": 4, "25": 2, "2d": [5, 9], "2f": 2, "3": [2, 4], "331841": 0, "4": 2, "455600": 2, "462200": 2, "5": [2, 5], "622059": 0, "7319500": 2, "7327100": 2, "8": [2, 5], "9": 4, "A": 10, "For": [2, 4], "If": [2, 4], "In": 5, "It": 2, "ON": 4, "The": [1, 2, 5], "Then": [2, 4], "To": [2, 4], "_": [2, 5], "about": [3, 5], "achiev": [2, 4], "activ": [2, 4, 5], "ad": [2, 3], "addit": [4, 5], "after": [2, 4], "all": [1, 5], "allow": 5, "along": 5, "also": [4, 5], "an": [2, 4, 10], "ani": [2, 5], "api": 3, "approach": [0, 5], "ar": [0, 2, 4, 10], "arg": 9, "argument": [2, 5, 9], "assum": 2, "avail": 4, "axi": [2, 5], "b": [2, 5], "base": [5, 10], "been": 2, "being": 0, "below": 10, "benchmark": 10, "between": [2, 5], "bin": [2, 4], "binari": 4, "blue": 2, "both": 2, "bound": 5, "branch": 4, "brew": 4, "build": [2, 3], "build_opm_mpi": 4, "built": 4, "c": [2, 5], "calcit": 10, "call": 2, "can": [2, 4, 5], "case": [2, 5], "cd": 4, "cell": [2, 5], "center": 0, "cfd": 10, "challeng": 0, "changu": 2, "check": 10, "ci": 4, "clone": 4, "clorbar": 2, "cmake": 4, "co2": [2, 10], "coarsen": 10, "code": 4, "color": [2, 5], "colormap": [2, 5], "com": 4, "comma": 2, "command": 4, "common": 4, "compar": 2, "concept": 3, "configur": 2, "contain": 1, "content": [1, 3, 5, 6], "contribut": [0, 4], "convert": [3, 4, 5], "copi": 4, "core": [1, 4, 6, 7], "correspond": 5, "could": 4, "creat": [2, 4], "csp": 10, "cssr": [0, 4], "cubehelix": 2, "current": [4, 5], "current_directori": 4, "d": [2, 5], "dcmake_build_typ": 4, "dcmake_disable_find_package_mpi": 4, "dcmake_prefix_path": 4, "deactiv": 4, "deck": 3, "default": [2, 5], "definit": 2, "depend": 4, "depth": 5, "describ": 5, "dev": 4, "dic": 9, "dict": 9, "dictionari": 9, "differ": [1, 3, 5], "dimens": 5, "direct": 5, "directli": 2, "dmar": 2, "do": 4, "document": 5, "done": 4, "dopm_enable_python": 4, "dot": 2, "download": 2, "dpython_execut": 4, "dune": 4, "dunecontrol": 4, "duse_mpi": 4, "dwith_ndebug": 4, "dynam": [2, 5, 10], "e": [2, 4, 5], "echo": 4, "egrid": [2, 4], "enabl": 2, "environ": 4, "equal": 4, "exampl": 3, "execut": [1, 2, 4, 5, 9], "exist": 4, "expans": 10, "export": 4, "exprecc": 3, "f": [2, 5], "faster": 4, "fgip": [2, 5], "field": 5, "figur": [2, 5], "file": [3, 4, 5], "final": 5, "fipnum": [2, 5], "first": [2, 4], "flag": [2, 4], "flexibl": [5, 10], "flore": 2, "flow": [2, 3, 5, 9, 10], "fluid": 5, "folder": [1, 2, 4, 5], "follow": [2, 4, 5], "font": [2, 5], "fork": 0, "format": 5, "found": 4, "framework": [5, 10], "from": [2, 4, 5], "function": 9, "fund": 0, "g": [2, 4, 5], "ga": [2, 5], "gener": [3, 5], "geolog": [5, 9, 10], "geometri": 4, "get": 4, "gigatonn": 0, "git": 4, "github": 4, "gitlab": 4, "give": 2, "given": [2, 5], "global": 9, "grid": [2, 4, 5, 9], "h": 2, "ha": 2, "handl": 1, "handle_slide_i": [7, 8, 9], "handle_slide_x": [7, 8, 9], "handle_slide_z": [7, 8, 9], "have": 2, "help": 2, "here": 2, "higher": 4, "homebuildbinflow": 5, "horda": 10, "howev": 2, "hpc": 0, "http": 4, "i": [0, 1, 2, 4, 5], "imag": 10, "implement": 5, "inch": 2, "includ": 4, "increas": 2, "index": 3, "induc": 10, "inform": 5, "init": [2, 4], "initi": [2, 5], "inject": 2, "input": [3, 5], "insid": [2, 4], "inspect": 5, "instal": [2, 3], "instead": 4, "interest": [4, 10], "introduct": 3, "istl": 4, "j": 5, "j5": 4, "jet": 5, "just": 2, "k": [2, 5], "l": [2, 5], "lambda": [2, 5], "larg": 4, "last": 5, "leakag": 10, "let": 2, "librari": [4, 5], "limit": 2, "line": [2, 4], "linestyl": 5, "lint": 4, "linux": 3, "load_pars": [7, 8, 9], "locat": [1, 2], "look": 2, "lower": [2, 5], "m": [2, 4, 5], "maco": 3, "macport": 4, "main": [1, 7, 8, 9], "make": 4, "manual": 2, "map": [5, 9], "master": 4, "matplotlib": 5, "method": 1, "micp": 3, "microbi": 10, "microsystem": 10, "middl": 5, "might": [4, 10], "mkdir": 4, "model": [2, 4, 5, 9, 10], "modifi": [4, 9], "modul": [1, 3, 4, 6, 10], "more": [0, 2, 5], "mpi": 4, "n": [2, 5], "name": 5, "need": 4, "nice": 5, "norn": 3, "norne_atw2013": 2, "number": [0, 2, 5], "o": [2, 5], "obtain": 9, "one": [2, 5], "onli": 4, "open": 10, "opm": [2, 3, 5, 9, 10], "option": [2, 5, 9], "order": 2, "org": 4, "other": 5, "otherwis": 4, "out": 10, "output": [2, 4, 5], "outsid": 2, "overview": [2, 3, 4], "p": [2, 5], "packag": [0, 1, 3, 6], "page": 3, "paper": 5, "paraview": [2, 5], "part": 5, "path": [2, 5], "permx": 5, "permz": 5, "pip": 4, "place": [2, 5], "plane": 5, "platform": 10, "plopm": [2, 4, 5], "plot": [1, 2, 5, 9], "png": 5, "pore": 5, "poro": 5, "poros": 5, "porv": 5, "posit": 5, "possibl": [2, 4], "postprocess": 5, "precipit": 10, "prerequisit": 4, "present": 5, "pressur": 5, "previou": 4, "process": 9, "progress": 0, "project": [0, 4, 10], "properti": [5, 9], "pull": 0, "pwd": 4, "py": 2, "pycopm": 3, "pymm": 3, "pyopmnearwel": 3, "pyopmspe11": [2, 3], "pyproject": 4, "python": [3, 5, 10], "python3": 4, "pythonpath": 4, "quantiti": 2, "quick": 5, "r": [2, 4, 5], "rate": 2, "read": 4, "recommend": 4, "red": 2, "reduc": 2, "regard": 4, "relat": 3, "releas": 4, "reli": 2, "remedi": 10, "remov": 4, "repo": 4, "report": 2, "repositori": 4, "request": 0, "requir": 4, "resdata": [2, 4, 5], "reservoir": 5, "resourc": [0, 10], "restar": 2, "restart": [2, 5], "result": [2, 5], "return": 9, "run": [2, 4], "same": 5, "satnum": 5, "satur": [2, 5], "save": 2, "scale": 5, "script": [1, 4, 9], "search": 3, "see": [2, 4], "seem": 4, "select": 9, "separ": [2, 5], "set": [2, 4, 5], "sett": 2, "setuptool": 4, "sga": 2, "sh": 4, "should": [2, 4], "simplifi": [5, 10], "simul": [0, 2, 4, 5, 10], "size": [2, 5], "slide": [5, 9], "so": 4, "softwar": 0, "solid": [2, 5], "some": [2, 10], "some_input": 5, "some_output_fold": 5, "sourc": [2, 3, 5, 10], "space": 2, "spe10_model2": 2, "spe11": 10, "spe11b": [3, 5], "spe11b_larger_inj": 2, "spe11b_tun": 5, "specifi": 5, "static": 5, "step": 2, "storag": [0, 10], "studi": 10, "submodul": [1, 6, 7], "subpackag": [1, 3, 6], "subsurfac": 0, "subsystem": 4, "succe": 2, "summari": [2, 5], "support": [4, 5], "surfac": 5, "sustain": 0, "t": [2, 5], "tab20c": 2, "tcpu": 2, "temp": 2, "temperatur": 2, "termin": [2, 4], "test": [2, 4], "test_generic_deck": 2, "than": [0, 2, 4, 5], "them": [5, 10], "thi": [0, 2, 4, 5], "time": 2, "titl": [2, 5], "toml": 4, "tool": [2, 4, 5, 10], "top": 2, "true": 2, "try": 4, "turn": 4, "two": [2, 5], "txt": 4, "type": 2, "u": [2, 5], "unit": 5, "unrst": [2, 4], "upgrad": 4, "upper": 5, "us": [0, 2, 4, 5, 10], "user": [2, 4], "util": 1, "v": [2, 5], "v2": 4, "vairabl": 5, "variabl": [2, 5], "vector": [2, 5], "venv": 4, "version": 4, "view": 2, "virtual": 4, "visual": [2, 5], "volum": 5, "vplopm": 4, "vtk": [3, 4, 5], "w": [2, 5], "we": 2, "welcom": 0, "well": [2, 4, 5, 10], "were": 2, "wheel": 4, "when": 2, "where": [2, 5], "which": [4, 5], "white": 2, "window": 3, "work": 0, "write": 2, "written": 2, "x": [2, 5], "xlim": 2, "xy": [2, 5, 9], "xz": [5, 9], "y": [2, 5], "ye": [2, 5], "year": 2, "ylim": 2, "yml": 4, "you": [2, 4], "yz": 9, "z": [2, 5]}, "titles": ["About plopm", "plopm Python API", "Examples", "Welcome to plopm\u2019s documentation!", "Installation", "Introduction", "plopm", "plopm package", "plopm.core package", "plopm.core.plopm module", "Related"], "titleterms": {"": 3, "about": 0, "ad": 10, "api": 1, "build": 4, "concept": 5, "content": [7, 8], "convert": 2, "core": [8, 9], "deck": 2, "differ": 2, "document": 3, "exampl": 2, "exprecc": 10, "file": 2, "flow": 4, "gener": 2, "indic": 3, "input": 2, "instal": 4, "introduct": 5, "linux": 4, "maco": 4, "micp": 10, "modul": [7, 8, 9], "norn": 2, "opm": 4, "overview": 5, "packag": [4, 7, 8], "plopm": [0, 1, 3, 6, 7, 8, 9], "pycopm": 10, "pymm": 10, "pyopmnearwel": 10, "pyopmspe11": 10, "python": [1, 4], "relat": 10, "sourc": 4, "spe11b": 2, "submodul": 8, "subpackag": 7, "tabl": 3, "vtk": 2, "welcom": 3, "window": 4}}) \ No newline at end of file +Search.setIndex({"docnames": ["about", "api", "examples", "index", "installation", "introduction", "modules", "plopm", "plopm.core", "plopm.core.plopm", "related"], "filenames": ["about.rst", "api.rst", "examples.rst", "index.rst", "installation.rst", "introduction.rst", "modules.rst", "plopm.rst", "plopm.core.rst", "plopm.core.plopm.rst", "related.rst"], "titles": ["About plopm", "plopm Python API", "Examples", "Welcome to plopm\u2019s documentation!", "Installation", "Introduction", "plopm", "plopm package", "plopm.core package", "plopm.core.plopm module", "Related"], "terms": {"i": [0, 1, 2, 4, 5], "being": 0, "fund": 0, "hpc": 0, "simul": [0, 2, 4, 5, 10], "softwar": 0, "gigatonn": 0, "storag": [0, 10], "challeng": 0, "project": [0, 4, 10], "number": [0, 2, 5], "622059": 0, "center": 0, "sustain": 0, "subsurfac": 0, "resourc": [0, 10], "cssr": [0, 4, 5], "331841": 0, "thi": [0, 2, 4, 5], "work": 0, "progress": 0, "contribut": [0, 4], "ar": [0, 2, 4, 10], "more": [0, 2, 5], "than": [0, 2, 4, 5], "welcom": 0, "us": [0, 2, 4, 5, 10], "fork": 0, "pull": 0, "request": 0, "approach": [0, 5], "For": [0, 2, 4, 5], "new": 0, "featur": 0, "pleas": 0, "them": [0, 5, 10], "rais": 0, "an": [0, 2, 4, 10], "issu": 0, "The": [1, 2, 5], "main": [1, 7, 8, 9], "script": [1, 4, 9], "execut": [1, 2, 4, 5, 9], "locat": [1, 2], "core": [1, 4, 6, 7], "folder": [1, 2, 4, 5], "util": 1, "contain": 1, "all": [1, 5], "differ": [1, 3, 5], "method": 1, "handl": 1, "plot": [1, 2, 5, 9], "packag": [1, 3, 6], "subpackag": [1, 3, 6], "submodul": [1, 6, 7], "modul": [1, 3, 4, 6, 10], "content": [1, 3, 6], "were": 2, "pyopmspe11": [2, 3], "run": [2, 4], "configur": 2, "Then": [2, 4], "you": [2, 4], "succe": 2, "instal": [2, 3], "plopm": [2, 4, 5], "insid": [2, 4], "type": [2, 5], "termin": [2, 4, 5], "follow": [2, 4, 5], "figur": [2, 4, 5], "should": [2, 4], "test": [2, 4], "default": [2, 5], "argument": [2, 5, 9], "option": [2, 5, 9], "o": [2, 5], "v": [2, 5], "m": [2, 4, 5], "png": [2, 5], "": [2, 4, 5], "1": [2, 4, 5], "p": [2, 5], "flow": [2, 3, 5, 9, 10], "z": [2, 5], "ye": 2, "f": [2, 5], "14": [2, 5], "x": [2, 5], "y": [2, 5], "u": [2, 4, 5], "resdata": [2, 4, 5], "c": [2, 5], "e": [2, 4, 5], "n": [2, 5], "b": [2, 5], "d": [2, 5], "8": [2, 5], "16": [2, 5], "l": [2, 5], "t": [2, 5], "r": [2, 4, 5], "w": [2, 5], "0": [2, 4, 5], "g": [2, 4, 5], "time": 2, "ylabel": 2, "xlabel": 2, "ylnum": 2, "4": [2, 5], "xlnum": 2, "cnum": 2, "clabel": 2, "label": [2, 5], "axgrid": 2, "dpi": 2, "300": [2, 5], "xformat": 2, "yformat": 2, "xunit": 2, "yunit": 2, "remov": [2, 4, 5], "facecolor": 2, "save": 2, "log": [2, 5], "global": [2, 9], "ncolor": 2, "see": [2, 4], "overview": [2, 3, 4], "h": [2, 5], "definit": 2, "ga": [2, 5], "satur": [2, 5], "report": 2, "step": 2, "given": [2, 5], "colormap": [2, 5], "sga": 2, "cubehelix": 2, "place": [2, 5], "summari": [2, 5], "vector": [2, 5], "color": [2, 5], "line": [2, 4], "style": 2, "font": [2, 4, 5], "size": [2, 5], "dimens": [2, 5], "date": [2, 5], "fgip": [2, 5], "12": 2, "5": [2, 5], "test_generic_deck": 2, "py": 2, "where": [2, 5], "from": [2, 4, 5], "spe10_model2": 2, "model": [2, 4, 5, 9, 10], "download": 2, "opm": [2, 3, 5, 9, 10], "permz": [2, 5], "km": [2, 5], "6": 2, "2f": 2, "k": [2, 5], "_z": 2, "forth": 2, "slide": [2, 5, 9], "xz": [2, 5, 9], "plane": [2, 5], "1e": [2, 5], "7": 2, "1e3": 2, "here": 2, "we": 2, "look": 2, "scale": [2, 5], "permeabl": 2, "direct": [2, 5], "well": [2, 4, 5, 10], "chang": 2, "axi": [2, 5], "unit": [2, 5], "set": [2, 4, 5], "format": [2, 4, 5], "two": [2, 5], "float": 2, "manual": 2, "upper": [2, 5], "lower": [2, 5], "bound": [2, 5], "map": [2, 5, 9], "To": [2, 4], "inform": [2, 5], "grid": [2, 4, 5, 9], "also": [2, 4, 5], "top": 2, "view": 2, "achiev": [2, 4], "3": [2, 4], "reli": 2, "result": [2, 5], "If": [2, 4], "tool": [2, 4, 5, 10], "norne_atw2013": 2, "some": [2, 10], "In": [2, 4, 5], "order": 2, "reduc": 2, "white": [2, 5], "space": 2, "outsid": [2, 5], "activ": [2, 4, 5], "cell": [2, 5], "can": [2, 4, 5], "ahiev": 2, "65": 2, "6456335": 2, "3476500": 2, "5600": 2, "7600": 2, "20": 2, "let": 2, "assum": 2, "have": 2, "case": [2, 5], "first": [2, 4], "call": 2, "inject": 2, "rate": 2, "ha": 2, "been": 2, "increas": 2, "spe11b_larger_inj": 2, "both": 2, "home": [2, 5], "user": [2, 4, 5], "fgipm": [2, 5], "solid": [2, 5], "compar": 2, "total": 2, "mass": [2, 5], "10": [2, 4, 5], "kilo": 2, "ton": 2, "shown": 2, "week": [2, 5], "ani": [2, 5], "variabl": [2, 5], "one": [2, 5], "give": 2, "path": [2, 5], "just": 2, "separ": [2, 5], "comma": [2, 5], "between": [2, 5], "dynam": [2, 5, 10], "restar": 2, "changu": 2, "clorbar": 2, "limit": 2, "tab20c": 2, "lambda": [2, 5], "_": [2, 5], "3f": 2, "creat": [2, 4], "egrid": [2, 4], "init": [2, 4], "unrst": [2, 4], "temperatur": 2, "fipnum": [2, 5], "co2": [2, 5, 10], "restart": [2, 5], "initi": [2, 5], "build": [2, 3, 5], "sourc": [2, 3, 5, 10], "temp": 2, "co2m": [2, 5], "dmar": 2, "bin": [2, 4, 5], "visual": [2, 5], "paraview": [2, 5], "after": [2, 4], "25": 2, "year": [2, 5], "It": 2, "possibl": [2, 4], "write": 2, "directli": 2, "ad": [2, 3, 4], "flag": [2, 4], "enabl": 2, "output": [2, 4, 5], "true": [2, 5], "howev": 2, "quantiti": [2, 5], "written": 2, "flore": 2, "addit": [2, 4, 5], "support": [2, 4, 5], "compon": 2, "h2o": 2, "when": [2, 4], "help": [2, 5], "introduct": 3, "concept": 3, "python": [3, 5, 10], "linux": 3, "window": 3, "maco": 3, "exampl": 3, "spe11b": [3, 5], "gener": [3, 5], "deck": 3, "rotat": [3, 5], "translat": [3, 5], "zoom": 3, "input": [3, 5], "file": [3, 4, 5], "convert": [3, 4, 5], "vtk": [3, 4, 5], "api": 3, "relat": 3, "pyopmnearwel": 3, "exprecc": 3, "pycopm": 3, "micp": 3, "pymm": 3, "about": [3, 5], "index": 3, "search": 3, "page": 3, "exist": 4, "environ": 4, "pip": 4, "git": 4, "http": [4, 5], "github": [4, 5], "com": [4, 5], "interest": [4, 10], "modifi": [4, 9], "code": 4, "clone": 4, "repositori": 4, "requir": 4, "virtual": 4, "command": 4, "repo": 4, "get": 4, "cd": 4, "python3": 4, "venv": 4, "vplopm": 4, "upgrad": 4, "setuptool": 4, "wheel": 4, "lint": 4, "dev": 4, "txt": 4, "depend": 4, "sudo": 4, "apt": 4, "texliv": 4, "recommend": 4, "extra": 4, "dvipng": 4, "cm": [4, 5], "super": 4, "need": 4, "org": 4, "releas": 4, "2024": 4, "04": 4, "current": [4, 5], "master": 4, "branch": 4, "ci": 4, "yml": 4, "binari": 4, "includ": 4, "subsystem": 4, "could": 4, "try": 4, "prerequisit": 4, "mpi": 4, "which": [4, 5], "turn": 4, "current_directori": 4, "pwd": 4, "common": 4, "do": 4, "done": 4, "mkdir": 4, "cmake": 4, "duse_mpi": 4, "dwith_ndebug": 4, "dcmake_build_typ": 4, "dcmake_prefix_path": 4, "make": 4, "j5": 4, "sh": 4, "build_opm_mpi": 4, "copi": 4, "previou": 4, "regard": 4, "read": 4, "instead": 4, "seem": 4, "faster": 4, "larg": 4, "avail": 4, "so": 4, "built": 4, "dune": 4, "librari": [4, 5], "macport": 4, "brew": 4, "geometri": 4, "istl": 4, "gitlab": 4, "v2": 4, "9": [4, 5], "dunecontrol": 4, "onli": 4, "dcmake_disable_find_package_mpi": 4, "dpython_execut": 4, "dopm_enable_python": 4, "ON": 4, "echo": 4, "export": 4, "pythonpath": 4, "deactiv": 4, "might": [4, 10], "version": 4, "found": 4, "equal": 4, "higher": 4, "otherwis": 4, "pyproject": 4, "toml": 4, "document": 5, "describ": 5, "host": 5, "simplifi": [5, 10], "flexibl": [5, 10], "framework": [5, 10], "quick": 5, "geolog": [5, 9, 10], "static": 5, "poros": 5, "pore": 5, "volum": 5, "fluid": 5, "pressur": 5, "properti": [5, 9], "2d": [5, 9], "middl": 5, "part": 5, "reservoir": 5, "xy": [5, 9], "field": 5, "inspect": 5, "nice": 5, "paper": 5, "present": 5, "same": 5, "allow": 5, "other": 5, "postprocess": 5, "implement": 5, "name": 5, "_of_input_fil": 5, "base": [5, 10], "full": 5, "spe11b_tun": 5, "specifi": 5, "vairabl": 5, "special": 5, "extens": 5, "gasm": 5, "dism": 5, "liqm": 5, "vapm": 5, "h2om": 5, "fwcdm": 5, "porv": 5, "permx": 5, "poro": 5, "satnum": 5, "3d": 5, "surfac": 5, "j": 5, "along": 5, "100": 5, "200": 5, "jet": 5, "linestyl": 5, "0f": 5, "11": 5, "inch": 5, "2": 5, "titl": 5, "final": 5, "correspond": 5, "last": 5, "posit": 5, "bar": 5, "mt": 5, "im": 5, "second": 5, "minut": 5, "hour": 5, "dai": 5, "text": 5, "lnum": 5, "num": 5, "colorbar": 5, "abel": 5, "legend": 5, "xgrid": 5, "pi": 5, "dot": 5, "per": 5, "2e": 5, "exponenti": 5, "notat": 5, "1f": 5, "decim": 5, "spatial": 5, "meter": 5, "kilomet": 5, "centimet": 5, "milimet": 5, "mm": 5, "emov": 5, "entri": 5, "left": 5, "bottom": 5, "acecolor": 5, "av": 5, "og": 5, "otat": 5, "grade": 5, "ranslat": 5, "lobal": 5, "min": 5, "max": 5, "valu": 5, "whole": 5, "inact": 5, "show": 5, "handle_slide_x": [7, 8, 9], "handle_slide_i": [7, 8, 9], "handle_slide_z": [7, 8, 9], "load_pars": [7, 8, 9], "dic": 9, "process": 9, "select": 9, "yz": 9, "obtain": 9, "arg": 9, "dict": 9, "dictionari": 9, "return": 9, "function": 9, "below": 10, "check": 10, "out": 10, "A": 10, "csp": 10, "spe11": 10, "benchmark": 10, "expans": 10, "horda": 10, "platform": 10, "coarsen": 10, "studi": 10, "leakag": 10, "remedi": 10, "microbi": 10, "induc": 10, "calcit": 10, "precipit": 10, "open": 10, "imag": 10, "cfd": 10, "microsystem": 10}, "objects": {"": [[7, 0, 0, "-", "plopm"]], "plopm": [[8, 0, 0, "-", "core"]], "plopm.core": [[9, 0, 0, "-", "plopm"]], "plopm.core.plopm": [[9, 1, 1, "", "handle_slide_x"], [9, 1, 1, "", "handle_slide_y"], [9, 1, 1, "", "handle_slide_z"], [9, 1, 1, "", "load_parser"], [9, 1, 1, "", "main"], [9, 1, 1, "", "plopm"]]}, "objtypes": {"0": "py:module", "1": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"]}, "titleterms": {"about": 0, "plopm": [0, 1, 3, 6, 7, 8, 9], "python": [1, 4], "api": 1, "exampl": 2, "spe11b": 2, "gener": 2, "deck": 2, "rotat": 2, "translat": 2, "zoom": 2, "differ": 2, "input": 2, "file": 2, "convert": 2, "vtk": 2, "welcom": 3, "": 3, "document": 3, "indic": 3, "tabl": 3, "instal": 4, "packag": [4, 7, 8], "opm": 4, "flow": 4, "sourc": 4, "build": 4, "linux": 4, "window": 4, "maco": 4, "introduct": 5, "concept": 5, "overview": 5, "subpackag": 7, "modul": [7, 8, 9], "content": [7, 8], "core": [8, 9], "submodul": 8, "relat": 10, "pyopmspe11": 10, "pyopmnearwel": 10, "exprecc": 10, "pycopm": 10, "ad": 10, "micp": 10, "pymm": 10}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"About plopm": [[0, "about-plopm"]], "plopm Python API": [[1, "plopm-python-api"]], "plopm": [[1, "plopm"], [6, "plopm"]], "Examples": [[2, "examples"]], "SPE11B": [[2, "spe11b"]], "Generic deck": [[2, "generic-deck"]], "Rotation, translation, and zoom": [[2, "rotation-translation-and-zoom"]], "Different input files": [[2, "different-input-files"]], "Convert to VTK": [[2, "convert-to-vtk"]], "Welcome to plopm\u2019s documentation!": [[3, "welcome-to-plopm-s-documentation"]], "Indices and tables": [[3, "indices-and-tables"]], "Installation": [[4, "installation"]], "Python package": [[4, "python-package"]], "OPM Flow": [[4, "opm-flow"]], "Source build in Linux/Windows": [[4, "source-build-in-linux-windows"]], "Source build in macOS": [[4, "source-build-in-macos"]], "Introduction": [[5, "introduction"]], "Concept": [[5, "concept"]], "Overview": [[5, "overview"]], "plopm package": [[7, "plopm-package"]], "Subpackages": [[7, "subpackages"]], "Module contents": [[7, "module-plopm"], [8, "module-plopm.core"]], "plopm.core package": [[8, "plopm-core-package"]], "Submodules": [[8, "submodules"]], "plopm.core.plopm module": [[9, "module-plopm.core.plopm"]], "Related": [[10, "related"]], "pyopmspe11": [[10, "pyopmspe11"]], "pyopmnearwell": [[10, "pyopmnearwell"]], "expreccs": [[10, "expreccs"]], "pycopm": [[10, "pycopm"]], "ad-micp": [[10, "ad-micp"]], "pymm": [[10, "pymm"]]}, "indexentries": {"module": [[7, "module-plopm"], [8, "module-plopm.core"], [9, "module-plopm.core.plopm"]], "plopm": [[7, "module-plopm"]], "plopm.core": [[8, "module-plopm.core"]], "handle_slide_x() (in module plopm.core.plopm)": [[9, "plopm.core.plopm.handle_slide_x"]], "handle_slide_y() (in module plopm.core.plopm)": [[9, "plopm.core.plopm.handle_slide_y"]], "handle_slide_z() (in module plopm.core.plopm)": [[9, "plopm.core.plopm.handle_slide_z"]], "load_parser() (in module plopm.core.plopm)": [[9, "plopm.core.plopm.load_parser"]], "main() (in module plopm.core.plopm)": [[9, "plopm.core.plopm.main"]], "plopm() (in module plopm.core.plopm)": [[9, "plopm.core.plopm.plopm"]], "plopm.core.plopm": [[9, "module-plopm.core.plopm"]]}}) \ No newline at end of file diff --git a/docs/text/about.rst b/docs/text/about.rst index 972aa90..22b4c6c 100644 --- a/docs/text/about.rst +++ b/docs/text/about.rst @@ -3,9 +3,8 @@ About plopm =========== .. image:: ./figs/about.png - :scale: 25% -This **plopm** package is being funded by the `HPC Simulation Software for the Gigatonne Storage Challenge project `_ +**plopm** is being funded by the `HPC Simulation Software for the Gigatonne Storage Challenge project `_ [project number 622059] and `Center for Sustainable Subsurface Resources (CSSR) `_ [project no. 331841]. This is work in progress. -Contributions are more than welcome using the fork and pull request approach. \ No newline at end of file +Contributions are more than welcome using the fork and pull request approach. For new features, please request them raising an issue. \ No newline at end of file diff --git a/docs/text/conf.py b/docs/text/conf.py index 420b18b..abbfb8e 100644 --- a/docs/text/conf.py +++ b/docs/text/conf.py @@ -23,7 +23,7 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = 'sphinx_rtd_theme' -html_logo = "./figs/fipnum_norne.png" +html_logo = "./figs/permx_log.png" html_theme_options = { "logo_only": True, "style_nav_header_background": "#aaaaaa", diff --git a/docs/text/examples.rst b/docs/text/examples.rst index 8d7e4e3..9683b9d 100644 --- a/docs/text/examples.rst +++ b/docs/text/examples.rst @@ -22,43 +22,26 @@ The default argument options are: .. code-block:: bash - plopm -i SPE11B -o . -s ,1, -f 14 -x '' -y '' -z yes -u resdata -v '' -c '' -n '' -l '' -r -1 -w 0 + plopm -i SPE11B -o . -v '' -m png -s ,1, -p flow -z yes -f 14 -x '' -y '' -u resdata -c '' -e '' -n '' -b '' -d 8,16 -l '' -t '' -r -1 -w 0 -g 0 -a 1 -time s -ylabel '' -xlabel '' -ylnum 4 -xlnum 4 -cnum '' -clabel '' -labels '' -axgrid 1 -dpi 300 -xformat '' -yformat '' -xunits m -yunits m -remove 0,0,0,0 -facecolor w -save '' -log 0 -rotate 0 -translate '[0,0]' -global 0 -ncolor w See the :ref:`overview` or run `plopm -h` for the definition of the argument options. -For example, for the gas saturation at the report step number 4: +For example, for the gas saturation at the report step number 4 using a given colormap (-c): .. code-block:: bash - plopm -i SPE11B -v sgas -c cubehelix -r 4 -n "lambda x, _: f'{x:.2f}'" + plopm -i SPE11B -v sgas -r 4 -c cubehelix .. figure:: figs/sgas_spe11b.png -and for the gas in place summary vector: +and for the gas in place summary vector given a color, line style, font size, dimension of the figure, and using dates for the times: .. code-block:: bash - plopm -i SPE11B -v fgip -c k + plopm -i SPE11B -v fgip -c b -e ':' -f 12 -d 5,5 -time dates .. figure:: figs/fgip_spe11b.png - :scale: 20% - -===== -Norne -===== - -This example relies on the simulation results in `opm-tests `_. If you -download the files in that folder, then by using the **plopm** tool: - -.. code-block:: bash - - plopm -i NORNE_ATW2013 -o . -s ,,1 -x 455600,462200 -y 7319500,7327100 - -these are some of the generated figures: - -.. image:: ./figs/plopm.png - -Here, we plot the top view (xy axis, k=1), and we set the xlim (-x) and ylim (-y) in order to reduce the white space outside the active cells. + :scale: 30% ============ Generic deck @@ -73,16 +56,41 @@ for an example where **plopm** is used to generate figures from the .. code-block:: bash - plopm -i SPE10_MODEL2 -o . -s 4,, + plopm -i SPE10_MODEL2 -v permz -s ,4, -log 1 -xunits km -yunits km -xlnum 6 -yformat .2f -t 'K$_z$ at the forth slide in the xz plane' -b '[1e-7,1e3]' -To plot the location of the wells from the top view, then: +Here, we look at the forth slide in the xz plane and use log scale for the permeability in the z direction, as well as changing the axis units to km, +setting the format to the numbers to two floats in the y axis, and setting manualli the upper and lower bound for the color map. + +To plot information for the grid, and also the location of the wells from the top view, this is achieved by: .. code-block:: bash - plopm -i SPE10_MODEL2 -w 1 + plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -g 1 && plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -w 1 .. image:: ./figs/wells.png - :scale: 20% + +=============================== +Rotation, translation, and zoom +=============================== + +This example relies on the simulation results in `opm-tests `_. If you +download the files in that folder, then by using the **plopm** tool: + +.. code-block:: bash + + plopm -i NORNE_ATW2013 -s ,,1 + +these are some of the generated figures: + +.. image:: ./figs/norne.png + +In order to reduce the white space outside the active cells, as well as to rotate the grid and translate it, this can be ahieved by: + +.. code-block:: bash + + plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 20 + +.. image:: ./figs/norne_transformed.png ===================== Different input files @@ -93,11 +101,12 @@ called spe11b_larger_inj. Then, to plot the summary vector for both runs we can .. code-block:: bash - plopm -i spe11b/SPE11B,/Users/dmar/spe11b_larger_inj/SPE11B -v tcpu -d 5,5 -c r,b -e 'solid;:' -t 'Comparing the simulation times' -f 10 + plopm -i spe11b/SPE11B,/home/user/spe11b_larger_inj/SPE11B -v fgipm -a 1e-6 -time w -d 5,5 -c r,b -e 'solid;:' -t 'Comparing the total mass' -f 10 -.. image:: ./figs/tcpu.png +.. image:: ./figs/fgipm.png + :scale: 30% -Here, we have lower the size of the figure to 5,5 inches, set to use red and blue colors with solid and dotted lines, as well as settting the title and lower the font size to 10. +Here, we plot the injected mass and scaled to kilo tons, and the time is shown in weeks. .. tip:: For any summary variable, one can give the path to more than two different simulation cases, just by separating the folder paths by commas in the -i. @@ -114,7 +123,7 @@ To changue the colormap and setting the clorbar limits manually, this can be ach .. code-block:: bash - plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]' + plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]' -n "lambda x, _: f'{x:.3f}'" .. image:: ./figs/sgas_diff_edit.png @@ -122,12 +131,12 @@ To changue the colormap and setting the clorbar limits manually, this can be ach Convert to VTK ============== Inside the `examples folder `_, then we can create VTKs from the -OPM Flow simulation results (i.e., .EGRID, .INIT, .UNRST). For example, to create VTKS for the temperature from the restart -files from the initial (0) to the number 5 restart, using a OPM Flow build from source in a given path, this can be achieved by: +OPM Flow simulation results (i.e., .EGRID, .INIT, .UNRST). For example, to create VTKS for the temperature, fipnum, and the co2 mass +from the restart files from the initial (0) to the number 5 restart, using a OPM Flow build from source in a given path, this can be achieved by: .. code-block:: bash - plopm -i SPE11B -v temp -r 0,5 -m vtk -p /Users/dmar/build/opm-simulators/bin/flow + plopm -i SPE11B -v temp,fipnum,co2m -r 0,5 -m vtk -p /Users/dmar/build/opm-simulators/bin/flow .. figure:: ./figs/vtk_temp.png @@ -136,4 +145,5 @@ files from the initial (0) to the number 5 restart, using a OPM Flow build from .. note:: It is possible to write directly VTKs from OPM Flow simulations by adding the flag **--enable-vtk-output=true**. - However, there are quantities that are not written (e.g., fipnum, flores). This is when **plopm** can be helpful. \ No newline at end of file + However, there are quantities that are not written (e.g., fipnum, flores), in addition to quantities not supported + such as component mass (e.g., co2, h2o). This is when **plopm** can be helpful. \ No newline at end of file diff --git a/docs/text/figs/about.png b/docs/text/figs/about.png index 3a175a9..e47e3f5 100644 Binary files a/docs/text/figs/about.png and b/docs/text/figs/about.png differ diff --git a/docs/text/figs/fgip_spe11b.png b/docs/text/figs/fgip_spe11b.png index 8cec964..b0bfda7 100644 Binary files a/docs/text/figs/fgip_spe11b.png and b/docs/text/figs/fgip_spe11b.png differ diff --git a/docs/text/figs/fgipm.png b/docs/text/figs/fgipm.png new file mode 100644 index 0000000..18a8696 Binary files /dev/null and b/docs/text/figs/fgipm.png differ diff --git a/docs/text/figs/fipnum_norne.png b/docs/text/figs/fipnum_norne.png deleted file mode 100644 index f9ff958..0000000 Binary files a/docs/text/figs/fipnum_norne.png and /dev/null differ diff --git a/docs/text/figs/norne.png b/docs/text/figs/norne.png new file mode 100644 index 0000000..52212b0 Binary files /dev/null and b/docs/text/figs/norne.png differ diff --git a/docs/text/figs/norne_transformed.png b/docs/text/figs/norne_transformed.png new file mode 100644 index 0000000..9fe06ba Binary files /dev/null and b/docs/text/figs/norne_transformed.png differ diff --git a/docs/text/figs/permx_log.png b/docs/text/figs/permx_log.png new file mode 100644 index 0000000..b659676 Binary files /dev/null and b/docs/text/figs/permx_log.png differ diff --git a/docs/text/figs/plopm.png b/docs/text/figs/plopm.png index 76ae289..434af77 100644 Binary files a/docs/text/figs/plopm.png and b/docs/text/figs/plopm.png differ diff --git a/docs/text/figs/spe10.png b/docs/text/figs/spe10.png index 00e6578..260187f 100644 Binary files a/docs/text/figs/spe10.png and b/docs/text/figs/spe10.png differ diff --git a/docs/text/figs/tcpu.png b/docs/text/figs/tcpu.png deleted file mode 100644 index f735d80..0000000 Binary files a/docs/text/figs/tcpu.png and /dev/null differ diff --git a/docs/text/figs/wells.png b/docs/text/figs/wells.png index 612d9f3..a02dc14 100644 Binary files a/docs/text/figs/wells.png and b/docs/text/figs/wells.png differ diff --git a/docs/text/installation.rst b/docs/text/installation.rst index b13688f..f670a5f 100644 --- a/docs/text/installation.rst +++ b/docs/text/installation.rst @@ -34,6 +34,7 @@ install the Python requirements in a virtual environment with the following comm .. note:: For not macOS users, to install the Python opm package, execute in the terminal **pip install opm**. + In addition, to install the dependencies used for the figure's formatting, execute **sudo apt-get install texlive-fonts-recommended texlive-fonts-extra dvipng cm-super**. For macOS, see :ref:`macOS`. OPM Flow @@ -84,7 +85,7 @@ in the terminal the following lines (which in turn should build flow in the fold You can create a .sh file (e.g., build_opm_mpi.sh), copy the previous lines, and run in the terminal **source build_opm_mpi.sh** Regarding the reading of from OPM Flow output files (i.e., .EGRID, .INIT, .UNRST), it is possible to use the opm python package instead of resdata (e.g., it seems the opm Python package -is faster than resdata to read large simulation files). To use opm, you first need to install it, by executing in the terminal **pip install opm**. +is faster than resdata to read large simulation files). To use opm, you first need to install it, by executing in the terminal **pip install opm** and when executing plopm adding the flag **-u opm**. .. _macOS: diff --git a/docs/text/introduction.rst b/docs/text/introduction.rst index 0eb2153..61e7db2 100644 --- a/docs/text/introduction.rst +++ b/docs/text/introduction.rst @@ -4,11 +4,11 @@ Introduction .. image:: ./figs/plopm.png -This documentation describes the content of the **plopm** tool. +This documentation describes the **plopm** tool hosted in `https://github.com/cssr-tools/plopm `_. Concept ------- -Simplified and flexible framework for quick visualization of `OPM Flow `_ geological models. +Simplified and flexible framework for quick visualization of `OPM Flow `_ geological models. The approach is the generation of PNG figures from static (e.g, porosity, pore volume fluid in place numbers) and dynamic (e.g., pressure, fluid saturations) properties given any 2D slide (e.g., the middle part of a reservoir in the xy plane), as well as plotting any given summary vector (e.g., field gas in place a.k.a fgip). @@ -26,29 +26,55 @@ The current implementation supports the following executable with the argument o .. code-block:: bash - plopm -i some_input -o some_output_folder + plopm -i name(s)_of_input_file(s) where -- \-i: The base name of the input files; if more than one is given, separate them by ',' (e.g, 'SPE11B,SPE11B_TUNED') (`SPE11B` by default). -- \-o: The base name of the output folder (`.` by default). -- \-f: The font size (`14` by default). -- \-s: The slide for the 2D maps of the static variables, e.g, `10,,` to plot the xz plane on all cells with i=10 (`,1,` by default, i.e., the xz surface at j=1). -- \-x: Option to set the lower and upper bounds in the 2D map along x ('' by default). -- \-y: Option to set the lower and upper bounds in the 2D map along y ('' by default). -- \-z: The option to scale the axis in the 2D maps (`yes` by default). -- \-u: Use resdata or opm Python libraries (`resdata` by default). -- \-v: Specify the name of the static vairable to plot (e.g., `depth`) ('' by default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum). -- \-c: Specify the colormap (e.g., `jet`) ('' by default, i.e., set by plopm). -- \-n: Specify the format for the numbers in the colormap (e.g., "lambda x, _: f'{x:.0f}'") ('' by default, i.e., set by plopm). -- \-l: Specify the units (e.g., \"[m\\$^2\\$]\") ('' by default, i.e., set by plopm). -- \-r: Restart number to plot the dynamic variable, where 1 corresponds to the initial one ('-1' by default, i.e., the last restart file). -- \-w: Plot the positions of the wells or sources ('0' by default). -- \-g: Plot information about the number of cells in the x, y, and z directions and number of active grid cells ('0' by default). -- \-e: Specify the linestyles separated by ';' (e.g., 'solid;:') ('' by default, i.e., set by plopm). -- \-b: Specify the upper and lower bounds for the color map (e.g., '[-0.1,11]') ('' by default, i.e., set by matplotlib). -- \-d: Specify the dimensions of the Figure (e.g., '5,5') ('8,16' by default). -- \-t: Specify the figure title (e.g., 'Final saturation map') ('' by default, i.e., set by plopm). -- \-r: Restart number to plot the dynamic variable, where 1 corresponds to the initial one ('-1' by default, i.e., the last restart file). -- \-p: Path to flow (e.g., '\home\build\bin\flow'). This is used to generate the grid for the vtk files ('flow' by default). -- \-m: Generate 'png' or 'vtk' files ('png' by default). \ No newline at end of file +-i The base name (or full path) of the input files; if more than one is given, separate them by ',' (e.g, 'SPE11B,\\home\\user\\SPE11B_TUNED') ('SPE11B' by default). +-o The base name (or full path) of the output folder ('.' by default, i.e., the folder where plopm is executed). +-v Specify the name of the vairable to plot, e.g., 'pressure', in addition to special extensive quantities for the mass such as 'gasm', 'dism', 'liqm', 'vapm', 'co2m', 'h2om', 'fwcdm', and 'fgipm' ('' by default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum). +-m Generate 'png' or 'vtk' files ('png' by default). +-s The slide in the 3D model to plot the 2D maps, e.g, '10,,' to plot the xz plane on all cells with i=10 (',1,' by default, i.e., the xz surface at j=1). +-p Path to flow, e.g., '\\home\\build\\bin\\flow'. This is used to generate the grid for the vtk files ('flow' by default). +-z Scale the axis in the 2D maps ('1' by default). +-f The font size ('14' by default). +-x Set the lower and upper bounds along x, e.g., '[-100,200]' ('' by default). +-y Set the lower and upper bounds along y, e.g., '[-10,300]' ('' by default). +-u Use resdata or opm Python libraries ('resdata' by default). +-c Specify the colormap, e.g., 'jet', or color(s) for the summary, e.g., 'b,r' ('' by default, i.e., set by plopm). +-e Specify the linestyles separated by ';', e.g., 'solid;:' ('' by default, i.e., set by plopm). +-n Specify the format for the numbers in the colormap, e.g., "lambda x, _ f'{x:.0f}'" ('' by default, i.e., set by plopm). +-b Specify the upper and lower bounds for the color map, e.g., '[-0.1,11]' ('' by default, i.e., set by plopm). +-d Specify the dimensions in inches generated png, e.g., '5,5' ('8,16' by default). +-l Specify the units of the variable, e.g., \"[m\\$^2\\$]\" ('' by default, i.e., set by plopm). +-t Specify the figure title, e.g., 'Final saturation map' ('' by default, i.e., set by plopm). +-r Restart number to plot the dynamic variable, where 1 corresponds to the initial one ('-1' by default, i.e., the last restart file). +-w Plot the positions of the wells or sources ('0' by default). +-g Plot information about the number of cells in the x, y, and z directions and number of active grid cells ('0' by default). +-a Scale the mass variable, e.g., 1e-9 for the color bar for the CO2 mass to be in Mt ('1' by default). +-time For the x axis in the summary use seconds 's', minutes 'm', hours 'h', days 'd', weeks 'w', years 'y', or dates 'dates' ('s' by default). +-ylabel Text for the y axis ('' by default, i.e., set by plopm). +-xlabel Text for the x axis ('' by default, i.e., set by plopm). +-ylnum Number of y axis labels ('4' by default). +-xlnum Number of x axis labels ('4' by default). +-cnum Number of color labels ('' by default, i.e., set by plopm). +-clabel Text for the colorbar ('' by default, i.e., set by plopm). +-labels Legend in the summary plot, separated by commas if more than one ('' by default, i.e., set by plopm). +-axgrid Set axis.grid to True for the summary plots ('1' by default). +-dpi Dots per inch for the figure ('300' by default). +-xformat Format for the x numbers, e.g., .2e for exponential notation ('' by default, i.e., set by plopm). +-yformat Format for the y numbers, e.g., .1f for one decimal ('' by default, i.e., set by plopm). +-xunits For the x axis in the spatial maps meters 'm', kilometers 'km', centimeters 'cm', or milimeters 'mm' ('m' by default). +-yunits For the y axis in the spatial maps meters 'm', kilometers 'km', centimeters 'cm', or milimeters 'mm' ('m' by default). +-remove Set the entries to 1 to remove in the spatial maps the left axis, bottom axis, colorbar, and title ('0,0,0,0' by default). +-facecolor Color outside the spatial map ('w' by default, i.e., white). +-save Name of the output files ('' by default, i.e., set by plopm). +-log Log scale for the color map ('0' by default). +-rotate Grades to rotate the grid in the 2D maps ('0' by default). +-translate Translate the grid in the 2D maps x,y directions ('[0,0]' by default). +-global Min and max in the colorbars from the current 2D slide values (0) or whole 3D model '1' ('0' by default). +-ncolor Color for the inactive cells in the 2D maps ('w' by default, i.e., white). + +.. tip:: + + Type in the terminal **plopm --help** to show these argument options. \ No newline at end of file diff --git a/src/plopm/core/plopm.py b/src/plopm/core/plopm.py index 3ef4f19..30a33ec 100755 --- a/src/plopm/core/plopm.py +++ b/src/plopm/core/plopm.py @@ -20,7 +20,7 @@ get_yzcoords_resdata, get_yzcoords_opm, ) -from plopm.utils.mapping import map_xycoords, map_xzcoords, map_yzcoords +from plopm.utils.mapping import map_xycoords, map_xzcoords, map_yzcoords, rotate_grid from plopm.utils.vtk import make_vtks from plopm.utils.write import make_summary, make_2dmaps @@ -51,6 +51,8 @@ def plopm(): handle_slide_y(dic) else: handle_slide_z(dic) + if dic["rotate"] != 0 or dic["translate"] != ["[0", "0]"]: + rotate_grid(dic) make_2dmaps(dic) @@ -133,28 +135,53 @@ def load_parser(): "-i", "--input", default="SPE11B", - help="The base name of the input files; if more than one is given, separate " - "them by ',' (e.g, 'SPE11B,SPE11B_TUNED') ('SPE11B' by default).", + help="The base name (or full path) of the input files; if more than" + " one is given, separate them by ',' (e.g, " + "'SPE11B,\\home\\user\\SPE11B_TUNED') ('SPE11B' by default).", ) parser.add_argument( "-o", "--output", default=".", - help="The base name of the output folder ('.' by default).", + help="The base name (or full path) of the output folder ('.' by " + "default, i.e., the folder where plopm is executed).", + ) + parser.add_argument( + "-v", + "--variable", + default="", + help="Specify the name of the vairable to plot, e.g., 'pressure', in " + "addition to special extensive quantities for the mass such as " + "'gasm', 'dism', 'liqm', 'vapm', 'co2m', 'h2om', 'fwcdm', and 'fgipm' " + "('' by default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum).", + ) + parser.add_argument( + "-m", + "--mode", + default="png", + help="Generate 'png' or 'vtk' files ('png' by default).", ) parser.add_argument( "-s", "--slide", default=",1,", - help="The slide for the 2d maps of the static variables, e.g," + help="The slide in the 3D model to plot the 2D maps, e.g," " '10,,' to plot the xz plane on all cells with i=10 (',1,' " - " by default, i.e., the xz surface at j=1.)", + " by default, i.e., the xz surface at j=1).", + ) + parser.add_argument( + "-p", + "--path", + default="flow", + help="Path to flow, e.g., \\home\\build\\bin\\flow'." + " This is used to generate the grid for the vtk files ('flow' by " + "default).", ) parser.add_argument( "-z", "--scale", - default="yes", - help="Scale the 2d maps ('yes' by default)", + default=1, + help="Scale the axis in the 2D maps ('1' by default).", ) parser.add_argument( "-f", @@ -166,74 +193,69 @@ def load_parser(): "-x", "--xlim", default="", - help="Set the lower and upper bounds in the 2D map along x ('' by default).", + help="Set the lower and upper bounds along x, e.g., '[-100,200]' " + "('' by default).", ) parser.add_argument( "-y", "--ylim", default="", - help="Set the lower and upper bounds in the 2D map along y ('' by default).", + help="Set the lower and upper bounds along y, e.g., '[-10,300]' " + "('' by default).", ) parser.add_argument( "-u", "--use", default="resdata", - help="Use resdata or opm Python libraries ('resdata' by default).", - ) - parser.add_argument( - "-v", - "--variable", - default="", - help="Specify the name of the static vairable to plot (e.g.,'depth') ('' by " - "default, i.e., plotting: porv, permx, permz, poro, fipnum, and satnum).", + help="Use resdata or OPM Python libraries ('resdata' by default).", ) parser.add_argument( "-c", "--colormap", default="", - help="Specify the colormap (e.g., 'jet') or color(s) for the summary " - "(e.g., 'b,r') ('' by default, i.e., set by plopm).", + help="Specify the colormap, e.g., 'jet', or color(s) for the summary, " + "e.g., 'b,r' ('' by default, i.e., set by plopm).", ) parser.add_argument( "-e", "--linsty", default="", - help="Specify the linestyles separated by ';' (e.g., 'solid;:') ('' by default, " - "i.e., set by plopm).", + help="Specify the linestyles for the summary plots separated by ';', " + "e.g., 'solid;:' ('' by default, i.e., set by plopm).", ) parser.add_argument( "-n", "--numbers", default="", - help="Specify the format for the numbers in the colormap (e.g., " - "\"lambda x, _: f'{x:.0f}'\") ('' by default, i.e., set by plopm).", + help="Specify the format for the numbers in the colormap, e.g., " + "\"lambda x, _: f'{x:.0f}'\" ('' by default, i.e., set by plopm).", ) parser.add_argument( "-b", "--bounds", default="", - help="Specify the upper and lower bounds for the colormap (e.g., " - " '[-0.1,11]') ('' by default, i.e., set by matplotlib).", + help="Specify the upper and lower bounds for the colormap, e.g., " + " '[-0.1,11]' ('' by default, i.e., set by plopm).", ) parser.add_argument( "-d", "--dimensions", default="8,16", - help="Specify the dimensions of the Figure (e.g., " - " '5,5') ('8,16' by default).", + help="Specify the dimensions in inches of the generated png, e.g., " + "'5,5' ('8,16' by default).", ) parser.add_argument( "-l", "--legend", default="", - help="Specify the units (e.g., \"[m\\$^2\\$]\") ('' by " - "default, i.e., set by plopm).", + help='Specify the units of the variable, e.g., "[m\\$^2\\$]" ' + "('' by default, i.e., set by plopm).", ) parser.add_argument( "-t", "--title", default="", - help="Specify the figure title (e.g., 'Final saturation map') ('' by " + help="Specify the figure title, e.g., 'Final saturation map' ('' by " "default, i.e., set by plopm).", ) parser.add_argument( @@ -254,21 +276,156 @@ def load_parser(): "--grid", default=0, help="Plot information about the number of cells in the x, y, and z " - " directions and number of active grid cells ('0' by default).", + "directions and number of active grid cells ('0' by default).", ) parser.add_argument( - "-p", - "--path", - default="flow", - help="Path to flow (e.g., \\home\\build\\bin\\flow')." - " This is used to generate the grid for the vtk files ('flow' by " - "default, make sure to write inside ' ').", + "-a", + "--adjust", + default=1.0, + help="Scale the mass variable, e.g., 1e-9 for the color bar for " + "the CO2 mass to be in Mt ('1' by default).", ) parser.add_argument( - "-m", - "--mode", - default="png", - help="Generate 'png' or 'vtk' files ('png' by default).", + "-time", + "--time", + default="s", + help="For the x axis in the summary use seconds 's', minutes 'm', " + "hours 'h', days 'd', weeks 'w', years 'y', or dates 'dates' ('s' " + "by default).", + ) + parser.add_argument( + "-ylabel", + "--ylabel", + default="", + help="Text for the y axis ('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-xlabel", + "--xlabel", + default="", + help="Text for the x axis ('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-ylnum", + "--ylnum", + default=4, + help="Number of y axis labels ('4' by default).", + ) + parser.add_argument( + "-xlnum", + "--xlnum", + default=4, + help="Number of x axis labels ('4' by default).", + ) + parser.add_argument( + "-cnum", + "--cnum", + default="", + help="Number of color labels ('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-clabel", + "--clabel", + default="", + help="Text for the colorbar ('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-labels", + "--labels", + default="", + help="Legend in the summary plot, separated by commas if more than " + "one ('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-axgrid", + "--axgrid", + default=1, + help="Set axis.grid to True for the summary plots ('1' by default).", + ) + parser.add_argument( + "-dpi", + "--dpi", + default=300, + help="Dots per inch for the figure ('300' by default).", + ) + parser.add_argument( + "-xformat", + "--xformat", + default="", + help="Format for the x numbers, e.g., .2e for exponential notation " + "('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-yformat", + "--yformat", + default="", + help="Format for the y numbers, e.g., .1f for one decimal " + "('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-xunits", + "--xunits", + default="m", + help="For the x axis in the spatial maps meters 'm', kilometers 'km', " + "centimeters 'cm', or milimeters 'mm' ('m' by default).", + ) + parser.add_argument( + "-yunits", + "--yunits", + default="m", + help="For the y axis in the spatial maps meters 'm', kilometers 'km', " + "centimeters 'cm', or milimeters 'mm' ('m' by default).", + ) + parser.add_argument( + "-remove", + "--remove", + default="0,0,0,0", + help="Set the entries to 1 to remove in the spatial maps " + "the left axis, bottom axis, colorbar, and title ('0,0,0,0' by default).", + ) + parser.add_argument( + "-facecolor", + "--facecolor", + default="w", + help="Color outside the spatial map ('w' by default, i.e., white).", + ) + parser.add_argument( + "-save", + "--save", + default="", + help="Name of the output files ('' by default, i.e., set by plopm).", + ) + parser.add_argument( + "-log", + "--log", + default=0, + help="Log scale for the color map ('0' by default).", + ) + parser.add_argument( + "-rotate", + "--rotate", + default=0, + help="Grades to rotate the grid in the 2D maps ('0' by default).", + ) + parser.add_argument( + "-translate", + "--translate", + default="[0,0]", + help="Translate the grid in the 2D maps x,y directions ('[0,0]' " + "by default).", + ) + parser.add_argument( + "-global", + "--global", + default=0, + help="Min and max in the colorbars from the current 2D slide values" + " (0) or whole 3D model '1' ('0' by default).", + ) + parser.add_argument( + "-ncolor", + "--ncolor", + default="w", + help="Color for the inactive cells in the 2D maps ('w' by default, i.e., white).", ) return vars(parser.parse_known_args()[0]) diff --git a/src/plopm/utils/initialization.py b/src/plopm/utils/initialization.py index d9579a6..2f737ac 100755 --- a/src/plopm/utils/initialization.py +++ b/src/plopm/utils/initialization.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: 2024 NORCE # SPDX-License-Identifier: GPL-3.0 -# pylint: disable=W0123 +# pylint: disable=W0123,R0915,R0912 """ Utiliy functions to set the requiried input values by plopm. @@ -43,7 +43,7 @@ def ini_dic(cmdargs): if len(names) > 1: dic["names"] = names dic["coords"] = ["x", "y", "z"] - dic["scale"] = cmdargs["scale"].strip() + dic["scale"] = int(cmdargs["scale"]) dic["use"] = cmdargs["use"].strip() dic["variable"] = cmdargs["variable"].strip() dic["size"] = float(cmdargs["size"]) @@ -56,9 +56,38 @@ def ini_dic(cmdargs): dic["colormap"] = cmdargs["colormap"].strip() dic["mode"] = cmdargs["mode"].strip() dic["flow"] = cmdargs["path"].strip() - dic["xlim"], dic["ylim"], dic["wells"], dic["vsum"] = [], [], [], [] - dic["grid"], dic["summary"], dic["vsum"], dic["time"] = [], [], [], [] - dic["unrst"] = [] + dic["fc"] = cmdargs["facecolor"].strip() + dic["ncolor"] = cmdargs["ncolor"].strip() + dic["cnum"] = cmdargs["cnum"].strip() + dic["clabel"] = cmdargs["clabel"].strip() + dic["labels"] = (cmdargs["labels"].strip()).split(",") + dic["rm"] = (cmdargs["remove"].strip()).split(",") + dic["rm"] = [int(val) for val in dic["rm"]] + dic["times"] = cmdargs["time"].strip() + dic["skl"] = float(cmdargs["adjust"]) + dic["axgrid"] = int(cmdargs["axgrid"]) + dic["dpi"] = int(cmdargs["dpi"]) + dic["log"] = int(cmdargs["log"]) + dic["rotate"] = int(cmdargs["rotate"]) + dic["global"] = int(cmdargs["global"]) + dic["save"] = cmdargs["save"].strip() + dic["translate"] = (cmdargs["translate"].strip()).split(",") + for i in ["x", "y"]: + dic[f"{i}label"] = cmdargs[f"{i}label"].strip() + dic[f"{i}format"] = cmdargs[f"{i}format"].strip() + dic[f"{i}lnum"] = int(cmdargs[f"{i}lnum"]) + dic[f"{i}units"] = cmdargs[f"{i}units"].strip() + dic[f"{i}lim"] = (cmdargs[f"{i}lim"].strip()).split(",") + for name in [ + "wells", + "vsum", + "grid", + "summary", + "vsum", + "time", + "unrst", + ]: + dic[name] = [] dic["dtitle"] = "" if len((cmdargs["restart"].strip()).split(",")) == 1 and dic["mode"] != "vtk": dic["restart"] = int(cmdargs["restart"]) @@ -71,14 +100,7 @@ def ini_dic(cmdargs): dic["slide"] = ( np.genfromtxt(StringIO(cmdargs["slide"]), delimiter=",", dtype=int) - 1 ) - if cmdargs["xlim"]: - dic["xlim"] = np.genfromtxt( - StringIO(cmdargs["xlim"]), delimiter=",", dtype=float - ) - if cmdargs["ylim"]: - dic["ylim"] = np.genfromtxt( - StringIO(cmdargs["ylim"]), delimiter=",", dtype=float - ) + dic["mass"] = ["gasm", "dism", "liqm", "vapm", "co2m", "h2om"] return dic @@ -189,6 +211,7 @@ def ini_properties(dic): ] if dic["variable"]: initialize_variable(dic) + initialize_mass(dic) else: dic["props"] = [ "porv", @@ -244,6 +267,60 @@ def ini_properties(dic): } ) dic["xc"], dic["yc"] = [], [] + dic["tskl"], dic["tunit"] = initialize_time(dic["times"]) + dic["xskl"], dic["xunit"] = initialize_spatial(dic["xunits"]) + dic["yskl"], dic["yunit"] = initialize_spatial(dic["yunits"]) + + +def initialize_spatial(unit): + """ + Handle the units for the axis in the spatial maps + + Args: + unit (str): Type for the axis unit + + Returns: + scale (float): Scale for the coordinates\n + unit (str): Units for the axis + + """ + if unit == "m": + return 1, " [m]" + if unit == "km": + return 1e-3, " [km]" + if unit == "cm": + return 1e2, " [cm]" + return 1e3, " [mm]" + + +def initialize_time(times): + """ + Handle the time units for the x axis in the summary + + Args: + times (str): Type for the time to plot + + Returns: + scale (float): Scale for the times\n + unit (str): Units for the x label + + """ + scale, unit = 1.0 * 86400, "Time [seconds]" + if times == "s": + scale, unit = 1.0 * 86400, "Time [seconds]" + if times == "m": + scale, unit = 1.0 * 86400 / 60, "Time [minutes]" + if times == "h": + scale, unit = 1.0 * 86400 / 3600, "Time [hours]" + if times == "d": + scale, unit = 1.0 * 86400 / 86400, "Time [days]" + if times == "w": + scale, unit = 1.0 * 86400 / 604800, "Time [weeks]" + if times == "y": + scale, unit = 1.0 * 86400 / 31557600, "Time [years]" + if times == "dates": + scale, unit = 1, "Dates" + return scale, unit def initialize_variable(dic): @@ -284,6 +361,8 @@ def initialize_variable(dic): dic["cmaps"] = ["seismic"] if dic["variable"].lower() in ["pressure"]: dic["units"] = [" [bar]"] + if dic["variable"].lower() in ["fgip", "fgit"]: + dic["units"] = [" [sm$^3$]"] if dic["variable"].lower() in ["sgas", "rsw"]: dic["format"] = [lambda x, _: f"{x:.2f}"] if dic["variable"].lower() in ["rvw"]: @@ -292,3 +371,29 @@ def initialize_variable(dic): dic["cmaps"] = [dic["colormap"]] if dic["numbers"]: dic["format"] = [eval(dic["numbers"])] + + +def initialize_mass(dic): + """ + Initialize the mass properties according to the given variable + + Args: + dic (dict): Global dictionary + + Returns: + dic (dict): Modified global dictionary + + """ + dic["smass"] = ["fwcdm", "fgipm"] + if dic["variable"].lower() in dic["mass"] + dic["smass"]: + dic["units"] = [" [kg]"] + if dic["skl"] == 1e-3: + dic["units"] = [" [t]"] + elif dic["skl"] == 1e-6: + dic["units"] = [" [Kt]"] + elif dic["skl"] == 1e-9: + dic["units"] = [" [Mt]"] + elif dic["skl"] == 1e3: + dic["units"] = [" [g]"] + elif dic["skl"] == 1e6: + dic["units"] = [" [mg]"] diff --git a/src/plopm/utils/mapping.py b/src/plopm/utils/mapping.py index 1ce7b2f..51be2fa 100644 --- a/src/plopm/utils/mapping.py +++ b/src/plopm/utils/mapping.py @@ -5,6 +5,44 @@ Utiliy function for the grid and locations in the geological models. """ +import numpy as np + + +def rotate_grid(dic): + """ + Rotate the grid if requiered. + + Args: + dic (dict): Global dictionary + + Returns: + dic (dict): Modified global dictionary + + """ + xc, yc = [], [] + length = dic["xc"][-1][-1] - dic["xc"][0][0] + width = dic["yc"][0][-1] - dic["yc"][-1][0] + x_dis = float(dic["translate"][0][1:]) + y_dis = float(dic["translate"][1][:-1]) + for rowx, rowy in zip(dic["xc"], dic["yc"]): + xc.append([]) + yc.append([]) + for i, j in zip(rowx, rowy): + xc[-1].append( + 1.5 * length + + x_dis + + (i - 1.5 * length) * np.cos(dic["rotate"] * np.pi / 180) + - (j - 1.5 * width) * np.sin(dic["rotate"] * np.pi / 180) + ) + yc[-1].append( + 1.5 * width + + y_dis + + (j - 1.5 * width) * np.cos(dic["rotate"] * np.pi / 180) + + (i - 1.5 * length) * np.sin(dic["rotate"] * np.pi / 180) + ) + dic["xc"] = xc + dic["yc"] = yc + def map_yzcoords(dic): """ diff --git a/src/plopm/utils/readers.py b/src/plopm/utils/readers.py index 5c0de47..e1ab8f8 100644 --- a/src/plopm/utils/readers.py +++ b/src/plopm/utils/readers.py @@ -6,8 +6,13 @@ """ import csv +import sys +import datetime import numpy as np +GAS_DEN_REF = 1.86843 +WAT_DEN_REF = 998.108 + def get_yzcoords_resdata(dic): """ @@ -254,6 +259,10 @@ def get_kws_resdata(dic): dic (dict): Modified global dictionary """ + dic["porv"] = np.array(dic["init"].iget_kw("PORV")[0]) + dic["porva"] = np.ones(dic["mx"] * dic["my"]) * np.nan + dic["pv"] = np.array([porv for porv in dic["porv"] if porv > 0]) + dic["actind"] = np.cumsum([1 if porv > 0 else 0 for porv in dic["porv"]]) - 1 for name in dic["props"]: if dic["init"].has_kw(name.upper()): dic[name] = np.array(dic["init"].iget_kw(name.upper())[0]) @@ -273,12 +282,125 @@ def get_kws_resdata(dic): elif dic["summary"][0].has_key(name.upper()): for i, _ in enumerate(dic["names"]): dic["vsum"].append(dic["summary"][i][name.upper()].values) - dic["time"].append(dic["summary"][i]["TIME"].values) + if dic["times"] == "dates": + dic["time"].append(dic["summary"][i].dates) + else: + dic["time"].append(dic["summary"][i]["TIME"].values * dic["tskl"]) return + elif name.lower() in dic["mass"] + dic["smass"]: + handle_mass_resdata(dic, name) + else: + print(f"Unknow -v variable ({name}).") + sys.exit() dic[name + "a"] = np.ones(dic["mx"] * dic["my"]) * np.nan - dic["porv"] = np.array(dic["init"].iget_kw("PORV")[0]) - dic["porva"] = np.ones(dic["mx"] * dic["my"]) * np.nan - dic["actind"] = np.cumsum([1 if porv > 0 else 0 for porv in dic["porv"]]) - 1 + + +def handle_mass_resdata(dic, name): + """ + Mass using resdata. + + Args: + dic (dict): Global dictionary\n + name (str): Name of the variable for the mass spatial map + + Returns: + dic (dict): Modified global dictionary + + """ + if name.lower() in dic["mass"]: + if len(dic["names"]) == 1: + dic[name] = handle_mass(dic, name, 0, dic["restart"]) + else: + dic[name] = handle_mass(dic, name, 0, dic["restart"]) - handle_mass( + dic, name, 1, dic["restart"] + ) + ntot = len(dic["unrst"][0]["SGAS"]) + dic["dtitle"] = ( + f", rst {ntot if dic['restart']==0 else dic['restart']} out of {ntot}," + + f" total sum={sum(dic[name]):.2E}" + ) + dic[name] *= dic["skl"] + else: + for i, _ in enumerate(dic["names"]): + dic["vsum"].append( + dic["summary"][i][name[:-1].upper()].values * GAS_DEN_REF * dic["skl"] + ) + if dic["times"] == "dates": + dic["time"].append(dic["summary"][i].dates) + else: + dic["time"].append(dic["summary"][i]["TIME"].values * dic["tskl"]) + + +def handle_mass(dic, name, i, nrst): + """ + Compute the mass (intensive quantities). + + Args: + dic (dict): Global dictionary\n + name (str): Name of the variable for the mass spatial map\n + i (int): Number of the geological model\n + nrst (int): Number of restart step + + Returns: + mass (array): Floats with the computed mass + + """ + if dic["use"] == "resdata": + sgas = abs(np.array(dic["unrst"][i]["SGAS"][nrst - 1])) + rhog = np.array(dic["unrst"][i]["GAS_DEN"][nrst - 1]) + rhow = np.array(dic["unrst"][i]["WAT_DEN"][nrst - 1]) + if dic["unrst"][i].has_kw("RSW"): + rsw = np.array(dic["unrst"][i]["RSW"][nrst - 1]) + else: + rsw = 0.0 * sgas + if dic["unrst"][i].has_kw("RVW"): + rvw = np.array(dic["unrst"][i]["RVW"][nrst - 1]) + else: + rvw = 0.0 * sgas + else: + nrst = nrst - 1 if nrst > 0 else dic["unrst"][0].count("SGAS") - 1 + sgas = abs(np.array(dic["unrst"][i]["SGAS", nrst])) + rhog = np.array(dic["unrst"][i]["GAS_DEN", nrst]) + rhow = np.array(dic["unrst"][i]["WAT_DEN", nrst]) + if dic["unrst"][i].count("RSW"): + rsw = np.array(dic["unrst"][i]["RSW", nrst]) + else: + rsw = 0.0 * sgas + if dic["unrst"][i].count("RVW"): + rvw = np.array(dic["unrst"][i]["RVW", nrst]) + else: + rvw = 0.0 * sgas + co2_g = sgas * rhog * dic["pv"] + co2_d = rsw * rhow * (1.0 - sgas) * dic["pv"] * GAS_DEN_REF / WAT_DEN_REF + h2o_l = (1 - sgas) * rhow * dic["pv"] + h2o_v = rvw * rhog * sgas * dic["pv"] * WAT_DEN_REF / GAS_DEN_REF + return type_of_mass(name, co2_g, co2_d, h2o_l, h2o_v) + + +def type_of_mass(name, co2_g, co2_d, h2o_l, h2o_v): + """ + From the given variable return the associated mass + + Args: + name (str): Name of the variable for the mass spatial map\n + co2_g: Mass of CO2 in the gas phase\n + co2_d: Mass of CO2 in the liquid phase\n + h2o_l: Mass of H2O in the liquid phase\n + h2o_v: Mass of H2O in the gas phase + + Returns: + mass (array): Floats with the computed mass + + """ + if name == "gasm": + return co2_g + if name == "dism": + return co2_d + if name == "liqm": + return h2o_l + if name == "vapm": + return h2o_v + return co2_g + co2_d def get_kws_opm(dic): @@ -292,6 +414,10 @@ def get_kws_opm(dic): dic (dict): Modified global dictionary """ + dic["porv"] = np.array(dic["init"]["PORV"]) + dic["porva"] = np.ones(dic["mx"] * dic["my"]) * np.nan + dic["pv"] = np.array([porv for porv in dic["porv"] if porv > 0]) + dic["actind"] = np.cumsum([1 if porv > 0 else 0 for porv in dic["porv"]]) - 1 for name in dic["props"]: if dic["init"].count(name.upper()): dic[name] = np.array(dic["init"][name.upper()]) @@ -314,12 +440,64 @@ def get_kws_opm(dic): elif name.upper() in dic["summary"][0].keys(): for i, _ in enumerate(dic["names"]): dic["vsum"].append(dic["summary"][i][name.upper()]) - dic["time"].append(dic["summary"][i]["TIME"]) + if dic["times"] == "dates": + smsp_dates = 86400 * dic["summary"][i]["TIME"] + smsp_dates = [ + dic["summary"][i].start_date + + datetime.timedelta(seconds=seconds) + for seconds in smsp_dates + ] + dic["time"].append(smsp_dates) + else: + dic["time"].append(dic["summary"][i]["TIME"] * dic["tskl"]) return + elif name.lower() in dic["mass"] + dic["smass"]: + handle_mass_opm(dic, name) + else: + print(f"Unknow -v variable ({name}).") + sys.exit() dic[name + "a"] = np.ones(dic["mx"] * dic["my"]) * np.nan - dic["porv"] = np.array(dic["init"]["PORV"]) - dic["porva"] = np.ones(dic["mx"] * dic["my"]) * np.nan - dic["actind"] = np.cumsum([1 if porv > 0 else 0 for porv in dic["porv"]]) - 1 + + +def handle_mass_opm(dic, name): + """ + Mass using opm. + + Args: + dic (dict): Global dictionary\n + name (str): Name of the variable for the mass spatial map + + Returns: + dic (dict): Modified global dictionary + + """ + if name.lower() in dic["mass"]: + if len(dic["names"]) == 1: + dic[name] = handle_mass(dic, name, 0, dic["restart"]) + else: + dic[name] = handle_mass(dic, name, 0, dic["restart"]) - handle_mass( + dic, name, 1, dic["restart"] + ) + ntot = dic["unrst"][0].count("SGAS") + dic["dtitle"] = ( + f", rst {ntot if dic['restart']==0 else dic['restart']} out of {ntot}," + + f" total sum={sum(dic[name]):.2E}" + ) + dic[name] *= dic["skl"] + else: + for i, _ in enumerate(dic["names"]): + dic["vsum"].append( + dic["summary"][i][name[:-1].upper()] * GAS_DEN_REF * dic["skl"] + ) + if dic["times"] == "dates": + smsp_dates = 86400 * dic["summary"][i]["TIME"] + smsp_dates = [ + dic["summary"][i].start_date + datetime.timedelta(seconds=seconds) + for seconds in smsp_dates + ] + dic["time"].append(smsp_dates) + else: + dic["time"].append(dic["summary"][i]["TIME"] * dic["tskl"]) def get_wells(dic): diff --git a/src/plopm/utils/vtk.py b/src/plopm/utils/vtk.py index 32a70bc..94ed150 100644 --- a/src/plopm/utils/vtk.py +++ b/src/plopm/utils/vtk.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: 2024 NORCE # SPDX-License-Identifier: GPL-3.0 -# pylint: disable=W3301 +# pylint: disable=W3301,R0912 """ Utiliy functions to write the vtks. @@ -10,6 +10,7 @@ import csv from subprocess import PIPE, Popen import numpy as np +from plopm.utils.readers import handle_mass try: from resdata.resfile import ResdataFile @@ -55,16 +56,21 @@ def make_vtks(dic): os.system(f"cd .. && rm -rf plopm_vtks_temporal {deck[4:]}") os.chdir(cwd) for ext in ["init", "unrst"]: + dic[ext] = [] if os.path.isfile(f"{dic['name']}.{ext.upper()}"): if dic["use"] == "resdata": - dic[ext] = ResdataFile(f"{dic['name']}.{ext.upper()}") + dic[ext].append(ResdataFile(f"{dic['name']}.{ext.upper()}")) else: - dic[ext] = OpmFile(f"{dic['name']}.{ext.upper()}") + dic[ext].append(OpmFile(f"{dic['name']}.{ext.upper()}")) if not "init" in dic.keys() or not "unrst" in dic.keys(): return if dic["use"] == "resdata": + dic["porv"] = np.array(dic["init"][0]["PORV"][0]) + dic["pv"] = np.array([porv for porv in dic["porv"] if porv > 0]) opmtovtk_resdata(dic) else: + dic["porv"] = np.array(dic["init"][0]["PORV"]) + dic["pv"] = np.array([porv for porv in dic["porv"] if porv > 0]) opmtovtk_opm(dic) @@ -101,12 +107,27 @@ def opmtovtk_resdata(dic): f"\n\t\t\t\t\t\n", ) - if dic["init"].has_kw(var.upper()): + if dic["init"][0].has_kw(var.upper()): base_vtk.insert( 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(int(val) + inc) for val in dic["init"][var.upper()][0]] + + [ + str(int(val) + inc) + for val in dic["init"][0][var.upper()][0] + ] + + ["\n\t\t\t\t\t"] + ), + ) + elif var.lower() in dic["mass"]: + base_vtk.insert( + 6 + 2 * n, + " ".join( + ["\t\t\t\t\t "] + + [ + str(int(val) + inc) + for val in handle_mass(dic, var.lower(), 0, i) + ] + ["\n\t\t\t\t\t"] ), ) @@ -115,7 +136,10 @@ def opmtovtk_resdata(dic): 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(int(val) + inc) for val in dic["unrst"][var.upper()][i]] + + [ + str(int(val) + inc) + for val in dic["unrst"][0][var.upper()][i] + ] + ["\n\t\t\t\t\t"] ), ) @@ -125,12 +149,27 @@ def opmtovtk_resdata(dic): f"\n\t\t\t\t\t\n", ) - if dic["init"].has_kw(var.upper()): + if dic["init"][0].has_kw(var.upper()): + base_vtk.insert( + 6 + 2 * n, + " ".join( + ["\t\t\t\t\t "] + + [ + str(np.float16(val)) + for val in dic["init"][0][var.upper()][0] + ] + + ["\n\t\t\t\t\t"] + ), + ) + elif var.lower() in dic["mass"]: base_vtk.insert( 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(np.float16(val)) for val in dic["init"][var.upper()][0]] + + [ + str(np.float16(val)) + for val in handle_mass(dic, var.lower(), 0, i) + ] + ["\n\t\t\t\t\t"] ), ) @@ -139,14 +178,18 @@ def opmtovtk_resdata(dic): 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(np.float16(val)) for val in dic["unrst"][var.upper()][i]] + + [ + str(np.float16(val)) + for val in dic["unrst"][0][var.upper()][i] + ] + ["\n\t\t\t\t\t"] ), ) base_vtk.insert(7 + 2 * n, "\n\t\t\t\t\n") with open( - f"{dic['name']}-{0 if i<1000 else ''}{0 if i<100 else ''}{0 if i<10 else ''}{int(i)}.vtu", + f"{dic['save'] if dic['save'] else dic['name']}" + + f"-{0 if i<1000 else ''}{0 if i<100 else ''}{0 if i<10 else ''}{int(i)}.vtu", "w", encoding="utf8", ) as file: @@ -167,6 +210,7 @@ def additional_vtks_resdata(dic, base_vtk): None """ + inc = 0 if int(dic["restart"][0]) == 0 and len(dic["restart"]) == 2: dic["restart"] = range(0, int(dic["restart"][1]) + 1) for i in dic["restart"][1:]: @@ -179,10 +223,22 @@ def additional_vtks_resdata(dic, base_vtk): f"\n\t\t\t\t\t\n" ) - if dic["init"].has_kw(var.upper()): + if dic["init"][0].has_kw(var.upper()): base_vtk[6 + 2 * n] = " ".join( ["\t\t\t\t\t "] - + [str(int(val) + inc) for val in dic["init"][var.upper()][0]] + + [ + str(int(val) + inc) + for val in dic["init"][0][var.upper()][0] + ] + + ["\n\t\t\t\t\t"] + ) + elif var.lower() in dic["mass"]: + base_vtk[6 + 2 * n] = " ".join( + ["\t\t\t\t\t "] + + [ + str(int(val) + inc) + for val in handle_mass(dic, var.lower(), 0, i_i) + ] + ["\n\t\t\t\t\t"] ) else: @@ -190,7 +246,7 @@ def additional_vtks_resdata(dic, base_vtk): ["\t\t\t\t\t "] + [ str(int(val) + inc) - for val in dic["unrst"][var.upper()][i_i] + for val in dic["unrst"][0][var.upper()][i_i] ] + ["\n\t\t\t\t\t"] ) @@ -199,10 +255,22 @@ def additional_vtks_resdata(dic, base_vtk): f"\n\t\t\t\t\t\n" ) - if dic["init"].has_kw(var.upper()): + if dic["init"][0].has_kw(var.upper()): + base_vtk[6 + 2 * n] = " ".join( + ["\t\t\t\t\t "] + + [ + str(np.float16(val)) + for val in dic["init"][0][var.upper()][0] + ] + + ["\n\t\t\t\t\t"] + ) + elif var.lower() in dic["mass"]: base_vtk[6 + 2 * n] = " ".join( ["\t\t\t\t\t "] - + [str(np.float16(val)) for val in dic["init"][var.upper()][0]] + + [ + str(np.float16(val)) + for val in handle_mass(dic, var.lower(), 0, i_i) + ] + ["\n\t\t\t\t\t"] ) else: @@ -210,12 +278,13 @@ def additional_vtks_resdata(dic, base_vtk): ["\t\t\t\t\t "] + [ str(np.float16(val)) - for val in dic["unrst"][var.upper()][i_i] + for val in dic["unrst"][0][var.upper()][i_i] ] + ["\n\t\t\t\t\t"] ) with open( - f"{dic['name']}-{0 if i_i<1000 else ''}{0 if i_i<100 else ''}" + f"{dic['save'] if dic['save'] else dic['name']}" + + f"-{0 if i_i<1000 else ''}{0 if i_i<100 else ''}" + f"{0 if i_i<10 else ''}{i_i}.vtu", "w", encoding="utf8", @@ -256,12 +325,24 @@ def opmtovtk_opm(dic): f"\n\t\t\t\t\t\n", ) - if dic["init"].count(var.upper()): + if dic["init"][0].count(var.upper()): base_vtk.insert( 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(int(val) + inc) for val in dic["init"][var.upper()]] + + [str(int(val) + inc) for val in dic["init"][0][var.upper()]] + + ["\n\t\t\t\t\t"] + ), + ) + elif var.lower() in dic["mass"]: + base_vtk.insert( + 6 + 2 * n, + " ".join( + ["\t\t\t\t\t "] + + [ + str(int(val) + inc) + for val in handle_mass(dic, var.lower(), 0, i) + ] + ["\n\t\t\t\t\t"] ), ) @@ -270,7 +351,10 @@ def opmtovtk_opm(dic): 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(int(val) + inc) for val in dic["unrst"][var.upper(), i]] + + [ + str(int(val) + inc) + for val in dic["unrst"][0][var.upper(), i] + ] + ["\n\t\t\t\t\t"] ), ) @@ -280,12 +364,24 @@ def opmtovtk_opm(dic): f"\n\t\t\t\t\t\n", ) - if dic["init"].count(var.upper()): + if dic["init"][0].count(var.upper()): + base_vtk.insert( + 6 + 2 * n, + " ".join( + ["\t\t\t\t\t "] + + [str(np.float16(val)) for val in dic["init"][0][var.upper()]] + + ["\n\t\t\t\t\t"] + ), + ) + elif var.lower() in dic["mass"]: base_vtk.insert( 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(np.float16(val)) for val in dic["init"][var.upper()]] + + [ + str(np.float16(val)) + for val in handle_mass(dic, var.lower(), 0, i) + ] + ["\n\t\t\t\t\t"] ), ) @@ -294,13 +390,17 @@ def opmtovtk_opm(dic): 6 + 2 * n, " ".join( ["\t\t\t\t\t "] - + [str(np.float16(val)) for val in dic["unrst"][var.upper(), i]] + + [ + str(np.float16(val)) + for val in dic["unrst"][0][var.upper(), i] + ] + ["\n\t\t\t\t\t"] ), ) base_vtk.insert(7 + 2 * n, "\n\t\t\t\t\n") with open( - f"{dic['name']}-{0 if i<1000 else ''}{0 if i<100 else ''}{0 if i<10 else ''}{int(i)}.vtu", + f"{dic['save'] if dic['save'] else dic['name']}-{0 if i<1000 else ''}" + + f"{0 if i<100 else ''}{0 if i<10 else ''}{int(i)}.vtu", "w", encoding="utf8", ) as file: @@ -321,6 +421,7 @@ def additional_vtks_opm(dic, base_vtk): None """ + inc = 0 if int(dic["restart"][0]) == 0 and len(dic["restart"]) == 2: dic["restart"] = range(0, int(dic["restart"][1]) + 1) for i in dic["restart"][1:]: @@ -333,10 +434,19 @@ def additional_vtks_opm(dic, base_vtk): f"\n\t\t\t\t\t\n" ) - if dic["init"].count(var.upper()): + if dic["init"][0].count(var.upper()): base_vtk[6 + 2 * n] = " ".join( ["\t\t\t\t\t "] - + [str(int(val) + inc) for val in dic["init"][var.upper()]] + + [str(int(val) + inc) for val in dic["init"][0][var.upper()]] + + ["\n\t\t\t\t\t"] + ) + elif var.lower() in dic["mass"]: + base_vtk[6 + 2 * n] = " ".join( + ["\t\t\t\t\t "] + + [ + str(int(val) + inc) + for val in handle_mass(dic, var.lower(), 0, i_i) + ] + ["\n\t\t\t\t\t"] ) else: @@ -344,7 +454,7 @@ def additional_vtks_opm(dic, base_vtk): ["\t\t\t\t\t "] + [ str(int(val) + inc) - for val in dic["unrst"][var.upper(), i_i] + for val in dic["unrst"][0][var.upper(), i_i] ] + ["\n\t\t\t\t\t"] ) @@ -353,10 +463,19 @@ def additional_vtks_opm(dic, base_vtk): f"\n\t\t\t\t\t\n" ) - if dic["init"].count(var.upper()): + if dic["init"][0].count(var.upper()): base_vtk[6 + 2 * n] = " ".join( ["\t\t\t\t\t "] - + [str(np.float16(val)) for val in dic["init"][var.upper()]] + + [str(np.float16(val)) for val in dic["init"][0][var.upper()]] + + ["\n\t\t\t\t\t"] + ) + elif var.lower() in dic["mass"]: + base_vtk[6 + 2 * n] = " ".join( + ["\t\t\t\t\t "] + + [ + str(np.float16(val)) + for val in handle_mass(dic, var.lower(), 0, i_i) + ] + ["\n\t\t\t\t\t"] ) else: @@ -364,12 +483,13 @@ def additional_vtks_opm(dic, base_vtk): ["\t\t\t\t\t "] + [ str(np.float16(val)) - for val in dic["unrst"][var.upper(), i_i] + for val in dic["unrst"][0][var.upper(), i_i] ] + ["\n\t\t\t\t\t"] ) with open( - f"{dic['name']}-{0 if i_i<1000 else ''}{0 if i_i<100 else ''}" + f"{dic['save'] if dic['save'] else dic['name']}-{0 if i_i<1000 else ''}" + + f"{0 if i_i<100 else ''}" + f"{0 if i_i<10 else ''}{i_i}.vtu", "w", encoding="utf8", diff --git a/src/plopm/utils/write.py b/src/plopm/utils/write.py index 4e5b05b..4440675 100644 --- a/src/plopm/utils/write.py +++ b/src/plopm/utils/write.py @@ -1,14 +1,16 @@ # SPDX-FileCopyrightText: 2024 NORCE # SPDX-License-Identifier: GPL-3.0 -# pylint: disable=W3301 +# pylint: disable=W3301,W0123,R0912,R0915,R0914 """ Utiliy functions to write the PNGs figures. """ +import sys import numpy as np import matplotlib import matplotlib.pyplot as plt +from matplotlib import colors from mpl_toolkits.axes_grid1 import make_axes_locatable @@ -30,7 +32,8 @@ def make_summary(dic): dic["colors"] = dic["cmaps"][0].split(",") if len(dic["linsty"].split(";")) == len(dic["names"]) and dic["linsty"]: dic["linestyle"] = dic["linsty"].split(";") - plt.rcParams.update({"axes.grid": True}) + if dic["axgrid"] == 1: + plt.rcParams.update({"axes.grid": True}) fig, axis = plt.subplots() min_t, min_v = min(dic["time"][0]), min(dic["vsum"][0]) max_t, max_v = max(dic["time"][0]), max(dic["vsum"][0]) @@ -38,6 +41,8 @@ def make_summary(dic): label = name if len(name.split("/")) > 1: label = name.split("/")[-2] + "/" + name.split("/")[-1] + if dic["labels"][0] != "": + label = dic["labels"][i] axis.step( dic["time"][i], dic["vsum"][i], @@ -49,28 +54,62 @@ def make_summary(dic): min_v = min(min_v, min(dic["vsum"][i])) max_t = max(max_t, max(dic["time"][i])) max_v = max(max_v, max(dic["vsum"][i])) - axis.set_ylabel(dic["props"][0]) - axis.set_xlabel("Time [s]") - axis.set_xlim([min_t, max_t]) + axis.set_ylabel(dic["props"][0] + dic["units"][0]) axis.set_ylim([min_v, max_v]) - axis.set_xticks( - np.linspace( + axis.set_xlabel(dic["tunit"]) + if dic["xlabel"]: + axis.set_xlabel(dic["xlabel"]) + if dic["ylabel"]: + axis.set_ylabel(dic["ylabel"]) + if len(dic["xlim"]) > 1: + axis.set_xlim([float(dic["xlim"][0][1:]), float(dic["xlim"][1][:-1])]) + xlabels = np.linspace( + float(dic["xlim"][0][1:]), + float(dic["xlim"][1][:-1]), + dic["xlnum"], + ) + elif dic["times"] != "dates": + axis.set_xlim([min_t, max_t]) + xlabels = np.linspace( min_t, max_t, - 4, + dic["xlnum"], ) - ) - axis.set_yticks( - np.linspace( + if len(dic["ylim"]) > 1: + axis.set_ylim([float(dic["ylim"][0][1:]), float(dic["ylim"][1][:-1])]) + ylabels = np.linspace( + float(dic["ylim"][0][1:]), + float(dic["ylim"][1][:-1]), + dic["ylnum"], + ) + else: + axis.set_ylim([min_v, max_v]) + ylabels = np.linspace( min_v, max_v, - 4, + dic["ylnum"], ) - ) + if dic["times"] != "dates": + if dic["xformat"]: + func = "f'{x:" + dic["xformat"] + "}'" + axis.set_xticks([float(eval(func)) for x in xlabels]) + axis.set_xticklabels([eval(func) for x in xlabels]) + else: + axis.set_xticks(xlabels) + if dic["yformat"]: + func = "f'{y:" + dic["yformat"] + "}'" + axis.set_yticks([float(eval(func)) for y in ylabels]) + axis.set_yticklabels([eval(func) for y in ylabels]) + else: + axis.set_yticks(ylabels) axis.legend() if dic["titles"] != "": axis.set_title(dic["titles"]) - fig.savefig(f"{dic['output']}/{dic['variable']}.png", bbox_inches="tight", dpi=300) + fig.savefig( + f"{dic['output']}/{dic['save'] if dic['save'] else dic['variable']}.png", + bbox_inches="tight", + dpi=dic["dpi"], + ) plt.close() @@ -94,17 +133,15 @@ def make_2dmaps(dic): fig, axis = plt.subplots() for i in np.arange(0, dic["my"]): maps[i, :] = dic[name + "a"][i * (dic["mx"]) : (i + 1) * (dic["mx"])] - imag = axis.pcolormesh( - dic["xc"], - dic["yc"], - maps, - shading="flat", - cmap=dic["cmaps"][n], - ) ntick = 5 + ncolor = dic["units"][n] if dic["well"] != 1 and dic["grid"] != 1: - minc = dic[name][~np.isnan(dic[name])].min() - maxc = dic[name][~np.isnan(dic[name])].max() + if dic["global"] == 0: + minc = maps[~np.isnan(maps)].min() + maxc = maps[~np.isnan(maps)].max() + else: + minc = dic[name][~np.isnan(dic[name])].min() + maxc = dic[name][~np.isnan(dic[name])].max() if len(dic["bounds"]) == 2: minc = float(dic["bounds"][0][1:]) maxc = float(dic["bounds"][1][:-1]) @@ -115,10 +152,34 @@ def make_2dmaps(dic): if maxc == minc: ntick = 1 elif name in ["fipnum", "satnum"]: - ntick = maxc + ntick = int(maxc) else: minc = 0 maxc = len(dic["wells"]) + if dic["cnum"]: + ntick = int(dic["cnum"]) + if dic["clabel"]: + ncolor = dic["clabel"] + cmap = matplotlib.colormaps.get_cmap(dic["cmaps"][n]) + if dic["ncolor"] != "w": + cmap.set_bad(color=dic["ncolor"]) + if dic["log"] == 0: + imag = axis.pcolormesh( + dic["xc"], + dic["yc"], + maps, + shading="flat", + cmap=cmap, + ) + else: + imag = axis.pcolormesh( + dic["xc"], + dic["yc"], + maps, + shading="flat", + cmap=cmap, + norm=colors.LogNorm(vmin=minc, vmax=maxc), + ) divider = make_axes_locatable(axis) vect = np.linspace( minc, @@ -126,24 +187,64 @@ def make_2dmaps(dic): ntick, endpoint=True, ) - if dic["well"] != 1 and dic["grid"] != 1: - fig.colorbar( - imag, - cax=divider.append_axes("right", size="5%", pad=0.05), - orientation="vertical", - ticks=vect, - label=dic["units"][n], - format=dic["format"][n], - ) + if dic["well"] != 1 and dic["grid"] != 1 and dic["rm"][2] == 0: + if dic["log"] == 0: + fig.colorbar( + imag, + cax=divider.append_axes("right", size="5%", pad=0.05), + orientation="vertical", + ticks=vect, + label=ncolor, + format=dic["format"][n], + ) + else: + if minc == 0: + print( + f"It is not possible to plot {name} in log scale" + " since there are 0 values. Try without log." + ) + sys.exit() + fig.colorbar( + imag, + cax=divider.append_axes("right", size="5%", pad=0.05), + orientation="vertical", + label=ncolor, + ) else: handle_well_or_grid(dic, fig, imag, divider, vect) - imag.set_clim( - minc, - maxc, - ) + if dic["rm"][2] == 0: + imag.set_clim( + minc, + maxc, + ) handle_axis(dic, axis, name) + if dic["xlabel"] and dic["rm"][1] == 0: + axis.set_xlabel(dic["xlabel"]) + elif dic["rm"][1] == 0: + axis.set_xlabel(f"{dic['xmeaning']+dic['xunit']}") + if dic["ylabel"] and dic["rm"][0] == 0: + axis.set_ylabel(dic["ylabel"]) + elif dic["rm"][0] == 0: + axis.set_ylabel(f"{dic['ymeaning']+dic['yunit']}") + # axis.spines['left'].set_color('white') + # axis.yaxis.label.set_color('white') + # axis.tick_params(axis='y', colors='white') + # plt.setp(axis.get_xticklabels(), visible=False) + # axis.spines['bottom'].set_color('white') + # axis.xaxis.label.set_color('white') + # axis.tick_params(axis='x', colors='white') + if dic["rm"][2] == 1: + fig.delaxes(fig.axes[1]) + if dic["rm"][1] == 1: + axis.tick_params(axis="x", which="both", bottom=False, labelbottom=False) + if dic["rm"][0] == 1: + axis.tick_params(axis="y", which="both", left=False, labelleft=False) + fig.set_facecolor(dic["fc"]) + name = f"{name}_{dic['nslide']}" fig.savefig( - f"{dic['output']}/{name}_{dic['nslide']}.png", bbox_inches="tight", dpi=300 + f"{dic['output']}/{dic['save'] if dic['save'] else name}.png", + bbox_inches="tight", + dpi=dic["dpi"], ) plt.close() @@ -161,41 +262,64 @@ def handle_axis(dic, axis, name): axis (class): Modified axis object """ - if dic["scale"] == "yes": + if dic["scale"] == 1: axis.axis("scaled") - axis.set_xlabel(f"{dic['xmeaning']} [m]") - axis.set_ylabel(f"{dic['ymeaning']} [m]") extra = "" if name == "porv": extra = f" (sum={sum(dic[name]):.3e})" - axis.set_title(name + dic["tslide"] + dic["dtitle"] + extra) - if name == "grid": + if dic["rm"][3] == 0: + axis.set_title(name + dic["tslide"] + dic["dtitle"] + extra) + if name == "grid" and dic["rm"][3] == 0: axis.set_title( f"Grid = [{dic['nx']},{dic['ny']},{dic['nz']}], " + f"Total no. active cells = {max(dic['actind'])+1}" ) - if dic["titles"] != "": + if dic["titles"] != "" and dic["rm"][3] == 0: axis.set_title(dic["titles"]) if dic["slide"][2] == -2: axis.invert_yaxis() - axis.set_xticks( - np.linspace( - min(min(dic["xc"])), - max(max(dic["xc"])), - 4, + if len(dic["xlim"]) > 1 and dic["rm"][1] == 0: + axis.set_xlim([float(dic["xlim"][0][1:]), float(dic["xlim"][1][:-1])]) + xlabels = np.linspace( + float(dic["xlim"][0][1:]), + float(dic["xlim"][1][:-1]), + dic["xlnum"], ) - ) - axis.set_yticks( - np.linspace( - min(min(dic["yc"])), - max(max(dic["yc"])), - 4, + else: + xlabels = np.linspace( + min(min(dic["xc"])) * dic["xskl"], + max(max(dic["xc"])) * dic["xskl"], + dic["xlnum"], ) - ) - if len(dic["xlim"]) > 1: - axis.set_xlim(dic["xlim"]) - if len(dic["ylim"]) > 1: - axis.set_ylim(dic["ylim"]) + if dic["xformat"] and dic["rm"][1] == 0: + func = "f'{x:" + dic["xformat"] + "}'" + axis.set_xticks([float(eval(func)) / dic["xskl"] for x in xlabels]) + axis.set_xticklabels([eval(func) for x in xlabels]) + elif dic["rm"][1] == 0: + axis.set_xticks(xlabels / dic["xskl"]) + if dic["xskl"] != 1: + axis.set_xticklabels(xlabels) + if len(dic["ylim"]) > 1 and dic["rm"][0] == 0: + axis.set_ylim([float(dic["ylim"][0][1:]), float(dic["ylim"][1][:-1])]) + ylabels = np.linspace( + float(dic["ylim"][0][1:]), + float(dic["ylim"][1][:-1]), + dic["ylnum"], + ) + else: + ylabels = np.linspace( + min(min(dic["yc"])) * dic["yskl"], + max(max(dic["yc"])) * dic["yskl"], + dic["ylnum"], + ) + if dic["yformat"] and dic["rm"][0] == 0: + func = "f'{y:" + dic["yformat"] + "}'" + axis.set_yticks([float(eval(func)) / dic["yskl"] for y in ylabels]) + axis.set_yticklabels([eval(func) for y in ylabels]) + elif dic["rm"][0] == 0: + axis.set_yticks(ylabels / dic["yskl"]) + if dic["yskl"] != 1: + axis.set_yticklabels(ylabels) def handle_well_or_grid(dic, fig, imag, divider, vect): @@ -222,7 +346,7 @@ def handle_well_or_grid(dic, fig, imag, divider, vect): format=lambda x, _: "", ) cmap = matplotlib.colormaps["nipy_spectral"] - colors = cmap(np.linspace(0, 1, len(dic["wells"]) + 1)) + colour = cmap(np.linspace(0, 1, len(dic["wells"]) + 1)) if len(dic["wells"]) < 20: for i, well in enumerate(dic["wells"]): if well[2] != well[3]: @@ -230,7 +354,7 @@ def handle_well_or_grid(dic, fig, imag, divider, vect): 0, i, f"{i}-({well[0]+1},{well[1]+1},{well[2]+1}-{well[3]+1})", - c=colors[i], + c=colour[i], fontweight="bold", ) else: @@ -238,7 +362,7 @@ def handle_well_or_grid(dic, fig, imag, divider, vect): 0, i, f"{i}-({well[0]+1},{well[1]+1},{well[2]+1})", - c=colors[i], + c=colour[i], fontweight="bold", ) else: @@ -250,7 +374,7 @@ def handle_well_or_grid(dic, fig, imag, divider, vect): 0, i, f"{i}-({well[0]+1},{well[1]+1},{well[2]+1}-{well[3]+1})", - c=colors[i], + c=colour[i], fontweight="bold", ) else: @@ -258,6 +382,6 @@ def handle_well_or_grid(dic, fig, imag, divider, vect): 0, i, f"{i}-({well[0]+1},{well[1]+1},{well[2]+1})", - c=colors[i], + c=colour[i], fontweight="bold", ) diff --git a/tests/test_generic_deck.py b/tests/test_generic_deck.py index 3f08a0a..ec6c28d 100644 --- a/tests/test_generic_deck.py +++ b/tests/test_generic_deck.py @@ -41,7 +41,7 @@ def test_generic_deck(): ["4,,", ",8,", ",,20"], ["poro", "porv", "permx"], ["4,*,*", "*,8,*", "*,*,20"] ): subprocess.run( - ["plopm", "-i", "SPE10_MODEL2", "-o", ".", "-s", slide], + ["plopm", "-i", "SPE10_MODEL2", "-s", slide, "-u", "opm"], check=True, ) assert os.path.exists(f"{cwd}/tests/generic_deck/{name}_{nslide}.png")