diff --git a/.gitignore b/.gitignore index 2598273..5fcc3aa 100644 --- a/.gitignore +++ b/.gitignore @@ -163,22 +163,27 @@ cython_debug/ .DS_Store # Tests -examples/fipnum_*,1,*.png -examples/permx_*,1,*.png -examples/permz_*,1,*.png -examples/poro_*,1,*.png -examples/porv_*,1,*.png -examples/satnum_*,1,*.png -examples/sgas_*,1,*.png -examples/rsw_*,1,*.png +examples/spe11b_fipnum_*,1,*_t5.png +examples/spe11b_permx_*,1,*_t5.png +examples/spe11b_permz_*,1,*_t5.png +examples/spe11b_poro_*,1,*_t5.png +examples/spe11b_porv_*,1,*_t5.png +examples/spe11b_satnum_*,1,*_t5.png +examples/spe11b_sgas_*,1,*_t4.png +examples/spe11b_rsw_*,1,*_t5.png +examples/spe11b_sgas_*,1,*_t5.png +examples/subfigs_summary.png +examples/spe11b_xco2l.gif examples/fgip.png examples/SPE11B-*.vtu +examples/SPE11B.pvd tests/generic_deck # Python environment vplopm/ # Developing +debugging/ developing/ studies/ prototyping/ diff --git a/README.md b/README.md index 9f1795c..2446ac4 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ # plopm: Simplified and flexible tool to visualize OPM Flow geological models ## Main feature -Quick generation of PNG figures and VTKs from a OPM Flow type model. +Quick generation of PNG figures, GIFs, and VTKs from a OPM Flow type model. ## Installation To install the _plopm_ executable in an existing Python environment: diff --git a/docs/_images/comparison.png b/docs/_images/comparison.png new file mode 100644 index 0000000..8cc2ebc Binary files /dev/null and b/docs/_images/comparison.png differ diff --git a/docs/_images/fgip.png b/docs/_images/fgip.png new file mode 100644 index 0000000..ab89d02 Binary files /dev/null and b/docs/_images/fgip.png differ diff --git a/docs/_images/fgip_spe11b.png b/docs/_images/fgip_spe11b.png deleted file mode 100644 index b0bfda7..0000000 Binary files a/docs/_images/fgip_spe11b.png and /dev/null differ diff --git a/docs/_images/fgipm.png b/docs/_images/fgipm.png deleted file mode 100644 index 18a8696..0000000 Binary files a/docs/_images/fgipm.png and /dev/null differ diff --git a/docs/_images/norne.png b/docs/_images/norne.png index 52212b0..e4350ec 100644 Binary files a/docs/_images/norne.png and b/docs/_images/norne.png differ diff --git a/docs/_images/norne_transformed.png b/docs/_images/norne_transformed.png index 9fe06ba..d286452 100644 Binary files a/docs/_images/norne_transformed.png and b/docs/_images/norne_transformed.png differ diff --git a/docs/_images/satnum_spe11b.png b/docs/_images/satnum_spe11b.png deleted file mode 100644 index 648aecc..0000000 Binary files a/docs/_images/satnum_spe11b.png and /dev/null differ diff --git a/docs/_images/sgas_diff.png b/docs/_images/sgas_diff.png index df68c1a..daa1f40 100644 Binary files a/docs/_images/sgas_diff.png and b/docs/_images/sgas_diff.png differ diff --git a/docs/_images/sgas_diff_edit.png b/docs/_images/sgas_diff_edit.png index e0e11dd..87a55fc 100644 Binary files a/docs/_images/sgas_diff_edit.png and b/docs/_images/sgas_diff_edit.png differ diff --git a/docs/_images/sgas_spe11b.png b/docs/_images/sgas_spe11b.png deleted file mode 100644 index bd2dcfa..0000000 Binary files a/docs/_images/sgas_spe11b.png and /dev/null differ diff --git a/docs/_images/spe10.png b/docs/_images/spe10.png deleted file mode 100644 index 260187f..0000000 Binary files a/docs/_images/spe10.png and /dev/null differ diff --git a/docs/_images/spe10_model2_permz_*,4,*_t0.png b/docs/_images/spe10_model2_permz_*,4,*_t0.png new file mode 100644 index 0000000..d7d7b58 Binary files /dev/null and b/docs/_images/spe10_model2_permz_*,4,*_t0.png differ diff --git a/docs/_images/spe11b_satnum_*,1,*_t5.png b/docs/_images/spe11b_satnum_*,1,*_t5.png new file mode 100644 index 0000000..a130cd1 Binary files /dev/null and b/docs/_images/spe11b_satnum_*,1,*_t5.png differ diff --git a/docs/_images/spe11b_sgas_*,1,*_t4.png b/docs/_images/spe11b_sgas_*,1,*_t4.png new file mode 100644 index 0000000..1a64cc6 Binary files /dev/null and b/docs/_images/spe11b_sgas_*,1,*_t4.png differ diff --git a/docs/_images/wells.png b/docs/_images/wells.png index a02dc14..fcef9bc 100644 Binary files a/docs/_images/wells.png and b/docs/_images/wells.png differ diff --git a/docs/_images/xco2l.gif b/docs/_images/xco2l.gif new file mode 100644 index 0000000..4c2b110 Binary files /dev/null and b/docs/_images/xco2l.gif differ diff --git a/docs/_sources/examples.rst.txt b/docs/_sources/examples.rst.txt index 9683b9d..743f3ec 100644 --- a/docs/_sources/examples.rst.txt +++ b/docs/_sources/examples.rst.txt @@ -16,15 +16,10 @@ Then, if you succeed in installing **plopm**, inside the `examples folder `_, then it runs with the default terminal argument options). -.. figure:: figs/satnum_spe11b.png +.. figure:: figs/spe11b_satnum_*,1,*_t5.png -The default argument options are: - -.. code-block:: bash - - 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. +See the :ref:`overview` or run `plopm -h` for the definition of the argument options, as well as using `-printv` flag to output the available +summary, init, and restart available variables given an input deck. For example, for the gas saturation at the report step number 4 using a given colormap (-c): @@ -32,16 +27,16 @@ For example, for the gas saturation at the report step number 4 using a given co plopm -i SPE11B -v sgas -r 4 -c cubehelix -.. figure:: figs/sgas_spe11b.png +.. figure:: figs/spe11b_sgas_*,1,*_t4.png -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: +and for the gas in place summary vector given a color, line style, font size, dimension of the figure, line width, and using dates for the times: .. code-block:: bash - plopm -i SPE11B -v fgip -c b -e ':' -f 12 -d 5,5 -time dates + plopm -i SPE11B -v fgip -c b -e dotted -f 12 -d 5,5 -lw 4 -tunits dates -.. figure:: figs/fgip_spe11b.png - :scale: 30% +.. figure:: figs/fgip.png + :scale: 7% ============ Generic deck @@ -52,23 +47,26 @@ for an example where **plopm** is used to generate figures from the `SPE10_MODEL2 model `_ by downloading the files and using the `OPM Flow `_ simulator. -.. image:: ./figs/spe10.png +.. image:: ./figs/spe10_model2_permz_*,4,*_t0.png .. code-block:: bash 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. +setting the format to the numbers to two floats in the y axis, and setting manually 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 -s 1,, -d 3,4 -f 8 -g 1 && plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -w 1 + plopm -i SPE10_MODEL2 -s ,,1 -d 3,4 -f 8 -v grid -remove 0,0,1,0 && plopm -i SPE10_MODEL2 -s ,,1 -d 3,4 -f 8 -v wells -remove 0,0,0,1 .. image:: ./figs/wells.png +Here, we use the remove flag to delete the colorbar axis in the maps for the grid and to delete the generated title in the wells plot (the first entry +in remove would delete the left axis, e.g., the y label and y ticks in this example, while the second entry if set to 1 would remove the x axis). + =============================== Rotation, translation, and zoom =============================== @@ -88,10 +86,31 @@ In order to reduce the white space outside the active cells, as well as to rotat .. code-block:: bash - plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 20 + plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 30 .. image:: ./figs/norne_transformed.png +============== +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, fipnum, the co2 mass, and the co2 mass fraction in the liquid phase +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,fipnum,co2m,xco2l -vtkformat Float32,UInt16,Float64,Float32 -r 0,5 -m vtk + +.. figure:: ./figs/vtk_temp.png + + Visualization using paraview of the grid and temperature after 25 years of CO2 injection. + +.. 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), in addition to quantities not supported + such as component mass (e.g., co2, h2o). This is when **plopm** can be helpful. + ===================== Different input files ===================== @@ -101,49 +120,39 @@ called spe11b_larger_inj. Then, to plot the summary vector for both runs we can .. code-block:: bash - 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 + plopm -i 'spe11b/SPE11B spe11b_larger_inj/SPE11B' -v 'fgip,fgipm,RGIP:3 / 2' -a 1,1e-6 -tunits w -d 10,5 -c r,b -e 'solid,dashed' -t 'Field gas in place Comparing the total mass Half gas in place in fipnum 3' -f 14 -subfigs 2,2 -delax 1 -loc empty,empty,empty,center -save comparison -.. image:: ./figs/fgipm.png - :scale: 30% +.. image:: ./figs/comparison.png + :scale: 6% -Here, we plot the injected mass and scaled to kilo tons, and the time is shown in weeks. +Here, using subplots, we plot the gas in place, injected mass and scaled to kilo tons, the regional gas in place in fipnum 3 divided by 2, 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. + For any summary variable, one can give the path to more than two different simulation cases, just by separating the folder paths by spaces in the -i. To look at the difference between these two simulations for the dynamic variable sgas at the restar step 3, this can be achieved by executing: .. code-block:: bash - plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 + plopm -i spe11b_larger_inj/SPE11B -v sgas -r 3 -diff spe11b/SPE11B -remove 0,0,0,1 .. image:: ./figs/sgas_diff.png -To changue the colormap and setting the clorbar limits manually, this can be achieved by: +To changue the colormap and setting the colorbar limits manually, this can be achieved by: .. code-block:: bash - plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]' -n "lambda x, _: f'{x:.3f}'" + plopm -i spe11b_larger_inj/SPE11B -v sgas -r 3 -diff spe11b/SPE11B -remove 0,0,0,1 -c tab20c_r -b '[0,0.8]' -cformat .3 -cnum 9 .. image:: ./figs/sgas_diff_edit.png -============== -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, 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: +============ +GIF and mask +============ +To create a gif and mask the results using the satnum numbers (any variable should be supported) for the different rock properties, this can be achieved by: .. code-block:: bash - - 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 - - Visualization using paraview of the grid and temperature after 25 years of CO2 injection. + plopm -v xco2l -subfigs 1,2 -i 'spe11b/SPE11B spe11b_larger_inj/SPE11B' -d 16,2.5 -mask satnum -r 0,5 -m gif -dpi 1000 -t "spe11b spe11b larger injection" -f 16 -interval 1000 -loop 1 -cformat .2f -cbsfax 0.30,0.01,0.4,0.02 -.. 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), 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 +.. image:: ./figs/xco2l.gif \ No newline at end of file diff --git a/docs/_sources/installation.rst.txt b/docs/_sources/installation.rst.txt index f670a5f..4379c36 100644 --- a/docs/_sources/installation.rst.txt +++ b/docs/_sources/installation.rst.txt @@ -57,25 +57,25 @@ in the terminal the following lines (which in turn should build flow in the fold CURRENT_DIRECTORY="$PWD" - for repo in common grid models simulators + for repo in common grid simulators do git clone https://github.com/OPM/opm-$repo.git done mkdir build - for repo in common grid models + for repo in common grid do mkdir build/opm-$repo cd build/opm-$repo - cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-$repo + cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common" $CURRENT_DIRECTORY/opm-$repo make -j5 opm$repo cd ../.. done mkdir build/opm-simulators cd build/opm-simulators - cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid;$CURRENT_DIRECTORY/build/opm-models" $CURRENT_DIRECTORY/opm-simulators + cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-simulators make -j5 flow cd ../.. @@ -106,7 +106,7 @@ package (see the `prerequisites `_, which ./dune-common/bin/dunecontrol --only=dune-$module make -j5 done - for repo in common grid models simulators + for repo in common grid simulators do git clone https://github.com/OPM/opm-$repo.git done @@ -115,18 +115,18 @@ package (see the `prerequisites `_, which mkdir build - for repo in common grid models + for repo in common grid do mkdir build/opm-$repo cd build/opm-$repo - cmake -DPYTHON_EXECUTABLE=$(which python) -DWITH_NDEBUG=1 -DUSE_MPI=0 -DOPM_ENABLE_PYTHON=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-$repo - make -j5 + cmake -DPYTHON_EXECUTABLE=$(which python) -DWITH_NDEBUG=1 -DUSE_MPI=0 -DOPM_ENABLE_PYTHON=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common" $CURRENT_DIRECTORY/opm-$repo + make -j5 opm$repo cd ../.. done mkdir build/opm-simulators cd build/opm-simulators - cmake -DUSE_MPI=0 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid;$CURRENT_DIRECTORY/build/opm-models" $CURRENT_DIRECTORY/opm-simulators + cmake -DUSE_MPI=0 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-simulators make -j5 flow cd ../.. diff --git a/docs/_sources/introduction.rst.txt b/docs/_sources/introduction.rst.txt index 966ec42..1f23df1 100644 --- a/docs/_sources/introduction.rst.txt +++ b/docs/_sources/introduction.rst.txt @@ -10,11 +10,11 @@ Concept ------- 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), +and dynamic (e.g., pressure, fluid saturations) properties given any 2D slide with the option to generate GIFs (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). The **plopm** tool can be useful for quick inspection of geological models, as well as for generation of nice -figures for papers/presentations. Also, **plopm** can plot summary results from different simulation cases in the same figure, +figures for papers/presentations. Also, **plopm** can plot summary results from different simulation cases in the same figure (e.g., using subplots), as well as the difference between given dynamic variables (e.g., pressure) for two different simulations cases. In addition, **plopm** can convert OPM Flow output files to vtk, which allows to use other visualization/postprocessing tools (e.g., `paraview `_) @@ -30,40 +30,39 @@ The current implementation supports the following executable with the argument o where --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). +-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). +-v Specify the name of the vairable to plot, e.g., 'pressure', in addition to special extensive quantities for the mass such as 'grid', 'wells', 'gasm', 'dism', 'liqm', 'vapm', 'co2m', 'h2om', 'xco2l', 'xh2ov', 'xco2v', 'xh2ol', 'fwcdm', and 'fgipm' ('poro,permx,permz,porv,fipnum,satnum' by default). +-m Generate 'png', 'gif', 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). +-f The font size ('12' 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). +-e Specify the linestyles, e.g., 'solid,dotted' ('' 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). +-r Restart number to plot the dynamic variable, where 0 corresponds to the initial one ('-1' by default, i.e., the last restart file). -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). +-tunits 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). +-xlog Use log scale for the x axis ('0' by default). +-ylog Use log scale for the y axis ('0' by default). -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). +-dpi Dots per inch for the figure ('1200' 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). +-cformat Specify the format for the numbers in the colormap, e.g., .2f for two decimals ('' 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). @@ -74,7 +73,23 @@ where -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). - +-lw Line width separated by commas if more than one ('1' by default). +-subfigs Generate separated or a single Figure (e.g., '2,2' for four subfigures) ('' by default, i.e., separate figures). +-loc Location of the legend ('best' by default). +-delax Delete aligned axis labels in subfigures ('0' by default). +-printv Print the avaiable variables to plot ('0' by default). +-vtkformat Format for each variable in the vtks, support for Float64, Float32, and UInt16 ('Float64' by default). +-vtknames Label each variable in the written vtk ('' by default, i.e., the names given in the -v argument). +-mask Static variable to use as 2D map background ('' by default). +-diff The base name (or full path) of the input file to substract ('' by default). +-suptitle Title for the subfigures ('' by default, i.e., set by plopm, if 0, then it is removed; otherwise, write the text). +-cbsfax Set the global axis position and size for the colorbar ('0.40,0.01,0.2,0.02' by default). +-vmin Set a minimum threshold to remove values in the variable ('' by default). +-vmax Set a maximum threshold to remove values in the variable ('' by default). +-maskthr Set the threshold for the variable to mask " "('1e-3' by default). +-interval Time for the frames in the GIF in milli second ('1000' by default). +-loop Set to 1 for infinity loop in the GIF ('0' by default). + .. tip:: - Type in the terminal **plopm --help** to show these argument options. \ No newline at end of file + Type in the terminal **plopm -h** to show these argument options. \ No newline at end of file diff --git a/docs/examples.html b/docs/examples.html index 8a81bf5..871485c 100644 --- a/docs/examples.html +++ b/docs/examples.html @@ -53,8 +53,9 @@
  • SPE11B
  • Generic deck
  • Rotation, translation, and zoom
  • -
  • Different input files
  • Convert to VTK
  • +
  • Different input files
  • +
  • GIF and mask
  • plopm Python API
  • @@ -98,26 +99,23 @@

    SPE11B<

    the following figure should be generated (this example is used in the tests, then it runs with the default terminal argument options).

    -_images/satnum_spe11b.png +_images/spe11b_satnum_%2A%2C1%2C%2A_t5.png
    -

    The default argument options are:

    -
    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.

    +

    See the Overview or run plopm -h for the definition of the argument options, as well as using -printv flag to output the available +summary, init, and restart available variables given an input deck.

    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 +_images/spe11b_sgas_%2A%2C1%2C%2A_t4.png
    -

    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
    +

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

    +
    plopm -i SPE11B -v fgip -c b -e dotted -f 12 -d 5,5 -lw 4 -tunits dates
     
    -_images/fgip_spe11b.png +_images/fgip.png
    @@ -126,17 +124,19 @@

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

    -_images/spe10.png +_images/spe10_model2_permz_%2A%2C4%2C%2A_t0.png
    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.

    +setting the format to the numbers to two floats in the y axis, and setting manually 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
    +
    plopm -i SPE10_MODEL2 -s ,,1 -d 3,4 -f 8 -v grid -remove 0,0,1,0 && plopm -i SPE10_MODEL2 -s ,,1 -d 3,4 -f 8 -v wells -remove 0,0,0,1
     
    _images/wells.png +

    Here, we use the remove flag to delete the colorbar axis in the maps for the grid and to delete the generated title in the wells plot (the first entry +in remove would delete the left axis, e.g., the y label and y ticks in this example, while the second entry if set to 1 would remove the x axis).

    Rotation, translation, and zoom

    @@ -148,56 +148,64 @@

    Rotation, translation, and zoom

    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
    +
    plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 30
     
    _images/norne_transformed.png

    +
    +

    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, fipnum, the co2 mass, and the co2 mass fraction in the liquid phase +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,xco2l -vtkformat Float32,UInt16,Float64,Float32 -r 0,5 -m vtk
    +
    +
    +
    +_images/vtk_temp.png +
    +

    Visualization using paraview of the grid and temperature after 25 years of CO2 injection.

    +
    +
    +
    +

    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), in addition to quantities not supported +such as component mass (e.g., co2, h2o). This is when plopm can be helpful.

    +
    +

    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,/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
    +
    plopm -i 'spe11b/SPE11B spe11b_larger_inj/SPE11B' -v 'fgip,fgipm,RGIP:3 / 2' -a 1,1e-6 -tunits w -d 10,5 -c r,b -e 'solid,dashed' -t 'Field gas in place  Comparing the total mass  Half gas in place in fipnum 3' -f 14 -subfigs 2,2 -delax 1 -loc empty,empty,empty,center -save comparison
     
    -_images/fgipm.png -

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

    +_images/comparison.png +

    Here, using subplots, we plot the gas in place, injected mass and scaled to kilo tons, the regional gas in place in fipnum 3 divided by 2, 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.

    +

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

    To look at the difference between these two simulations for the dynamic variable sgas at the restar step 3, this can be achieved by executing:

    -
    plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3
    +
    plopm -i spe11b_larger_inj/SPE11B -v sgas -r 3 -diff spe11b/SPE11B -remove 0,0,0,1
     
    _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]' -n "lambda x, _: f'{x:.3f}'"
    +

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

    +
    plopm -i spe11b_larger_inj/SPE11B -v sgas -r 3 -diff spe11b/SPE11B -remove 0,0,0,1 -c tab20c_r -b '[0,0.8]' -cformat .3 -cnum 9
     
    _images/sgas_diff_edit.png
    -
    -

    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, 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
    +
    +

    GIF and mask

    +

    To create a gif and mask the results using the satnum numbers (any variable should be supported) for the different rock properties, this can be achieved by:

    +
    plopm -v xco2l -subfigs 1,2 -i 'spe11b/SPE11B spe11b_larger_inj/SPE11B' -d 16,2.5 -mask satnum -r 0,5 -m gif -dpi 1000 -t "spe11b  spe11b larger injection" -f 16 -interval 1000 -loop 1 -cformat .2f -cbsfax 0.30,0.01,0.4,0.02
     
    -
    -_images/vtk_temp.png -
    -

    Visualization using paraview of the grid and temperature after 25 years of CO2 injection.

    -
    -
    -
    -

    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), in addition to quantities not supported -such as component mass (e.g., co2, h2o). This is when plopm can be helpful.

    -
    +_images/xco2l.gif
    diff --git a/docs/genindex.html b/docs/genindex.html index 32535d8..29c9f14 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -79,26 +79,11 @@

    Index

    - H - | L + L | M | P
    -

    H

    - - - -
    -

    L

  • plopm Python API
      diff --git a/docs/installation.html b/docs/installation.html index 6f9c4bc..f0a6b6d 100644 --- a/docs/installation.html +++ b/docs/installation.html @@ -137,25 +137,25 @@

      Source build in Linux/Windows
      CURRENT_DIRECTORY="$PWD"
       
      -for repo in common grid models simulators
      +for repo in common grid simulators
       do
           git clone https://github.com/OPM/opm-$repo.git
       done
       
       mkdir build
       
      -for repo in common grid models
      +for repo in common grid
       do
           mkdir build/opm-$repo
           cd build/opm-$repo
      -    cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-$repo
      +    cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common" $CURRENT_DIRECTORY/opm-$repo
           make -j5 opm$repo
           cd ../..
       done
       
       mkdir build/opm-simulators
       cd build/opm-simulators
      -cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid;$CURRENT_DIRECTORY/build/opm-models" $CURRENT_DIRECTORY/opm-simulators
      +cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-simulators
       make -j5 flow
       cd ../..
       
      @@ -181,7 +181,7 @@

      Source build in Linux/Windows ./dune-common/bin/dunecontrol --only=dune-$module make -j5 done -for repo in common grid models simulators +for repo in common grid simulators do git clone https://github.com/OPM/opm-$repo.git done @@ -190,18 +190,18 @@

      Source build in Linux/Windowsmkdir build -for repo in common grid models +for repo in common grid do mkdir build/opm-$repo cd build/opm-$repo - cmake -DPYTHON_EXECUTABLE=$(which python) -DWITH_NDEBUG=1 -DUSE_MPI=0 -DOPM_ENABLE_PYTHON=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-$repo - make -j5 + cmake -DPYTHON_EXECUTABLE=$(which python) -DWITH_NDEBUG=1 -DUSE_MPI=0 -DOPM_ENABLE_PYTHON=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common" $CURRENT_DIRECTORY/opm-$repo + make -j5 opm$repo cd ../.. done mkdir build/opm-simulators cd build/opm-simulators -cmake -DUSE_MPI=0 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid;$CURRENT_DIRECTORY/build/opm-models" $CURRENT_DIRECTORY/opm-simulators +cmake -DUSE_MPI=0 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-simulators make -j5 flow cd ../.. diff --git a/docs/introduction.html b/docs/introduction.html index b406e08..910ee17 100644 --- a/docs/introduction.html +++ b/docs/introduction.html @@ -91,10 +91,10 @@

      Introduction

      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), +and dynamic (e.g., pressure, fluid saturations) properties given any 2D slide with the option to generate GIFs (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).

      The plopm tool can be useful for quick inspection of geological models, as well as for generation of nice -figures for papers/presentations. Also, plopm can plot summary results from different simulation cases in the same figure, +figures for papers/presentations. Also, plopm can plot summary results from different simulation cases in the same figure (e.g., using subplots), as well as the difference between given dynamic variables (e.g., pressure) for two different simulations cases. In addition, plopm can convert OPM Flow output files to vtk, which allows to use other visualization/postprocessing tools (e.g., paraview)

      @@ -107,16 +107,16 @@

      Concept

      where

      -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).

      +

      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).

      +

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

      -m
      -

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

      +

      Generate ‘png’, ‘gif’, 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).

      @@ -128,7 +128,7 @@

      Concept

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

      -f
      -

      The font size (‘14’ by default).

      +

      The font size (‘12’ by default).

      -x

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

      @@ -143,10 +143,7 @@

      Concept

      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).

      +

      Specify the linestyles, e.g., ‘solid,dotted’ (’’ 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).

      @@ -154,25 +151,16 @@

      Concept
      -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).

      +

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

      -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
      +
      -tunits

      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
      @@ -190,6 +178,12 @@

      Concept
      -cnum

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

      +
      -xlog
      +

      Use log scale for the x axis (‘0’ by default).

      +
      +
      -ylog
      +

      Use log scale for the y axis (‘0’ by default).

      +
      -clabel

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

      @@ -200,7 +194,7 @@

      Concept

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

      -dpi
      -

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

      +

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

      -xformat

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

      @@ -208,6 +202,9 @@

      Concept
      -yformat

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

      +
      -cformat
      +

      Specify the format for the numbers in the colormap, e.g., .2f for two decimals (’’ 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).

      @@ -238,10 +235,58 @@

      Concept
      -ncolor

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

      +
      -lw
      +

      Line width separated by commas if more than one (‘1’ by default).

      +
      +
      -subfigs
      +

      Generate separated or a single Figure (e.g., ‘2,2’ for four subfigures) (’’ by default, i.e., separate figures).

      +
      +
      -loc
      +

      Location of the legend (‘best’ by default).

      +
      +
      -delax
      +

      Delete aligned axis labels in subfigures (‘0’ by default).

      +
      +
      -printv
      +

      Print the avaiable variables to plot (‘0’ by default).

      +
      +
      -vtkformat
      +

      Format for each variable in the vtks, support for Float64, Float32, and UInt16 (‘Float64’ by default).

      +
      +
      -vtknames
      +

      Label each variable in the written vtk (’’ by default, i.e., the names given in the -v argument).

      +
      +
      -mask
      +

      Static variable to use as 2D map background (’’ by default).

      +
      +
      -diff
      +

      The base name (or full path) of the input file to substract (’’ by default).

      +
      +
      -suptitle
      +

      Title for the subfigures (’’ by default, i.e., set by plopm, if 0, then it is removed; otherwise, write the text).

      +
      +
      -cbsfax
      +

      Set the global axis position and size for the colorbar (‘0.40,0.01,0.2,0.02’ by default).

      +
      +
      -vmin
      +

      Set a minimum threshold to remove values in the variable (’’ by default).

      +
      +
      -vmax
      +

      Set a maximum threshold to remove values in the variable (’’ by default).

      +
      +
      -maskthr
      +

      Set the threshold for the variable to mask “ “(‘1e-3’ by default).

      +
      +
      -interval
      +

      Time for the frames in the GIF in milli second (‘1000’ by default).

      +
      +
      -loop
      +

      Set to 1 for infinity loop in the GIF (‘0’ by default).

      +

      Tip

      -

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

      +

      Type in the terminal plopm -h to show these argument options.

      diff --git a/docs/objects.inv b/docs/objects.inv index fa55ec3..7aa7fc9 100644 --- a/docs/objects.inv +++ b/docs/objects.inv @@ -2,5 +2,7 @@ # Project: plopm # Version: # The remainder of this file is compressed using zlib. -xڭTN0F&k +>Z ;b4LǓiZ*>cz{j$znhF妄E3!}:߲B(X9%kUp/MA'g.q2L,+כh&ՇMb* ل@[ -r96s{; %qE6PB*Ր;0^@qzr4* gMnyTx#A0|,N#D3nPJt]I%ӒWs)κ>KRr딼GxAk gCQ &)xU]Jͪ7l6dzokBI2nnm\54ńv@. 3b29<7-L M1<@- +U5@Q$Ñ$Z̘1^Ar:n +jBqL6L/!^6B52_rV-VoיCwۃ9hy!yZ˕M'o`ވ~x4#aydmGhd=ҼZӁ*j^B`o!oex \ No newline at end of file diff --git a/docs/plopm.core.html b/docs/plopm.core.html index 8e39969..08fef30 100644 --- a/docs/plopm.core.html +++ b/docs/plopm.core.html @@ -88,9 +88,6 @@

      Submodules
      • plopm.core.plopm module
          -
        • handle_slide_x()
        • -
        • handle_slide_y()
        • -
        • handle_slide_z()
        • load_parser()
        • main()
        • plopm()
        • diff --git a/docs/plopm.core.plopm.html b/docs/plopm.core.plopm.html index ffc9b62..e1c2c30 100644 --- a/docs/plopm.core.plopm.html +++ b/docs/plopm.core.plopm.html @@ -85,42 +85,6 @@

          plopm.core.plopm module

          Script to plot 2D maps of OPM Flow geological models.

          -
          -
          -plopm.core.plopm.handle_slide_x(dic)
          -

          Processing the selected yz slide to obtain the grid properties

          -
          -
          Args:

          dic (dict): Global dictionary

          -
          -
          Returns:

          dic (dict): Modified global dictionary

          -
          -
          -
          - -
          -
          -plopm.core.plopm.handle_slide_y(dic)
          -

          Processing the selected xz slide to obtain the grid properties

          -
          -
          Args:

          dic (dict): Global dictionary

          -
          -
          Returns:

          dic (dict): Modified global dictionary

          -
          -
          -
          - -
          -
          -plopm.core.plopm.handle_slide_z(dic)
          -

          Processing the selected xy slide to obtain the grid properties

          -
          -
          Args:

          dic (dict): Global dictionary

          -
          -
          Returns:

          dic (dict): Modified global dictionary

          -
          -
          -
          -
          plopm.core.plopm.load_parser()
          diff --git a/docs/plopm.html b/docs/plopm.html index 98ca84b..c65bbbe 100644 --- a/docs/plopm.html +++ b/docs/plopm.html @@ -89,9 +89,6 @@

          Subpackagesplopm.core package
          • Submodules
            • plopm.core.plopm module
                -
              • handle_slide_x()
              • -
              • handle_slide_y()
              • -
              • handle_slide_z()
              • load_parser()
              • main()
              • plopm()
              • diff --git a/docs/searchindex.js b/docs/searchindex.js index 5f9d4a5..d3a63fc 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -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 +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, 2], "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, 5], "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], "see": [2, 4], "overview": [2, 3, 4], "h": [2, 5], "definit": 2, "well": [2, 4, 5, 10], "printv": 2, "flag": [2, 4], "output": [2, 4, 5], "avail": [2, 4], "summari": [2, 5], "init": [2, 4], "restart": [2, 5], "variabl": [2, 5], "given": [2, 5], "ga": [2, 5], "satur": [2, 5], "report": 2, "step": 2, "4": [2, 5], "colormap": [2, 5], "c": [2, 5], "v": [2, 5], "sga": 2, "r": [2, 4, 5], "cubehelix": 2, "place": [2, 5], "vector": [2, 5], "color": [2, 5], "line": [2, 4, 5], "style": 2, "font": [2, 4, 5], "size": [2, 5], "dimens": [2, 5], "width": [2, 5], "date": [2, 5], "time": [2, 5], "fgip": [2, 5], "b": [2, 5], "e": [2, 4, 5], "dot": [2, 5], "f": [2, 5], "12": [2, 5], "d": [2, 5], "5": [2, 5], "lw": 2, "tunit": 2, "test_generic_deck": 2, "py": 2, "where": [2, 5], "from": [2, 4, 5], "spe10_model2": 2, "model": [2, 5, 9, 10], "download": 2, "opm": [2, 3, 5, 9, 10], "flow": [2, 3, 5, 9, 10], "permz": [2, 5], "": [2, 4, 5], "log": [2, 5], "1": [2, 4, 5], "xunit": 2, "km": [2, 5], "yunit": 2, "xlnum": 2, "6": 2, "yformat": 2, "2f": [2, 5], "t": [2, 5], "k": [2, 5], "_z": 2, "forth": 2, "slide": [2, 5], "xz": [2, 5], "plane": [2, 5], "1e": [2, 5], "7": 2, "1e3": 2, "here": 2, "we": 2, "look": 2, "scale": [2, 5], "permeabl": 2, "z": [2, 5], "direct": [2, 5], "chang": 2, "axi": [2, 5], "unit": [2, 5], "set": [2, 4, 5], "format": [2, 4, 5], "two": [2, 5], "float": 2, "y": [2, 5], "manual": 2, "upper": [2, 5], "lower": [2, 5], "bound": [2, 5], "map": [2, 5, 9], "To": [2, 4], "inform": 2, "grid": [2, 4, 5], "also": [2, 4, 5], "top": 2, "view": 2, "achiev": [2, 4], "3": [2, 4, 5], "8": [2, 5], "remov": [2, 4, 5], "0": [2, 4, 5], "delet": [2, 5], "colorbar": [2, 5], "titl": [2, 5], "first": [2, 4], "entri": [2, 5], "would": 2, "left": [2, 5], "g": [2, 4, 5], "label": [2, 5], "tick": 2, "while": 2, "second": [2, 5], "x": [2, 5], "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], "cell": [2, 5], "can": [2, 4, 5], "ahiev": 2, "65": 2, "6456335": 2, "3476500": 2, "5600": 2, "7600": 2, "30": 2, "creat": [2, 4], "egrid": [2, 4], "unrst": [2, 4], "temperatur": 2, "fipnum": [2, 5], "co2": [2, 5, 10], "mass": [2, 5], "fraction": 2, "liquid": 2, "phase": 2, "initi": [2, 5], "build": [2, 3, 5], "sourc": [2, 3, 10], "path": [2, 5], "temp": 2, "co2m": [2, 5], "xco2l": [2, 5], "vtkformat": 2, "float32": [2, 5], "uint16": [2, 5], "float64": [2, 5], "m": [2, 4, 5], "visual": [2, 5], "paraview": [2, 5], "after": [2, 4], "25": 2, "year": [2, 5], "inject": 2, "It": 2, "possibl": [2, 4], "write": [2, 5], "directli": 2, "ad": [2, 3, 4], "enabl": 2, "true": [2, 5], "howev": 2, "quantiti": [2, 5], "written": [2, 5], "flore": 2, "addit": [2, 4, 5], "support": [2, 4, 5], "compon": 2, "h2o": 2, "when": [2, 4], "help": 2, "let": 2, "u": [2, 4, 5], "assum": 2, "have": 2, "case": [2, 5], "save": 2, "call": 2, "rate": 2, "ha": 2, "been": 2, "increas": 2, "spe11b_larger_inj": 2, "both": 2, "fgipm": [2, 5], "rgip": 2, "2": [2, 5], "w": [2, 5], "10": [2, 4, 5], "solid": [2, 5], "dash": 2, "field": [2, 5], "compar": 2, "total": 2, "half": 2, "14": 2, "subfig": 2, "delax": 2, "loc": 2, "empti": 2, "comparison": 2, "subplot": [2, 5], "kilo": 2, "ton": 2, "region": 2, "divid": 2, "shown": 2, "week": [2, 5], "ani": [2, 5], "one": [2, 5], "give": 2, "just": 2, "separ": [2, 5], "between": [2, 5], "dynam": [2, 5, 10], "restar": 2, "diff": 2, "changu": 2, "limit": 2, "tab20c_r": 2, "cformat": 2, "cnum": 2, "9": [2, 4, 5], "satnum": [2, 5], "rock": 2, "properti": [2, 5], "16": [2, 5], "dpi": 2, "1000": [2, 5], "larger": 2, "interv": 2, "loop": [2, 5], "cbsfax": 2, "01": [2, 5], "02": [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, "convert": [3, 4, 5], "vtk": [3, 4, 5], "input": [3, 5], "file": [3, 4, 5], "gif": [3, 5], "mask": [3, 5], "api": 3, "relat": 3, "pyopmnearwel": 3, "exprecc": 3, "pycopm": 3, "micp": 3, "pymm": 3, "about": 3, "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, "code": 4, "clone": 4, "repositori": 4, "requir": 4, "virtual": 4, "command": 4, "repo": 4, "get": 4, "cd": 4, "python3": 4, "venv": 4, "vplopm": 4, "bin": [4, 5], "upgrad": 4, "setuptool": 4, "wheel": 4, "lint": 4, "dev": 4, "txt": 4, "user": [4, 5], "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, "resdata": [4, 5], "seem": 4, "faster": 4, "larg": 4, "so": 4, "built": 4, "dune": 4, "librari": [4, 5], "macport": 4, "brew": 4, "geometri": 4, "istl": 4, "gitlab": 4, "v2": 4, "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, 5], "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], "png": 5, "static": 5, "poros": 5, "pore": 5, "volum": 5, "fluid": 5, "pressur": 5, "2d": [5, 9], "middl": 5, "part": 5, "reservoir": 5, "xy": 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, "home": 5, "spe11b_tun": 5, "o": 5, "specifi": 5, "vairabl": 5, "special": 5, "extens": 5, "gasm": 5, "dism": 5, "liqm": 5, "vapm": 5, "h2om": 5, "xh2ov": 5, "xco2v": 5, "xh2ol": 5, "fwcdm": 5, "poro": 5, "permx": 5, "porv": 5, "3d": 5, "surfac": 5, "j": 5, "p": 5, "along": 5, "100": 5, "200": 5, "300": 5, "jet": 5, "linestyl": 5, "11": 5, "inch": 5, "final": 5, "correspond": 5, "last": 5, "bar": 5, "mt": 5, "minut": 5, "hour": 5, "dai": 5, "text": 5, "lnum": 5, "num": 5, "l": 5, "abel": 5, "legend": 5, "comma": 5, "xgrid": 5, "pi": 5, "per": 5, "1200": 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, "bottom": 5, "acecolor": 5, "av": 5, "og": 5, "otat": 5, "grade": 5, "ranslat": 5, "lobal": 5, "min": 5, "max": 5, "valu": 5, "whole": 5, "n": 5, "inact": 5, "ubfig": 5, "singl": 5, "four": 5, "subfigur": 5, "oc": 5, "best": 5, "elax": 5, "align": 5, "rintv": 5, "print": 5, "avaiabl": 5, "tkformat": 5, "each": 5, "tkname": 5, "ask": 5, "background": 5, "iff": 5, "substract": 5, "uptitl": 5, "bsfax": 5, "global": 5, "posit": 5, "40": 5, "minimum": 5, "threshold": 5, "maximum": 5, "askthr": 5, "nterval": 5, "frame": 5, "milli": 5, "oop": 5, "infin": 5, "show": 5, "load_pars": [7, 8, 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, "", "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, "convert": 2, "vtk": 2, "differ": 2, "input": 2, "file": 2, "gif": 2, "mask": 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"]], "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"]], "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"]], "Examples": [[2, "examples"]], "SPE11B": [[2, "spe11b"]], "Generic deck": [[2, "generic-deck"]], "Rotation, translation, and zoom": [[2, "rotation-translation-and-zoom"]], "Convert to VTK": [[2, "convert-to-vtk"]], "Different input files": [[2, "different-input-files"]], "GIF and mask": [[2, "gif-and-mask"]], "Introduction": [[5, "introduction"]], "Concept": [[5, "concept"]], "Overview": [[5, "overview"]]}, "indexentries": {}}) \ No newline at end of file diff --git a/docs/text/examples.rst b/docs/text/examples.rst index 9683b9d..743f3ec 100644 --- a/docs/text/examples.rst +++ b/docs/text/examples.rst @@ -16,15 +16,10 @@ Then, if you succeed in installing **plopm**, inside the `examples folder `_, then it runs with the default terminal argument options). -.. figure:: figs/satnum_spe11b.png +.. figure:: figs/spe11b_satnum_*,1,*_t5.png -The default argument options are: - -.. code-block:: bash - - 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. +See the :ref:`overview` or run `plopm -h` for the definition of the argument options, as well as using `-printv` flag to output the available +summary, init, and restart available variables given an input deck. For example, for the gas saturation at the report step number 4 using a given colormap (-c): @@ -32,16 +27,16 @@ For example, for the gas saturation at the report step number 4 using a given co plopm -i SPE11B -v sgas -r 4 -c cubehelix -.. figure:: figs/sgas_spe11b.png +.. figure:: figs/spe11b_sgas_*,1,*_t4.png -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: +and for the gas in place summary vector given a color, line style, font size, dimension of the figure, line width, and using dates for the times: .. code-block:: bash - plopm -i SPE11B -v fgip -c b -e ':' -f 12 -d 5,5 -time dates + plopm -i SPE11B -v fgip -c b -e dotted -f 12 -d 5,5 -lw 4 -tunits dates -.. figure:: figs/fgip_spe11b.png - :scale: 30% +.. figure:: figs/fgip.png + :scale: 7% ============ Generic deck @@ -52,23 +47,26 @@ for an example where **plopm** is used to generate figures from the `SPE10_MODEL2 model `_ by downloading the files and using the `OPM Flow `_ simulator. -.. image:: ./figs/spe10.png +.. image:: ./figs/spe10_model2_permz_*,4,*_t0.png .. code-block:: bash 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. +setting the format to the numbers to two floats in the y axis, and setting manually 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 -s 1,, -d 3,4 -f 8 -g 1 && plopm -i SPE10_MODEL2 -s 1,, -d 3,4 -f 8 -w 1 + plopm -i SPE10_MODEL2 -s ,,1 -d 3,4 -f 8 -v grid -remove 0,0,1,0 && plopm -i SPE10_MODEL2 -s ,,1 -d 3,4 -f 8 -v wells -remove 0,0,0,1 .. image:: ./figs/wells.png +Here, we use the remove flag to delete the colorbar axis in the maps for the grid and to delete the generated title in the wells plot (the first entry +in remove would delete the left axis, e.g., the y label and y ticks in this example, while the second entry if set to 1 would remove the x axis). + =============================== Rotation, translation, and zoom =============================== @@ -88,10 +86,31 @@ In order to reduce the white space outside the active cells, as well as to rotat .. code-block:: bash - plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 20 + plopm -i NORNE_ATW2013 -s ,,1 -rotate 65 -translate '[6456335.5,-3476500]' -x '[0,5600]' -y '[0,7600]' -f 30 .. image:: ./figs/norne_transformed.png +============== +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, fipnum, the co2 mass, and the co2 mass fraction in the liquid phase +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,fipnum,co2m,xco2l -vtkformat Float32,UInt16,Float64,Float32 -r 0,5 -m vtk + +.. figure:: ./figs/vtk_temp.png + + Visualization using paraview of the grid and temperature after 25 years of CO2 injection. + +.. 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), in addition to quantities not supported + such as component mass (e.g., co2, h2o). This is when **plopm** can be helpful. + ===================== Different input files ===================== @@ -101,49 +120,39 @@ called spe11b_larger_inj. Then, to plot the summary vector for both runs we can .. code-block:: bash - 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 + plopm -i 'spe11b/SPE11B spe11b_larger_inj/SPE11B' -v 'fgip,fgipm,RGIP:3 / 2' -a 1,1e-6 -tunits w -d 10,5 -c r,b -e 'solid,dashed' -t 'Field gas in place Comparing the total mass Half gas in place in fipnum 3' -f 14 -subfigs 2,2 -delax 1 -loc empty,empty,empty,center -save comparison -.. image:: ./figs/fgipm.png - :scale: 30% +.. image:: ./figs/comparison.png + :scale: 6% -Here, we plot the injected mass and scaled to kilo tons, and the time is shown in weeks. +Here, using subplots, we plot the gas in place, injected mass and scaled to kilo tons, the regional gas in place in fipnum 3 divided by 2, 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. + For any summary variable, one can give the path to more than two different simulation cases, just by separating the folder paths by spaces in the -i. To look at the difference between these two simulations for the dynamic variable sgas at the restar step 3, this can be achieved by executing: .. code-block:: bash - plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 + plopm -i spe11b_larger_inj/SPE11B -v sgas -r 3 -diff spe11b/SPE11B -remove 0,0,0,1 .. image:: ./figs/sgas_diff.png -To changue the colormap and setting the clorbar limits manually, this can be achieved by: +To changue the colormap and setting the colorbar limits manually, this can be achieved by: .. code-block:: bash - plopm -i spe11b/SPE11B,spe11b_larger_inj/SPE11B -v sgas -r 3 -c tab20c -b '[-0.8,0]' -n "lambda x, _: f'{x:.3f}'" + plopm -i spe11b_larger_inj/SPE11B -v sgas -r 3 -diff spe11b/SPE11B -remove 0,0,0,1 -c tab20c_r -b '[0,0.8]' -cformat .3 -cnum 9 .. image:: ./figs/sgas_diff_edit.png -============== -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, 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: +============ +GIF and mask +============ +To create a gif and mask the results using the satnum numbers (any variable should be supported) for the different rock properties, this can be achieved by: .. code-block:: bash - - 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 - - Visualization using paraview of the grid and temperature after 25 years of CO2 injection. + plopm -v xco2l -subfigs 1,2 -i 'spe11b/SPE11B spe11b_larger_inj/SPE11B' -d 16,2.5 -mask satnum -r 0,5 -m gif -dpi 1000 -t "spe11b spe11b larger injection" -f 16 -interval 1000 -loop 1 -cformat .2f -cbsfax 0.30,0.01,0.4,0.02 -.. 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), 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 +.. image:: ./figs/xco2l.gif \ No newline at end of file diff --git a/docs/text/figs/comparison.png b/docs/text/figs/comparison.png new file mode 100644 index 0000000..8cc2ebc Binary files /dev/null and b/docs/text/figs/comparison.png differ diff --git a/docs/text/figs/fgip.png b/docs/text/figs/fgip.png new file mode 100644 index 0000000..ab89d02 Binary files /dev/null and b/docs/text/figs/fgip.png differ diff --git a/docs/text/figs/fgip_spe11b.png b/docs/text/figs/fgip_spe11b.png deleted file mode 100644 index b0bfda7..0000000 Binary files a/docs/text/figs/fgip_spe11b.png and /dev/null differ diff --git a/docs/text/figs/fgipm.png b/docs/text/figs/fgipm.png deleted file mode 100644 index 18a8696..0000000 Binary files a/docs/text/figs/fgipm.png and /dev/null differ diff --git a/docs/text/figs/norne.png b/docs/text/figs/norne.png index 52212b0..e4350ec 100644 Binary files a/docs/text/figs/norne.png and b/docs/text/figs/norne.png differ diff --git a/docs/text/figs/norne_transformed.png b/docs/text/figs/norne_transformed.png index 9fe06ba..d286452 100644 Binary files a/docs/text/figs/norne_transformed.png and b/docs/text/figs/norne_transformed.png differ diff --git a/docs/text/figs/satnum_spe11b.png b/docs/text/figs/satnum_spe11b.png deleted file mode 100644 index 648aecc..0000000 Binary files a/docs/text/figs/satnum_spe11b.png and /dev/null differ diff --git a/docs/text/figs/sgas_diff.png b/docs/text/figs/sgas_diff.png index df68c1a..daa1f40 100644 Binary files a/docs/text/figs/sgas_diff.png and b/docs/text/figs/sgas_diff.png differ diff --git a/docs/text/figs/sgas_diff_edit.png b/docs/text/figs/sgas_diff_edit.png index e0e11dd..87a55fc 100644 Binary files a/docs/text/figs/sgas_diff_edit.png and b/docs/text/figs/sgas_diff_edit.png differ diff --git a/docs/text/figs/sgas_spe11b.png b/docs/text/figs/sgas_spe11b.png deleted file mode 100644 index bd2dcfa..0000000 Binary files a/docs/text/figs/sgas_spe11b.png and /dev/null differ diff --git a/docs/text/figs/spe10.png b/docs/text/figs/spe10.png deleted file mode 100644 index 260187f..0000000 Binary files a/docs/text/figs/spe10.png and /dev/null differ diff --git a/docs/text/figs/spe10_model2_permz_*,4,*_t0.png b/docs/text/figs/spe10_model2_permz_*,4,*_t0.png new file mode 100644 index 0000000..d7d7b58 Binary files /dev/null and b/docs/text/figs/spe10_model2_permz_*,4,*_t0.png differ diff --git a/docs/text/figs/spe11b_satnum_*,1,*_t5.png b/docs/text/figs/spe11b_satnum_*,1,*_t5.png new file mode 100644 index 0000000..a130cd1 Binary files /dev/null and b/docs/text/figs/spe11b_satnum_*,1,*_t5.png differ diff --git a/docs/text/figs/spe11b_sgas_*,1,*_t4.png b/docs/text/figs/spe11b_sgas_*,1,*_t4.png new file mode 100644 index 0000000..1a64cc6 Binary files /dev/null and b/docs/text/figs/spe11b_sgas_*,1,*_t4.png differ diff --git a/docs/text/figs/wells.png b/docs/text/figs/wells.png index a02dc14..fcef9bc 100644 Binary files a/docs/text/figs/wells.png and b/docs/text/figs/wells.png differ diff --git a/docs/text/figs/xco2l.gif b/docs/text/figs/xco2l.gif new file mode 100644 index 0000000..4c2b110 Binary files /dev/null and b/docs/text/figs/xco2l.gif differ diff --git a/docs/text/installation.rst b/docs/text/installation.rst index f670a5f..4379c36 100644 --- a/docs/text/installation.rst +++ b/docs/text/installation.rst @@ -57,25 +57,25 @@ in the terminal the following lines (which in turn should build flow in the fold CURRENT_DIRECTORY="$PWD" - for repo in common grid models simulators + for repo in common grid simulators do git clone https://github.com/OPM/opm-$repo.git done mkdir build - for repo in common grid models + for repo in common grid do mkdir build/opm-$repo cd build/opm-$repo - cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-$repo + cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common" $CURRENT_DIRECTORY/opm-$repo make -j5 opm$repo cd ../.. done mkdir build/opm-simulators cd build/opm-simulators - cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid;$CURRENT_DIRECTORY/build/opm-models" $CURRENT_DIRECTORY/opm-simulators + cmake -DUSE_MPI=1 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-simulators make -j5 flow cd ../.. @@ -106,7 +106,7 @@ package (see the `prerequisites `_, which ./dune-common/bin/dunecontrol --only=dune-$module make -j5 done - for repo in common grid models simulators + for repo in common grid simulators do git clone https://github.com/OPM/opm-$repo.git done @@ -115,18 +115,18 @@ package (see the `prerequisites `_, which mkdir build - for repo in common grid models + for repo in common grid do mkdir build/opm-$repo cd build/opm-$repo - cmake -DPYTHON_EXECUTABLE=$(which python) -DWITH_NDEBUG=1 -DUSE_MPI=0 -DOPM_ENABLE_PYTHON=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-$repo - make -j5 + cmake -DPYTHON_EXECUTABLE=$(which python) -DWITH_NDEBUG=1 -DUSE_MPI=0 -DOPM_ENABLE_PYTHON=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common" $CURRENT_DIRECTORY/opm-$repo + make -j5 opm$repo cd ../.. done mkdir build/opm-simulators cd build/opm-simulators - cmake -DUSE_MPI=0 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid;$CURRENT_DIRECTORY/build/opm-models" $CURRENT_DIRECTORY/opm-simulators + cmake -DUSE_MPI=0 -DWITH_NDEBUG=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$CURRENT_DIRECTORY/dune-common/build-cmake;$CURRENT_DIRECTORY/dune-grid/build-cmake;$CURRENT_DIRECTORY/dune-geometry/build-cmake;$CURRENT_DIRECTORY/dune-istl/build-cmake;$CURRENT_DIRECTORY/build/opm-common;$CURRENT_DIRECTORY/build/opm-grid" $CURRENT_DIRECTORY/opm-simulators make -j5 flow cd ../.. diff --git a/docs/text/introduction.rst b/docs/text/introduction.rst index 966ec42..1f23df1 100644 --- a/docs/text/introduction.rst +++ b/docs/text/introduction.rst @@ -10,11 +10,11 @@ Concept ------- 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), +and dynamic (e.g., pressure, fluid saturations) properties given any 2D slide with the option to generate GIFs (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). The **plopm** tool can be useful for quick inspection of geological models, as well as for generation of nice -figures for papers/presentations. Also, **plopm** can plot summary results from different simulation cases in the same figure, +figures for papers/presentations. Also, **plopm** can plot summary results from different simulation cases in the same figure (e.g., using subplots), as well as the difference between given dynamic variables (e.g., pressure) for two different simulations cases. In addition, **plopm** can convert OPM Flow output files to vtk, which allows to use other visualization/postprocessing tools (e.g., `paraview `_) @@ -30,40 +30,39 @@ The current implementation supports the following executable with the argument o where --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). +-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). +-v Specify the name of the vairable to plot, e.g., 'pressure', in addition to special extensive quantities for the mass such as 'grid', 'wells', 'gasm', 'dism', 'liqm', 'vapm', 'co2m', 'h2om', 'xco2l', 'xh2ov', 'xco2v', 'xh2ol', 'fwcdm', and 'fgipm' ('poro,permx,permz,porv,fipnum,satnum' by default). +-m Generate 'png', 'gif', 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). +-f The font size ('12' 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). +-e Specify the linestyles, e.g., 'solid,dotted' ('' 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). +-r Restart number to plot the dynamic variable, where 0 corresponds to the initial one ('-1' by default, i.e., the last restart file). -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). +-tunits 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). +-xlog Use log scale for the x axis ('0' by default). +-ylog Use log scale for the y axis ('0' by default). -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). +-dpi Dots per inch for the figure ('1200' 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). +-cformat Specify the format for the numbers in the colormap, e.g., .2f for two decimals ('' 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). @@ -74,7 +73,23 @@ where -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). - +-lw Line width separated by commas if more than one ('1' by default). +-subfigs Generate separated or a single Figure (e.g., '2,2' for four subfigures) ('' by default, i.e., separate figures). +-loc Location of the legend ('best' by default). +-delax Delete aligned axis labels in subfigures ('0' by default). +-printv Print the avaiable variables to plot ('0' by default). +-vtkformat Format for each variable in the vtks, support for Float64, Float32, and UInt16 ('Float64' by default). +-vtknames Label each variable in the written vtk ('' by default, i.e., the names given in the -v argument). +-mask Static variable to use as 2D map background ('' by default). +-diff The base name (or full path) of the input file to substract ('' by default). +-suptitle Title for the subfigures ('' by default, i.e., set by plopm, if 0, then it is removed; otherwise, write the text). +-cbsfax Set the global axis position and size for the colorbar ('0.40,0.01,0.2,0.02' by default). +-vmin Set a minimum threshold to remove values in the variable ('' by default). +-vmax Set a maximum threshold to remove values in the variable ('' by default). +-maskthr Set the threshold for the variable to mask " "('1e-3' by default). +-interval Time for the frames in the GIF in milli second ('1000' by default). +-loop Set to 1 for infinity loop in the GIF ('0' by default). + .. tip:: - Type in the terminal **plopm --help** to show these argument options. \ No newline at end of file + Type in the terminal **plopm -h** 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 4666e46..1287e4b 100755 --- a/src/plopm/core/plopm.py +++ b/src/plopm/core/plopm.py @@ -1,28 +1,20 @@ # SPDX-FileCopyrightText: 2024 NORCE # SPDX-License-Identifier: GPL-3.0 -# pylint: disable=R1702, W0123, W1401 +# pylint: disable=R1702,W0123,W1401,R0915 """ Script to plot 2D maps of OPM Flow geological models. """ import argparse -import numpy as np -from plopm.utils.initialization import ini_dic, ini_properties, ini_readers -from plopm.utils.readers import ( - get_kws_resdata, - get_kws_opm, - get_wells, - get_xycoords_resdata, - get_xycoords_opm, - get_xzcoords_resdata, - get_xzcoords_opm, - get_yzcoords_resdata, - get_yzcoords_opm, +from plopm.utils.initialization import ( + ini_dic, + ini_properties, + is_summary, + ini_summary, ) -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 +from plopm.utils.write import make_summary, make_maps def plopm(): @@ -32,97 +24,12 @@ def plopm(): if dic["mode"] == "vtk": make_vtks(dic) return - ini_properties(dic) - ini_readers(dic) - if dic["use"] == "resdata": - get_kws_resdata(dic) - else: - get_kws_opm(dic) - if len(dic["vsum"]) > 0: + if is_summary(dic): + ini_summary(dic) make_summary(dic) return - if dic["well"] == 1: - get_wells(dic) - if dic["grid"] == 1: - dic["grida"] = np.ones((dic["mx"]) * (dic["my"])) * np.nan - if dic["slide"][0] > -1: - handle_slide_x(dic) - elif dic["slide"][1] > -1: - handle_slide_y(dic) - else: - handle_slide_z(dic) - if dic["rotate"] != 0 or dic["translate"] != ["[0", "0]"]: - rotate_grid(dic) - make_2dmaps(dic) - - -def handle_slide_x(dic): - """ - Processing the selected yz slide to obtain the grid properties - - Args: - dic (dict): Global dictionary - - Returns: - dic (dict): Modified global dictionary - - """ - dic["tslide"] = f", slide i={dic['slide'][0]+1}" - dic["nslide"] = f"{dic['slide'][0]+1},*,*" - for well in reversed(dic["wells"]): - if well[0] != dic["slide"][0]: - dic["wells"].remove(well) - if dic["use"] == "resdata": - get_yzcoords_resdata(dic) - else: - get_yzcoords_opm(dic) - map_yzcoords(dic) - - -def handle_slide_y(dic): - """ - Processing the selected xz slide to obtain the grid properties - - Args: - dic (dict): Global dictionary - - Returns: - dic (dict): Modified global dictionary - - """ - dic["tslide"] = f", slide j={dic['slide'][1]+1}" - dic["nslide"] = f"*,{dic['slide'][1]+1},*" - for well in reversed(dic["wells"]): - if well[1] != dic["slide"][1]: - dic["wells"].remove(well) - if dic["use"] == "resdata": - get_xzcoords_resdata(dic) - else: - get_xzcoords_opm(dic) - map_xzcoords(dic) - - -def handle_slide_z(dic): - """ - Processing the selected xy slide to obtain the grid properties - - Args: - dic (dict): Global dictionary - - Returns: - dic (dict): Modified global dictionary - - """ - dic["tslide"] = f", slide k={dic['slide'][2]+1}" - dic["nslide"] = f"*,*,{dic['slide'][2]+1}" - for well in reversed(dic["wells"]): - if dic["slide"][2] not in range(well[2], well[3] + 1): - dic["wells"].remove(well) - if dic["use"] == "resdata": - get_xycoords_resdata(dic) - else: - get_xycoords_opm(dic) - map_xycoords(dic) + ini_properties(dic) + make_maps(dic) def load_parser(): @@ -136,8 +43,8 @@ def load_parser(): "--input", default="SPE11B", 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).", + " one is given, separate them by spaces ' ' (e.g, " + "'SPE11B /home/user/SPE11B_TUNED') ('SPE11B' by default).", ) parser.add_argument( "-o", @@ -149,17 +56,18 @@ def load_parser(): parser.add_argument( "-v", "--variable", - default="", + default="poro,permx,permz,porv,fipnum,satnum", 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).", + "addition to special variables such as 'grid', 'wells', " + "'gasm', 'dism', 'liqm', 'vapm', 'co2m', 'h2om', 'xco2l', 'xh2ov', " + "'xco2v', 'xh2ol', 'fwcdm', and 'fgipm' " + "('poro,permx,permz,porv,fipnum,satnum' by default.", ) parser.add_argument( "-m", "--mode", default="png", - help="Generate 'png' or 'vtk' files ('png' by default).", + help="Generate 'png', 'gif', or 'vtk' files ('png' by default).", ) parser.add_argument( "-s", @@ -186,8 +94,8 @@ def load_parser(): parser.add_argument( "-f", "--size", - default=14, - help="The font size ('14' by default)", + default=12, + help="The font size ('12' by default)", ) parser.add_argument( "-x", @@ -211,24 +119,17 @@ def load_parser(): ) parser.add_argument( "-c", - "--colormap", + "--colors", 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).", ) parser.add_argument( "-e", - "--linsty", + "--linestyle", default="", - 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 linestyles for the summary plots, " + "e.g., 'solid,dotted' ('' by default, i.e., set by plopm).", ) parser.add_argument( "-b", @@ -244,50 +145,30 @@ def load_parser(): 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 of the variable, e.g., "[m\\$^2\\$]" ' - "('' by default, i.e., set by plopm).", - ) parser.add_argument( "-t", "--title", - default="", + default="0", help="Specify the figure title, e.g., 'Final saturation map' ('' by " - "default, i.e., set by plopm).", + "default, i.e., set by plopm, set to 0 to remove).", ) parser.add_argument( "-r", "--restart", default="-1", - help="Restart number to plot the dynamic variable, where 1 corresponds to " + help="Restart number to plot the dynamic variable, where 0 corresponds to " "the initial one ('-1' by default, i.e., the last restart file).", ) - parser.add_argument( - "-w", - "--wells", - default=0, - help="Plot the positions of the wells or sources ('0' by default).", - ) - parser.add_argument( - "-g", - "--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).", - ) parser.add_argument( "-a", "--adjust", - default=1.0, + 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( - "-time", - "--time", + "-tunits", + "--tunits", 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' " @@ -308,13 +189,13 @@ def load_parser(): parser.add_argument( "-ylnum", "--ylnum", - default=4, + default="4", help="Number of y axis labels ('4' by default).", ) parser.add_argument( "-xlnum", "--xlnum", - default=4, + default="4", help="Number of x axis labels ('4' by default).", ) parser.add_argument( @@ -323,6 +204,18 @@ def load_parser(): default="", help="Number of color labels ('' by default, i.e., set by plopm).", ) + parser.add_argument( + "-xlog", + "--xlog", + default="0", + help="Use log scale for the x axis ('0' by default).", + ) + parser.add_argument( + "-ylog", + "--ylog", + default="0", + help="Use log scale for the y axis ('0' by default).", + ) parser.add_argument( "-clabel", "--clabel", @@ -333,20 +226,20 @@ def load_parser(): "-labels", "--labels", default="", - help="Legend in the summary plot, separated by commas if more than " + help="Legend in the summary plot, separated by two spaces if more than " "one ('' by default, i.e., set by plopm).", ) parser.add_argument( "-axgrid", "--axgrid", - default=1, + 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).", + default="1200", + help="Dots per inch for the figure ('1200' by default).", ) parser.add_argument( "-xformat", @@ -362,6 +255,13 @@ def load_parser(): help="Format for the y numbers, e.g., .1f for one decimal " "('' by default, i.e., set by plopm).", ) + parser.add_argument( + "-cformat", + "--cformat", + default="", + help="Format for the numbers in the colormap, e.g., " + ".2f for two decimals ('' by default, i.e., set by plopm).", + ) parser.add_argument( "-xunits", "--xunits", @@ -398,13 +298,13 @@ def load_parser(): parser.add_argument( "-log", "--log", - default=0, + default="0", help="Log scale for the color map ('0' by default).", ) parser.add_argument( "-rotate", "--rotate", - default=0, + default="0", help="Grades to rotate the grid in the 2D maps ('0' by default).", ) parser.add_argument( @@ -427,6 +327,110 @@ def load_parser(): default="w", help="Color for the inactive cells in the 2D maps ('w' by default, i.e., white).", ) + parser.add_argument( + "-lw", + "--lw", + default="", + help="Line width separated by commas if more than one ('1' by default).", + ) + parser.add_argument( + "-subfigs", + "--subfigs", + default="", + help="Generate separated or a single Figure (e.g., '2,2' for four " + "subfigures) ('' by default, i.e., separate figures).", + ) + parser.add_argument( + "-loc", + "--loc", + default="best", + help="Location of the legend ('best' by default).", + ) + parser.add_argument( + "-delax", + "--delax", + default=0, + help="Delete aligned axis labels in subfigures ('0' by default).", + ) + parser.add_argument( + "-printv", + "--printv", + default=0, + help="Print the avaiable variables to plot ('0' by default).", + ) + parser.add_argument( + "-vtkformat", + "--vtkformat", + default="Float64", + help="Format for each variable in the vtks, support for Float64, " + "Float32, and UInt16 ('Float64' by default).", + ) + parser.add_argument( + "-vtknames", + "--vtknames", + default="", + help="Label each variable in the written vtk ('' by default, " + "i.e., the names given in the -v argument).", + ) + parser.add_argument( + "-mask", + "--mask", + default="", + help="Static variable to use as 2D map background ('' by default).", + ) + parser.add_argument( + "-diff", + "--diff", + default="", + help="The base name (or full path) of the input file to substract" + " ('' by default).", + ) + parser.add_argument( + "-suptitle", + "--suptitle", + default="", + help="Title for the subfigures ('' by default, i.e., set by plopm, " + "if 0, then it is removed; otherwise, write the text).", + ) + parser.add_argument( + "-cbsfax", + "--cbsfax", + default="0.40,0.01,0.2,0.02", + help="Set the global axis position and size for the colorbar " + "('0.40,0.01,0.2,0.02' by default).", + ) + parser.add_argument( + "-vmin", + "--vmin", + default="", + help="Set a minimum threshold to remove values in the variable " + "('' by default).", + ) + parser.add_argument( + "-vmax", + "--vmax", + default="", + help="Set a maximum threshold to remove values in the variable " + "('' by default).", + ) + parser.add_argument( + "-maskthr", + "--maskthr", + default=1e-3, + help="Set the threshold for the variable to mask " "('1e-3' by default).", + ) + parser.add_argument( + "-interval", + "--interval", + default=1000, + help="Time for the frames in the GIF in milli second ('1000' by default).", + ) + parser.add_argument( + "-loop", + "--loop", + default=0, + help="Set to 1 for infinity loop in the GIF ('0' by default).", + ) return vars(parser.parse_known_args()[0]) diff --git a/src/plopm/utils/initialization.py b/src/plopm/utils/initialization.py index 5d9b332..c217494 100755 --- a/src/plopm/utils/initialization.py +++ b/src/plopm/utils/initialization.py @@ -7,6 +7,7 @@ """ import os +import sys from io import StringIO import numpy as np import matplotlib @@ -14,14 +15,12 @@ try: from opm.io.ecl import EclFile as OpmFile - from opm.io.ecl import EGrid as OpmGrid from opm.io.ecl import ESmry as OpmSummary except ImportError: print("The Python package opm was not found, using resdata") try: from resdata.resfile import ResdataFile from resdata.summary import Summary - from resdata.grid import Grid except ImportError: print("The resdata Python package was not found, using opm") @@ -38,77 +37,193 @@ def ini_dic(cmdargs): """ dic = {"output": cmdargs["output"].strip()} - names = (cmdargs["input"].strip()).split(",") - dic["names"], dic["name"] = names, names[0] - if len(names) > 1: - dic["names"] = names + names = (cmdargs["input"].strip()).split(" ") + names = [var.split(" ") for var in names] + dic["mode"] = cmdargs["mode"].strip() + if names[0][0] == "." or names[0][0] == "./": + names = [] + names.append([]) + for root, _, files in os.walk("."): + for file in files: + if dic["mode"] == "vtk": + if file.endswith(".DATA"): + names[-1].append(os.path.join(root, file)[2:-5]) + else: + if file.endswith(".SMSPEC"): + names[-1].append(os.path.join(root, file)[2:-7]) + dic["names"], dic["name"] = names, names[0][0] dic["coords"] = ["x", "y", "z"] dic["scale"] = int(cmdargs["scale"]) + dic["delax"] = int(cmdargs["delax"]) + dic["printv"] = int(cmdargs["printv"]) + dic["subfigs"] = (cmdargs["subfigs"].strip()).split(",") dic["use"] = cmdargs["use"].strip() - dic["variable"] = cmdargs["variable"].strip() + dic["vrs"] = (cmdargs["variable"].strip()).split(",") + dic["lw"] = cmdargs["lw"].strip() dic["size"] = float(cmdargs["size"]) - dic["legend"] = cmdargs["legend"].strip() - dic["titles"] = cmdargs["title"].strip() - dic["bounds"] = (cmdargs["bounds"].strip()).split(",") + dic["maskthr"] = float(cmdargs["maskthr"]) + dic["interval"] = float(cmdargs["interval"]) + dic["loop"] = int(cmdargs["loop"]) + dic["titles"] = (cmdargs["title"].strip()).split(" ") + dic["bounds"] = (cmdargs["bounds"].strip()).split(" ") + dic["bounds"] = [var.split(",") for var in dic["bounds"]] dic["dims"] = (cmdargs["dimensions"].strip()).split(",") - dic["numbers"] = cmdargs["numbers"].strip() - dic["linsty"] = cmdargs["linsty"].strip() - dic["colormap"] = cmdargs["colormap"].strip() - dic["mode"] = cmdargs["mode"].strip() + dic["cf"] = cmdargs["cformat"].strip() + dic["linestyle"] = cmdargs["linestyle"].strip() + dic["colors"] = cmdargs["colors"].strip() + dic["vmin"] = (cmdargs["vmin"].strip()).split(",") + dic["vmax"] = (cmdargs["vmax"].strip()).split(",") dic["flow"] = cmdargs["path"].strip() dic["fc"] = cmdargs["facecolor"].strip() dic["ncolor"] = cmdargs["ncolor"].strip() - dic["cnum"] = cmdargs["cnum"].strip() + dic["cnum"] = (cmdargs["cnum"].strip()).split(",") + dic["mask"] = cmdargs["mask"].strip() + dic["suptitle"] = cmdargs["suptitle"].strip() + dic["diff"] = cmdargs["diff"].strip() dic["clabel"] = cmdargs["clabel"].strip() - dic["labels"] = (cmdargs["labels"].strip()).split(",") + dic["labels"] = (cmdargs["labels"].strip()).split(" ") + dic["labels"] = [var.split(" ") for var in dic["labels"]] 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["tunits"] = (cmdargs["tunits"].strip()).split(",") + # dic["skl"] = float(cmdargs["adjust"]) + dic["avar"] = (cmdargs["adjust"].strip()).split(",") + dic["axgrid"] = (cmdargs["axgrid"].strip()).split(",") + dic["dpi"] = (cmdargs["dpi"].strip()).split(",") + dic["loc"] = (cmdargs["loc"].strip()).split(",") + dic["vtkformat"] = (cmdargs["vtkformat"].strip()).split(",") + dic["vtknames"] = (cmdargs["vtknames"].strip()).split(" ") + dic["log"] = (cmdargs["log"].strip()).split(",") + dic["rotate"] = (cmdargs["rotate"].strip()).split(",") dic["global"] = int(cmdargs["global"]) - dic["save"] = cmdargs["save"].strip() - dic["translate"] = (cmdargs["translate"].strip()).split(",") + dic["save"] = (cmdargs["save"].strip()).split(" ") + dic["translate"] = (cmdargs["translate"]).split(" ") + dic["translate"] = [var.split(",") for var in dic["translate"]] + dic["restart"] = (cmdargs["restart"].strip()).split(",") + dic["cbsfax"] = [float(val) for val in (cmdargs["cbsfax"].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(",") + dic[f"{i}label"] = (cmdargs[f"{i}label"].strip()).split(" ") + dic[f"{i}format"] = (cmdargs[f"{i}format"].strip()).split(",") + dic[f"{i}lnum"] = (cmdargs[f"{i}lnum"].strip()).split(",") + dic[f"{i}log"] = (cmdargs[f"{i}log"].strip()).split(",") + dic[f"{i}lim"] = (cmdargs[f"{i}lim"]).split(" ") + dic[f"{i}lim"] = [var.split(",") for var in dic[f"{i}lim"]] for name in [ - "wells", "vsum", - "grid", "summary", "vsum", "time", - "unrst", + "wells", ]: dic[name] = [] dic["dtitle"] = "" - if len((cmdargs["restart"].strip()).split(",")) == 1 and dic["mode"] != "vtk": - dic["restart"] = int(cmdargs["restart"]) + if dic["restart"][0] == "-1": + dic["restart"] = [-1] + elif int(dic["restart"][0]) == 0 and len(dic["restart"]) == 2: + dic["restart"] = list(range(0, int(dic["restart"][1]) + 1)) else: - dic["restart"] = (cmdargs["restart"].strip()).split(",") - dic["well"] = int(cmdargs["wells"]) - dic["grid"] = int(cmdargs["grid"]) - if dic["restart"] == -1: - dic["restart"] = 0 + dic["restart"] = [int(i) for i in dic["restart"]] dic["slide"] = ( np.genfromtxt(StringIO(cmdargs["slide"]), delimiter=",", dtype=int) - 1 ) dic["mass"] = ["gasm", "dism", "liqm", "vapm", "co2m", "h2om"] + dic["smass"] = ["FWCDM", "FGIPM"] + dic["xmass"] = ["xco2l", "xh2ov", "xco2v", "xh2ol"] if not os.path.exists(dic["output"]): os.system(f"mkdir {dic['output']}") + dic["COLORS"] = [ + "k", + "b", + "#ff7f0e", + "#2ca02c", + "#d62728", + "#9467bd", + "#8c564b", + "#e377c2", + "#7f7f7f", + "#bcbd22", + "#17becf", + "#1f77b4", + "r", + ] + dic["LINESTYLE"] = [ + "-", + "--", + (0, (1, 1)), + "-.", + (0, (1, 10)), + (0, (1, 1)), + (5, (10, 3)), + (0, (5, 10)), + (0, (5, 5)), + (0, (5, 1)), + (0, (3, 10, 1, 10)), + (0, (3, 5, 1, 5)), + (0, (3, 1, 1, 1)), + (0, (3, 5, 1, 5, 1, 5)), + (0, (3, 10, 1, 10, 1, 10)), + (0, (3, 1, 1, 1, 1, 1)), + (0, ()), + ] + dic["LW"] = ["1"] * len(dic["names"][0]) + font = {"family": "normal", "weight": "normal", "size": dic["size"]} + matplotlib.rc("font", **font) + plt.rcParams.update( + { + "text.usetex": True, + "font.family": "monospace", + "legend.columnspacing": 0.9, + "legend.handlelength": 3.5, + "legend.fontsize": dic["size"], + "lines.linewidth": 4, + "axes.titlesize": dic["size"], + "axes.grid": False, + "figure.figsize": (float(dic["dims"][0]), float(dic["dims"][1])), + } + ) + for name in ["vtkformat", "avar", "vtknames"]: + if len(dic[name]) < len(dic["vrs"]): + dic[name] = [dic[name][0]] * len(dic["vrs"]) + if len(dic["save"]) < len(dic["vrs"]): + dic["save"] = [dic["save"][0]] * len(dic["vrs"]) + if len(dic["bounds"]) < len(dic["vrs"]): + dic["bounds"] = [dic["bounds"][0]] * len(dic["vrs"]) + if len(dic["rotate"]) < len(dic["names"][0]): + dic["rotate"] = [dic["rotate"][0]] * len(dic["names"][0]) + if len(dic["translate"]) < len(dic["names"][0]): + dic["translate"] = [dic["translate"][0]] * len(dic["names"][0]) + if len(dic["titles"]) < max(len(dic["names"][0]), len(dic["vrs"])): + dic["titles"] = [dic["titles"][0]] * max(len(dic["names"][0]), len(dic["vrs"])) + for val in [ + "xformat", + "yformat", + "xlog", + "ylog", + "xlabel", + "ylabel", + "labels", + "tunits", + "loc", + "dpi", + "ylnum", + "xlnum", + "avar", + "save", + "axgrid", + "cnum", + "log", + "vmin", + "vmax", + ]: + if len(dic[val]) < len(dic["vrs"]): + dic[val] = [dic[val][0]] * len(dic["vrs"]) return dic -def ini_readers(dic): +def ini_summary(dic): """ - Set the classes for reading the properties + Initialize the needed objects for the summary plots Args: dic (dict): Global dictionary @@ -117,31 +232,86 @@ def ini_readers(dic): dic (dict): Modified global dictionary """ - if dic["use"] == "resdata": - dic["egrid"] = Grid(f"{dic['name']}.EGRID") - dic["init"] = ResdataFile(f"{dic['name']}.INIT") - dic["nx"] = dic["egrid"].nx - dic["ny"] = dic["egrid"].ny - dic["nz"] = dic["egrid"].nz - if os.path.isfile(f"{dic['name']}.UNRST"): - for name in dic["names"]: - dic["unrst"].append(ResdataFile(f"{name}.UNRST")) - if os.path.isfile(f"{dic['name']}.SMSPEC"): - for name in dic["names"]: - dic["summary"].append(Summary(f"{name}.SMSPEC")) - else: - dic["egrid"] = OpmGrid(f"{dic['name']}.EGRID") - dic["init"] = OpmFile(f"{dic['name']}.INIT") - dic["nx"] = dic["egrid"].dimension[0] - dic["ny"] = dic["egrid"].dimension[1] - dic["nz"] = dic["egrid"].dimension[2] - if os.path.isfile(f"{dic['name']}.UNRST"): - for name in dic["names"]: - dic["unrst"].append(OpmFile(f"{name}.UNRST")) - if os.path.isfile(f"{dic['name']}.SMSPEC"): - for name in dic["names"]: - dic["summary"].append(OpmSummary(f"{name}.SMSPEC")) - ini_slides(dic) + dic["numc"] = 1 if len(dic["names"]) < len(dic["vrs"]) else len(dic["vrs"]) + for val in ["colors", "linestyle", "lw"]: + if dic[val]: + dic[val] = dic[val].split(":") + dic[val] = [var.split(",") for var in dic[val]] + if len(dic[val]) < len(dic["vrs"]): + dic[val] = [dic[val][0]] * len(dic["vrs"]) + else: + dic[val] = [dic[val.upper()]] * len(dic["vrs"]) + for i in ["x", "y"]: + if len(dic[f"{i}lim"]) < len(dic["vrs"]) and dic[f"{i}lim"][0][0]: + dic[f"{i}lim"] = [dic[f"{i}lim"][0]] * len(dic["vrs"]) + for val in [ + "names", + "titles", + "xformat", + "yformat", + "xlog", + "ylog", + "xlabel", + "ylabel", + "labels", + "tunits", + "loc", + "dpi", + "ylnum", + "xlnum", + "avar", + "save", + "axgrid", + ]: + if len(dic[val]) < len(dic["vrs"]): + dic[val] = [dic[val][0]] * len(dic["vrs"]) + + +def is_summary(dic): + """ + Check flag arguments and files for summary plot + + Args: + dic (dict): Global dictionary + + Returns: + bool: True if one variable is in the summary keys + + """ + ntot = 0 + if dic["printv"] == 1: + for ext, what in zip(["init", "unrst"], ["init", "restart"]): + if os.path.isfile(f"{dic['name']}.{ext.upper()}"): + if dic["use"] == "resdata": + reader = ResdataFile(f"{dic['name']}.{ext.upper()}") + keys = list(reader.keys()) + if ext == "unrst": + ntot = len(reader.iget_kw("PRESSURE")) + else: + reader = OpmFile(f"{dic['name']}.{ext.upper()}") + keys = list(reader.keys()) + if ext == "unrst": + ntot = reader.count("PRESSURE") + print(f"The {what} available variables for {dic['name']} are:") + print(keys) + if ext == "unrst": + print(f"The available restarts for {dic['name']} are:") + print(list(range(0, ntot))) + if os.path.isfile(f"{dic['name']}.SMSPEC"): + if dic["use"] == "resdata": + summary = Summary(f"{dic['name']}.SMSPEC").keys() + else: + summary = OpmSummary(f"{dic['name']}.SMSPEC").keys() + if dic["printv"] == 1: + print(f"The summary available variables for {dic['name']} are:") + print(summary) + sys.exit() + for name in dic["vrs"]: + if name.upper() in summary + dic["smass"]: + return True + if dic["printv"] == 1: + sys.exit() + return False def ini_slides(dic): @@ -177,97 +347,63 @@ def ini_properties(dic): dic (dict): Modified global dictionary """ - dic["colors"] = [ - "#ff7f0e", - "#2ca02c", - "#d62728", - "#9467bd", - "#8c564b", - "#e377c2", - "#7f7f7f", - "#bcbd22", - "#17becf", - "#1f77b4", - "r", + dic["units"] = [ + " [-]", + " [mD]", + " [mD]", + r" [m$^3$]", + " [-]", + " [-]", ] - dic["linestyle"] = [ - "-", - "--", - (0, (1, 1)), - "-.", - (0, (1, 10)), - (0, (1, 1)), - (5, (10, 3)), - (0, (5, 10)), - (0, (5, 5)), - (0, (5, 1)), - (0, (3, 10, 1, 10)), - (0, (3, 5, 1, 5)), - (0, (3, 1, 1, 1)), - (0, (3, 5, 1, 5, 1, 5)), - (0, (3, 10, 1, 10, 1, 10)), - (0, (3, 1, 1, 1, 1, 1)), - (0, ()), + dic["cformat"] = [ + ".1f", + ".0f", + ".0f", + ".2e", + ".0f", + ".0f", ] - if dic["variable"]: - initialize_variable(dic) - initialize_mass(dic) - else: - dic["props"] = [ - "porv", - "permx", - "permz", - "poro", - "fipnum", - "satnum", - ] - dic["units"] = [ - r" [m$^3$]", - " [mD]", - " [mD]", - " [-]", - " [-]", - " [-]", - ] - dic["format"] = [ - lambda x, _: f"{x:.2e}", - lambda x, _: f"{x:.0f}", - lambda x, _: f"{x:.0f}", - lambda x, _: f"{x:.1f}", - lambda x, _: f"{x:.0f}", - lambda x, _: f"{x:.0f}", - ] - dic["cmaps"] = [ - "terrain", - "turbo", - "turbo", - "gnuplot", - "tab20b", - "tab20b", - ] - if dic["well"] == 1 or dic["grid"] == 1: - dic["props"] = [] - dic["grid"] = 1 - dic["units"] = [" [-]"] - dic["cmaps"] = ["nipy_spectral"] - dic["format"] = [lambda x, _: f"{x:.0f}"] - font = {"family": "normal", "weight": "normal", "size": dic["size"]} - matplotlib.rc("font", **font) - plt.rcParams.update( - { - "text.usetex": True, - "font.family": "monospace", - "legend.columnspacing": 0.9, - "legend.handlelength": 3.5, - "legend.fontsize": dic["size"], - "lines.linewidth": 4, - "axes.titlesize": dic["size"], - "axes.grid": False, - "figure.figsize": (int(dic["dims"][0]), int(dic["dims"][1])), - } - ) - dic["xc"], dic["yc"] = [], [] - dic["tskl"], dic["tunit"] = initialize_time(dic["times"]) + dic["cmaps"] = [ + "jet", + "turbo", + "turbo", + "terrain", + "tab20b", + "tab20b", + ] + if dic["colors"]: + dic["cmaps"] = dic["colors"].split(",") + elif dic["diff"]: + dic["cmaps"] = ["RdYlGn"] + elif dic["mask"]: + dic["cmaps"] = ["RdGy_r"] + if dic["vrs"]: # dic["well"] == 1 + if dic["vrs"][0] == "wells": + dic["units"] = [" [-]"] + dic["cmaps"] = ["nipy_spectral"] + dic["cformat"] = [".0f"] + if ( + "num" in dic["vrs"][0] + and not dic["mask"] + and not dic["diff"] + and not dic["colors"] + ): + dic["cmaps"] = ["tab20"] + dic["units"] = [" [-]"] + dic["cformat"] = [".0f"] + if "index" in dic["vrs"][0]: + dic["units"] = [" [-]"] + dic["cformat"] = [".0f"] + if dic["cf"]: + dic["cformat"] = dic["cf"].split(",") + if len(dic["cmaps"]) < len(dic["vrs"]): + dic["cmaps"] = [dic["cmaps"][0]] * len(dic["vrs"]) + if len(dic["xlim"]) < len(dic["vrs"]): + dic["xlim"] = [dic["xlim"][0]] * len(dic["vrs"]) + if len(dic["ylim"]) < len(dic["vrs"]): + dic["ylim"] = [dic["ylim"][0]] * len(dic["vrs"]) + if len(dic["cformat"]) < len(dic["vrs"]): + dic["cformat"] = [dic["cformat"][0]] * len(dic["vrs"]) dic["xskl"], dic["xunit"] = initialize_spatial(dic["xunits"]) dic["yskl"], dic["yunit"] = initialize_spatial(dic["yunits"]) @@ -293,87 +429,7 @@ def initialize_spatial(unit): 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): - """ - Initialize the properties according to the given variable - - Args: - dic (dict): Global dictionary - - Returns: - dic (dict): Modified global dictionary - - """ - dic["props"] = [dic["variable"]] - if dic["variable"].lower() in ["disperc", "depth", "dx", "dy", "dz"]: - dic["units"] = [" [m]"] - dic["cmaps"] = ["jet"] - dic["format"] = [lambda x, _: f"{x:.2e}"] - elif dic["variable"].lower() in ["porv"]: - dic["units"] = [r" [m$^3$]"] - dic["cmaps"] = ["terrain"] - dic["format"] = [lambda x, _: f"{x:.2e}"] - elif dic["variable"].lower() in ["permx", "permy", "permz"]: - dic["units"] = [" [mD]"] - dic["cmaps"] = ["turbo"] - dic["format"] = [lambda x, _: f"{x:.0f}"] - elif "num" in dic["variable"].lower(): - dic["units"] = [" [-]"] - dic["cmaps"] = ["tab20b"] - dic["format"] = [lambda x, _: f"{x:.2f}"] - else: - dic["units"] = [" [-]"] - dic["cmaps"] = ["gnuplot"] - dic["format"] = [lambda x, _: f"{x:.0f}"] - if dic["legend"]: - dic["units"] = [f" {dic['legend']}"] - if len(dic["names"]) == 2: - 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"]: - dic["format"] = [lambda x, _: f"{x:.2e}"] - if dic["colormap"]: - dic["cmaps"] = [dic["colormap"]] - if dic["numbers"]: - dic["format"] = [eval(dic["numbers"])] - - -def initialize_mass(dic): +def initialize_mass(mskl): """ Initialize the mass properties according to the given variable @@ -384,16 +440,17 @@ def initialize_mass(dic): 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]"] + vunit = "" + if mskl == 1e-3: + vunit = " [t]" + elif mskl == 1e-6: + vunit = " [Kt]" + elif mskl == 1e-9: + vunit = " [Mt]" + elif mskl == 1e3: + vunit = " [g]" + elif mskl == 1e6: + vunit = " [mg]" + elif mskl == 1: + vunit = " [kg]" + return vunit diff --git a/src/plopm/utils/mapping.py b/src/plopm/utils/mapping.py index 51be2fa..80a9436 100644 --- a/src/plopm/utils/mapping.py +++ b/src/plopm/utils/mapping.py @@ -6,9 +6,83 @@ """ import numpy as np +from plopm.utils.readers import ( + get_xycoords_resdata, + get_xycoords_opm, + get_xzcoords_resdata, + get_xzcoords_opm, + get_yzcoords_resdata, + get_yzcoords_opm, +) -def rotate_grid(dic): +def handle_slide_x(dic): + """ + Processing the selected yz slide to obtain the grid properties + + Args: + dic (dict): Global dictionary + + Returns: + dic (dict): Modified global dictionary + + """ + dic["tslide"] = f", slide i={dic['slide'][0]+1}" + dic["nslide"] = f"{dic['slide'][0]+1},*,*" + for well in reversed(dic["wells"]): + if well[0] != dic["slide"][0]: + dic["wells"].remove(well) + if dic["use"] == "resdata": + get_yzcoords_resdata(dic) + else: + get_yzcoords_opm(dic) + + +def handle_slide_y(dic): + """ + Processing the selected xz slide to obtain the grid properties + + Args: + dic (dict): Global dictionary + + Returns: + dic (dict): Modified global dictionary + + """ + dic["tslide"] = f", slide j={dic['slide'][1]+1}" + dic["nslide"] = f"*,{dic['slide'][1]+1},*" + for well in reversed(dic["wells"]): + if well[1] != dic["slide"][1]: + dic["wells"].remove(well) + if dic["use"] == "resdata": + get_xzcoords_resdata(dic) + else: + get_xzcoords_opm(dic) + + +def handle_slide_z(dic): + """ + Processing the selected xy slide to obtain the grid properties + + Args: + dic (dict): Global dictionary + + Returns: + dic (dict): Modified global dictionary + + """ + dic["tslide"] = f", slide k={dic['slide'][2]+1}" + dic["nslide"] = f"*,*,{dic['slide'][2]+1}" + for well in reversed(dic["wells"]): + if dic["slide"][2] not in range(well[2], well[3] + 1): + dic["wells"].remove(well) + if dic["use"] == "resdata": + get_xycoords_resdata(dic) + else: + get_xycoords_opm(dic) + + +def rotate_grid(dic, n): """ Rotate the grid if requiered. @@ -19,11 +93,12 @@ def rotate_grid(dic): dic (dict): Modified global dictionary """ + grd = int(dic["rotate"][n]) 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]) + x_dis = float(dic["translate"][n][0][1:]) + y_dis = float(dic["translate"][n][1][:-1]) for rowx, rowy in zip(dic["xc"], dic["yc"]): xc.append([]) yc.append([]) @@ -31,20 +106,20 @@ def rotate_grid(dic): 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) + + (i - 1.5 * length) * np.cos(grd * np.pi / 180) + - (j - 1.5 * width) * np.sin(grd * 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) + + (j - 1.5 * width) * np.cos(grd * np.pi / 180) + + (i - 1.5 * length) * np.sin(grd * np.pi / 180) ) dic["xc"] = xc dic["yc"] = yc -def map_yzcoords(dic): +def map_xzcoords(dic, var, quan): """ Map the properties from the simulations to the 2D slide @@ -56,29 +131,33 @@ def map_yzcoords(dic): """ for k in range(dic["nz"]): - for j in range(dic["ny"]): - ind = dic["slide"][0] + j * dic["nx"] + k * dic["nx"] * dic["ny"] + for i in range(dic["nx"]): + ind = i + dic["slide"][1] * dic["nx"] + k * dic["nx"] * dic["ny"] if dic["porv"][ind] > 0: - for name in dic["props"]: - dic[name + "a"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = dic[ - name - ][dic["actind"][ind]] - if "porv" in dic["props"]: - dic["porva"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = dic[ - "porv" - ][ind] - if len(dic["wells"]) > 0: - dic["wellsa"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = len( + if var.lower() == "grid": + dic["grida"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = 1 + elif var.lower() == "wells": + dic["wellsa"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = len( dic["wells"] ) - if dic["grid"] == 1: - dic["grida"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = 1 + elif var.lower() == "index_i": + dic["index_ia"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = i + elif var.lower() == "index_j": + dic["index_ja"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = dic[ + "slide" + ][1] + elif var.lower() == "index_k": + dic["index_ka"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = k + else: + dic[var + "a"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = quan[ + dic["actind"][ind] + ] for i, well in enumerate(dic["wells"]): for k in range(well[2], well[3] + 1): - dic["wellsa"][2 * well[1] + 2 * (dic["nz"] - k - 1) * dic["mx"]] = i + dic["wellsa"][2 * well[0] + 2 * (dic["nz"] - k - 1) * dic["mx"]] = i -def map_xzcoords(dic): +def map_yzcoords(dic, var, quan): """ Map the properties from the simulations to the 2D slide @@ -90,29 +169,33 @@ def map_xzcoords(dic): """ for k in range(dic["nz"]): - for i in range(dic["nx"]): - ind = i + dic["slide"][1] * dic["nx"] + k * dic["nx"] * dic["ny"] + for j in range(dic["ny"]): + ind = dic["slide"][0] + j * dic["nx"] + k * dic["nx"] * dic["ny"] if dic["porv"][ind] > 0: - for name in dic["props"]: - dic[name + "a"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = dic[ - name - ][dic["actind"][ind]] - if "porv" in dic["props"]: - dic["porva"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = dic[ - "porv" - ][ind] - if len(dic["wells"]) > 0: - dic["wellsa"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = len( + if var.lower() == "grid": + dic["grida"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = 1 + elif var.lower() == "wells": + dic["wellsa"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = len( dic["wells"] ) - if dic["grid"] == 1: - dic["grida"][2 * i + 2 * (dic["nz"] - k - 1) * dic["mx"]] = 1 + elif var.lower() == "index_i": + dic[var + "a"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = dic[ + "slide" + ][0] + elif var.lower() == "index_j": + dic[var + "a"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = j + elif var.lower() == "index_k": + dic[var + "a"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = k + else: + dic[var + "a"][2 * j + 2 * (dic["nz"] - k - 1) * dic["mx"]] = quan[ + dic["actind"][ind] + ] for i, well in enumerate(dic["wells"]): for k in range(well[2], well[3] + 1): - dic["wellsa"][2 * well[0] + 2 * (dic["nz"] - k - 1) * dic["mx"]] = i + dic["wellsa"][2 * well[1] + 2 * (dic["nz"] - k - 1) * dic["mx"]] = i -def map_xycoords(dic): +def map_xycoords(dic, var, quan): """ Map the properties from the simulations to the 2D slide @@ -127,15 +210,17 @@ def map_xycoords(dic): for i in range(dic["nx"]): ind = i + j * dic["nx"] + dic["slide"][2] * dic["nx"] * dic["ny"] if dic["porv"][ind] > 0: - for name in dic["props"]: - dic[name + "a"][2 * i + 2 * j * dic["mx"]] = dic[name][ - dic["actind"][ind] - ] - if "porv" in dic["props"]: - dic["porva"][2 * i + 2 * j * dic["mx"]] = dic["porv"][ind] - if len(dic["wells"]) > 0: - dic["wellsa"][2 * i + 2 * j * dic["mx"]] = len(dic["wells"]) - if dic["grid"] == 1: + if var.lower() == "grid": dic["grida"][2 * i + 2 * j * dic["mx"]] = 1 + elif var.lower() == "wells": + dic["wellsa"][2 * i + 2 * j * dic["mx"]] = len(dic["wells"]) + elif var.lower() == "index_i": + dic[var + "a"][2 * i + 2 * j * dic["mx"]] = i + elif var.lower() == "index_j": + dic[var + "a"][2 * i + 2 * j * dic["mx"]] = j + elif var.lower() == "index_k": + dic[var + "a"][2 * i + 2 * j * dic["mx"]] = dic["slide"][2] + else: + dic[var + "a"][2 * i + 2 * j * dic["mx"]] = quan[dic["actind"][ind]] for i, well in enumerate(dic["wells"]): dic["wellsa"][2 * well[0] + 2 * well[1] * dic["mx"]] = i diff --git a/src/plopm/utils/readers.py b/src/plopm/utils/readers.py index 99ad1ca..2fddcbe 100644 --- a/src/plopm/utils/readers.py +++ b/src/plopm/utils/readers.py @@ -1,14 +1,30 @@ # SPDX-FileCopyrightText: 2024 NORCE # SPDX-License-Identifier: GPL-3.0 +# pylint: disable=R0911,R0912,R0913,R0915 """ Utiliy functions to read the OPM Flow simulator type output files. """ +import os import csv import sys import datetime import numpy as np +from plopm.utils.initialization import initialize_mass + +try: + from opm.io.ecl import EclFile as OpmFile + from opm.io.ecl import EGrid as OpmGrid + from opm.io.ecl import ESmry as OpmSummary +except ImportError: + pass +try: + from resdata.resfile import ResdataFile + from resdata.summary import Summary + from resdata.grid import Grid +except ImportError: + pass GAS_DEN_REF = 1.86843 WAT_DEN_REF = 998.108 @@ -248,9 +264,9 @@ def get_xycoords_opm(dic): ) -def get_kws_resdata(dic): +def read_summary(dic, case, quan, tunit, qskl): """ - Get the static properties from the INIT file using ResdataFile + Handle the summary vectors Args: dic (dict): Global dictionary @@ -259,86 +275,303 @@ 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]) - elif dic["unrst"][0].has_kw(name.upper()): - if len(dic["names"]) == 1: - dic[name] = np.array( - dic["unrst"][0].iget_kw(name.upper())[dic["restart"] - 1] - ) - else: - dic[name] = np.array( - dic["unrst"][0].iget_kw(name.upper())[dic["restart"] - 1] - ) - np.array(dic["unrst"][1].iget_kw(name.upper())[dic["restart"] - 1]) - ntot = len(dic["unrst"][0].iget_kw(name.upper())) - dic["dtitle"] = ( - f", rst {ntot if dic['restart']==0 else dic['restart']} out of {ntot}" - ) - elif dic["summary"][0].has_key(name.upper()): - for i, _ in enumerate(dic["names"]): - dic["vsum"].append(dic["summary"][i][name.upper()].values) - if dic["times"] == "dates": - dic["time"].append(dic["summary"][i].dates) + vunit = "" + tskl, tunit = initialize_time(tunit) + quans = quan.split(" ") + if dic["use"] == "resdata": + summary = Summary(f"{case}.SMSPEC") + if quans[0].upper() in dic["smass"]: + var = summary[quans[0][:-1].upper()].values + else: + var = summary[quans[0].upper()].values + if len(quans) > 1: + for i, val in enumerate(quans[2::2]): + if val.upper() in summary.keys(): + quan1 = summary[val.upper()].values 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) + quan1 = float(val) + var = operate(var, quan1, i, quans[1::2]) + if tunit == "Dates": + time = summary.dates else: - print(f"Unknow -v variable ({name}).") - sys.exit() - dic[name + "a"] = np.ones(dic["mx"] * dic["my"]) * np.nan + time = summary["TIME"].values * tskl + else: + summary = OpmSummary(f"{case}.SMSPEC") + if quans[0].upper() in dic["smass"]: + var = summary[quans[0][:-1].upper()] + else: + var = summary[quans[0].upper()] + if len(quans) > 1: + for i, val in enumerate(quans[2::2]): + if val.upper() in summary.keys(): + quan1 = summary[val.upper()] + else: + quan1 = float(val) + var = operate(var, quan1, i, quans[1::2]) + if tunit == "Dates": + smsp_dates = 86400 * summary["TIME"] + smsp_dates = [ + summary.start_date + datetime.timedelta(seconds=seconds) + for seconds in smsp_dates + ] + time = smsp_dates + else: + time = summary["TIME"] * tskl + if quans[0].lower() in ["fgip", "fgit"]: + vunit = " [sm$^3$]" + elif quans[0].upper() in dic["smass"]: + var *= GAS_DEN_REF + vunit = initialize_mass(qskl) + elif quans[0].lower() in ["time"]: + vunit = " [d]" + return time, var * qskl, tunit, vunit + + +def operate(var, quan1, i, oper): + """ + Applied the requested operation + + Args: + var (array): Floats with the current values\n + quan1 (array): Value(s) to operate\n + i (int): Index of the operator\n + oper (list): Input operators + + Returns: + var (array): Modified values after applying the operator + + """ + if oper[i] == "+": + var += quan1 + elif oper[i] == "-": + var -= quan1 + elif oper[i] == "*": + var *= quan1 + elif oper[i] == "/": + var /= quan1 + else: + print(f"Unknow operation ({oper[i]}).") + sys.exit() + return var -def handle_mass_resdata(dic, name): +def initialize_time(times): """ - Mass using resdata. + Handle the time units for the x axis in the summary Args: - dic (dict): Global dictionary\n - name (str): Name of the variable for the mass spatial map + 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 get_readers(dic): + """ + Load the opm/resdata methods + + Args: + dic (dict): Global dictionary 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"]) + for ext in ["init", "unrst"]: + if os.path.isfile(f"{dic['deck']}.{ext.upper()}"): + dic[ext] = [] + if dic["use"] == "resdata": + dic[ext] = ResdataFile(f"{dic['deck']}.{ext.upper()}") + else: + dic[ext] = OpmFile(f"{dic['deck']}.{ext.upper()}") + if os.path.isfile(f"{dic['deck']}.EGRID") and dic["mode"] != "vtk": + dic["egrid"] = [] + if dic["use"] == "resdata": + dic["egrid"] = Grid(f"{dic['deck']}.EGRID") 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"] + dic["egrid"] = OpmGrid(f"{dic['deck']}.EGRID") + if not "init" in dic.keys() and not "unrst" in dic.keys(): + print(f"Unable to find {dic['deck']} with .EGRID or .INIT.") + sys.exit() + dic["tnrst"] = [] + dic["ntot"] = 1 + if dic["use"] == "resdata": + dic["porv"] = np.array(dic["init"]["PORV"][0]) + dic["nxyz"] = len(dic["porv"]) + 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 + if "unrst" in dic.keys(): + dic["ntot"] = len(dic["unrst"].iget_kw("PRESSURE")) + for ntm in range(dic["ntot"]): + dic["tnrst"].append(dic["unrst"]["DOUBHEAD"][ntm][0]) + if "egrid" in dic.keys(): + dic["nx"] = dic["egrid"].nx + dic["ny"] = dic["egrid"].ny + dic["nz"] = dic["egrid"].nz 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"]) + dic["porv"] = np.array(dic["init"]["PORV"]) + dic["nxyz"] = len(dic["porv"]) + 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 + if "unrst" in dic.keys(): + dic["ntot"] = dic["unrst"].count("PRESSURE") + for ntm in range(dic["ntot"]): + dic["tnrst"].append(dic["unrst"]["DOUBHEAD", ntm][0]) + if "egrid" in dic.keys(): + dic["nx"] = dic["egrid"].dimension[0] + dic["ny"] = dic["egrid"].dimension[1] + dic["nz"] = dic["egrid"].dimension[2] + if not dic["tnrst"]: + dic["tnrst"] = [0] * len(dic["restart"]) + if dic["restart"][0] == -1: + dic["restart"] = [dic["ntot"] - 1] + + +def get_unit(name): + """ + Get the variable unit + + Args: + name (str): Variable + + Returns: + dic (dict): Modified global dictionary + + """ + if name.lower() in ["disperc", "depth", "dx", "dy", "dz"]: + unit = " [m]" + elif name.lower() in ["porv"]: + unit = r" [m$^3$]" + elif name.lower() in ["permx", "permy", "permz"]: + unit = " [mD]" + elif name.lower() in ["pressure"]: + unit = " [bar]" + elif name.lower() in ["fgip", "fgit"]: + unit = " [sm$^3$]" + else: + unit = " [-]" + return unit + + +def get_quantity(dic, name, n, nrst): + """ + Compute the mass (intensive quantities). + + Args: + dic (dict): Global dictionary\n + name (str): Name of the variable\n + skl (float): Scaling for the mass quantity\n + nrst (int): Number of restart step + Returns: + unit (str): Corresponding physical unit\n + quan (array): Floats with the requested quantity -def handle_mass(dic, name, i, nrst): + """ + skl = float(dic["avar"][n]) + unit = get_unit(name) + names = name.split(" ") + if dic["use"] == "resdata": + if dic["init"].has_kw(names[0]): + quan = np.array(dic["init"][names[0]][0]) * 1.0 + if names[0].lower() == "porv": + quan = dic["pv"] + elif names[0].lower() == "grid": + quan = np.array(dic["init"]["SATNUM"][0]) * 0 + elif names[0].lower() == "wells": + quan = np.array(dic["init"]["SATNUM"][0]) * 0 + dic["wells"] = [] + get_wells(dic) + elif "index" in names[0].lower(): + quan = np.array(dic["init"]["SATNUM"][0]) * 0 + elif dic["unrst"].has_kw(names[0]): + quan = np.array(dic["unrst"][names[0]][nrst]) * 1.0 + elif names[0].lower() in dic["mass"] + dic["xmass"]: + quan = handle_mass(dic, names[0].lower(), nrst) * skl + if names[0].lower() in dic["mass"]: + unit = initialize_mass(skl) + else: + print(f"Unknow -v variable ({names[0]}).") + sys.exit() + if len(names) > 1: + for j, val in enumerate(names[2::2]): + if dic["init"].has_kw(val): + quan1 = np.array(dic["init"][val][0]) * 1.0 + elif dic["unrst"].has_kw(val): + quan1 = np.array(dic["unrst"][val][nrst]) * 1.0 + elif val.lower() in dic["mass"] + dic["xmass"]: + quan1 = handle_mass(dic, val.lower(), nrst) * skl + else: + quan1 = float(val) + quan = operate(quan, quan1, j, names[1::2]) + else: + if dic["init"].count(names[0]): + quan = dic["init"][names[0]] + if names[0].lower() == "porv": + quan = dic["pv"] + elif names[0].lower() == "grid": + quan = np.array(dic["init"]["SATNUM"]) * 0 + elif names[0].lower() == "wells": + quan = np.array(dic["init"]["SATNUM"]) * 0 + dic["wells"] = [] + get_wells(dic) + elif "index" in names[0].lower(): + quan = np.array(dic["init"]["SATNUM"]) * 0 + elif dic["unrst"].count(names[0]): + quan = dic["unrst"][names[0], nrst] + elif names[0].lower() in dic["mass"] + dic["xmass"]: + quan = handle_mass(dic, names[0].lower(), nrst) * skl + if names[0].lower() in dic["mass"]: + unit = initialize_mass(skl) + else: + print(f"Unknow -v variable ({names[0]}).") + sys.exit() + if len(names) > 1: + for j, val in enumerate(names[2::2]): + if dic["init"].count(val): + quan1 = dic["init"][val] + elif dic["unrst"].count(val): + quan1 = dic["unrst"][val, nrst] + elif val.lower() in dic["mass"] + dic["xmass"]: + quan1 = handle_mass(dic, val.lower(), nrst) * skl + else: + quan1 = float(val) + quan = operate(quan, quan1, j, names[1::2]) + if dic["vmin"][n]: + quan = np.array(quan) + quan[quan < float(dic["vmin"][n])] = np.nan + if dic["vmax"][n]: + quan = np.array(quan) + quan[float(dic["vmax"][n]) < quan] = np.nan + return unit, quan + + +def handle_mass(dic, name, 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: @@ -346,28 +579,27 @@ def handle_mass(dic, name, i, nrst): """ 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]) + sgas = np.array(dic["unrst"]["SGAS"][nrst]) + rhog = np.array(dic["unrst"]["GAS_DEN"][nrst]) + rhow = np.array(dic["unrst"]["WAT_DEN"][nrst]) + if dic["unrst"].has_kw("RSW"): + rsw = np.array(dic["unrst"]["RSW"][nrst]) else: rsw = 0.0 * sgas - if dic["unrst"][i].has_kw("RVW"): - rvw = np.array(dic["unrst"][i]["RVW"][nrst - 1]) + if dic["unrst"].has_kw("RVW"): + rvw = np.array(dic["unrst"]["RVW"][nrst]) 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]) + sgas = np.array(dic["unrst"]["SGAS", nrst]) + rhog = np.array(dic["unrst"]["GAS_DEN", nrst]) + rhow = np.array(dic["unrst"]["WAT_DEN", nrst]) + if dic["unrst"].count("RSW"): + rsw = np.array(dic["unrst"]["RSW", nrst]) else: rsw = 0.0 * sgas - if dic["unrst"][i].count("RVW"): - rvw = np.array(dic["unrst"][i]["RVW", nrst]) + if dic["unrst"].count("RVW"): + rvw = np.array(dic["unrst"]["RVW", nrst]) else: rvw = 0.0 * sgas x_l_co2 = np.divide(rsw, rsw + WAT_DEN_REF / GAS_DEN_REF) @@ -376,10 +608,10 @@ def handle_mass(dic, name, i, nrst): co2_d = x_l_co2 * (1.0 - sgas) * rhow * dic["pv"] h2o_l = (1 - x_l_co2) * (1 - sgas) * rhow * dic["pv"] h2o_v = x_g_h2o * sgas * rhog * dic["pv"] - return type_of_mass(name, co2_g, co2_d, h2o_l, h2o_v) + return type_of_mass(name, co2_g, co2_d, h2o_l, h2o_v, x_l_co2, x_g_h2o) -def 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, x_l_co2, x_g_h2o): """ From the given variable return the associated mass @@ -404,106 +636,17 @@ def type_of_mass(name, co2_g, co2_d, h2o_l, h2o_v): return h2o_v if name == "h2om": return h2o_v + h2o_l + if name == "xco2l": + return x_l_co2 + if name == "xh2ov": + return x_g_h2o + if name == "xco2v": + return 1 - x_g_h2o + if name == "xh2ol": + return 1 - x_l_co2 return co2_g + co2_d -def get_kws_opm(dic): - """ - Get the static properties from the INIT file using Opm - - Args: - dic (dict): Global dictionary - - Returns: - 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()]) - elif dic["unrst"][0].count(name.upper()): - nrst = ( - dic["restart"] - 1 - if dic["restart"] > 0 - else dic["unrst"][0].count(name.upper()) - 1 - ) - if len(dic["names"]) == 1: - dic[name] = np.array(dic["unrst"][0][name.upper(), nrst]) - else: - dic[name] = np.array(dic["unrst"][0][name.upper(), nrst]) - np.array( - dic["unrst"][1][name.upper(), nrst] - ) - ntot = dic["unrst"][0].count(name.upper()) - dic["dtitle"] = ( - f", rst {ntot if dic['restart']==0 else dic['restart']} out of {ntot}" - ) - elif name.upper() in dic["summary"][0].keys(): - for i, _ in enumerate(dic["names"]): - dic["vsum"].append(dic["summary"][i][name.upper()]) - 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 - - -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): """ Using the input deck (.DATA) to read the i,j well locations @@ -516,6 +659,7 @@ def get_wells(dic): """ dic["wellsa"] = np.ones((dic["mx"]) * (dic["my"])) * np.nan + dic["grida"] = np.ones((dic["mx"]) * (dic["my"])) * np.nan wells, sources = False, False with open(f"{dic['name']}.DATA", "r", encoding="utf8") as file: for row in csv.reader(file): diff --git a/src/plopm/utils/vtk.py b/src/plopm/utils/vtk.py index e481b80..28e4dc7 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,R0912 +# pylint: disable=W3301,R0912,R0915 """ Utiliy functions to write the vtks. @@ -8,18 +8,10 @@ import os import csv +import sys from subprocess import PIPE, Popen import numpy as np -from plopm.utils.readers import handle_mass - -try: - from resdata.resfile import ResdataFile -except ImportError: - print("The resdata Python package was not found, using opm") -try: - from opm.io.ecl import EclFile as OpmFile -except ImportError: - print("The Python package opm was not found, using resdata") +from plopm.utils.readers import get_quantity, get_readers def make_vtks(dic): @@ -33,61 +25,46 @@ def make_vtks(dic): None """ - dic["deck"] = dic["name"] - if len(dic["name"].split("/")) > 1: - dic["deck"] = dic["name"].split("/")[-1] - dic["dry"] = "_DRYRUN" - dic["UInt16"] = ["MPI_RANK", "SATNUM", "FIPNUM", "PVTNUM"] - if not os.path.isfile(f"{dic['output']}/{dic['name']}-GRID.vtu"): - cwd = os.getcwd() - if len(dic["name"].split("/")) > 1: - os.chdir("/".join(dic["name"].split("/")[:-1])) - flags, thermal = get_flags() - with Popen(args=f"{dic['flow']} --version", stdout=PIPE, shell=True) as process: - dic["flow_version"] = str(process.communicate()[0])[7:-3] - if dic["flow_version"] == "2024.04": - make_dry_deck(dic) - else: - os.system(f"cp {dic['deck']}.DATA {dic['deck']+dic['dry']}.DATA") - flags += " --enable-dry-run=1" - os.system("mkdir plopm_vtks_temporal") - deck = f" ../{dic['deck']+dic['dry']}.DATA" - os.chdir("plopm_vtks_temporal") - if "SPE11B" in dic["name"] or "SPE11C" in dic["name"]: - os.system(dic["flow"] + deck + flags + thermal) - else: - os.system(dic["flow"] + deck + flags) - os.system( - f"mv {dic['deck']+dic['dry']}-00000.vtu {cwd}/{dic['output']}/{dic['deck']}-GRID.vtu" - ) - 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].append(ResdataFile(f"{dic['name']}.{ext.upper()}")) + for k, case in enumerate(dic["names"][0]): + dic["deck"] = case + if len(dic["deck"].split("/")) > 1: + dic["deck"] = dic["deck"].split("/")[-1] + if not os.path.isfile(f"{dic['output']}/{dic['deck']}-GRID.vtu"): + cwd = os.getcwd() + if len(case.split("/")) > 1: + os.chdir("/".join(case.split("/")[:-1])) + flags, thermal = get_flags() + with Popen( + args=f"{dic['flow']} --version", stdout=PIPE, shell=True + ) as process: + dic["flow_version"] = str(process.communicate()[0])[7:-3] + if dic["flow_version"] == "2024.04": + make_dry_deck(dic) + else: + os.system(f"cp {dic['deck']}.DATA {dic['deck']}_DRYRUN.DATA") + flags += " --enable-dry-run=1" + os.system("mkdir plopm_vtks_temporal") + deck = f" ../{dic['deck']}_DRYRUN.DATA" + os.chdir("plopm_vtks_temporal") + if "SPE11B" in dic["deck"] or "SPE11C" in dic["deck"]: + os.system(dic["flow"] + deck + flags + thermal) else: - 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["nxyz"] = len(dic["porv"]) - dic["pv"] = np.array([porv for porv in dic["porv"] if porv > 0]) - dic["actind"] = list(i for i, p_v in enumerate(dic["porv"]) if p_v > 0) - opmtovtk_resdata(dic) - else: - dic["porv"] = np.array(dic["init"][0]["PORV"]) - dic["nxyz"] = len(dic["porv"]) - dic["pv"] = np.array([porv for porv in dic["porv"] if porv > 0]) - dic["actind"] = list(i for i, p_v in enumerate(dic["porv"]) if p_v > 0) - opmtovtk_opm(dic) + os.system(dic["flow"] + deck + flags) + os.system( + f"mv {dic['deck']}_DRYRUN-00000.vtu " + + f"{cwd}/{dic['output']}/{dic['deck']}-GRID.vtu" + ) + os.system(f"cd .. && rm -rf plopm_vtks_temporal {deck[4:]}") + os.chdir(cwd) + get_readers(dic) + opmtovtk(dic, k) + writepvd(dic, k) -def opmtovtk_resdata(dic): +def writepvd(dic, k): """ - Use resdata to generate the vtks + Generate the pvd file\n + k (int): Index of the geological model Args: dic (dict): Global dictionary @@ -96,219 +73,37 @@ def opmtovtk_resdata(dic): None """ - base_vtk = [] - skip = False - with open(f"{dic['output']}/{dic['deck']}-GRID.vtu", encoding="utf8") as file: - for line in file: - if skip and "CellData" in line: - skip = False - continue - if "CellData" in line: - skip = True - if not skip: - base_vtk.append(line) - i, n, inc = int(dic["restart"][0]), 0, 0 - base_vtk.insert(4, "\t\t\t\t") - for n, var in enumerate(dic["variable"].split(",")): - if var.upper() in dic["UInt16"]: - if var.upper() == "MPI_RANK": - inc = 1 - base_vtk.insert( - 5 + 2 * n, - f"\n\t\t\t\t\t\n", - ) - 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"][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 + 1) - ] - + ["\n\t\t\t\t\t"] - ), - ) - else: - base_vtk.insert( - 6 + 2 * n, - " ".join( - ["\t\t\t\t\t "] - + [ - str(int(val) + inc) - for val in dic["unrst"][0][var.upper()][i] - ] - + ["\n\t\t\t\t\t"] - ), - ) - else: - base_vtk.insert( - 5 + 2 * n, - f"\n\t\t\t\t\t\n", - ) - 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 handle_mass(dic, var.lower(), 0, i + 1) - ] - + ["\n\t\t\t\t\t"] - ), - ) - else: - base_vtk.insert( - 6 + 2 * n, - " ".join( - ["\t\t\t\t\t "] - + [ - 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") + where = dic["save"][k] if dic["save"][k] else dic["deck"] + base_pvd = [] + base_pvd.append( + "\n" + + "\n" + + " \n" + ) + for i in dic["restart"]: + base_pvd.append( + f" \n" + ) + base_pvd.append(" \n") with open( - f"{dic['output']}/{dic['save'] if dic['save'] else dic['deck']}" - + f"-{0 if i<1000 else ''}{0 if i<100 else ''}{0 if i<10 else ''}{int(i)}.vtu", + f"{dic['output']}/{where}.pvd", "w", encoding="utf8", ) as file: - file.write("".join(base_vtk)) - additional_vtks_resdata(dic, base_vtk) + file.write("".join(base_pvd)) -def additional_vtks_resdata(dic, base_vtk): +def opmtovtk(dic, k): """ - Use resdata to generate the additional vtks + Generate the vtks Args: - dic (dict): Global dictionary - base_vtk (list): Body text of the vtk template - i (int): - - Returns: - 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:]: - i_i = int(i) - for n, var in enumerate(dic["variable"].split(",")): - if var.upper() in dic["UInt16"]: - if var.upper() == "MPI_RANK": - inc = 1 - base_vtk[5 + 2 * n] = ( - f"\n\t\t\t\t\t\n" - ) - 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"][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 + 1) - ] - + ["\n\t\t\t\t\t"] - ) - else: - base_vtk[6 + 2 * n] = " ".join( - ["\t\t\t\t\t "] - + [ - str(int(val) + inc) - for val in dic["unrst"][0][var.upper()][i_i] - ] - + ["\n\t\t\t\t\t"] - ) - else: - base_vtk[5 + 2 * n] = ( - f"\n\t\t\t\t\t\n" - ) - 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 handle_mass(dic, var.lower(), 0, i_i + 1) - ] - + ["\n\t\t\t\t\t"] - ) - else: - base_vtk[6 + 2 * n] = " ".join( - ["\t\t\t\t\t "] - + [ - str(np.float16(val)) - for val in dic["unrst"][0][var.upper()][i_i] - ] - + ["\n\t\t\t\t\t"] - ) - with open( - f"{dic['output']}/{dic['save'] if dic['save'] else dic['deck']}" - + 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", - ) as file: - file.write("".join(base_vtk)) - - -def opmtovtk_opm(dic): - """ - Use opm to generate the vtks - - Args: - dic (dict): Global dictionary + dic (dict): Global dictionary\n + k (int): Index of the geological model Returns: None @@ -325,183 +120,77 @@ def opmtovtk_opm(dic): skip = True if not skip: base_vtk.append(line) - i, n, inc = int(dic["restart"][0]), 0, 0 - base_vtk.insert(4, "\t\t\t\t") - for n, var in enumerate(dic["variable"].split(",")): - if var.upper() in dic["UInt16"]: - if var.upper() == "MPI_RANK": - inc = 1 - base_vtk.insert( - 5 + 2 * n, - f"\n\t\t\t\t\t\n", - ) - 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"][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 + 1) - ] - + ["\n\t\t\t\t\t"] - ), - ) - else: - base_vtk.insert( - 6 + 2 * n, - " ".join( - ["\t\t\t\t\t "] - + [ - str(int(val) + inc) - for val in dic["unrst"][0][var.upper(), i] - ] - + ["\n\t\t\t\t\t"] - ), - ) - else: - base_vtk.insert( - 5 + 2 * n, - f"\n\t\t\t\t\t\n", - ) - 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 handle_mass(dic, var.lower(), 0, i + 1) - ] - + ["\n\t\t\t\t\t"] - ), - ) - else: + base_vtk.insert( + 4, + "\t\t\t\t", + ) + for i in dic["restart"]: + for n, var in enumerate(dic["vrs"]): + unit, quan = get_quantity(dic, var.upper(), n, i) + if i == 0: base_vtk.insert( - 6 + 2 * n, - " ".join( - ["\t\t\t\t\t "] - + [ - 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['output']}/{dic['save'] if dic['save'] else dic['deck']}-{0 if i<1000 else ''}" - + f"{0 if i<100 else ''}{0 if i<10 else ''}{int(i)}.vtu", - "w", - encoding="utf8", - ) as file: - file.write("".join(base_vtk)) - additional_vtks_opm(dic, base_vtk) - - -def additional_vtks_opm(dic, base_vtk): - """ - Use opm to generate the additional vtks - - Args: - dic (dict): Global dictionary - base_vtk (list): Body text of the vtk template - i (int): - - Returns: - 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:]: - i_i = int(i) - for n, var in enumerate(dic["variable"].split(",")): - if var.upper() in dic["UInt16"]: - if var.upper() == "MPI_RANK": - inc = 1 - base_vtk[5 + 2 * n] = ( - f"\n\t\t\t\t\t\n" - ) - 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"][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 + 1) - ] - + ["\n\t\t\t\t\t"] + 5 + 2 * n, + f"\n\t\t\t\t\t\n", + ) + if dic["vtkformat"][n] == "Float64": + if i == 0: + base_vtk.insert( + 6 + 2 * n, + " ".join( + ["\t\t\t\t\t "] + + [str(np.float32(val)) for val in quan] + + ["\n\t\t\t\t\t"] + ), ) else: base_vtk[6 + 2 * n] = " ".join( ["\t\t\t\t\t "] - + [ - str(int(val) + inc) - for val in dic["unrst"][0][var.upper(), i_i] - ] + + [str(np.float32(val)) for val in quan] + ["\n\t\t\t\t\t"] ) - else: - base_vtk[5 + 2 * n] = ( - f"\n\t\t\t\t\t\n" - ) - 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"][0][var.upper()]] - + ["\n\t\t\t\t\t"] + elif dic["vtkformat"][n] == "Float32": + if i == 0: + base_vtk.insert( + 6 + 2 * n, + " ".join( + ["\t\t\t\t\t "] + + [str(np.float16(val)) for val in quan] + + ["\n\t\t\t\t\t"] + ), ) - elif var.lower() in dic["mass"]: + else: 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 + 1) - ] + + [str(np.float16(val)) for val in quan] + ["\n\t\t\t\t\t"] ) + elif dic["vtkformat"][n] == "UInt16": + if i == 0: + base_vtk.insert( + 6 + 2 * n, + " ".join( + ["\t\t\t\t\t "] + + [str(int(val)) for val in quan] + + ["\n\t\t\t\t\t"] + ), + ) else: base_vtk[6 + 2 * n] = " ".join( ["\t\t\t\t\t "] - + [ - str(np.float16(val)) - for val in dic["unrst"][0][var.upper(), i_i] - ] + + [str(int(val)) for val in quan] + ["\n\t\t\t\t\t"] ) + else: + print(f"Unknow format ({dic['vtkformat'][n]}).") + sys.exit() + if i == 0: + base_vtk.insert(7 + 2 * (len(dic["vrs"]) - 1), "\n\t\t\t\t\n") + where = dic["save"][k] if dic["save"][k] else dic["deck"] with open( - f"{dic['output']}/{dic['save'] if dic['save'] else dic['deck']}-{0 if i_i<1000 else ''}" - + f"{0 if i_i<100 else ''}" - + f"{0 if i_i<10 else ''}{i_i}.vtu", + f"{dic['output']}/{where}-{0 if i<1000 else ''}" + + f"{0 if i<100 else ''}{0 if i<10 else ''}{int(i)}.vtu", "w", encoding="utf8", ) as file: diff --git a/src/plopm/utils/write.py b/src/plopm/utils/write.py index eed76a2..11f020a 100644 --- a/src/plopm/utils/write.py +++ b/src/plopm/utils/write.py @@ -1,6 +1,6 @@ # SPDX-FileCopyrightText: 2024 NORCE # SPDX-License-Identifier: GPL-3.0 -# pylint: disable=W3301,W0123,R0912,R0915,R0914 +# pylint: disable=W3301,W0123,R0912,R0915,R0914,R1702 """ Utiliy functions to write the PNGs figures. @@ -10,8 +10,20 @@ import numpy as np import matplotlib import matplotlib.pyplot as plt +from matplotlib import animation from matplotlib import colors from mpl_toolkits.axes_grid1 import make_axes_locatable +from plopm.utils.readers import read_summary, get_quantity, get_readers +from plopm.utils.initialization import ini_slides +from plopm.utils.mapping import ( + handle_slide_x, + handle_slide_y, + handle_slide_z, + rotate_grid, + map_xzcoords, + map_xycoords, + map_yzcoords, +) def make_summary(dic): @@ -25,97 +37,318 @@ def make_summary(dic): None """ + dic["fig"], dic["axis"] = [], [] + if dic["subfigs"][0]: + dic["fig"], dic["axis"] = plt.subplots( + int(dic["subfigs"][0]), int(dic["subfigs"][1]), layout="compressed" + ) + for j, quan in enumerate(dic["vrs"]): + k = j + if not dic["subfigs"][0]: + dic["fig"], dic["axis"] = plt.subplots(1, 1, layout="compressed") + dic["axis"] = np.array([dic["axis"]]) + k = 0 + dic["axis"].flat[k].grid(int(dic["axgrid"][j])) + for i, name in enumerate(dic["names"][j]): + time, var, tunit, vunit = read_summary( + dic, name, quan, dic["tunits"][j], float(dic["avar"][j]) + ) + label = name + if len(name.split("/")) > 1: + label = name.split("/")[-2] + "/" + name.split("/")[-1] + if dic["labels"][0][0]: + label = dic["labels"][j][i] + dic["axis"].flat[k].step( + time, + var, + color=dic["colors"][j][i], + ls=dic["linestyle"][j][i], + label=label, + lw=float(dic["lw"][j][i]), + ) + if i == 0: + min_t, min_v = min(time), min(var) + max_t, max_v = max(time), max(var) + else: + min_t = min(min_t, min(time)) + min_v = min(min_v, min(var)) + max_t = max(max_t, max(time)) + max_v = max(max_v, max(var)) + dic["axis"].flat[k].set_ylabel(quan + vunit) + dic["axis"].flat[k].set_ylim([min_v, max_v]) + if dic["delax"] == 0 or k + int(dic["subfigs"][1]) >= len(dic["vrs"]): + dic["axis"].flat[k].set_xlabel(tunit) + if dic["xlabel"][0]: + dic["axis"].flat[k].set_xlabel(dic["xlabel"][j]) + if dic["ylabel"][0]: + dic["axis"].flat[k].set_ylabel(dic["ylabel"][j]) + if len(dic["xlim"]) > 1: + dic["axis"].flat[k].set_xlim( + [float(dic["xlim"][j][0][1:]), float(dic["xlim"][j][1][:-1])] + ) + xlabels = np.linspace( + float(dic["xlim"][j][0][1:]), + float(dic["xlim"][j][1][:-1]), + int(dic["xlnum"][j]), + ) + elif tunit != "Dates": + dic["axis"].flat[k].set_xlim([min_t, max_t]) + xlabels = np.linspace( + min_t, + max_t, + int(dic["xlnum"][j]), + ) + if len(dic["ylim"]) > 1: + dic["axis"].flat[k].set_ylim( + [float(dic["ylim"][j][0][1:]), float(dic["ylim"][j][1][:-1])] + ) + ylabels = np.linspace( + float(dic["ylim"][j][0][1:]), + float(dic["ylim"][j][1][:-1]), + int(dic["ylnum"][j]), + ) + else: + dic["axis"].flat[k].set_ylim([min_v, max_v]) + ylabels = np.linspace( + min_v, + max_v, + int(dic["ylnum"][j]), + ) + if dic["xlog"][j] == "1": + dic["axis"].flat[k].set_xscale("log") + else: + if tunit != "Dates": + if dic["xformat"][0]: + func = "f'{x:" + dic["xformat"][j] + "}'" + dic["axis"].flat[k].set_xticks([float(eval(func)) for x in xlabels]) + dic["axis"].flat[k].set_xticklabels([eval(func) for x in xlabels]) + else: + dic["axis"].flat[k].set_xticks(xlabels) + if dic["ylog"][j] == "1": + dic["axis"].flat[k].set_yscale("log") + else: + if dic["yformat"][0]: + func = "f'{y:" + dic["yformat"][j] + "}'" + dic["axis"].flat[k].set_yticks([float(eval(func)) for y in ylabels]) + dic["axis"].flat[k].set_yticklabels([eval(func) for y in ylabels]) + else: + dic["axis"].flat[k].set_yticks(ylabels) + if dic["loc"][j] != "empty": + dic["axis"].flat[k].legend(loc=dic["loc"][j]) + if dic["titles"][j] != "0": + dic["axis"].flat[k].set_title(dic["titles"][j]) + if dic["delax"] == 1 and k + int(dic["subfigs"][1]) < len(dic["vrs"]): + dic["axis"].flat[k].tick_params( + axis="x", which="both", bottom=False, labelbottom=False + ) + if not dic["subfigs"][0] or j == len(dic["vrs"]) - 1: + if ( + len(dic["loc"]) == j + 2 + and j != 0 + and len(dic["axis"].flat) - len(dic["vrs"]) > 0 + ): + for jj, qua in enumerate(dic["vrs"][: dic["numc"]]): + for i, name in enumerate(dic["names"][jj]): + time, var, tunit, vunit = read_summary( + dic, name, qua, dic["tunits"][jj], float(dic["avar"][jj]) + ) + label = name + if len(name.split("/")) > 1: + label = name.split("/")[-2] + "/" + name.split("/")[-1] + if dic["labels"][0][0]: + label = dic["labels"][jj][i] + dic["axis"].flat[-1].step( + time, + var, + color=dic["colors"][jj][i], + ls=dic["linestyle"][jj][i], + label=label, + lw=float(dic["lw"][jj][i]), + ) + dic["axis"].flat[-1].axis("off") + dic["axis"].flat[-1].legend(loc=dic["loc"][-1]) + for line in dic["axis"].flat[-1].get_lines(): + line.remove() + for l in range(len(dic["axis"].flat) - len(dic["vrs"]) - 1): + dic["fig"].delaxes(dic["axis"].flat[-2 - l]) + else: + for l in range(len(dic["axis"].flat) - len(dic["vrs"])): + dic["fig"].delaxes(dic["axis"].flat[-1 - l]) + dic["fig"].savefig( + f"{dic['output']}/{dic['save'][j] if dic['save'][j] else quan}.png", + bbox_inches="tight", + dpi=int(dic["dpi"][j]), + ) + plt.close() + + +def prepare_maps(dic, n): + """ + Get the spatial coordinates + + Args: + dic (dict): Global dictionary\n + n (int): Number of deck + + Returns: + dic (dict): Modified global dictionary + + """ + if len(dic["deck"].split("/")) > 1: + dic["deckn"] = (dic["deck"].split("/")[-1]).lower() + else: + dic["deckn"] = dic["deck"].lower() + dic["xc"], dic["yc"] = [], [] + get_readers(dic) + ini_slides(dic) + if dic["slide"][0] > -1: + handle_slide_x(dic) + elif dic["slide"][1] > -1: + handle_slide_y(dic) + else: + handle_slide_z(dic) + if int(dic["rotate"][n]) != 0 or dic["translate"][n] != ["[0", "0]"]: + rotate_grid(dic, n) + + +def make_maps(dic): + """ + Method to create the 2d maps using pcolormesh + + Args: + dic (dict): Global dictionary + + Returns: + dic (dict): Modified global dictionary + + """ + dic["fig"], dic["axis"] = [], [] + dic["skip"] = 0 if ( - len(dic["cmaps"][0].split(",")) == len(dic["names"]) - and dic["cmaps"][0] != "gnuplot" + dic["subfigs"][0] + and len(dic["vrs"]) > 1 + and len(dic["restart"]) == 1 + and len(dic["names"][0]) == 1 ): - dic["colors"] = dic["cmaps"][0].split(",") - if len(dic["linsty"].split(";")) == len(dic["names"]) and dic["linsty"]: - dic["linestyle"] = dic["linsty"].split(";") - 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]) - for i, name in enumerate(dic["names"]): - 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], - color=dic["colors"][i], - ls=dic["linestyle"][i], - label=label, + dic["skip"] = 1 + if dic["subfigs"][0]: + dic["fig"], dic["axis"] = plt.subplots( + int(dic["subfigs"][0]), int(dic["subfigs"][1]) ) - min_t = min(min_t, min(dic["time"][i])) - 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] + dic["units"][0]) - axis.set_ylim([min_v, max_v]) - 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, - dic["xlnum"], + dic["sub0"] = int(dic["subfigs"][0]) + dic["sub1"] = int(dic["subfigs"][1]) + else: + dic["fig"], dic["axis"] = plt.subplots(1, 1, layout="compressed") + dic["sub0"] = 1 + dic["sub1"] = 1 + dic["original_loc"], dic["cb"] = [], [] + dic["minc"], dic["maxc"] = [1e20], [-1e20] + if dic["subfigs"][0] and dic["mode"] == "gif" and len(dic["names"][0]) > 1: + find_min_max(dic) + dic["fig"], dic["axis"] = plt.subplots( + int(dic["subfigs"][0]), int(dic["subfigs"][1]), layout="compressed" ) - 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"], + dic["axis"] = np.array([dic["axis"]]) + for _ in range(len(dic["axis"].flat)): + dic["original_loc"].append(dic["axis"].flat[0].get_axes_locator()) + dic["cb"].append("") + for l in range(len(dic["axis"].flat) - len(dic["names"][0])): + dic["fig"].delaxes(dic["axis"].flat[-1 - l]) + im_ani = animation.FuncAnimation( + dic["fig"], + mapit, + fargs=(dic, 0), + frames=len(dic["restart"]), + interval=dic["interval"], + blit=False, + repeat=False, ) - else: - axis.set_ylim([min_v, max_v]) - ylabels = np.linspace( - min_v, - max_v, - dic["ylnum"], + if dic["loop"] == 0: + im_ani.save(f"{dic['vrs'][0]}.gif", extra_args=["-loop", "-1"]) + else: + im_ani.save(f"{dic['vrs'][0]}.gif") + elif dic["subfigs"][0] and dic["mode"] == "gif" and len(dic["vrs"]) > 1: + find_min_max(dic) + if len(dic["restart"]) > 1: + dic["fig"], dic["axis"] = plt.subplots( + int(dic["subfigs"][0]), int(dic["subfigs"][1]) + ) + dic["axis"] = np.array([dic["axis"]]) + plt.tight_layout(pad=1.7) + dic["deck"] = dic["names"][0][0] + dic["ndeck"] = 0 + prepare_maps(dic, 0) + for _ in range(len(dic["axis"].flat)): + dic["original_loc"].append(dic["axis"].flat[0].get_axes_locator()) + dic["cb"].append("") + for l in range(len(dic["axis"].flat) - len(dic["vrs"])): + dic["fig"].delaxes(dic["axis"].flat[-1 - l]) + im_ani = animation.FuncAnimation( + dic["fig"], + mapit, + fargs=(dic, 0), + frames=len(dic["restart"]), + interval=dic["interval"], + blit=False, + repeat=False, ) - 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]) + if dic["loop"] == 0: + im_ani.save(f"{dic['deckn']}.gif", extra_args=["-loop", "-1"]) 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]) + im_ani.save(f"{dic['deckn']}.gif") else: - axis.set_yticks(ylabels) - axis.legend() - if dic["titles"] != "": - axis.set_title(dic["titles"]) - fig.savefig( - f"{dic['output']}/{dic['save'] if dic['save'] else dic['variable']}.png", - bbox_inches="tight", - dpi=dic["dpi"], - ) - plt.close() + find_min_max(dic) + dic["deck"] = dic["names"][0][0] + dic["ndeck"] = 0 + prepare_maps(dic, 0) + for n, var in enumerate(dic["vrs"]): + if len(dic["restart"]) > 1: + if dic["subfigs"][0]: + dic["fig"], dic["axis"] = plt.subplots( + int(dic["subfigs"][0]), + int(dic["subfigs"][1]), + ) + else: + dic["fig"], dic["axis"] = plt.subplots(1, 1) + if not dic["subfigs"][0]: + dic["fig"], dic["axis"] = plt.subplots(1, 1, layout="tight") + dic["axis"] = np.array([dic["axis"]]) + for _ in range(len(dic["axis"].flat)): + dic["original_loc"].append(dic["axis"].flat[0].get_axes_locator()) + dic["cb"].append("") + if len(dic["restart"]) > 1: + for l in range(len(dic["axis"].flat) - len(dic["restart"])): + dic["fig"].delaxes(dic["axis"].flat[-1 - l]) + if dic["mode"] == "gif" and len(dic["restart"]) > 1: + for l in range(len(dic["axis"].flat) - len(dic["restart"])): + dic["fig"].delaxes(dic["axis"].flat[-1 - l]) + im_ani = animation.FuncAnimation( + dic["fig"], + mapit, + fargs=(dic, n), + frames=len(dic["restart"]), + interval=dic["interval"], + blit=False, + repeat=False, + ) + if dic["loop"] == 0: + im_ani.save(f"{dic['deckn']}_{var}.gif", extra_args=["-loop", "-1"]) + else: + im_ani.save(f"{dic['deckn']}_{var}.gif") + else: + if len(dic["names"][0]) > 1: + for l in range(len(dic["axis"].flat) - len(dic["names"][0])): + dic["fig"].delaxes(dic["axis"].flat[-1 - l]) + for t, _ in enumerate(dic["restart"]): + if not dic["subfigs"][0]: + dic["fig"], dic["axis"] = plt.subplots(1, 1) + dic["axis"] = np.array([dic["axis"]]) + mapit(t, dic, n) -def make_2dmaps(dic): +def find_min_max(dic): """ - Method to create the 2d maps using pcolormesh + Method to find the min and max for the colorbars Args: dic (dict): Global dictionary @@ -124,47 +357,207 @@ def make_2dmaps(dic): dic (dict): Modified global dictionary """ + dic["deckd"] = "" + if dic["diff"]: + if len(dic["diff"].split("/")) > 1: + dic["deckd"] = (dic["diff"].split("/")[-1]).lower() + else: + dic["deckd"] = dic["diff"].lower() + dic["deck"] = dic["diff"] + dic["ndeck"] = 0 + var = dic["vrs"][0] + dic["diffa"] = [] + for t, _ in enumerate(dic["restart"]): + prepare_maps(dic, 0) + _, quan = get_quantity(dic, var.upper(), 0, dic["restart"][t]) + dic[var + "a"] = np.ones(dic["mx"] * dic["my"]) * np.nan + if dic["slide"][0] > -1: + map_yzcoords(dic, var, quan) + elif dic["slide"][1] > -1: + map_xzcoords(dic, var, quan) + else: + map_xycoords(dic, var, quan) + dic["diffa"].append(dic[var + "a"]) + for m, var in enumerate(dic["vrs"]): + dic["minc"].append(dic["minc"][-1]) + dic["maxc"].append(dic["maxc"][-1]) + for n, deck in enumerate(dic["names"][0]): + for t, _ in enumerate(dic["restart"]): + dic["deck"] = deck + dic["ndeck"] = n + prepare_maps(dic, n) + _, quan = get_quantity(dic, var.upper(), m, dic["restart"][t]) + dic[var + "a"] = np.ones(dic["mx"] * dic["my"]) * np.nan + if dic["slide"][0] > -1: + map_yzcoords(dic, var, quan) + elif dic["slide"][1] > -1: + map_xzcoords(dic, var, quan) + else: + map_xycoords(dic, var, quan) + if dic["diff"]: + dic[var + "a"] -= dic["diffa"][t] + dic["minc"][-2] = min( + dic["minc"][-2], dic[var + "a"][~np.isnan(dic[var + "a"])].min() + ) + dic["maxc"][-2] = max( + dic["maxc"][-2], dic[var + "a"][~np.isnan(dic[var + "a"])].max() + ) + if dic["mask"]: + var = dic["mask"] + dic["maska"] = [] + for n, deck in enumerate(dic["names"][0]): + dic["deck"] = deck + dic["ndeck"] = n + prepare_maps(dic, n) + _, quan = get_quantity(dic, var.upper(), 0, 0) + dic[var + "a"] = np.ones(dic["mx"] * dic["my"]) * np.nan + if dic["slide"][0] > -1: + map_yzcoords(dic, var, quan) + elif dic["slide"][1] > -1: + map_xzcoords(dic, var, quan) + else: + map_xycoords(dic, var, quan) + dic["maska"].append(dic[var + "a"]) + + +def mapit(t, dic, n): + """ + Method to coordinate the gebneration of axis + + Args: + t (int): Number of subplot\n + dic (dict): Global dictionary\n + n (int): Number of variable + + Returns: + dic (dict): Modified global dictionary + + """ + k = t + if not dic["subfigs"][0]: + k = 0 + elif len(dic["restart"]) == 1: + k = n + if dic["subfigs"][0] and len(dic["names"][0]) > 1: + for nn, deck in enumerate(dic["names"][0]): + dic["deck"] = deck + dic["ndeck"] = nn + prepare_maps(dic, nn) + mapits(dic, t, 0, nn) + elif dic["subfigs"][0] and len(dic["vrs"]) > 1 and dic["skip"] == 0: + for nn, _ in enumerate(dic["vrs"]): + mapits(dic, t, nn, nn) + else: + mapits(dic, t, n, k) + + +def mapits(dic, t, n, k): + """ + Generate the spatial maps + + Args: + dic (dict): Global dictionary\n + t (int): Number of restart\n + n (int): Number of variable\n + n (int): Number of subplot + + Returns: + dic (dict): Modified global dictionary + + """ + var = dic["vrs"][n] + unit, quan = get_quantity(dic, var.upper(), n, dic["restart"][t]) + dic[var + "a"] = np.ones(dic["mx"] * dic["my"]) * np.nan + if dic["slide"][0] > -1: + map_yzcoords(dic, var, quan) + elif dic["slide"][1] > -1: + map_xzcoords(dic, var, quan) + else: + map_xycoords(dic, var, quan) maps = np.ones([dic["my"], dic["mx"]]) * np.nan - if dic["well"] == 1: - dic["props"] += ["wells"] - elif dic["grid"] == 1: - dic["props"] += ["grid"] - for n, name in enumerate(dic["props"]): - fig, axis = plt.subplots() + if dic["diff"]: for i in np.arange(0, dic["my"]): - maps[i, :] = dic[name + "a"][i * (dic["mx"]) : (i + 1) * (dic["mx"])] - ntick = 5 - ncolor = dic["units"][n] - if dic["well"] != 1 and dic["grid"] != 1: - 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]) - elif len(dic["names"]) == 2: - minmax = max(abs(maxc), abs(minc)) - minc = -minmax - maxc = minmax - if maxc == minc: - ntick = 1 - elif name in ["fipnum", "satnum"]: - ntick = int(maxc) + maps[i, :] = ( + dic[var + "a"][i * (dic["mx"]) : (i + 1) * (dic["mx"])] + - dic["diffa"][t][i * (dic["mx"]) : (i + 1) * (dic["mx"])] + ) + else: + for i in np.arange(0, dic["my"]): + maps[i, :] = dic[var + "a"][i * (dic["mx"]) : (i + 1) * (dic["mx"])] + if dic["mask"]: + maxv = max(dic["maska"][k]) + for i in np.arange(0, dic["my"]): + maps[i, :] = [ + ( + (-dic["maxc"][n] * (maxv - val) / (maxv - 1)) + if act < dic["maskthr"] + else act + ) + for val, act in zip( + dic["maska"][k][i * (dic["mx"]) : (i + 1) * (dic["mx"])], + dic[var + "a"][i * (dic["mx"]) : (i + 1) * (dic["mx"])], + ) + ] + ntick = 3 + ncolor = var + " " + unit + if var.lower() != "wells" and var.lower() != "grid": + if len(dic["names"][0]) > 1 and dic["subfigs"][0]: + minc = dic["minc"][n] + maxc = dic["maxc"][n] + elif len(dic["vrs"]) > 1 and dic["subfigs"][0]: + minc = dic["minc"][n] + maxc = dic["maxc"][n] + elif ( + len(dic["restart"]) > 1 and dic["subfigs"][0] and len(dic["names"][0]) == 1 + ): + minc = dic["minc"][n] + maxc = dic["maxc"][n] + elif dic["mode"] == "gif" and not dic["subfigs"][0]: + minc = dic["minc"][n] + maxc = dic["maxc"][n] + elif dic["global"] == 0: + minc = maps[~np.isnan(maps)].min() + maxc = maps[~np.isnan(maps)].max() 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["grid"] == 1 and dic["well"] != 1: - imag = axis.pcolormesh( + minc = quan[~np.isnan(quan)].min() + maxc = quan[~np.isnan(quan)].max() + if dic["bounds"][n][0]: + minc = float(dic["bounds"][n][0][1:]) + maxc = float(dic["bounds"][n][1][:-1]) + elif dic["diff"]: + minmax = max(abs(maxc), abs(minc)) + minc = -minmax + maxc = minmax + if maxc == minc: + ntick = 1 + elif "num" in var.lower(): + ntick = int(maxc - minc + 1) + if dic["mask"]: + minc = -maxc + else: + minc = 0 + maxc = len(dic["wells"]) + if dic["cnum"][n]: + ntick = int(dic["cnum"][n]) + if dic["clabel"]: + ncolor = dic["clabel"] + cmap = matplotlib.colormaps.get_cmap(dic["cmaps"][n]) + if dic["ncolor"] != "w": + cmap.set_bad(color=dic["ncolor"]) + shc = 0 + if "num" in var.lower(): + if maxc == 1: + shc = 1 + from_list = matplotlib.colors.LinearSegmentedColormap.from_list + cmap = from_list( + None, plt.cm.get_cmap(dic["cmaps"][n])(range(0, ntick + shc)), ntick + ) + shc = 0.5 + if var.lower() == "grid" and var.lower() != "wells": + imag = ( + dic["axis"] + .flat[k] + .pcolormesh( dic["xc"], dic["yc"], maps, @@ -172,16 +565,24 @@ def make_2dmaps(dic): edgecolors="black", lw=0.001, ) - elif dic["log"] == 0: - imag = axis.pcolormesh( + ) + elif int(dic["log"][n]) == 0: + imag = ( + dic["axis"] + .flat[k] + .pcolormesh( dic["xc"], dic["yc"], maps, shading="flat", cmap=cmap, ) - else: - imag = axis.pcolormesh( + ) + else: + imag = ( + dic["axis"] + .flat[k] + .pcolormesh( dic["xc"], dic["yc"], maps, @@ -189,165 +590,353 @@ def make_2dmaps(dic): cmap=cmap, norm=colors.LogNorm(vmin=minc, vmax=maxc), ) - divider = make_axes_locatable(axis) + ) + if ( + dic["subfigs"][0] + and dic["mode"] == "gif" + and len(dic["vrs"]) > 1 + and dic["cb"][k] != "" + ): + dic["cb"][k].remove() + dic["axis"].flat[k].set_axes_locator(dic["original_loc"][k]) + if ( + dic["subfigs"][0] + and dic["mode"] == "gif" + and len(dic["names"][0]) > 1 + and dic["cb"][k] != "" + ): + dic["cb"][k].remove() + dic["axis"].flat[k].set_axes_locator(dic["original_loc"][k]) + if not dic["subfigs"][0] and dic["cb"][k] != "" and dic["mode"] == "gif": + dic["cb"][k].remove() + dic["axis"].flat[k].set_axes_locator(dic["original_loc"][k]) + divider = make_axes_locatable(dic["axis"].flat[k]) + if dic["mask"]: + vect = np.linspace( + 0, + maxc, + ntick, + endpoint=True, + ) + else: vect = np.linspace( minc, maxc, ntick, endpoint=True, ) - if dic["well"] != 1 and dic["grid"] != 1 and dic["rm"][2] == 0: - if dic["log"] == 0: - fig.colorbar( + if var.lower() != "wells" and var.lower() != "grid" and dic["rm"][2] == 0: + if int(dic["log"][n]) == 0: + func = "lambda x, _: f'{x:" + dic["cformat"][n] + "}'" + if ( + len(dic["restart"]) > 1 + and dic["subfigs"][0] + and len(dic["names"][0]) == 1 + ): + if k == 0: + dic["cb"][0] = dic["fig"].colorbar( + imag, + cax=dic["fig"].add_axes(dic["cbsfax"]), + ticks=vect, + label=ncolor, + format=eval(func), + shrink=0.2, + location="top", + ) + elif not dic["subfigs"][0] or len(dic["names"][0]) == 1: + dic["cb"][k] = dic["fig"].colorbar( imag, - cax=divider.append_axes("right", size="5%", pad=0.05), + cax=divider.append_axes("right", size="2%", pad=0.05), orientation="vertical", ticks=vect, label=ncolor, - format=dic["format"][n], + format=eval(func), ) - 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( + elif k == 0: + dic["cb"][0] = dic["fig"].colorbar( imag, - cax=divider.append_axes("right", size="5%", pad=0.05), - orientation="vertical", + cax=dic["fig"].add_axes(dic["cbsfax"]), + ticks=vect, label=ncolor, + format=eval(func), + shrink=0.2, + location="top", ) else: - handle_well_or_grid(dic, fig, imag, divider, vect) - if dic["rm"][2] == 0: - imag.set_clim( - minc, - maxc, + if minc == 0: + print( + f"It is not possible to plot {var} in log scale" + " since there are 0 values. Try without log." + ) + sys.exit() + dic["cb"][k] = dic["fig"].colorbar( + imag, + cax=divider.append_axes("right", size="5%", pad=0.05), + orientation="vertical", + label=ncolor, ) - 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']}/{dic['save'] if dic['save'] else name}.png", - bbox_inches="tight", - dpi=dic["dpi"], + else: + handle_well_or_grid(dic, imag, divider, vect) + if dic["rm"][2] == 0: + imag.set_clim( + minc - shc, + maxc + shc, ) - plt.close() + handle_axis(dic, var, n, t, k) + if dic["xlabel"][n] and dic["rm"][1] == 0: + dic["axis"].flat[k].set_xlabel(dic["xlabel"][n]) + elif ( + dic["rm"][1] == 0 + and len(dic["vrs"]) == 1 + and (k + dic["sub1"] >= len(dic["names"][0]) or not dic["subfigs"][0]) + ): + if len(dic["restart"]) > 1 and dic["subfigs"][0] and len(dic["names"][0]) == 1: + if k + dic["sub1"] >= len(dic["restart"]): + dic["axis"].flat[k].set_xlabel(f"{dic['xmeaning']+dic['xunit']}") + else: + dic["axis"].flat[k].set_xlabel(f"{dic['xmeaning']+dic['xunit']}") + elif ( + dic["rm"][1] == 0 + and len(dic["names"][0]) == 1 + and (k + dic["sub1"] >= len(dic["vrs"]) or not dic["subfigs"][0]) + ): + dic["axis"].flat[k].set_xlabel(f"{dic['xmeaning']+dic['xunit']}") + if dic["ylabel"][n] and dic["rm"][0] == 0: + dic["axis"].flat[k].set_ylabel(dic["ylabel"][n]) + elif dic["rm"][0] == 0 and (k % dic["sub1"] == 0 or not dic["subfigs"][0]): + dic["axis"].flat[k].set_ylabel(f"{dic['ymeaning']+dic['yunit']}") + if dic["rm"][2] == 1: + dic["fig"].delaxes(dic["fig"].axes[1]) + if dic["rm"][1] == 1 or ( + k + dic["sub1"] < len(dic["names"][0]) + and dic["subfigs"][0] + and len(dic["vrs"]) == 1 + ): + dic["axis"].flat[k].tick_params( + axis="x", which="both", bottom=False, labelbottom=False + ) + elif dic["rm"][1] == 1 or ( + k + dic["sub1"] < len(dic["vrs"]) + and dic["subfigs"][0] + and len(dic["names"][0]) == 1 + ): + dic["axis"].flat[k].tick_params( + axis="x", which="both", bottom=False, labelbottom=False + ) + elif ( + k + dic["sub1"] < len(dic["restart"]) + and len(dic["restart"]) > 1 + and dic["subfigs"][0] + and len(dic["names"][0]) == 1 + ): + dic["axis"].flat[k].tick_params( + axis="x", which="both", bottom=False, labelbottom=False + ) + if dic["rm"][0] == 1 or (k % dic["sub1"] > 0 and dic["subfigs"][0]): + dic["axis"].flat[k].tick_params( + axis="y", which="both", left=False, labelleft=False + ) + # if dic["mode"] != "gif": + # plt.tight_layout(pad=0) + if dic["mode"] != "gif": + if dic["subfigs"][0]: + if t == len(dic["restart"]) - 1 and len(dic["restart"]) > 1: + dic["fig"].set_facecolor(dic["fc"]) + name = f"{dic['deckn']}_{var}_{dic['nslide']}_t{dic['restart'][t]}" + dic["fig"].savefig( + f"{dic['output']}/{dic['save'][n] if dic['save'][n] else name}.png", + bbox_inches="tight", + dpi=int(dic["dpi"][0]), + ) + elif n == len(dic["vrs"]) - 1 and len(dic["vrs"]) > 1: + dic["fig"].set_facecolor(dic["fc"]) + name = f"{dic['deckn']}_{var}_{dic['nslide']}_t{dic['restart'][t]}" + dic["fig"].savefig( + f"{dic['output']}/{dic['save'][n] if dic['save'][n] else name}.png", + bbox_inches="tight", + dpi=int(dic["dpi"][0]), + ) + else: + if len(dic["restart"]) == 1: + if k == max(len(dic["vrs"]) - 1, len(dic["names"][0]) - 1): + dic["fig"].set_facecolor(dic["fc"]) + name = ( + f"{dic['deckn']}_{var}_{dic['nslide']}_t{dic['restart'][t]}" + ) + dic["fig"].savefig( + f"{dic['output']}/{dic['save'][n] if dic['save'][n] else name}.png", + bbox_inches="tight", + dpi=int(dic["dpi"][0]), + ) + elif len(dic["names"][0]) == 1: + if t == len(dic["restart"]) - 1: + dic["fig"].set_facecolor(dic["fc"]) + name = ( + f"{dic['deckn']}_{var}_{dic['nslide']}_t{dic['restart'][t]}" + ) + dic["fig"].savefig( + f"{dic['output']}/{dic['save'][n] if dic['save'][n] else name}.png", + bbox_inches="tight", + dpi=int(dic["dpi"][0]), + ) + else: + dic["fig"].set_facecolor(dic["fc"]) + name = f"{dic['deckn']}_{var}_{dic['nslide']}_t{dic['restart'][t]}" + dic["fig"].savefig( + f"{dic['output']}/{dic['save'][n] if dic['save'][n] else name}.png", + bbox_inches="tight", + dpi=int(dic["dpi"][0]), + ) + else: + dic["fig"].set_facecolor(dic["fc"]) + name = f"{dic['deckn']}_{var}_{dic['nslide']}_t{dic['restart'][t]}" + dic["fig"].savefig( + f"{dic['output']}/{dic['save'][n] if dic['save'][n] else name}.png", + bbox_inches="tight", + dpi=int(dic["dpi"][0]), + ) -def handle_axis(dic, axis, name): +def handle_axis(dic, name, n, t, k): """ Method to handle the figure axis Args: dic (dict): Global dictionary\n - axis (class): Axis object\n name (str): Property to plot Returns: - axis (class): Modified axis object + dic (dict): Modified global dictionary """ + time = f", time={dic['tnrst'][dic['restart'][t]]} days" if dic["scale"] == 1: - axis.axis("scaled") + dic["axis"].flat[k].axis("scaled") extra = "" if name == "porv": extra = f" (sum={sum(dic[name]):.3e})" - 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( + if dic["subfigs"][0] and len(dic["names"][0]) > 1 and dic["titles"][k] == "0": + dic["axis"].flat[k].set_title(dic["deckn"]) + if k == 0 and dic["suptitle"] != "0": + dic["fig"].suptitle(f"{dic['tnrst'][dic['restart'][t]]} days") + elif dic["subfigs"][0] and len(dic["vrs"]) > 1 and dic["titles"][k] == "0": + if k == 0 and dic["suptitle"] != "0": + dic["fig"].suptitle( + f"{dic['deckn']}, {dic['tnrst'][dic['restart'][t]]} days" + ) + elif dic["mode"] == "gif" and len(dic["vrs"]) == 1 and dic["titles"][k] == "0": + if dic["diff"]: + dic["axis"].flat[k].set_title( + f"{dic['deckn']}-{dic['deckd']}, {dic['tnrst'][dic['restart'][t]]} days" + ) + else: + dic["axis"].flat[k].set_title( + f"{dic['deckn']}, {dic['tnrst'][dic['restart'][t]]} days" + ) + elif ( + len(dic["restart"]) > 1 + and dic["subfigs"][0] + and len(dic["names"][0]) == 1 + and dic["titles"][k] == "0" + ): + dic["axis"].flat[k].set_title(f"{dic['tnrst'][dic['restart'][t]]} days") + if k == 0 and dic["suptitle"] != "0": + if dic["diff"]: + dic["fig"].suptitle(f"{dic['deckn']}-{dic['deckd']}") + else: + dic["fig"].suptitle(f"{dic['deckn']}") + elif dic["rm"][3] == 0 and dic["titles"][k] == "0": + if dic["diff"]: + dic["axis"].flat[k].set_title( + f"{dic['deckn']}-{dic['deckd']}" + + dic["tslide"] + + dic["dtitle"] + + extra + + time + ) + else: + dic["axis"].flat[k].set_title( + name + dic["tslide"] + dic["dtitle"] + extra + time + ) + elif dic["subfigs"][0] and len(dic["names"][0]) > 1: + if k == 0 and dic["suptitle"] != "0": + dic["fig"].suptitle(f"{dic['tnrst'][dic['restart'][t]]} days") + if name == "grid" and dic["rm"][3] == 0 and dic["titles"][k] == "0": + dic["axis"].flat[k].set_title( f"Grid = [{dic['nx']},{dic['ny']},{dic['nz']}], " + f"Total no. active cells = {max(dic['actind'])+1}" ) - if dic["titles"] != "" and dic["rm"][3] == 0: - axis.set_title(dic["titles"]) - if dic["slide"][2] == -2: - axis.invert_yaxis() - if len(dic["xlim"]) > 1 and dic["rm"][1] == 0: - axis.set_xlim([float(dic["xlim"][0][1:]), float(dic["xlim"][1][:-1])]) + if dic["titles"][k] != "0" and dic["rm"][3] == 0: + dic["axis"].flat[k].set_title(dic["titles"][k]) + if dic["slide"][2] == -2 and not dic["axis"].flat[k].yaxis_inverted(): + dic["axis"].flat[k].invert_yaxis() + if len(dic["xlim"][n]) > 1 and dic["rm"][1] == 0: + dic["axis"].flat[k].set_xlim( + [float(dic["xlim"][n][0][1:]), float(dic["xlim"][n][1][:-1])] + ) xlabels = np.linspace( - float(dic["xlim"][0][1:]), - float(dic["xlim"][1][:-1]), - dic["xlnum"], + float(dic["xlim"][k][0][1:]), + float(dic["xlim"][k][1][:-1]), + int(dic["xlnum"][n]), ) else: xlabels = np.linspace( min(min(dic["xc"])) * dic["xskl"], max(max(dic["xc"])) * dic["xskl"], - dic["xlnum"], + int(dic["xlnum"][n]), + ) + if dic["xformat"][n] and dic["rm"][1] == 0: + func = "f'{x:" + dic["xformat"][n] + "}'" + dic["axis"].flat[k].set_xticks( + [float(eval(func)) / dic["xskl"] for x in xlabels] ) - 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]) + dic["axis"].flat[k].set_xticklabels([eval(func) for x in xlabels]) elif dic["rm"][1] == 0: - axis.set_xticks(xlabels / dic["xskl"]) + dic["axis"].flat[k].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])]) + dic["axis"].flat[k].set_xticklabels(xlabels) + if len(dic["ylim"][n]) > 1 and dic["rm"][0] == 0: + dic["axis"].flat[k].set_ylim( + [float(dic["ylim"][n][0][1:]), float(dic["ylim"][n][1][:-1])] + ) ylabels = np.linspace( - float(dic["ylim"][0][1:]), - float(dic["ylim"][1][:-1]), - dic["ylnum"], + float(dic["ylim"][n][0][1:]), + float(dic["ylim"][n][1][:-1]), + int(dic["ylnum"][n]), ) else: ylabels = np.linspace( min(min(dic["yc"])) * dic["yskl"], max(max(dic["yc"])) * dic["yskl"], - dic["ylnum"], + int(dic["ylnum"][n]), + ) + if dic["yformat"][n] and dic["rm"][0] == 0: + func = "f'{y:" + dic["yformat"][n] + "}'" + dic["axis"].flat[k].set_yticks( + [float(eval(func)) / dic["yskl"] for y in ylabels] ) - 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]) + dic["axis"].flat[k].set_yticklabels([eval(func) for y in ylabels]) elif dic["rm"][0] == 0: - axis.set_yticks(ylabels / dic["yskl"]) + dic["axis"].flat[k].set_yticks(ylabels / dic["yskl"]) if dic["yskl"] != 1: - axis.set_yticklabels(ylabels) + dic["axis"].flat[k].set_yticklabels(ylabels) -def handle_well_or_grid(dic, fig, imag, divider, vect): +def handle_well_or_grid(dic, imag, divider, vect): """ Method to create the 2d maps using pcolormesh Args: dic (dict): Global dictionary\n - fig (class): Figure object\n imag (class): Actual plot object\n divider (class): Object for the color bar axis\n vect (array): Floats for the labels in the color bar Returns: - fig (class): Modified figure object\n plt (class): Modified plotting object\n """ - fig.colorbar( + dic["fig"].colorbar( imag, cax=divider.append_axes("right", size="0%", pad=0.05), orientation="vertical", diff --git a/tests/test_convert_to_vtk.py b/tests/test_convert_to_vtk.py index 5218161..c650185 100644 --- a/tests/test_convert_to_vtk.py +++ b/tests/test_convert_to_vtk.py @@ -28,4 +28,5 @@ def test_convert_to_vtk(): ) assert os.path.exists(f"{cwd}/examples/SPE11B-GRID.vtu") assert os.path.exists(f"{cwd}/examples/SPE11B-0005.vtu") + assert os.path.exists(f"{cwd}/examples/SPE11B.pvd") os.chdir(cwd) diff --git a/tests/test_difference.py b/tests/test_difference.py index b174dba..2c662f6 100644 --- a/tests/test_difference.py +++ b/tests/test_difference.py @@ -9,8 +9,8 @@ def test_difference(): cwd = os.getcwd() os.chdir(f"{os.getcwd()}/examples") subprocess.run( - ["plopm", "-i", "SPE11B,SPE11B", "-o", ".", "-v", "rsw"], + ["plopm", "-i", "SPE11B", "-o", ".", "-v", "rsw", "-diff", "SPE11B"], check=True, ) - assert os.path.exists(f"{cwd}/examples/rsw_*,1,*.png") + assert os.path.exists(f"{cwd}/examples/spe11b_rsw_*,1,*_t5.png") os.chdir(cwd) diff --git a/tests/test_dynamic.py b/tests/test_dynamic.py index 36a64d3..333e29b 100644 --- a/tests/test_dynamic.py +++ b/tests/test_dynamic.py @@ -21,10 +21,14 @@ def test_dynamic(): ",1,", "-r", "-1", - "-l", - "[-]", + "-clabel", + "gas saturation [-]", + "-f", + "8", + "-remove", + "0,0,0,1", ], check=True, ) - assert os.path.exists(f"{cwd}/examples/sgas_*,1,*.png") + assert os.path.exists(f"{cwd}/examples/spe11b_sgas_*,1,*_t5.png") os.chdir(cwd) diff --git a/tests/test_generic_deck.py b/tests/test_generic_deck.py index ec6c28d..4a5492f 100644 --- a/tests/test_generic_deck.py +++ b/tests/test_generic_deck.py @@ -37,12 +37,29 @@ def test_generic_deck(): os.system( "flow SPE10_MODEL2.DATA --parsing-strictness=low --enable-dry-run=true & wait\n" ) - for slide, name, nslide in zip( - ["4,,", ",8,", ",,20"], ["poro", "porv", "permx"], ["4,*,*", "*,8,*", "*,*,20"] + for slide, name, nslide, logs in zip( + ["4,,", ",8,", ",,20"], + ["poro", "porv", "permx"], + ["4,*,*", "*,8,*", "*,*,20"], + ["0", "0", "1"], ): subprocess.run( - ["plopm", "-i", "SPE10_MODEL2", "-s", slide, "-u", "opm"], + [ + "plopm", + "-i", + "SPE10_MODEL2", + "-v", + name, + "-s", + slide, + "-u", + "resdata", + "-log", + logs, + ], check=True, ) - assert os.path.exists(f"{cwd}/tests/generic_deck/{name}_{nslide}.png") + assert os.path.exists( + f"{cwd}/tests/generic_deck/spe10_model2_{name}_{nslide}_t0.png" + ) os.chdir(cwd) diff --git a/tests/test_gif.py b/tests/test_gif.py new file mode 100644 index 0000000..12efed9 --- /dev/null +++ b/tests/test_gif.py @@ -0,0 +1,34 @@ +"""Test the mask, gid, and subplot functionality""" + +import os +import subprocess + + +def test_difference(): + """See examples/SPE11B""" + cwd = os.getcwd() + os.chdir(f"{os.getcwd()}/examples") + subprocess.run( + [ + "plopm", + "-v", + "xco2l", + "-i", + "SPE11B", + "-m", + "gif", + "-mask", + "satnum", + "-r", + "0,5", + "-interval", + "1000", + "-loop", + "1", + "-d", + "8,5", + ], + check=True, + ) + assert os.path.exists(f"{cwd}/examples/spe11b_xco2l.gif") + os.chdir(cwd) diff --git a/tests/test_static.py b/tests/test_static.py index 589a7ff..5f277f6 100755 --- a/tests/test_static.py +++ b/tests/test_static.py @@ -9,6 +9,6 @@ def test_static(): cwd = os.getcwd() os.chdir(f"{os.getcwd()}/examples") main() - for name in ["porv", "poro", "permx", "satnum", "fipnum"]: - assert os.path.exists(f"{cwd}/examples/{name}_*,1,*.png") + for name in ["porv", "poro", "permx", "permz", "satnum", "fipnum"]: + assert os.path.exists(f"{cwd}/examples/spe11b_{name}_*,1,*_t5.png") os.chdir(cwd) diff --git a/tests/test_summary.py b/tests/test_summary.py index 4b94bab..e66e831 100644 --- a/tests/test_summary.py +++ b/tests/test_summary.py @@ -13,4 +13,9 @@ def test_summary(): check=True, ) assert os.path.exists(f"{cwd}/examples/fgip.png") + os.system( + "plopm -i 'SPE11B SPE11B' -v 'fgip,fgipm,RGIP:3 / 2' " + "-loc empty,empty,empty,center -subfigs 2,2 -save subfigs_summary -d 6,5" + ) + assert os.path.exists(f"{cwd}/examples/subfigs_summary.png") os.chdir(cwd) diff --git a/tests/test_wells.py b/tests/test_wells.py deleted file mode 100644 index 022cff8..0000000 --- a/tests/test_wells.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Test the summary functionality""" - -import os -import subprocess - - -def test_wells(): - """See tests/generic_deck""" - cwd = os.getcwd() - os.chdir(f"{cwd}/tests/generic_deck") - subprocess.run( - ["plopm", "-i", "SPE10_MODEL2", "-o", ".", "-w", "1"], - check=True, - ) - assert os.path.exists(f"{cwd}/tests/generic_deck/wells_*,1,*.png") - os.chdir(cwd) diff --git a/tests/test_wells_grid.py b/tests/test_wells_grid.py new file mode 100644 index 0000000..8a4ef71 --- /dev/null +++ b/tests/test_wells_grid.py @@ -0,0 +1,19 @@ +"""Test the grid and wells functionality""" + +import os +import subprocess + + +def test_wells_grid(): + """See tests/generic_deck""" + cwd = os.getcwd() + os.chdir(f"{cwd}/tests/generic_deck") + for name in ["grid", "wells"]: + subprocess.run( + ["plopm", "-i", "SPE10_MODEL2", "-o", ".", "-v", name], + check=True, + ) + assert os.path.exists( + f"{cwd}/tests/generic_deck/spe10_model2_{name}_*,1,*_t0.png" + ) + os.chdir(cwd)