diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 00000000..d310e7df --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,72 @@ +name: Tests for PROTEUS + +on: + push: + branches: + - master + pull_request: + branches: + - master + types: + - opened + - reopened + - synchronize + - ready_for_review + workflow_dispatch: + +jobs: + test: + if: github.event.pull_request.draft == false + name: Run Coverage and Tests + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10'] + + steps: + - uses: actions/checkout@v3 + with: + submodules: 'true' + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - uses: actions/cache@v3 + id: cache-virtualenv + with: + path: ${{ env.pythonLocation }} + key: ${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }} + + - name: Install dependencies + if: steps.cache-virtualenv.outputs.cache-hit != 'true' + run: | + python -m pip install -e .[develop] + + - name: Test with pytest + run: | + coverage run -m pytest + + - name: Report coverage + run: | + coverage json + export TOTAL=$(python -c "import json;print(json.load(open('coverage.json'))['totals']['percent_covered_display'])") + echo "total=$TOTAL" >> $GITHUB_ENV + echo "### Total coverage: ${TOTAL}%" >> $GITHUB_STEP_SUMMARY + echo $'\n```' >> $GITHUB_STEP_SUMMARY + coverage report >> $GITHUB_STEP_SUMMARY + echo $'\n```' >> $GITHUB_STEP_SUMMARY + + - name: Make coverage badge + if: ${{ github.ref == 'refs/heads/master' && matrix.python-version == '3.10' }} + uses: schneegans/dynamic-badges-action@v1.7.0 + with: + auth: ${{ secrets.GIST_TOKEN }} + gistID: b4ee7dab92e20644bcb3a5ad09f71165 + filename: covbadge.svg + label: Coverage + message: ${{ env.total }}% + minColorRange: 50 + maxColorRange: 90 + valColorRange: ${{ env.total }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ec5c2be..bcd30ae4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ git clone https://github.com/FormingWorlds/PROTEUS proteus Install using `virtualenv`: ```console -cd gemdat +cd proteus python3 -m venv .venv source .venv/bin/activate python3 -m pip install -e .[develop] @@ -28,6 +28,23 @@ conda activate proteus pip install -e .[develop] ``` +### Running tests + +PROTEUS uses [pytest](https://docs.pytest.org/en/latest/) to run the tests. +You can run the tests for yourself using: + +```console +pytest +``` + +To check coverage: + +```console +coverage run -m pytest +coverage report # to output to terminal +coverage html # to generate html report +``` + ### Building the documentation The documentation is written in [markdown](https://www.markdownguide.org/basic-syntax/), and uses [mkdocs](https://www.mkdocs.org/) to generate the pages. diff --git a/README.md b/README.md index 89b3e202..c9ddd73f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -[![Documentation Status](https://readthedocs.org/projects/fwl-proteus/badge/?version=latest)](https://fwl-proteus.readthedocs.io/en/latest/?badge=latest) +[![Tests for PROTEUS](https://github.com/FormingWorlds/actions/workflows/tests.yaml/badge.svg)](https://github.com/FormingWorlds/actions/workflows/tests.yaml) +![Coverage](https://gist.githubusercontent.com/stefsmeets/b4ee7dab92e20644bcb3a5ad09f71165/raw/covbadge.svg) +[![Documentation Status](https://readthedocs.org/projects/fwl-proteus/badge/?version=latest)](https://fwl-proteus.readthedocs.io/en/latest/?badge=latest) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![PROTEUS banner](https://raw.githubusercontent.com/FormingWorlds/PROTEUS/master/docs/images/PROTEUS_white.png#gh-light-mode-only) @@ -9,17 +11,17 @@ **PROTEUS** is a Python framework that simulates the coupled evolution of the atmospheres and interiors of rocky planets. -## Installation instructions +## Installation instructions Click [here](https://fwl-proteus.readthedocs.io/en/latest/installation.html) for steps and troubleshooting advice. ## Run instructions -Only attempt to run PROTEUS after you have followed all of the installation instructions. -If using a fresh shell, it is necessary to perform the following steps: -1. `conda activate proteus` (if using Anaconda/Miniconda) -2. `source PROTEUS.env` -Then you can start the model by running: `proteus.py`. See the ReadTheDocs pages for more information. +Only attempt to run PROTEUS after you have followed all of the installation instructions. +If using a fresh shell, it is necessary to perform the following steps: +1. `conda activate proteus` (if using Anaconda/Miniconda) +2. `source PROTEUS.env` +Then you can start the model by running: `start_proteus.py`. See the ReadTheDocs pages for more information. ## Updating the code @@ -29,7 +31,7 @@ Run `git submodule update --recursive --remote` | Name | Email address | | - | - | -Tim Lichtenberg | tim.lichtenberg[at]rug.nl | +Tim Lichtenberg | tim.lichtenberg[at]rug.nl | Harrison Nicholls | harrison.nicholls[at]physics.ox.ac.uk | Laurent Soucasse | l.soucasse[at]esciencecenter.nl | Stef Smeets | s.smeets[at]esciencecenter.nl | @@ -45,12 +47,13 @@ Hamish Innes | hamish.innes[at]fu-berlin.de | | Object | Description | | - | - | -| `proteus.py` | Main PROTEUS Python script | +| `start_proteus.py` | Main PROTEUS Python script | | `README.md` | Overview file | -| `pyproject.toml` | Documentation file | +| `pyproject.toml` | Project configuration file | | `CODE_OF_CONDUCT.md` | Project code of conduct | | `LICENSE.txt` | Project license | -| `JANUS/` | Submodule JANUS | +| `src/proteus` | Source code for PROTEUS | +| `JANUS/` | Submodule JANUS | | `SPIDER/` | Submodule SPIDER | | `VULCAN/` | Submodule VULCAN | | `Mors/` | Submodule Mors | @@ -58,5 +61,5 @@ Hamish Innes | hamish.innes[at]fu-berlin.de | | `plot/` | Code used for plotting results | | `output/` | Output folder with subfolders for each model run | | `input/` | Input folder (e.g. stellar spectra, example configs) | -| `docs/` | Documentation source files | -| `examples/` | Example cases that the model should be able to reproduce | +| `docs/` | Documentation source files | +| `examples/` | Example cases that the model should be able to reproduce | diff --git a/docs/usage.md b/docs/usage.md index 779089b8..9c97d9b6 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -5,7 +5,7 @@ You can directly run PROTEUS using the Python command: ```console -python proteus.py --cfg [cfgfile] +python start_proteus.py --cfg [cfgfile] ``` Where `[cfgfile]` is the path to the required configuration file. If @@ -49,23 +49,23 @@ Evolution model to use for star #### **star_rot_percentile** -The percentile used to find rotation rate of star from a distribution when the Mors evolution model is selected. +The percentile used to find rotation rate of star from a distribution when the Mors evolution model is selected. - Deprecated: False -- Type: Float +- Type: Float - Domain: 0 to 100. #### **star_mass** -Mass of the host star, in units of solar masses. +Mass of the host star, in units of solar masses. - Deprecated: False -- Type: Float +- Type: Float - Domain: Valid range depends on the stellar model used. For the Mors model, it should be between 0.1 and 1.25 solar masses. Values outside of the valid range will be clipped. #### **star_radius_modern** -Assumed radius of the host star as observed today, in units of solar radii. +Assumed radius of the host star as observed today, in units of solar radii. - Deprecated: False - Type: Float @@ -73,7 +73,7 @@ Assumed radius of the host star as observed today, in units of solar radii. #### **star_luminosity_modern** -Assumed luminosity of the host star as observed today, in units of solar luminosities. +Assumed luminosity of the host star as observed today, in units of solar luminosities. - Deprecated: False - Type: Float @@ -81,7 +81,7 @@ Assumed luminosity of the host star as observed today, in units of solar luminos #### **star_temperature_modern** -Assumed temperature of the host star as observed today, in units of kelvin. +Assumed temperature of the host star as observed today, in units of kelvin. - Deprecated: False - Type: Float @@ -89,7 +89,7 @@ Assumed temperature of the host star as observed today, in units of kelvin. #### **star_age_modern** -Estimated age of the host star as observed today, in units of years. +Estimated age of the host star as observed today, in units of years. - Deprecated: False - Type: Float @@ -97,7 +97,7 @@ Estimated age of the host star as observed today, in units of years. #### **star_rot_pctle** -Rotation rate percentile for the star, relative to other stars of the same mass. +Rotation rate percentile for the star, relative to other stars of the same mass. - Deprecated: False - Type: Float @@ -105,7 +105,7 @@ Rotation rate percentile for the star, relative to other stars of the same mass. #### **star_spectrum** -The spectrum of the host star as observed today. These files may be obtained using the ``GetStellarSpectrum`` tool. +The spectrum of the host star as observed today. These files may be obtained using the ``GetStellarSpectrum`` tool. - Deprecated: False - Type: String @@ -113,7 +113,7 @@ The spectrum of the host star as observed today. These files may be obtained usi #### **mean_distance** -Distance between the planet and its host star, in units of AU. +Distance between the planet and its host star, in units of AU. - Deprecated: False - Type: Float @@ -125,19 +125,19 @@ Mass of the planet, in units of Earth mass. - Deprecated: False - Type: Float -- Domain: Greater than zero. +- Domain: Greater than zero. #### **radius** -Radius of the planet at the surface, in units of Earth radius. +Radius of the planet at the surface, in units of Earth radius. - Deprecated: False -- Type: Float +- Type: Float - Domain: Greater than zero. #### **zenith_angle** -Angle of the incoming stellar radiation relative to the zenith, in units of degrees. +Angle of the incoming stellar radiation relative to the zenith, in units of degrees. - Deprecated: False - Type: Float @@ -145,7 +145,7 @@ Angle of the incoming stellar radiation relative to the zenith, in units of degr #### **asf_scalefactor** -Scale factor for the absorbed stellar flux (ASF), used in combination with ``zenith_angle``; see Cronin+14 for a discussion on this. +Scale factor for the absorbed stellar flux (ASF), used in combination with ``zenith_angle``; see Cronin+14 for a discussion on this. - Deprecated: False - Type: Float @@ -153,7 +153,7 @@ Scale factor for the absorbed stellar flux (ASF), used in combination with ``zen #### **albedo_s** -Albedo of the surface of the planet. +Albedo of the surface of the planet. - Deprecated: False - Type: Float @@ -161,7 +161,7 @@ Albedo of the surface of the planet. #### **albedo_pl** -Bond albedo of the planet. +Bond albedo of the planet. - Deprecated: False - Type: Float @@ -169,7 +169,7 @@ Bond albedo of the planet. #### **P_top** -Pressure at the top of the atmosphere, in units of bar. +Pressure at the top of the atmosphere, in units of bar. - Deprecated: False - Type: Float @@ -177,7 +177,7 @@ Pressure at the top of the atmosphere, in units of bar. #### **dir_output** -Name of the directory which will store the model output files. This includes data, plots, temporary files, and config information. +Name of the directory which will store the model output files. This includes data, plots, temporary files, and config information. - Deprecated: False - Type: String @@ -185,7 +185,7 @@ Name of the directory which will store the model output files. This includes dat #### **time_star** -Age of the star at the start of the simulation, in units of years. +Age of the star at the start of the simulation, in units of years. - Deprecated: False - Type: Float @@ -193,7 +193,7 @@ Age of the star at the start of the simulation, in units of years. #### **time_target** -Simulation time at which to stop the model, if it hasn't stopped already, in units of years. +Simulation time at which to stop the model, if it hasn't stopped already, in units of years. - Deprecated: False - Type: Float @@ -201,7 +201,7 @@ Simulation time at which to stop the model, if it hasn't stopped already, in uni #### **spectral_file** -Spectral file to use when running SOCRATES. +Spectral file to use when running SOCRATES. - Deprecated: False - Type: String @@ -209,7 +209,7 @@ Spectral file to use when running SOCRATES. #### **stellar_heating** -Flag to toggle stellar heating, including the downward shortwave stream. +Flag to toggle stellar heating, including the downward shortwave stream. - Deprecated: False - Type: Integer @@ -217,15 +217,15 @@ Flag to toggle stellar heating, including the downward shortwave stream. #### **plot_iterfreq** -Iteration frequency at which to make (or update) the plots. Plots can be generated during the simulation to follow its progress and status. +Iteration frequency at which to make (or update) the plots. Plots can be generated during the simulation to follow its progress and status. - Deprecated: False - Type: Integer -- Domain: 0: Do not make plots until the simulation is complete. Values greater than 0: make plots every ``plot_iterfreq`` iterations. +- Domain: 0: Do not make plots until the simulation is complete. Values greater than 0: make plots every ``plot_iterfreq`` iterations. #### **sspec_dt_update** -Time period at which to update the stellar spectrum using the stellar evolution model of choice, in units of years. +Time period at which to update the stellar spectrum using the stellar evolution model of choice, in units of years. - Deprecated: False - Type: Float @@ -233,7 +233,7 @@ Time period at which to update the stellar spectrum using the stellar evolution #### **sinst_dt_update** -Period at which to update the instellation flux and the stellar radius using the stellar evolution model of choice, in units of years. +Period at which to update the instellation flux and the stellar radius using the stellar evolution model of choice, in units of years. - Deprecated: False - Type: Float @@ -241,7 +241,7 @@ Period at which to update the instellation flux and the stellar radius using the #### **dt_maximum** -Maximum allowable time-step for the model, in units of years. +Maximum allowable time-step for the model, in units of years. - Deprecated: False - Type: Float @@ -249,7 +249,7 @@ Maximum allowable time-step for the model, in units of years. #### **dt_minimum** -Minimum allowable time-step for the model once the start-up phase has completed. Units of years. +Minimum allowable time-step for the model once the start-up phase has completed. Units of years. - Deprecated: False - Type: Float @@ -257,35 +257,35 @@ Minimum allowable time-step for the model once the start-up phase has completed. #### **dt_method** -Method to be used for calculating the time-step once the start-up phase has completed. Units of years. 'Proportional' sets ``dt`` to be some small fraction of the simulation time. 'Adapative' dynamically adjusts ``dt`` according to how rapidly the upward energy fluxes are changing. 'Maximum' sets ``dt`` to always be equal to ``dt_maximum``. +Method to be used for calculating the time-step once the start-up phase has completed. Units of years. 'Proportional' sets ``dt`` to be some small fraction of the simulation time. 'Adapative' dynamically adjusts ``dt`` according to how rapidly the upward energy fluxes are changing. 'Maximum' sets ``dt`` to always be equal to ``dt_maximum``. - Deprecated: False - Type: Integer -- Domain: 0: Proportional, 1: Adaptive, 2: Maximum. +- Domain: 0: Proportional, 1: Adaptive, 2: Maximum. #### **dt_propconst** -Proportionality constant when using ``dt_method=0``. Time step is set by ``dt = t/dt_propconst``, so larger values mean smaller steps. +Proportionality constant when using ``dt_method=0``. Time step is set by ``dt = t/dt_propconst``, so larger values mean smaller steps. - Deprecated: False - Type: Float -- Domain: Greater than zero. +- Domain: Greater than zero. #### **dt_atol** -Absolute tolerance on change in flux and melt fraction for each iteration. +Absolute tolerance on change in flux and melt fraction for each iteration. - Deprecated: False - Type: Float -- Domain: Greater than zero. +- Domain: Greater than zero. #### **dt_rtol** -Relative tolerance on change in flux and melt fraction for each iteration. +Relative tolerance on change in flux and melt fraction for each iteration. - Deprecated: False - Type: Float -- Domain: Greater than zero. +- Domain: Greater than zero. #### **dt_initial** @@ -293,11 +293,11 @@ Intial step size when using ``dt_method=1``, years. - Deprecated: False - Type: Float -- Domain: Greater than zero. +- Domain: Greater than zero. #### **shallow_ocean_layer** -Legacy method for converging atmospheric and interior upward fluxes. +Legacy method for converging atmospheric and interior upward fluxes. - Deprecated: True - Type: Integer @@ -305,11 +305,11 @@ Legacy method for converging atmospheric and interior upward fluxes. #### **F_atm_bc** -Boundary condition to use for calculating `F_atm`. Can be set to either the top of the atmosphere or the bottom. +Boundary condition to use for calculating `F_atm`. Can be set to either the top of the atmosphere or the bottom. - Deprecated: False - Type: Integer -- Domain: 0: Top of atmosphere, 1: Bottom of atmosphere. +- Domain: 0: Top of atmosphere, 1: Bottom of atmosphere. #### **F_crit** @@ -317,7 +317,7 @@ Critical flux. Once the upward net flux at the top of the atmosphere drops below - Deprecated: False - Type: Float -- Domain: Greater than or equal to 0. Set to 0 to disable. +- Domain: Greater than or equal to 0. Set to 0 to disable. #### **escape_model** @@ -325,7 +325,7 @@ Escape model to be used. - Deprecated: False - Type: Integer -- Domain: 0: None, 1: ZEPHYRUS, 2: Dummy +- Domain: 0: None, 1: ZEPHYRUS, 2: Dummy #### **escape_stop** @@ -345,7 +345,7 @@ Bulk escape rate for dummy escape model [kg s-1] #### **prevent_warming** -Flag to ensure that the net upward energy flux is always positive, which prevents the star from causing net heating inside the planet. +Flag to ensure that the net upward energy flux is always positive, which prevents the star from causing net heating inside the planet. - Deprecated: False - Type: Integer @@ -353,7 +353,7 @@ Flag to ensure that the net upward energy flux is always positive, which prevent #### **atmosphere_model** -Atmosphere model used to set T(p) and T_surf. +Atmosphere model used to set T(p) and T_surf. - Deprecated: False - Type: Integer @@ -361,7 +361,7 @@ Atmosphere model used to set T(p) and T_surf. #### **atmosphere_surf_state** -Surface boundary condition; e.g. T_surf set by conductive heat transport. +Surface boundary condition; e.g. T_surf set by conductive heat transport. - Deprecated: False - Type: Integer @@ -373,7 +373,7 @@ Conductive skin thickness, parameterising a thin layer at the surface. - Deprecated: False - Type: Float -- Domain: Greater than zero, metres. +- Domain: Greater than zero, metres. #### **skin_k``** @@ -381,35 +381,35 @@ Conductive skin thermal conductivity. - Deprecated: False - Type: Float -- Domain: Greater than zero, [W m-1 K-1]. +- Domain: Greater than zero, [W m-1 K-1]. #### **atmosphere_nlev** -Number of atmosphere model levels, measured at cell-centres. +Number of atmosphere model levels, measured at cell-centres. - Deprecated: False -- Type: Integer +- Type: Integer - Domain: Greater than 15. #### **solid_stop** -Flag to toggle the solidification break condition. +Flag to toggle the solidification break condition. - Deprecated: False -- Type: Integer +- Type: Integer - Domain: 0: Disabled, 1: Enabled. #### **phi_crit** -Value used for solidification break condition; stop the model once the global melt fraction drops below this value. This indiciates that the planet has solidified. Only applies when ``solid_stop`` is enabled. +Value used for solidification break condition; stop the model once the global melt fraction drops below this value. This indiciates that the planet has solidified. Only applies when ``solid_stop`` is enabled. - Deprecated: False - Type: Float -- Domain: Values between zero and unity. +- Domain: Values between zero and unity. #### **steady_stop** -Flag to toggle the steady-state break condition. +Flag to toggle the steady-state break condition. - Deprecated: False - Type: Integer @@ -417,11 +417,11 @@ Flag to toggle the steady-state break condition. #### **steady_flux** -Steady-state break condition, requiring that ``F_atm < steady_flux``. +Steady-state break condition, requiring that ``F_atm < steady_flux``. - Deprecated: False - Type: Float -- Domain: Values between zero and unity. +- Domain: Values between zero and unity. #### **steady_dprel** @@ -429,27 +429,27 @@ Steady-state break condition, requiring that ``dphi/dt < steady_dprel``. - Deprecated: False - Type: Float -- Domain: Values between zero and unity. +- Domain: Values between zero and unity. #### **min_temperature** -Temperature floor. The temperature of the atmosphere is prevented from dropping below this value. Units of kelvin. +Temperature floor. The temperature of the atmosphere is prevented from dropping below this value. Units of kelvin. - Deprecated: False - Type: Float -- Domain: Greater than 0. +- Domain: Greater than 0. #### **max_temperature** -Temperature ceiling. The temperature of the atmosphere is prevented from reaching above this value. Units of kelvin. +Temperature ceiling. The temperature of the atmosphere is prevented from reaching above this value. Units of kelvin. - Deprecated: False - Type: Float -- Domain: Greater than ``min_temperature``. +- Domain: Greater than ``min_temperature``. #### **tropopause** -Model of tropopause to be used before, or in the absence of, a time-stepped solution to the temperature structure. 'None' means no tropopause is applied. 'Skin' means that the tropopause will be set to the radiative skin temperature. 'Flux' dynamically sets the tropopause based on the heating rate. +Model of tropopause to be used before, or in the absence of, a time-stepped solution to the temperature structure. 'None' means no tropopause is applied. 'Skin' means that the tropopause will be set to the radiative skin temperature. 'Flux' dynamically sets the tropopause based on the heating rate. - Deprecated: False - Type: Integer @@ -513,7 +513,7 @@ Mixing length parameterisation to use in SPIDER. Can be constant or variable wit #### **solver_tolerance** -Tolerance to provide to SPIDER when it calls its numerical solver. +Tolerance to provide to SPIDER when it calls its numerical solver. - Deprecated: False - Type: Float @@ -521,7 +521,7 @@ Tolerance to provide to SPIDER when it calls its numerical solver. #### **tsurf_poststep_change** -Maximum allowed change in surface temperature calculated by SPIDER before it quits, to hand back to the other modules. Units of kelvin. +Maximum allowed change in surface temperature calculated by SPIDER before it quits, to hand back to the other modules. Units of kelvin. - Deprecated: False - Type: Float @@ -529,7 +529,7 @@ Maximum allowed change in surface temperature calculated by SPIDER before it qui #### **tsurf_poststep_change_frac** -Maximum allowed relative change in surface temperature calculated by SPIDER before it quits, to hand back to the other modules. +Maximum allowed relative change in surface temperature calculated by SPIDER before it quits, to hand back to the other modules. - Deprecated: False - Type: Float @@ -537,11 +537,11 @@ Maximum allowed relative change in surface temperature calculated by SPIDER befo #### **planet_coresize** -Size of the planet's core as a fraction of its total interior radius. +Size of the planet's core as a fraction of its total interior radius. - Deprecated: False - Type: Float -- Domain: Between zero and unity, exclusive. +- Domain: Between zero and unity, exclusive. #### **ic_adiabat_entropy** @@ -561,7 +561,7 @@ Entropy gradient for intialising a SPIDER at the start of the run, in units of #### **F_atm** -Initial guess for net upward flux `F_atm`. +Initial guess for net upward flux `F_atm`. - Deprecated: False - Type: Float @@ -569,7 +569,7 @@ Initial guess for net upward flux `F_atm`. #### **fO2_shift_IW** -Oxygen fugacity of the interior, measured in log10 units relative to the iron-wustite buffer. Positive values are oxidising, negative are reducing. +Oxygen fugacity of the interior, measured in log10 units relative to the iron-wustite buffer. Positive values are oxidising, negative are reducing. - Deprecated: False - Type: Float @@ -577,7 +577,7 @@ Oxygen fugacity of the interior, measured in log10 units relative to the iron-wu #### **solvevol_use_params** -Flag to enable solving for initial partial pressures subject to interior parameters, rather than using provided initial pressures. +Flag to enable solving for initial partial pressures subject to interior parameters, rather than using provided initial pressures. - Deprecated: False - Type: Integer @@ -585,7 +585,7 @@ Flag to enable solving for initial partial pressures subject to interior paramet #### **Phi_global** -Initial guess for mantle melt fraction. +Initial guess for mantle melt fraction. - Deprecated: False - Type: Float @@ -593,7 +593,7 @@ Initial guess for mantle melt fraction. #### **CH_ratio** -Required total-planet C/H mass ratio. Used when ``solvevol_use_params == 1``. +Required total-planet C/H mass ratio. Used when ``solvevol_use_params == 1``. - Deprecated: False - Type: Float @@ -601,7 +601,7 @@ Required total-planet C/H mass ratio. Used when ``solvevol_use_params == 1``. #### **hydrogen_earth_oceans** -Total hydrogen inventory of the planet. Used when when ``solvevol_use_params == 1``. Units of Earth oceans equivalent. +Total hydrogen inventory of the planet. Used when when ``solvevol_use_params == 1``. Units of Earth oceans equivalent. - Deprecated: False - Type: Float @@ -609,15 +609,15 @@ Total hydrogen inventory of the planet. Used when when ``solvevol_use_params == #### **nitrogen_ppmw** -Nitrogen concentration. Used when ``solvevol_use_params == 1``. Parts per million of total mantle mass. +Nitrogen concentration. Used when ``solvevol_use_params == 1``. Parts per million of total mantle mass. - Deprecated: False - Type: Float -- Domain: Greater than zero. +- Domain: Greater than zero. #### **sulfur_ppmw** -Sulfur concentration. Used when ``solvevol_use_params == 1``. Parts per million of total mantle mass. +Sulfur concentration. Used when ``solvevol_use_params == 1``. Parts per million of total mantle mass. - Deprecated: False - Type: Float @@ -633,8 +633,8 @@ Flag to include X in the model. For some (H2O, CO2, N2, S2) this will always equ #### **X_initial_bar** -Initial partial pressure of X. Used when ``solvepp_enabled == 0``. +Initial partial pressure of X. Used when ``solvepp_enabled == 0``. - Deprecated: False - Type: Float -- Domain: Greater than zero. \ No newline at end of file +- Domain: Greater than zero. diff --git a/pyproject.toml b/pyproject.toml index 1adb507c..50971fdb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,3 +64,10 @@ docs = [ [tool.setuptools] package-dir = {"proteus" = "src/proteus" } include-package-data = true + +[tool.coverage.run] +branch = true +source = ["proteus"] + +[tool.pytest.ini_options] +testpaths = ["tests"] diff --git a/src/proteus/__init__.py b/src/proteus/__init__.py index e69de29b..c9f0c790 100644 --- a/src/proteus/__init__.py +++ b/src/proteus/__init__.py @@ -0,0 +1,2 @@ +def hello_world(): + print('hello world') diff --git a/proteus.py b/start_proteus.py similarity index 100% rename from proteus.py rename to start_proteus.py diff --git a/tests/test_proteus.py b/tests/test_proteus.py new file mode 100644 index 00000000..b845ad9e --- /dev/null +++ b/tests/test_proteus.py @@ -0,0 +1,4 @@ +from proteus import hello_world + +def test_hello_world(): + hello_world() diff --git a/tools/GridPROTEUS.py b/tools/GridPROTEUS.py index 2d2402c9..37830dd7 100755 --- a/tools/GridPROTEUS.py +++ b/tools/GridPROTEUS.py @@ -11,14 +11,14 @@ raise Exception("Environment is not activated or is setup incorrectly") -# Custom logger instance +# Custom logger instance def setup_logger(logpath:str="new.log",level=1,logterm=True): # https://stackoverflow.com/a/61457119 custom_logger = logging.getLogger() custom_logger.handlers.clear() - + if os.path.exists(logpath): os.remove(logpath) @@ -31,8 +31,8 @@ def setup_logger(logpath:str="new.log",level=1,logterm=True): case 2: level_code = logging.WARNING case 3: - level_code = logging.ERROR - case 4: + level_code = logging.ERROR + case 4: level_code = logging.CRITICAL # Add terminal output to logger @@ -58,8 +58,8 @@ def handle_exception(exc_type, exc_value, exc_traceback): return custom_logger.critical("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception - - return + + return # Object for handling the parameter grid @@ -74,15 +74,15 @@ def __init__(self, name:str, base_config_path:str, symlink_dir:str="_UNSET"): self.conf = str(base_config_path) if not os.path.exists(self.conf): raise Exception("Base config file '%s' does not exist!" % self.conf) - + self.symlink_dir = symlink_dir if self.symlink_dir == "": raise Exception("Symlinked directory is set to a blank path") - + # Paths self.outdir = os.path.abspath(self.outdir) self.tmpdir = os.path.abspath(self.tmpdir) - + # Remove old output location if os.path.exists(self.outdir): if os.path.islink(self.outdir): @@ -94,7 +94,7 @@ def __init__(self, name:str, base_config_path:str, symlink_dir:str="_UNSET"): raise Exception("Not emptying directory - it contains a Git repository!") time.sleep(2.0) shutil.rmtree(self.outdir) - + # Create new output location if (self.symlink_dir == "_UNSET"): # Not using symlink @@ -131,22 +131,22 @@ def __init__(self, name:str, base_config_path:str, symlink_dir:str="_UNSET"): self.dim_param = [] # Dimension parameter of interest ('_hyper' for hypervariables) # Dimension variables (incl hypervariables) - self.dim_avars = {} + self.dim_avars = {} # Flattened pgrid self.flat = [] # List of grid points, each is a dictionary self.size = 0 # Total size of grid - + # Add a new empty dimension to the pgrid def add_dimension(self,name:str): if name in self.dim_names: raise Exception("Dimension '%s' cannot be added twice" % name) - + log.info("Added new dimension '%s' " % name) self.dim_names.append(name) self.dim_param.append("_empty") self.dim_avars[name] = None - + def _get_idx(self,name:str): if name not in self.dim_names: raise Exception("Dimension '%s' is not initialised" % name) @@ -177,7 +177,7 @@ def set_dimension_direct(self,name:str,var:str,values:list): the_list = list(set(values)) # remove duplicates if not isinstance(values[0],str): # sort if numeric the_list = sorted(the_list) - self.dim_avars[name] = the_list + self.dim_avars[name] = the_list # Set a dimension to take hypervariables def set_dimension_hyper(self,name:str): @@ -189,7 +189,7 @@ def set_dimension_hyper(self,name:str): # Add a new hypervariable to a _hyper dimension # This allows multiple variables to be considered as one - # e.g. Earth and Mars are two cases of the 'planet' hypervariable, but + # e.g. Earth and Mars are two cases of the 'planet' hypervariable, but # each contains their own sub-variables like mass, radius, etc. def append_dimension_hyper(self,name:str,value:dict): idx = self._get_idx(name) @@ -205,7 +205,7 @@ def print_setup(self): log.info(" ") for name in self.dim_names: idx = self._get_idx(name) - + log.info(" -- dimension: %s" % name) log.info(" parameter: %s" % self.dim_param[idx]) log.info(" values : %s" % self.dim_avars[name]) @@ -226,10 +226,10 @@ def generate(self): # Validate if len(self.dim_avars) == 0: raise Exception("pgrid is empty") - + # Dimension count log.info(" %d dimensions" % len(self.dim_names)) - + # Calculate total pgrid size values = list(self.dim_avars.values()) self.size = 1 @@ -237,7 +237,7 @@ def generate(self): self.size *= len(v) log.info(" %d points expected" % self.size) - # Create flattened parameter grid + # Create flattened parameter grid flat_values = list(itertools.product(*values)) log.info(" created %d grid points" % len(flat_values)) @@ -288,7 +288,7 @@ def run(self,num_threads:int,test_run:bool=False): log.info(" %d " % i) time.sleep(1.0) log.info(" ") - + # Print more often if this is a test else: check_interval = 1.0 @@ -300,22 +300,22 @@ def run(self,num_threads:int,test_run:bool=False): # Loop over grid points to write config files log.info("Writing config files") - for i,gp in enumerate(self.flat): + for i,gp in enumerate(self.flat): cfgfile = os.path.join(self.tmpdir,"case_%05d.cfg" % i) gp["dir_output"] = self.name+"/case_%05d"%i # Create config file for this case with open(cfgfile, 'w') as hdl: - + hdl.write("# GridPROTEUS config file \n") hdl.write("# gp_index = %d \n" % i) # Write lines for l in base_config: - if ('=' not in l): + if ('=' not in l): continue - + l = l.split('#')[0] key = l.split('=')[0].strip() @@ -329,13 +329,13 @@ def run(self,num_threads:int,test_run:bool=False): # Ensure data is written to disk hdl.flush() - os.fsync(hdl.fileno()) + os.fsync(hdl.fileno()) gc.collect() # Thread targget def _thread_target(cfg_path): - proteus_py = os.path.join(PROTEUS_DIR,"proteus.py") + proteus_py = os.path.join(PROTEUS_DIR,"start_proteus.py") if test_run: command = ['/bin/echo','Dummmy output. Config file is at "' + cfg_path + '"'] else: @@ -350,7 +350,7 @@ def _thread_target(cfg_path): cfg_path = os.path.join(self.tmpdir,"case_%05d.cfg" % i) # Check cfg exists cfgexists = False - waitfor = 4.0 + waitfor = 4.0 for _ in range(int(waitfor*100)): # do n=100*wait_for checks time.sleep(0.01) if os.path.exists(cfgfile): @@ -405,9 +405,9 @@ def _thread_target(cfg_path): # Done? if np.count_nonzero(status == 2) == self.size: - done = True + done = True log.info("Grid is complete") - break + break # Start new? start_new = np.count_nonzero(status == 1) < num_threads @@ -416,9 +416,9 @@ def _thread_target(cfg_path): if status[i] == 0: status[i] = 1 start_new = False - threads[i].start() + threads[i].start() break - + # Short sleeps while doing initial dispatch if step < num_threads: time.sleep(2.0) @@ -449,7 +449,7 @@ def _thread_target(cfg_path): log.warning("Case %05d has status=running but it is not alive. Setting status=died."%i) with open(status_path,'x') as hdl: hdl.write("25\n") - hdl.write("Error (died)\n") + hdl.write("Error (died)\n") time_end = datetime.now() log.info("All processes finished at: "+str(time_end.strftime('%Y-%m-%d_%H:%M:%S'))) @@ -486,7 +486,7 @@ def _thread_target(cfg_path): pg.add_dimension("Redox state") pg.set_dimension_direct("Redox state", "fO2_shift_IW", [-2, 0, 2, 4]) - + # ----- # Print state of parameter grid # ----- diff --git a/tools/RunPROTEUS.sh b/tools/RunPROTEUS.sh index 0cb961c0..0c848fae 100755 --- a/tools/RunPROTEUS.sh +++ b/tools/RunPROTEUS.sh @@ -8,25 +8,25 @@ echo "Start RunPROTEUS" if [[ -z $PROTEUS_DIR ]]; then echo "ERROR: Required global variables have not been set" echo " Did you source the env file yet?" - sleep 1.0 + sleep 1.0 exit 1 fi -if [[ -z $RAD_DIR ]]; then +if [[ -z $RAD_DIR ]]; then echo "ERROR: The RAD_DIR variable has not been set" - sleep 1.0 - exit 1 + sleep 1.0 + exit 1 fi # Check if the required arguments have been passed if [ -z "$4" ] then - echo "ERROR: One of the arguments was not provided" + echo "ERROR: One of the arguments was not provided" echo " First argument: config file (string)" echo " Second argument: screen alias (string)" echo " Third argument: resume? (y or n)" echo " Fourth argument: detach? (y or n)" - sleep 1.0 + sleep 1.0 exit 1 else # Set variables @@ -34,7 +34,7 @@ else ALIAS="$2" RESUME=$(echo "$3" | tr -d ' ' | tr '[:upper:]' '[:lower:]' | cut -c1-1) # strip spaces, covert to lowercase, get first char DETACH=$(echo "$4" | tr -d ' ' | tr '[:upper:]' '[:lower:]' | cut -c1-1) # strip spaces, covert to lowercase, get first char - EXECUTABLE="$PROTEUS_DIR/proteus.py" + EXECUTABLE="$PROTEUS_DIR/start_proteus.py" # Clear dead screens screen -wipe > /dev/null @@ -47,7 +47,7 @@ else exit 1 fi - # Setup paths + # Setup paths echo " Config path = '$CFGFILE' " echo " Screen alias = '$ALIAS' " @@ -55,16 +55,16 @@ else echo " Dispatching screen session..." COMMAND="python $EXECUTABLE --cfg $CFGFILE" - if [[ "$RESUME" == "y" ]]; then + if [[ "$RESUME" == "y" ]]; then COMMAND="$COMMAND --resume" - fi + fi - if [[ "$DETACH" == "y" ]]; then - screen -S $ALIAS -d -m bash -c "$COMMAND" - else - screen -S $ALIAS bash -c "$COMMAND" + if [[ "$DETACH" == "y" ]]; then + screen -S $ALIAS -d -m bash -c "$COMMAND" + else + screen -S $ALIAS bash -c "$COMMAND" fi - + # Done? echo " (detached)" exit 0