├── .github ├── ISSUE_TEMPLATE └── workflows │ ├── pypi.yml │ └── test.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .travis.yml ├── COPYING.txt ├── MANIFEST.in ├── Makefile ├── README.md ├── examples ├── abun_advanced.png ├── abun_basic.png ├── abun_bya.png ├── abun_bypandn.png ├── abundances.py ├── dynamo.py ├── dynamo1.png ├── dynamo2.png ├── kip.png ├── kip_age.png ├── kip_prof.png ├── plotKip.py ├── plotTRho.py └── trho.png ├── mesaPlot ├── __init__.py ├── debug.py ├── file_reader.py ├── plot.py └── version.py ├── pyproject.toml ├── setup.py ├── tests ├── LOGS │ ├── history.data │ ├── profile1.data │ ├── profile17.data │ ├── profile2.data │ ├── profile3.data │ ├── profile4.data │ ├── profile5.data │ ├── profile6.data │ └── profiles.index ├── __init__.py ├── test_mesaplot.py └── work │ ├── history_columns.list │ ├── inlist │ ├── inlist_pgstar │ ├── inlist_project │ └── profile_columns.list └── tox.ini /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | ## Expected Behavior 2 | 3 | 4 | ## Actual Behavior 5 | 6 | 7 | ## Steps to Reproduce the Problem 8 | 9 | 1. 10 | 1. 11 | 1. 12 | 13 | ## Specifications 14 | 15 | - Version: 16 | - Platform: 17 | 18 | ## Link to history/profile file(s) 19 | 20 | 21 | -------------------------------------------------------------------------------- /.github/workflows/pypi.yml: -------------------------------------------------------------------------------- 1 | name: Publish to pypi 2 | on: 3 | push: 4 | tags: 5 | - 'v*' 6 | 7 | 8 | jobs: 9 | pypi-publish: 10 | name: Upload release to PyPI 11 | runs-on: ubuntu-latest 12 | environment: 13 | name: pypi 14 | url: https://pypi.org/project/mesaPlot/ 15 | permissions: 16 | id-token: write # IMPORTANT: this permission is mandatory for trusted publishing 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | persist-credentials: false 21 | 22 | - name: Set up Python 23 | uses: actions/setup-python@v5 24 | with: 25 | python-version: '3.x' 26 | 27 | - name: Install dependencies 28 | run: | 29 | python -m pip install --upgrade pip 30 | python -m pip install build wheel pytest 31 | - name: Build a binary wheel and a source tarball 32 | run: >- 33 | python3 -m build 34 | - name: Test 35 | run: | 36 | python -m pip install dist/mesaplot*.tar.gz 37 | python -m pytest 38 | 39 | - name: Publish package distributions to PyPI 40 | uses: pypa/gh-action-pypi-publish@release/v1 41 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | permissions: {} 8 | 9 | jobs: 10 | test: 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ubuntu-latest, windows-latest] 15 | python-version: ['3.9','3.10','3.11','3.12'] 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | with: 20 | persist-credentials: false 21 | 22 | - name: Set up Python ${{ matrix.python-version }} 23 | uses: actions/setup-python@v5 24 | with: 25 | python-version: ${{ matrix.python-version }} 26 | cache: 'pip' 27 | 28 | - name: Install dependencies 29 | run: | 30 | python -m pip install --upgrade pip 31 | python -m pip install build wheel pytest 32 | 33 | - name: Build 34 | run: python -m pip install . 35 | 36 | - name: Test 37 | run: python -m pytest -v -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg* 25 | 26 | # Cached data 27 | *.pickle 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | 47 | # Translations 48 | *.mo 49 | *.pot 50 | 51 | # Django stuff: 52 | *.log 53 | 54 | # Sphinx documentation 55 | docs/_build/ 56 | 57 | # PyBuilder 58 | target/ 59 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | fail_fast: true 2 | repos: 3 | - repo: https://github.com/psf/black 4 | rev: 22.3.0 5 | hooks: 6 | - id: black 7 | language_version: python3 # Should be a command that runs python3.6+ 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | dist: xenial 3 | python: 4 | - "3.6" 5 | - "3.7" 6 | - "3.8" 7 | - "3.9" 8 | services: 9 | - xvfb 10 | # command to install dependencies 11 | install: 12 | - pip install -r requirements.txt 13 | - pip install -e .[dev] 14 | - python setup.py install 15 | # command to run tests 16 | script: 17 | - pytest 18 | cache: 19 | directories: 20 | # Cache for pip, mostly to speed up matplotlib install 21 | - $HOME/.cache/pip 22 | -------------------------------------------------------------------------------- /COPYING.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | include README.md 3 | include COPYING.txt 4 | include setup.py 5 | recursive-include mesaPlot *.py -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | python3 setup.py install --user 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![DOI](https://zenodo.org/badge/30720868.svg)](https://zenodo.org/badge/latestdoi/30720868) 4 | 5 | 6 | # mesaplot 7 | Library of python routines to read MESA ouput files and plot MESA quantites 8 | 9 | ## Installation instructions: 10 | git clone the repo then call 11 | ````bash 12 | python3 setup.py install 13 | ```` 14 | 15 | Depending on choice of python version, --user can also be passed to install locally 16 | 17 | ````bash 18 | make 19 | ```` 20 | 21 | Can be called as well 22 | 23 | ## Testing 24 | 25 | ````bash 26 | pytest 27 | ```` 28 | 29 | To run tests for current python version 30 | 31 | ````tox 32 | tox 33 | ```` 34 | 35 | will run tests for several python versions 36 | 37 | ## Contributing 38 | 39 | Bug reports should go to githubs issue tracker. 40 | 41 | Requests for new features should also got to the issue tracker. 42 | 43 | If you wish to submit your own fix/new feature please send a pull request. 44 | 45 | 46 | ## Reading data: 47 | 48 | ````python 49 | import mesaPlot as mp 50 | m=mp.MESA() 51 | ```` 52 | 53 | Now m contains all the useful stuff 54 | 55 | 56 | ### History files 57 | ````python 58 | m.loadHistory() 59 | ```` 60 | This loads up the history file data by default it will look for LOGS/history.data. 61 | But if you have a different folder to look at then you can either 62 | 63 | ````python 64 | m.log_fold='new_folder/LOGS/' 65 | m.loadHistory() 66 | ```` 67 | or 68 | ````python 69 | m.loadHistory(f='new_folder/LOGS/') 70 | ```` 71 | Note this will automatically clean the history data of retries, backups and restarts. To write that data back to disk 72 | ````python 73 | m.scrubHistory() 74 | ```` 75 | Which will create a file "LOGS/history.data.scrubbed" if you don't want that then: 76 | ````python 77 | m.scrubHistory(fileOut='newFile') 78 | ```` 79 | 80 | Data can be accessed as m.hist.data['COLUMN_NAME'] or m.hist.COLUMN_NAME. The second option is 81 | also tab completable. The header information is either m.hist.head['COLUMN_NAME'] or m.hist.COLUMN_NAME. 82 | 83 | ### Profile files 84 | To load a profile file its: 85 | ````python 86 | m.loadProfile() 87 | ```` 88 | Again you change the LOGS folder either with log_fold or f=. 89 | To choose which file to load, either: 90 | ````python 91 | m.loadProfile(num=MODEL_NUMBER) 92 | or 93 | m.loadProfile(prof=PROFILE_NUMBER) 94 | ```` 95 | Where MODEL_NUMBER is a MESA model number and PROFILE_NUMBER is the number in the profile file name. 96 | You can also set a mode 97 | ````python 98 | m.loadProfile(num=MODEL_NUMBER,mode='first|lower|upper|nearest') 99 | ```` 100 | This is for when the model you want isn't in the data. Either we load the first model, the model just before the one you want, the model just after the one you want or the nearest (above or below) the model you want. 101 | There are also two special model numbers 0 for first model and a negative number that counts backwards (-1 is the last model, -2 is last but one etc) 102 | 103 | Data can be accessed as m.prof.data['COLUMN_NAME'] or m.prof.COLUMN_NAME. The second option is 104 | also tab completable. The header information is either m.prof.head['COLUMN_NAME'] or m.prof.COLUMN_NAME. 105 | 106 | 107 | > **_NOTE:_** To speed up repeated readings of the LOG data, mesaPlot saves a 108 | binary version of the data (taking care to regenerate this file if the history/profile is updated). 109 | This binary file SHOULD NOT be depended upon for long term storage. The file format may change between 110 | versions and is not backward compatable. For long term storage allways keep the plain text history/profile file 111 | (possibly compressed to save space). 112 | 113 | 114 | 115 | ## Plotting 116 | 117 | Here we'll show the basics of plotting, there are more complex examples for each section. Commands will assume you are in a MESA work folder, such that the data is in a LOGS/ folder. 118 | 119 | 120 | ### History data 121 | 122 | ````python 123 | import mesaPlot as mp 124 | m=mp.MESA() 125 | p=mp.plot() 126 | m.loadHistory() 127 | p.plotHistory(m,xaxis='star_age',y1='log_center_T',y2='he_core_mass') 128 | ```` 129 | 130 | ### Profile data 131 | 132 | ````python 133 | import mesaPlot as mp 134 | m=mp.MESA() 135 | p=mp.plot() 136 | m.loadProfile(num=-1) 137 | p.plotProfile(m,xaxis='mass',y1='logT',y2='ye') 138 | ```` 139 | 140 | ### HR 141 | 142 | ````python 143 | import mesaPlot as mp 144 | m=mp.MESA() 145 | p=mp.plot() 146 | m.loadHistory() 147 | p.plotHR(m) 148 | ```` 149 | 150 | ### Kippenhan's 151 | 152 | Kippenhan plot with model number vs mass. Note all Kippenhan plots 153 | require your history file to have both mixing_regions X and burning_regions Y 154 | set in your history_columns.list file, where X and Y are integers that 155 | specify the maximum number of mixing/burning 156 | zones in your model, values around 20 will usually suffice. Models going to 157 | core collapse may want to increase this limit to 40. 158 | 159 | 160 | ````python 161 | import mesaPlot as mp 162 | m=mp.MESA() 163 | p=mp.plot() 164 | m.loadHistory() 165 | p.plotKip(m,show_mass_loc=True) 166 | ```` 167 | 168 | Kippenhan plot with star age vs mass 169 | ````python 170 | import mesaPlot as mp 171 | m=mp.MESA() 172 | p=mp.plot() 173 | m.loadHistory() 174 | p.plotKip2(m) 175 | ```` 176 | 177 | Generic kippenhan plotter 178 | ````python 179 | import mesaPlot as mp 180 | m=mp.MESA() 181 | p=mp.plot() 182 | m.loadHistory() 183 | p.plotKip3(m,show_mass_loc=True) 184 | ```` 185 | ![Kippenhan plotKip3 SAGB star](/examples/kip.png?raw=true "Kippenhan plot") 186 | 187 | New way of doing plotKip2 (star age vs mass) 188 | ````python 189 | import mesaPlot as mp 190 | m=mp.MESA() 191 | p=mp.plot() 192 | m.loadHistory() 193 | p.plotKip3(m,xaxis='star_age',age_lookback=True,age_log=True) 194 | ```` 195 | ![Kippenhan plotKip3 SAGB star 2](/examples/kip_age.png?raw=true "Kippenhan plot 2") 196 | 197 | Profile based kippenhans 198 | ````python 199 | import mesaPlot as mp 200 | 201 | m=mp.MESA() 202 | m.loadHistory() 203 | m.loadProfile(num=1) 204 | p=mp.plot() 205 | p.plotKip3(m,plot_type='profile',xaxis='model_number',yaxis='mass',zaxis='logRho',mod_min=1,mod_max=3000) 206 | ```` 207 | ![Kippenhan plotKip3 SAGB star 3](/examples/kip_prof.png?raw=true "Kippenhan plot 3") 208 | 209 | 210 | ### Abundances 211 | 212 | ````python 213 | import mesaPlot as mp 214 | m=mp.MESA() 215 | p=mp.plot() 216 | m.loadProfile(num=-1) 217 | p.plotAbun(m) 218 | ```` 219 | 220 | ![Basic abundance plot](/examples/abun_basic.png?raw=true "Abundance plot") 221 | 222 | ````python 223 | import mesaPlot as mp 224 | m=mp.MESA() 225 | p=mp.plot() 226 | m.loadProfile(num=-1) 227 | p.plotAbunByA(m) 228 | ```` 229 | 230 | ![Production plot](/examples/abun_bya.png?raw=true "Production plot") 231 | 232 | ````python 233 | import mesaPlot as mp 234 | m=mp.MESA() 235 | p=mp.plot() 236 | m.loadProfile(num=-1) 237 | m2=mp.MESA() 238 | m2.log_fold='../some/other/mesa/result' 239 | m2.loadprofile(num=-1) 240 | p.plotAbunByA(m,m2=m2) 241 | ```` 242 | 243 | ````python 244 | import mesaPlot as mp 245 | m=mp.MESA() 246 | p=mp.plot() 247 | p.set_solar('ag89') 248 | m.loadProfile(num=-1) 249 | #Plot the mass fractions relative to solar 250 | p.plotAbunByA(m,stable=True) 251 | ```` 252 | 253 | ````python 254 | import mesaPlot as mp 255 | m=mp.MESA() 256 | p=mp.plot() 257 | p.set_solar('ag89') 258 | m.loadProfile(num=-1) 259 | m2=mp.MESA() 260 | m2.log_fold='../some/other/mesa/result' 261 | m2.loadprofile(num=-1) 262 | #Plot the mass fractions relative to solar relative to 2nd model 263 | p.plotAbunByA(m,m2=m2,stable=True) 264 | ```` 265 | 266 | ````python 267 | import mesaPlot as mp 268 | m=mp.MESA() 269 | p=mp.plot() 270 | m.loadHistory() 271 | #Use the data in the history file at model_number==model 272 | p.plotAbunByA(m,plot_type='history',model=1000,prefix='log_center_') 273 | ```` 274 | 275 | 276 | ````python 277 | import mesaPlot as mp 278 | m=mp.MESA() 279 | p=mp.plot() 280 | p.set_solar('ag89') 281 | m.loadHistory() 282 | #Use the data in the history file, plotting relative to another model number after decaying the isotopes to thier stable versions 283 | p.plotAbunByA(m,plot_type='history',model=1000,model2=1,prefix='surface_',stable=True) 284 | ```` 285 | 286 | 287 | ````python 288 | import mesaPlot as mp 289 | m=mp.MESA() 290 | p=mp.plot() 291 | m.loadProfile(num=-1) 292 | p.plotAbunPAndN(m) 293 | ```` 294 | 295 | ![Nuclear abundances plot](/examples/abun_bypandn.png?raw=true "Nuclear chart") 296 | 297 | ````python 298 | import mesaPlot as mp 299 | m=mp.MESA() 300 | p=mp.plot() 301 | m.loadProfile(num=-1) 302 | p.plotAbunPAndN(m,plot_type='history',model=1000,prefix='log_center_') 303 | ```` 304 | 305 | ````python 306 | import mesaPlot as mp 307 | m=mp.MESA() 308 | p=mp.plot() 309 | m.loadHistory() 310 | p.plotAbunHist(m) 311 | ```` 312 | 313 | ### Burn data 314 | 315 | ````python 316 | import mesaPlot as mp 317 | m=mp.MESA() 318 | p=mp.plot() 319 | m.loadProfile(num=-1) 320 | p.plotBurn(m) 321 | ```` 322 | 323 | ````python 324 | import mesaPlot as mp 325 | m=mp.MESA() 326 | p=mp.plot() 327 | m.loadHistory() 328 | p.plotBurnHist(m) 329 | ```` 330 | 331 | ### Dynamos 332 | 333 | ````python 334 | import mesaPlot as mp 335 | m=mp.MESA() 336 | p=mp.plot() 337 | m.loadProfile(num=-1) 338 | p.plotDynamo(m) 339 | ```` 340 | 341 | ![Dynamo 50M_z2m2_high_rotation](/examples/dynamo1.png?raw=true "Dynamo 1 plot") 342 | 343 | ````python 344 | import mesaPlot as mp 345 | m=mp.MESA() 346 | p=mp.plot() 347 | m.loadProfile(num=-1) 348 | p.plotDyanmo2(m) 349 | ```` 350 | 351 | ![Dyanmo 2 50M_z2m2_high_rotation](/examples/dynamo2.png?raw=true "Dynamo 2 plot") 352 | 353 | ### Angular momentum mixing 354 | 355 | ````python 356 | import mesaPlot as mp 357 | m=mp.MESA() 358 | p=mp.plot() 359 | m.loadProfile(num=-1) 360 | p.plotAngMom(m) 361 | ```` 362 | 363 | ### Time series Profile plots 364 | ````python 365 | import mesaPlot as mp 366 | 367 | m=mp.MESA() 368 | m.loadHistory() 369 | m.loadProfile(num=1) 370 | p=mp.plot() 371 | p.plotSliderProf(m,'plotAbun') 372 | ```` 373 | 374 | Passing in a string for the name of a plotting function, (only ones based on profile data). 375 | This will show that plot with a slider that can be used to iterate over the available profile files 376 | plotSliderProf will take any extra arguments passed to it and 377 | pass them to the plotting function. 378 | 379 | 380 | ### Stacked plots 381 | 382 | ### Multi profile plots 383 | 384 | ### Grid plotting 385 | 386 | 387 | -------------------------------------------------------------------------------- /examples/abun_advanced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/abun_advanced.png -------------------------------------------------------------------------------- /examples/abun_basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/abun_basic.png -------------------------------------------------------------------------------- /examples/abun_bya.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/abun_bya.png -------------------------------------------------------------------------------- /examples/abun_bypandn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/abun_bypandn.png -------------------------------------------------------------------------------- /examples/abundances.py: -------------------------------------------------------------------------------- 1 | import mesaPlot as mp 2 | import matplotlib.pyplot as plt 3 | 4 | 5 | m=mp.MESA() 6 | 7 | m.log_fold='examples/LOGS/' 8 | 9 | m.loadHistory() 10 | m.loadProfile(num=-1) 11 | p=mp.plot() 12 | 13 | #Simply plot 14 | p.plotAbun(m) 15 | 16 | #Advanced 17 | fig=plt.figure(figsize=(12,12)) 18 | ax=fig.add_subplot(111) 19 | p.plotAbun(m,num_labels=6,rand_col=True,y1rng=[-6.5,0.5],show_title_model=True,show_title_age=True,fig=fig,ax=ax, 20 | xmax=5.0) 21 | 22 | 23 | # Abundace as function of atomic mass 24 | fig=plt.figure(figsize=(12,12)) 25 | ax=fig.add_subplot(111) 26 | p.plotAbunByA(m,mass_range=[0.0,5.0],fig=fig,ax=ax) 27 | 28 | # Abundance as a function of proton and neutron number 29 | fig=plt.figure(figsize=(12,12)) 30 | ax=fig.add_subplot(111) 31 | p.plotAbunPAndN(m,mass_range=[0.0,5.0],mass_frac_rng=[10**-5,1.0],fig=fig,ax=ax) 32 | -------------------------------------------------------------------------------- /examples/dynamo.py: -------------------------------------------------------------------------------- 1 | import mesaPlot as mp 2 | import matplotlib.pyplot as plt 3 | 4 | 5 | m=mp.MESA() 6 | m.log_fold='examples/LOGS/' 7 | 8 | m.loadHistory() 9 | m.loadProfile(num=-1) 10 | p=mp.plot() 11 | 12 | fig=plt.figure(figsize=(12,10)) 13 | ax=fig.add_subplot(111) 14 | p.plotDynamo(m,y1rng=[0,10],fig=fig,ax=ax,show_rotation=False) 15 | 16 | fig=plt.figure(figsize=(12,10)) 17 | ax=fig.add_subplot(111) 18 | p.plotDynamo(m,y1rng=[0,10],fig=fig,ax=ax,show_rotation=True) 19 | -------------------------------------------------------------------------------- /examples/dynamo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/dynamo1.png -------------------------------------------------------------------------------- /examples/dynamo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/dynamo2.png -------------------------------------------------------------------------------- /examples/kip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/kip.png -------------------------------------------------------------------------------- /examples/kip_age.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/kip_age.png -------------------------------------------------------------------------------- /examples/kip_prof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/kip_prof.png -------------------------------------------------------------------------------- /examples/plotKip.py: -------------------------------------------------------------------------------- 1 | import mesaPlot as mp 2 | import matplotlib.pyplot as plt 3 | 4 | 5 | m=mp.MESA() 6 | m.log_fold='examples/LOGS/' 7 | m.loadHistory() 8 | p=mp.plot() 9 | 10 | fig=plt.figure(figsize=(12,10)) 11 | ax=fig.add_subplot(111) 12 | 13 | #Simply plot 14 | p.plotKip(m,fig=fig,ax=ax,show=False) 15 | plt.show() 16 | 17 | -------------------------------------------------------------------------------- /examples/plotTRho.py: -------------------------------------------------------------------------------- 1 | import mesaPlot as mp 2 | import matplotlib.pyplot as plt 3 | 4 | 5 | m=mp.MESA() 6 | m.log_fold='examples/LOGS/' 7 | m.loadProfile(num=-1) 8 | p=mp.plot() 9 | 10 | fig=plt.figure(figsize=(12,10)) 11 | ax=fig.add_subplot(111) 12 | 13 | 14 | #Simply plot 15 | p.plotTRho(m,fig=fig,ax=ax,show=False,showAll=True,show_mix=True) 16 | plt.show() 17 | 18 | -------------------------------------------------------------------------------- /examples/trho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/examples/trho.png -------------------------------------------------------------------------------- /mesaPlot/__init__.py: -------------------------------------------------------------------------------- 1 | from mesaPlot.file_reader import * 2 | from mesaPlot.plot import * 3 | from mesaPlot.debug import * 4 | -------------------------------------------------------------------------------- /mesaPlot/debug.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017, Robert Farmer r.j.farmer@uva.nl 2 | 3 | # This program is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU General Public License 5 | # as published by the Free Software Foundation; either version 2 6 | # of the License, or (at your option) any later version. 7 | 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, write to the Free Software 15 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | 18 | from __future__ import print_function 19 | import numpy as np 20 | import matplotlib as mpl 21 | import matplotlib.colors as colors 22 | import matplotlib.cm as cm 23 | import matplotlib.pyplot as plt 24 | from matplotlib.ticker import MaxNLocator, AutoMinorLocator 25 | import matplotlib.patheffects as path_effects 26 | import os 27 | import glob 28 | import subprocess 29 | import collections 30 | 31 | 32 | class debug_logs(object): 33 | def __init__(self, folder): 34 | self.folder = folder 35 | self.names = [] 36 | self.size = [] 37 | self.data = [] 38 | 39 | def _load_log_size(self): 40 | with open(os.path.join(self.folder, "size.data")) as f: 41 | for line in f: 42 | self.size = [int(i) for i in line.strip("\n").split()] 43 | break 44 | 45 | def _load_log_names(self): 46 | with open(os.path.join(self.folder, "names.data")) as f: 47 | for line in f: 48 | self.names.append(line.strip(" \n")) 49 | 50 | def load_all_logs(self): 51 | self._load_log_names() 52 | self._load_log_size() 53 | 54 | for i in self.names: 55 | self.data.append([]) 56 | x = np.genfromtxt(os.path.join(self.folder, i + ".log")) 57 | self.data[-1] = x.reshape(self.size[::-1]) 58 | 59 | def plot_log( 60 | self, 61 | name="", 62 | save=False, 63 | folder=None, 64 | iter_min=-1, 65 | iter_max=99999999, 66 | zone_min=-1, 67 | zone_max=99999999, 68 | log=False, 69 | ): 70 | 71 | idx = self.names.index(name) 72 | 73 | if np.all(self.data[idx] == 0.0): 74 | print("Empty ", name) 75 | return 76 | 77 | if folder is not None: 78 | self.folder = folder 79 | 80 | plt.figure(figsize=(12, 12)) 81 | plt.title(name.replace("_", " ")) 82 | 83 | shp = np.shape(self.data[idx]) 84 | 85 | iter_min = max(iter_min, 0) 86 | iter_max = min(iter_max, shp[0]) 87 | zone_min = max(zone_min, 0) 88 | zone_max = min(zone_max, shp[1]) 89 | 90 | vmin = np.nanmin(self.data[idx][iter_min:iter_max, zone_min:zone_max]) 91 | vmax = np.nanmax(self.data[idx][iter_min:iter_max, zone_min:zone_max]) 92 | 93 | if vmin >= 0.0: 94 | vmin = 0.0 95 | cmap = "Reds" 96 | else: 97 | cmap = "seismic" 98 | if np.abs(vmin) < np.abs(vmax): 99 | vmin = -vmax 100 | else: 101 | vmax = np.abs(vmin) 102 | 103 | d = self.data[idx][iter_min:iter_max, zone_min:zone_max] 104 | if log: 105 | d = np.log10(np.abs(d)) 106 | vmin = np.nanmin(d) 107 | vmax = np.nanmax(d) 108 | 109 | plt.imshow( 110 | d, 111 | extent=(zone_min, zone_max, iter_min, iter_max), 112 | aspect="auto", 113 | cmap=cmap, 114 | vmin=vmin, 115 | vmax=vmax, 116 | interpolation="nearest", 117 | origin="lower", 118 | ) 119 | 120 | plt.xlim(zone_max, zone_min) 121 | plt.ylim(iter_min, iter_max) 122 | plt.xlabel("Zone") 123 | plt.ylabel("Iter") 124 | cb = plt.colorbar() 125 | cb.solids.set_edgecolor("face") 126 | if log: 127 | cb.set_label("log abs") 128 | 129 | if save: 130 | plt.savefig(os.path.join(self.folder, name + ".pdf")) 131 | else: 132 | plt.show() 133 | 134 | plt.close() 135 | 136 | def plot_all_logs( 137 | self, 138 | iter_min=-1, 139 | iter_max=99999999, 140 | zone_min=-1, 141 | zone_max=99999999, 142 | folder=None, 143 | ): 144 | if folder is not None: 145 | self.folder = folder 146 | for i in self.names: 147 | self.plot_log( 148 | name=i, 149 | save=True, 150 | folder=self.folder, 151 | iter_min=iter_min, 152 | iter_max=iter_max, 153 | zone_min=zone_min, 154 | zone_max=zone_max, 155 | ) 156 | print("Done ", i) 157 | 158 | def summary(self, iter_min=-1, iter_max=99999999, zone_min=-1, zone_max=99999999): 159 | print("Name Max Min Mean") 160 | for i in range(len(self.names)): 161 | if ( 162 | "corr_" in self.names[i] or "equ_" in self.names[i] 163 | ) and "delta_" not in self.names[i]: 164 | shp = np.shape(self.data[i]) 165 | iter_min = max(iter_min, 0) 166 | iter_max = min(iter_max, shp[0]) 167 | zone_min = max(zone_min, 0) 168 | zone_max = min(zone_max, shp[1]) 169 | print(self.names[i], end=" ") 170 | print( 171 | np.log10( 172 | np.abs( 173 | np.nanmax( 174 | self.data[i][iter_min:iter_max, zone_min:zone_max] 175 | ) 176 | ) 177 | ), 178 | end=" ", 179 | ) 180 | print( 181 | np.log10( 182 | np.abs( 183 | np.nanmin( 184 | self.data[i][iter_min:iter_max, zone_min:zone_max] 185 | ) 186 | ) 187 | ), 188 | end=" ", 189 | ) 190 | print( 191 | np.log10( 192 | np.abs( 193 | np.nanmean( 194 | self.data[i][iter_min:iter_max, zone_min:zone_max] 195 | ) 196 | ) 197 | ) 198 | ) 199 | 200 | 201 | class debug(object): 202 | def __init__(self, folder="plot_data"): 203 | self.solve = debug_logs(os.path.join(folder, "solve_logs")) 204 | self.res = debug_logs(os.path.join(folder, "residual_logs")) 205 | 206 | self.jacobian_default = folder 207 | 208 | def load_res(self): 209 | self.res.load_all_logs() 210 | 211 | def load_solve(self): 212 | self.solve.load_all_logs() 213 | 214 | def plot_res(self, iter_min=-1, iter_max=99999999, zone_min=-1, zone_max=99999999): 215 | self.res.plot_all_logs( 216 | iter_min=iter_min, iter_max=iter_max, zone_min=zone_min, zone_max=zone_max 217 | ) 218 | 219 | def plot_solve( 220 | self, iter_min=-1, iter_max=99999999, zone_min=-1, zone_max=99999999 221 | ): 222 | self.solve.plot_all_logs( 223 | iter_min=iter_min, iter_max=iter_max, zone_min=zone_min, zone_max=zone_max 224 | ) 225 | 226 | ################################### 227 | 228 | def _load_jacobian_size(self, folder): 229 | cols = 0 230 | rows = 0 231 | with open(os.path.join(folder, "jacobian_cols.data")) as f: 232 | for i, l in enumerate(f): 233 | pass 234 | cols = i + 1 235 | with open(os.path.join(folder, "jacobian_rows.data")) as f: 236 | for i, l in enumerate(f): 237 | pass 238 | rows = i + 1 239 | return cols, rows 240 | 241 | def _load_jacobian_names(self, folder): 242 | names = [] 243 | with open(os.path.join(folder, "names.data")) as f: 244 | for line in f: 245 | names.append(line.strip(" \n")) 246 | return names 247 | 248 | def _get_index(self, jacob, name): 249 | idx = None 250 | jdx = None 251 | try: 252 | idx = self.jacobian_folds.index(jacob) 253 | jdx = self.jacobian_names[idx].index(name) 254 | except: 255 | print("call load_all_jacobian") 256 | raise 257 | return (idx, jdx) 258 | 259 | def _load_all_jacobian_names(self, folder): 260 | self.jacob_type = [ 261 | "jacobian_data", 262 | "jacobian_diff_data", 263 | "jacobian_rel_diff_data", 264 | "numerical_jacobian", 265 | ] 266 | self.jacobian_names = [] 267 | self.jacobian_folds = [] 268 | self.jacobian_size = [] 269 | for i in self.jacob_type: 270 | try: 271 | self.jacobian_names.append( 272 | self._load_jacobian_names(os.path.join(folder, i)) 273 | ) 274 | self.jacobian_folds.append(i) 275 | print("Reading ", i) 276 | c, r = self._load_jacobian_size(os.path.join(folder, i)) 277 | self.jacobian_size.append([r, c]) 278 | except: 279 | pass 280 | 281 | def load_all_all_jacobian(self, folder=None): 282 | if folder is None: 283 | folder = self.jacobian_default 284 | 285 | self._load_all_jacobian_names(folder) 286 | 287 | self.jacobian_data = [] 288 | for idx, i in enumerate(self.jacobian_folds): 289 | self.jacobian_data.append([]) 290 | for jdx, j in enumerate(self.jacobian_names[idx]): 291 | print("Reading ", i, j) 292 | x = np.genfromtxt(os.path.join(folder, i, j + ".data")) 293 | self.jacobian_data[-1].append(x) 294 | 295 | def load_all_jacobian(self, jacob="jacobian_data", folder=None): 296 | if folder is None: 297 | folder = self.jacobian_default 298 | 299 | self._load_all_jacobian_names(folder) 300 | 301 | self.jacobian_data = [[], [], [], [], []] 302 | idx = self.jacobian_folds.index(jacob) 303 | for jdx, j in enumerate(self.jacobian_names[idx]): 304 | print("Reading ", jacob, j) 305 | x = np.genfromtxt(os.path.join(folder, jacob, j + ".data")) 306 | self.jacobian_data[idx].append(x) 307 | 308 | def list_avail_jacobians(self): 309 | try: 310 | return self.jacobian_folds 311 | except: 312 | print("call load_all_jacobian") 313 | raise 314 | 315 | def list_avail_names(self, name): 316 | try: 317 | idx = self.jacobian_folds.index(name) 318 | return self.jacobian_names[idx] 319 | except: 320 | print("call load_all_jacobian") 321 | raise 322 | 323 | def get_jacob_data(self, jacob, name): 324 | idx, jdx = self._get_index(jacob, name) 325 | return self.jacobian_data[idx][jdx] 326 | 327 | def plot_all_all_jacob_data(self, folder=None): 328 | if folder is not None: 329 | folder = self.jacobian_default 330 | 331 | for j in self.jacob_type: 332 | for i in iter(self.list_avail_names(j)): 333 | self.plot_jacob_data(jacob=j, name=i, save=True, folder=folder) 334 | print("Plotting ", j, i) 335 | 336 | def plot_all_jacob_data(self, jacob="jacobian_data", folder=None): 337 | if folder is not None: 338 | folder = self.jacobian_default 339 | 340 | for i in iter(self.list_avail_names(jacob)): 341 | self.plot_jacob_data(jacob=jacob, name=i, save=True, folder=folder) 342 | print("Plotting ", jacob, i) 343 | 344 | def plot_jacob_data( 345 | self, 346 | jacob, 347 | name, 348 | save=False, 349 | folder=None, 350 | iter_min=-1, 351 | iter_max=99999999, 352 | zone_min=-1, 353 | zone_max=99999999, 354 | ): 355 | if folder is None: 356 | folder = self.jacobian_default 357 | 358 | idx, jdx = self._get_index(jacob, name) 359 | data = self.get_jacob_data(jacob, name) 360 | 361 | if np.all(data[idx] == 0.0): 362 | print("Empty ", jacob, name) 363 | return 364 | 365 | plt.figure(figsize=(12, 12)) 366 | plt.title(name.replace("_", " ")) 367 | 368 | shp = np.shape(data) 369 | zone_min = max(zone_min, 0) 370 | zone_max = min(zone_max, shp[1]) 371 | 372 | vmin = np.nanmin(data[:, zone_min:zone_max]) 373 | vmax = np.nanmax(data[:, zone_min:zone_max]) 374 | 375 | if np.abs(vmin) < np.abs(vmax): 376 | vmin = -vmax 377 | else: 378 | vmax = np.abs(vmin) 379 | 380 | plt.imshow( 381 | data[:, zone_min:zone_max], 382 | extent=(zone_min, zone_max, -1, 1), 383 | aspect="auto", 384 | cmap="seismic", 385 | vmin=vmin, 386 | vmax=vmax, 387 | interpolation="nearest", 388 | origin="lower", 389 | ) 390 | 391 | plt.xlim(zone_min, zone_max) 392 | plt.yticks([-1, 0.0, 1.0], ["mm", "00", "pm"]) 393 | plt.xlabel("Zone") 394 | plt.ylabel("Iter") 395 | cb = plt.colorbar() 396 | cb.solids.set_edgecolor("face") 397 | 398 | if save: 399 | plt.savefig(os.path.join(folder, jacob, name + ".pdf")) 400 | else: 401 | plt.show() 402 | 403 | plt.close() 404 | 405 | def find_bad_data(self, jacob): 406 | for name in iter(self.list_avail_names(jacob)): 407 | x = self.get_jacob_data(jacob, name) 408 | print( 409 | name, 410 | np.maximum(np.abs(np.nanmax(x[1])), np.abs(np.nanmin(x[1]))), 411 | np.nanmax(x[1]), 412 | np.nanmin(x[1]), 413 | np.nanargmax(x[1]), 414 | np.nanargmin(x[1]), 415 | ) 416 | 417 | 418 | class plotEOS(object): 419 | def __init__(self): 420 | self.data = [] 421 | self.name = [] 422 | self.teff = 0 423 | self.rho = 0 424 | 425 | def load(self, folder="plot_data_DT"): 426 | self.folder = folder 427 | self.teff = np.genfromtxt(folder + "/logT.data") 428 | self.rho = np.genfromtxt(folder + "/logRho.data") 429 | 430 | for i in glob.glob(folder + "/*.data"): 431 | if ( 432 | "/logT.data" not in i 433 | and "/logRho.data" not in i 434 | and "/params.data" not in i 435 | ): 436 | print("Load", i) 437 | self.name.append( 438 | i.replace(folder, "").replace(".data", "").replace("/", "") 439 | ) 440 | x = np.genfromtxt(i) 441 | self.data.append(x.reshape((np.size(self.rho), np.size(self.teff)))) 442 | 443 | def plot(self, name, save=False, only_neg=False): 444 | idx = self.name.index(name) 445 | 446 | if np.all(self.data[idx] == 0.0): 447 | print("Empty ", name) 448 | return 449 | 450 | plt.figure(figsize=(12, 12)) 451 | plt.title(name.replace("_", " ")) 452 | 453 | data = self.data[idx] 454 | 455 | vmin = np.nanmin(data) 456 | vmax = np.nanmax(data) 457 | 458 | if vmin >= 0.0: 459 | vmin = 0.0 460 | cmap = "Reds" 461 | else: 462 | cmap = "seismic" 463 | if np.abs(vmin) < np.abs(vmax): 464 | vmin = -vmax 465 | else: 466 | vmax = np.abs(vmin) 467 | 468 | if only_neg: 469 | vmax = 0.0 470 | vmin = np.nanmin(data) 471 | cmap = "Reds_r" 472 | data[data > 0.0] = np.nan 473 | 474 | plt.imshow( 475 | data, 476 | extent=( 477 | np.nanmin(self.rho), 478 | np.nanmax(self.rho), 479 | np.nanmin(self.teff), 480 | np.nanmax(self.teff), 481 | ), 482 | aspect="auto", 483 | cmap=cmap, 484 | vmin=vmin, 485 | vmax=vmax, 486 | interpolation="nearest", 487 | origin="lower", 488 | ) 489 | 490 | plt.xlim(np.nanmin(self.rho), np.nanmax(self.rho)) 491 | plt.ylim(np.nanmin(self.teff), np.nanmax(self.teff)) 492 | plt.xlabel("LogRho") 493 | plt.ylabel("LogT") 494 | cb = plt.colorbar() 495 | cb.solids.set_edgecolor("face") 496 | 497 | if save: 498 | plt.savefig(os.path.join(self.folder, name + ".pdf")) 499 | else: 500 | plt.show() 501 | 502 | plt.close() 503 | 504 | def plot_all(self, only_neg=False): 505 | for i in self.name: 506 | print("Plot", i) 507 | self.plot(name=i, save=True, only_neg=only_neg) 508 | 509 | 510 | class plotRate(object): 511 | def __init__(self): 512 | self.data = [] 513 | self.name = [] 514 | 515 | def load(self, filename): 516 | from io import BytesIO 517 | 518 | d = subprocess.check_output( 519 | os.path.expandvars("$MESA_DIR") + "/rates/test/show_rates " + filename, 520 | shell=True, 521 | ) 522 | 523 | if type(d) is not type("a"): 524 | data = d.decode().replace("D", "E") 525 | 526 | if "failed" in data: 527 | raise ValueError("Cant read rate " + filename) 528 | 529 | self.name.append(os.path.basename(filename)) 530 | 531 | data = data.encode() 532 | data = np.genfromtxt(BytesIO(data), names=["t8", "rate"], skip_header=4) 533 | 534 | self.data.append(data) 535 | 536 | def load_all(self, folder="cache"): 537 | for i in glob.glob( 538 | os.path.expandvars("$MESA_DIR") + "/data/rates_data/" + folder + "/r_*.bin" 539 | ): 540 | print(i) 541 | self.load(i) 542 | 543 | def plot(self, name, show=True, trng=None, rrng=None): 544 | 545 | for n, data in zip(self.name, self.data): 546 | if n == name: 547 | d = data 548 | 549 | fig = plt.figure(figsize=(12, 12)) 550 | ax = fig.add_subplot(111) 551 | ax.plot(np.log10(d["t8"] * 10 ** 8), np.log10(d["rate"]), linewidth=2) 552 | ax.scatter(np.log10(d["t8"] * 10 ** 8), np.log10(d["rate"])) 553 | ax.set_xlabel(r"$\rm{T}_8$") 554 | ax.set_ylabel(r"$\rm{Rate}$") 555 | ax.set_title(name.replace("_", "\\_")) 556 | if trng is not None: 557 | ax.set_xlim(trng) 558 | if rrng is not None: 559 | ax.set_ylim(rrng) 560 | 561 | ax.autoscale() 562 | if show: 563 | plt.show() 564 | else: 565 | plt.savefig(name.replace(".bin", "") + ".pdf") 566 | plt.close(fig) 567 | 568 | def plot_all(self, show=False, trng=None, rrng=None): 569 | for i in self.name: 570 | print(i) 571 | self.plot(i, show, trng, rrng) 572 | 573 | def load_reaclib(self, name="jina_reaclib_results_v2.2"): 574 | reactions = [] 575 | with open( 576 | os.path.join(os.path.expandvars("$MESA_DIR"), "data", "rates_data", name), 577 | "r", 578 | ) as f: 579 | c = 0 580 | lines = [] 581 | for line in f: 582 | lines.append(line) 583 | c = c + 1 584 | if c == 4: 585 | print(lines) 586 | reactions.append({}) 587 | reactions[-1]["chapter"] = int(lines[0]) 588 | s = lines[1] 589 | reactions[-1]["nuclides"] = s[5:35] 590 | reactions[-1]["setlablel"] = s[43:47] 591 | reactions[-1]["ratetype"] = s[47] 592 | reactions[-1]["revrate"] = s[48] 593 | reactions[-1]["q"] = float(s[52:].strip()) 594 | ( 595 | reactions[-1]["num_lhs"], 596 | reactions[-1]["num_rhs"], 597 | ) = self._reaclib_chapter(reactions[-1]["chapter"]) 598 | reactions[-1]["nuclides"] = self._reaction_name(reactions[-1]) 599 | 600 | l2 = [float(lines[2][i * 13 : (i * 13) + 13]) for i in range(4)] 601 | l3 = [float(lines[3][i * 13 : (i * 13) + 13]) for i in range(3)] 602 | reactions[-1]["coef"] = l2 + l3 603 | c = 0 604 | lines = [] 605 | print() 606 | self.reactions = reactions 607 | 608 | def _reaclib_chapter(self, chap): 609 | lhs = 0 610 | rhs = 0 611 | if chap == 1: 612 | lhs = 1 613 | rhs = 1 614 | elif chap == 2: 615 | lhs = 1 616 | rhs = 2 617 | elif chap == 3: 618 | lhs = 1 619 | rhs = 3 620 | elif chap == 4: 621 | lhs = 2 622 | rhs = 1 623 | elif chap == 5: 624 | lhs = 2 625 | rhs = 2 626 | elif chap == 6: 627 | lhs = 2 628 | rhs = 3 629 | elif chap == 7: 630 | lhs = 2 631 | rhs = 4 632 | elif chap == 8: 633 | lhs = 3 634 | rhs = 1 635 | elif chap == 9: 636 | lhs = 3 637 | rhs = 2 638 | elif chap == 10: 639 | lhs = 4 640 | rhs = 2 641 | elif chap == 11: 642 | lhs = 1 643 | rhs = 4 644 | else: 645 | raise ValueError("Bad Chapter " + str(chap)) 646 | 647 | return lhs, rhs 648 | 649 | def _reaction_name(self, reac): 650 | r = reac["nuclides"] 651 | nuclides = [r[i * 5 : (i * 5) + 5] for i in range(len(r))] 652 | lhs_iso = nuclides[: reac["num_lhs"]] 653 | rhs_iso = nuclides[reac["num_lhs"] : reac["num_rhs"] + 1] 654 | 655 | lhs_iso = [i.strip() for i in lhs_iso] 656 | rhs_iso = [i.strip() for i in rhs_iso] 657 | 658 | lhs_iso = collections.Counter(lhs_iso) 659 | rhs_iso = collections.Counter(rhs_iso) 660 | 661 | lhs_names = [] 662 | rhs_names = [] 663 | 664 | for i in lhs_iso: 665 | if lhs_iso[i] == 1: 666 | lhs_names.append(i) 667 | else: 668 | lhs_names.append(str(lhs_iso[i]) + i) 669 | 670 | for i in rhs_iso: 671 | if rhs_iso[i] == 1: 672 | rhs_names.append(i) 673 | else: 674 | rhs_names.append(str(rhs_iso[i]) + i) 675 | 676 | return [lhs_names, rhs_names] 677 | 678 | def rate(self, reaction, T9): 679 | c = reaction["coef"] 680 | s = c[0] 681 | for i in range(1, 6): 682 | s = s + c[i] * T9 ** ((2.0 * i - 5.0) / 3.0) 683 | s = s + c[6] * np.log(T9) 684 | return s 685 | 686 | 687 | class debug_mesh(object): 688 | def __init__(self): 689 | self.data_old = [] 690 | self.data_new = [] 691 | 692 | def load( 693 | self, 694 | folder="mesh_plot_data", 695 | mesh_new="new_mesh.data", 696 | mesh_old="mesh_plan.data", 697 | ): 698 | self.data_old = np.genfromtxt(os.path.join(folder, mesh_old), names=True) 699 | self.data_new = np.genfromtxt(os.path.join(folder, mesh_new), names=True) 700 | 701 | def plot_gval(self, data, show=True): 702 | for i in data.dtype.names: 703 | if i.startswith("gval_"): 704 | plt.plot(data["mass"], data[i], label=i.replace("_", "\\_"), linewidth=2) 705 | 706 | plt.legend(loc=0) 707 | if show: 708 | plt.show() 709 | 710 | 711 | class plotNeu(object): 712 | def __init__(self): 713 | self.data = [] 714 | self.name = [] 715 | self.teff = 0 716 | self.rho = 0 717 | 718 | def load(self, folder="plot_data"): 719 | self.folder = folder 720 | self.teff = np.genfromtxt(folder + "/tmp.data") 721 | self.rho = np.genfromtxt(folder + "/rho.data") 722 | 723 | for i in glob.glob(folder + "/*.data"): 724 | if "/tmp.data" not in i and "/rho.data" not in i: 725 | print("Load", i) 726 | self.name.append( 727 | i.replace(folder, "").replace(".data", "").replace("/", "") 728 | ) 729 | x = np.genfromtxt(i) 730 | self.data.append(x.reshape((np.size(self.rho), np.size(self.teff)))) 731 | 732 | def plot(self, name, save=False, only_neg=False, log=True): 733 | idx = self.name.index(name) 734 | 735 | if np.all(self.data[idx] == 0.0): 736 | print("Empty ", name) 737 | return 738 | 739 | fig = plt.figure(figsize=(12, 12)) 740 | ax = fig.add_subplot(111) 741 | ax.set_title(name.replace("_", " ")) 742 | 743 | data = self.data[idx] 744 | 745 | vmin = np.nanmin(data) 746 | vmax = np.nanmax(data) 747 | label = "" 748 | if log: 749 | ind = data == 0.0 750 | data = np.log10(np.abs(data)) 751 | label = "Log" 752 | data[ind] = np.nan 753 | vmin = np.nanmin(data) 754 | vmax = np.nanmax(data) 755 | 756 | if vmin >= 0.0: 757 | cmap = "Reds" 758 | else: 759 | cmap = "seismic" 760 | if np.abs(vmin) < np.abs(vmax): 761 | vmin = -vmax 762 | else: 763 | vmax = np.abs(vmin) 764 | 765 | if only_neg: 766 | vmax = 0.0 767 | vmin = np.nanmin(data) 768 | cmap = "Reds_r" 769 | data[data > 0.0] = np.nan 770 | 771 | cax = ax.imshow( 772 | data, 773 | extent=( 774 | np.nanmin(self.rho), 775 | np.nanmax(self.rho), 776 | np.nanmin(self.teff), 777 | np.nanmax(self.teff), 778 | ), 779 | aspect="auto", 780 | cmap=cmap, 781 | vmin=vmin, 782 | vmax=vmax, 783 | interpolation="nearest", 784 | origin="lower", 785 | ) 786 | 787 | ax.set_xlim(np.nanmin(self.rho), np.nanmax(self.rho)) 788 | ax.set_ylim(np.nanmin(self.teff), np.nanmax(self.teff)) 789 | ax.set_xlabel("Log Rho") 790 | ax.set_ylabel("Log T") 791 | cb = plt.colorbar(cax) 792 | cb.solids.set_edgecolor("face") 793 | cb.set_label(label) 794 | 795 | if save: 796 | plt.savefig(os.path.join(self.folder, name + ".pdf")) 797 | else: 798 | plt.show() 799 | 800 | plt.close() 801 | 802 | def plot_all(self, only_neg=False): 803 | for i in self.name: 804 | print("Plot", i) 805 | self.plot(name=i, save=True, only_neg=only_neg) 806 | 807 | 808 | class plotKap(object): 809 | def __init__(self): 810 | self.data = [] 811 | self.name = [] 812 | self.teff = 0 813 | self.rho = 0 814 | 815 | def load(self, folder="plot_data"): 816 | self.folder = folder 817 | self.teff = np.genfromtxt(folder + "/logT.data") 818 | self.rho = np.genfromtxt(folder + "/logRho.data") 819 | 820 | for i in glob.glob(folder + "/*.data"): 821 | if ( 822 | "/logT.data" not in i 823 | and "/logRho.data" not in i 824 | and "params.data" not in i 825 | ): 826 | print("Load", i) 827 | self.name.append( 828 | i.replace(folder, "").replace(".data", "").replace("/", "") 829 | ) 830 | x = np.genfromtxt(i) 831 | self.data.append(x.reshape((np.size(self.rho), np.size(self.teff)))) 832 | 833 | def plot(self, name, save=False, only_neg=False, log=True): 834 | idx = self.name.index(name) 835 | 836 | if np.all(self.data[idx] == 0.0): 837 | print("Empty ", name) 838 | return 839 | 840 | fig = plt.figure(figsize=(12, 12)) 841 | ax = fig.add_subplot(111) 842 | ax.set_title(name.replace("_", " ")) 843 | 844 | data = self.data[idx] 845 | 846 | vmin = np.nanmin(data) 847 | vmax = np.nanmax(data) 848 | label = "" 849 | if log: 850 | ind = data == 0.0 851 | data = np.log10(np.abs(data)) 852 | label = "Log" 853 | data[ind] = np.nan 854 | vmin = np.nanmin(data) 855 | vmax = np.nanmax(data) 856 | 857 | if vmin >= 0.0: 858 | cmap = "Reds" 859 | else: 860 | cmap = "seismic" 861 | if np.abs(vmin) < np.abs(vmax): 862 | vmin = -vmax 863 | else: 864 | vmax = np.abs(vmin) 865 | 866 | if only_neg: 867 | vmax = 0.0 868 | vmin = np.nanmin(data) 869 | cmap = "Reds_r" 870 | data[data > 0.0] = np.nan 871 | 872 | cax = ax.imshow( 873 | data, 874 | extent=( 875 | np.nanmin(self.rho), 876 | np.nanmax(self.rho), 877 | np.nanmin(self.teff), 878 | np.nanmax(self.teff), 879 | ), 880 | aspect="auto", 881 | cmap=cmap, 882 | vmin=vmin, 883 | vmax=vmax, 884 | interpolation="nearest", 885 | origin="lower", 886 | ) 887 | 888 | ax.set_xlim(np.nanmin(self.rho), np.nanmax(self.rho)) 889 | ax.set_ylim(np.nanmin(self.teff), np.nanmax(self.teff)) 890 | ax.set_xlabel("Log Rho") 891 | ax.set_ylabel("Log T") 892 | cb = plt.colorbar(cax) 893 | cb.solids.set_edgecolor("face") 894 | cb.set_label(label) 895 | 896 | if save: 897 | plt.savefig(os.path.join(self.folder, name + ".pdf")) 898 | else: 899 | plt.show() 900 | 901 | plt.close() 902 | 903 | def plot_all(self, only_neg=False): 904 | for i in self.name: 905 | print("Plot", i) 906 | if "dfr" in i: 907 | self.plot(name=i, save=True, only_neg=True, log=False) 908 | elif "log" in i: 909 | self.plot(name=i, save=True, only_neg=only_neg, log=False) 910 | else: 911 | self.plot(name=i, save=True, only_neg=only_neg, log=True) 912 | -------------------------------------------------------------------------------- /mesaPlot/file_reader.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017, Robert Farmer r.j.farmer@uva.nl 2 | 3 | # This program is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU General Public License 5 | # as published by the Free Software Foundation; either version 2 6 | # of the License, or (at your option) any later version. 7 | 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, write to the Free Software 15 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | 17 | from __future__ import print_function 18 | import numpy as np 19 | import os 20 | import pickle 21 | import bisect 22 | import subprocess 23 | import hashlib 24 | from io import BytesIO 25 | import pandas 26 | 27 | msun = 1.9892 * 10 ** 33 28 | 29 | # Conviently the index of this list is the proton number 30 | _elementsPretty = [ 31 | "neut", 32 | "H", 33 | "He", 34 | "Li", 35 | "Be", 36 | "B", 37 | "C", 38 | "N", 39 | "O", 40 | "F", 41 | "Ne", 42 | "Na", 43 | "Mg", 44 | "Al", 45 | "Si", 46 | "P", 47 | "S", 48 | "Cl", 49 | "Ar", 50 | "K", 51 | "Ca", 52 | "Sc", 53 | "Ti", 54 | "V", 55 | "Cr", 56 | "Mn", 57 | "Fe", 58 | "Co", 59 | "Ni", 60 | "Cu", 61 | "Zn", 62 | "Ga", 63 | "Ge", 64 | "As", 65 | "Se", 66 | "Br", 67 | "Kr", 68 | "Rb", 69 | "Sr", 70 | "Y", 71 | "Zr", 72 | "Nb", 73 | "Mo", 74 | "Tc", 75 | "Ru", 76 | "Rh", 77 | "Pd", 78 | "Ag", 79 | "Cd", 80 | "In", 81 | "Sn", 82 | "Sb", 83 | "Te", 84 | "I", 85 | "Xe", 86 | "Cs", 87 | "Ba", 88 | "La", 89 | "Ce", 90 | "Pr", 91 | "Nd", 92 | "Pm", 93 | "Sm", 94 | "Eu", 95 | "Gd", 96 | "Tb", 97 | "Dy", 98 | "Ho", 99 | "Er", 100 | "Tm", 101 | "Yb", 102 | "Lu", 103 | "Hf", 104 | "Ta", 105 | "W", 106 | "Re", 107 | "Os", 108 | "Ir", 109 | "Pt", 110 | "Au", 111 | "Hg", 112 | "Tl", 113 | "Pb", 114 | "Bi", 115 | "Po", 116 | "At", 117 | "Rn", 118 | "Fr", 119 | "Ra", 120 | "Ac", 121 | "Th", 122 | "Pa", 123 | "U", 124 | "Np", 125 | "Pu", 126 | "Am", 127 | "Cm", 128 | "Bk", 129 | "Cf", 130 | "Es", 131 | "Fm", 132 | "Md", 133 | "No", 134 | "Lr", 135 | "Rf", 136 | "Db", 137 | "Sg", 138 | "Bh", 139 | "Hs", 140 | "Mt", 141 | "Ds", 142 | "Rg", 143 | "Uub", 144 | "Uut", 145 | "Uuq", 146 | "Uup", 147 | "Uuh", 148 | "Uus", 149 | "Uuo", 150 | ] 151 | _elements = [x.lower() for x in _elementsPretty] 152 | 153 | _PICKLE_VERSION = 6 154 | 155 | 156 | def _hash(fname): 157 | hash_md5 = hashlib.md5() 158 | if not os.path.exists(fname): 159 | return None 160 | 161 | try: 162 | x = subprocess.check_output(["md5sum", fname]) 163 | return x.split()[0].decode() 164 | except (FileNotFoundError, subprocess.CalledProcessError): # (no md5sum, no file) 165 | pass 166 | 167 | with open(fname, "rb") as f: 168 | for chunk in iter(lambda: f.read(4096), b""): 169 | hash_md5.update(chunk) 170 | return hash_md5.hexdigest() 171 | 172 | 173 | class data(object): 174 | def __init__(self): 175 | self.data = {} 176 | self.head = {} 177 | self._loaded = False 178 | self._mph = "" 179 | self._type = "" 180 | 181 | def __getattr__(self, name): 182 | if "data" in self.__dict__: 183 | if len(self.data) == 0: 184 | raise AttributeError("Must load data first") 185 | 186 | return self.__getitem__(name) 187 | 188 | def __contains__(self, key): 189 | return key in self.keys() 190 | 191 | def keys(self): 192 | try: 193 | return list(self.data.keys()) + list(self.head.keys()) 194 | except AttributeError: 195 | return list(self.data.dtype.names) + list(self.head.dtype.names) 196 | 197 | def __dir__(self): 198 | return self.keys() + list(self.__dict__.keys()) 199 | 200 | def __getitem__(self, key): 201 | if "data" in self.__dict__: 202 | if key in self.data.dtype.names: 203 | return self.data[key] 204 | if key in self.head.dtype.names: 205 | return np.atleast_1d(self.head[key])[0] 206 | 207 | 208 | try: 209 | return self.__dict__[key] 210 | except KeyError: 211 | raise AttributeError(f"No attribute {key} found") 212 | 213 | def __iter__(self): 214 | if len(self.data): 215 | for i in self.keys(): 216 | yield i 217 | 218 | def loadFile( 219 | self, 220 | filename, 221 | max_num_lines=-1, 222 | cols=[], 223 | final_lines=-1, 224 | _dbg=False, 225 | use_pickle=True, 226 | reload_pickle=False, 227 | silent=False, 228 | is_mod=False, 229 | ): 230 | 231 | if is_mod: 232 | self._loadMod(filename) 233 | return 234 | 235 | pickname = filename + ".pickle" 236 | if ( 237 | use_pickle 238 | and os.path.exists(pickname) 239 | and not reload_pickle 240 | and final_lines < 0 241 | ): 242 | if self._loadPickle(pickname, filename): 243 | return 244 | 245 | # Not using pickle 246 | self._loadFile(filename, max_num_lines, cols, final_lines) 247 | 248 | def _loadPickle(self, pickname, filename): 249 | if not os.path.exists(pickname): 250 | return False 251 | 252 | with open(pickname, "rb") as f: 253 | # Get checksum 254 | filehash = _hash(filename) 255 | try: 256 | version = pickle.load(f) 257 | except Exception: 258 | raise ValueError("Pickle file corrupted please delete it and try again") 259 | 260 | # For mesaplot 1.* this is a hash, while 2.* is a version number 261 | if len(str(version)) > 12: 262 | # Version 1.0 hash 263 | pickhash = version 264 | else: 265 | if int(version) != int(_PICKLE_VERSION): 266 | raise ValueError("Pickle file not recongised please delete it and try again") 267 | 268 | pickhash = pickle.load(f) 269 | 270 | if ( 271 | os.path.exists(filename) and pickhash == filehash 272 | ) or not os.path.exists(filename): 273 | # Data has not changed 274 | # Get Data 275 | data = pickle.load(f) 276 | 277 | try: 278 | head = pickle.load(f) 279 | self.head = head 280 | self.data = data 281 | except EOFError: # Handle 1.* verisons of pickle files 282 | self.data = data.data 283 | self.head = data.head 284 | 285 | self._loaded = True 286 | return True 287 | return False 288 | 289 | def _loadFile(self, filename, max_num_lines=-1, cols=[], final_lines=-1): 290 | if not os.path.exists(filename): 291 | raise FileNotFoundError("No file " + str(filename) + " found") 292 | 293 | head = pandas.read_csv(filename, sep=r'\s+', header=1, nrows=1) 294 | 295 | if max_num_lines > 0: 296 | data = pandas.read_csv( 297 | filename, sep=r'\s+', header=4, nrows=max_num_lines 298 | ) 299 | else: 300 | data = pandas.read_csv(filename, sep=r'\s+', header=4) 301 | 302 | if final_lines > 0: 303 | data = self.data[-final_lines:] 304 | 305 | # Convert from pandas to numpy 306 | # dtype = np.dtype( 307 | # [ 308 | # (data.dtypes.index[idx].values, data.dtypes[idx].name) 309 | # for idx, i in enumerate(data.dtypes) 310 | # ] 311 | # ) 312 | # self.data = np.zeros(np.size(data[dtype.names[0]]), dtype=dtype) 313 | # for i in data: 314 | # self.data[i] = data[i].to_numpy() 315 | 316 | records = data.to_records(index=False) 317 | self.data = np.array(records, dtype = records.dtype.descr) 318 | 319 | # dtype = np.dtype( 320 | # [ 321 | # (head.dtypes.index[idx], head.dtypes[idx].name) 322 | # for idx, i in enumerate(head.dtypes) 323 | # ] 324 | # ) 325 | # self.head = np.zeros(1, dtype=dtype) 326 | # for i in head: 327 | # self.head[i] = head[i].to_numpy() 328 | 329 | records = head.to_records(index=False) 330 | self.head = np.array(records, dtype = records.dtype.descr) 331 | 332 | 333 | self._loaded = True 334 | self._saveFile(filename) 335 | 336 | def _saveFile(self, filename): 337 | filehash = _hash(filename) 338 | pickname = filename + ".pickle" 339 | with open(filename + ".pickle", "wb") as f: 340 | pickle.dump(_PICKLE_VERSION, f) 341 | pickle.dump(filehash, f) 342 | pickle.dump(self.data, f) 343 | pickle.dump(self.head, f) 344 | 345 | def _loadMod(self, filename): 346 | from io import BytesIO, StringIO 347 | 348 | count = 0 349 | with open(filename, "r") as f: 350 | for l in f: 351 | count = count + 1 352 | if "!" not in l: 353 | break 354 | head = [] 355 | head_names = [] 356 | head.append(str(l.split()[0])) 357 | head_names.append("mod_version") 358 | # Blank line 359 | f.readline() 360 | count = count + 1 361 | # Gap between header and main data 362 | for l in f: 363 | count = count + 1 364 | if l == "\n": 365 | break 366 | head.append(str(l.split()[1])) 367 | head_names.append(l.split()[0]) 368 | data_names = [] 369 | l = f.readline() 370 | count = count + 1 371 | data_names.append("zone") 372 | data_names.extend(l.split()) 373 | # Make a dictionary of converters 374 | 375 | # Replace MMsun with star_mass 376 | head_names[head_names.index("M/Msun")] = "star_mass" 377 | 378 | d = {k: self._fds2f for k in range(len(head_names))} 379 | self.head = np.genfromtxt( 380 | StringIO(" ".join(head)), 381 | names=head_names, 382 | dtype=None, 383 | encoding="ascii", 384 | converters=d, 385 | ) 386 | 387 | d = {k: self._fds2f for k in range(len(data_names))} 388 | 389 | data = np.genfromtxt( 390 | filename, 391 | skip_header=count, 392 | names=data_names, 393 | skip_footer=5, 394 | dtype=None, 395 | converters=d, 396 | encoding="ascii", 397 | ) 398 | 399 | # Add mass co-ord 400 | 401 | mass = np.cumsum(data["dq"][::-1])[::-1] * self.head["star_mass"] 402 | 403 | olddt = data.dtype 404 | newdt = np.dtype(olddt.descr + [("mass", ("= 2 and "burn_" not in j: 433 | if ( 434 | i[0].isalpha() 435 | and (i[1].isalpha() or i[1].isdigit()) 436 | and any(char.isdigit() for char in i) 437 | and i[-1].isdigit() 438 | ): 439 | if (len(i) == 5 and i[-1].isdigit() and i[-2].isdigit()) or len( 440 | i 441 | ) < 5: 442 | abun_list.append(j) 443 | if i == "neut" or i == "prot": 444 | abun_list.append(j) 445 | 446 | for idx, i in enumerate(abun_list): 447 | if type(i) is bytes: 448 | abun_list[idx] = i.decode() 449 | 450 | return abun_list 451 | 452 | def splitIso(self, iso, prefix=""): 453 | name = "" 454 | mass = "" 455 | iso = iso[len(prefix) :] 456 | for i in iso: 457 | if i.isdigit(): 458 | mass += i 459 | else: 460 | name += i 461 | if "neut" in name or "prot" in name: 462 | mass = 1 463 | return name, int(mass) 464 | 465 | def getIso(self, iso, prefix=""): 466 | name, mass = self.splitIso(iso, prefix) 467 | if "prot" in name: 468 | p = 1 469 | n = 0 470 | else: 471 | p = _elements.index(name) 472 | n = mass - p 473 | return name, p, n 474 | 475 | def listBurn(self): 476 | burnList = [] 477 | ignore = ["qtop", "type", "min"] 478 | extraBurn = [ 479 | "pp", 480 | "cno", 481 | "tri_alfa", 482 | "c12_c12", 483 | "c12_O16", 484 | "o16_o16", 485 | "pnhe4", 486 | "photo", 487 | "other", 488 | ] 489 | for i in self.keys(): 490 | if ("burn_" in i or i in extraBurn) and not any(j in i for j in ignore): 491 | burnList.append(str(i)) 492 | return burnList 493 | 494 | def listMix(self): 495 | mixList = [ 496 | "log_D_conv", 497 | "log_D_semi", 498 | "log_D_ovr", 499 | "log_D_th", 500 | "log_D_thrm", 501 | "log_D_minimum", 502 | "log_D_anon", 503 | "log_D_rayleigh_taylor", 504 | "log_D_soft", 505 | ] 506 | mixListOut = [] 507 | for i in self.keys(): 508 | if i in mixList: 509 | mixListOut.append(str(i)) 510 | return mixListOut 511 | 512 | def abunSum(self, iso, mass_min=0.0, mass_max=9999.0): 513 | if "mass" in self.keys(): 514 | ind = (self.data["mass"] >= mass_min) & (self.data["mass"] <= mass_max) 515 | mdiff = self._getMdiff() 516 | return np.sum(self.data[iso][ind] * mdiff[ind]) 517 | else: 518 | return self._getMassHist(iso) 519 | 520 | def eleSum(self, element, mass_min=0.0, mass_max=9999.0, prefix=""): 521 | la = self.listAbun(prefix) 522 | x = 0.0 523 | for i in la: 524 | if element == self.splitIso(i)[0]: 525 | x = x + self.abunSum(i, mass_min, mass_max) 526 | return x 527 | 528 | def getMassFrac(self, iso, ind=None, log=False, prof=True): 529 | if prof: 530 | if "logdq" in self.keys(): 531 | scale = 10 ** (self.data["logdq"][ind]) 532 | elif "dq" in self.keys(): 533 | scale = self.data["dq"][ind] 534 | elif "dm" in self.keys(): 535 | scale = self.data["dm"][ind] / (msun * self.mass_star()) 536 | else: 537 | raise AttributeError( 538 | "No suitable mass co-ordinate available for getMassFrac, need either logdq, dq or dm in profile" 539 | ) 540 | else: 541 | scale = 1.0 542 | 543 | if log: 544 | x = np.sum(10 ** self.data[i][ind] * scale) 545 | else: 546 | x = np.sum(self.data[i][ind] * scale) 547 | 548 | return x 549 | 550 | @property 551 | def mass_star(self): 552 | if "star_mass" in self.data.dtype.names: 553 | return self.data["star_mass"] 554 | elif "star_mass" in self.head_names: 555 | return self.head["star_mass"] 556 | else: 557 | raise ValueError("No star_mass available") 558 | 559 | def _getMdiff(self): 560 | sm = self.head["star_mass"] 561 | if "M_center" in self.head_names: 562 | sm = sm - self.head["M_center"] / msun 563 | 564 | if "logdq" in self.keys(): 565 | return 10 ** (self.data["logdq"]) * sm 566 | elif "dq" in self.keys(): 567 | return self.data["dq"] * sm 568 | elif "dm" in self.keys(): 569 | return self.data["dm"] 570 | else: 571 | raise AttributeError( 572 | "No suitable mass co-ordinate available for _getMdiff, need either logdq, dq or dm in data" 573 | ) 574 | 575 | def _getMassHist(self, iso): 576 | if "log_total_mass_" + iso in self.keys(): 577 | return 10 ** self.data["log_total_mass_" + iso] 578 | elif "total_mass_" + iso in self.keys(): 579 | return self.data["log_total_mass_" + iso] 580 | else: 581 | return None 582 | 583 | def core_mass( 584 | self, 585 | element, 586 | prev_element=None, 587 | core_boundary_fraction=0.01, 588 | min_boundary_fraction=0.1, 589 | ): 590 | if prev_element is None: 591 | if element == "he4": 592 | prev_element = "h1" 593 | elif element == "c12": 594 | prev_element = "he4" 595 | elif element == "o16": 596 | prev_element = "c12" 597 | elif element == "si28": 598 | prev_element = "o16" 599 | elif element == "fe56": 600 | prev_element = "si28" 601 | 602 | ind = self.data[element] >= core_boundary_fraction 603 | ind = ind & (self.data[prev_element] <= min_boundary_fraction) 604 | return np.max(self.data["mass"][ind]) 605 | 606 | def mergeHist(self,*new): 607 | self.hist.data = np.concatenate((self.hist.data, 608 | [i.hist.data for i in new]), 609 | dtype=self.hist.data.dtype) 610 | 611 | 612 | class MESA(object): 613 | def __init__(self): 614 | self.hist = data() 615 | self.prof = data() 616 | self.binary = data() 617 | self.prof_ind = "" 618 | self.log_fold = "" 619 | self.clearProfCache() 620 | self.cache_limit = 100 621 | self._cache_wd = "" 622 | 623 | self.hist._mph = "history" 624 | self.prof._mph = "profile" 625 | self.hist._type = "loadHistory" 626 | self.prof._type = "loadProfile" 627 | 628 | self.hist._mph = "binary" 629 | self.hist._mph = "loadBinary" 630 | 631 | def loadHistory( 632 | self, 633 | f="", 634 | filename_in=None, 635 | max_model=-1, 636 | max_num_lines=-1, 637 | cols=[], 638 | final_lines=-1, 639 | _dbg=False, 640 | use_pickle=True, 641 | reload_pickle=False, 642 | ): 643 | """ 644 | Reads a MESA history file. 645 | 646 | Optional: 647 | f: Folder in which history.data exists, if not present uses self.log_fold, if that is 648 | not set try the current working directory. 649 | filename_in: Reads the file given by name 650 | max_model: Maximum model to read into, may help when having to clean files with many retires, backups and restarts by not processing data beyond max_model 651 | max_num_lines: Maximum number of lines to read from the file, maps ~maximum model number but not quite (retires, backups and restarts effect this) 652 | cols: If none returns all columns, else if set as a list only stores those columns, will always add model_number to the list 653 | final_lines: Reads number of lines from end of the file if > 0 654 | 655 | 656 | Returns: 657 | self.hist.head: The header data in the history file as a structured dtype 658 | self.hist.data: The data in the main body of the history file as a structured dtype 659 | self.hist.head_names: List of names of the header fields 660 | self.hist.data_names: List of names of the data fields 661 | 662 | Note it will clean the file up of backups,retries and restarts, preferring to use 663 | the newest data line. 664 | """ 665 | if len(f) == 0: 666 | if len(self.log_fold) == 0: 667 | self.log_fold = "LOGS/" 668 | f = self.log_fold 669 | else: 670 | self.log_fold = f + "/" 671 | 672 | if filename_in is None: 673 | filename = os.path.join(self.log_fold, "history.data") 674 | else: 675 | filename = filename_in 676 | 677 | self.hist.loadFile( 678 | filename, 679 | max_num_lines, 680 | cols, 681 | final_lines=final_lines, 682 | _dbg=_dbg, 683 | use_pickle=use_pickle, 684 | reload_pickle=reload_pickle, 685 | ) 686 | if max_model > 0: 687 | self.hist.data = self.hist.data[self.hist.model_number <= max_model] 688 | 689 | # Reverse model numbers, we want the unique elements 690 | # but keeping the last not the first. 691 | if np.unique(np.diff(self.hist.model_number)).size == 1: 692 | # Return early if all step sizes are constant 693 | return 694 | 695 | # Fix case where we have at end of file numbers: 696 | # 1 2 3 4 5 3, without this we get the extra 4 and 5 697 | if np.size(self.hist.model_number) > 1: 698 | self.hist.data = self.hist.data[ 699 | self.hist.model_number <= self.hist.model_number[-1] 700 | ] 701 | mod_rev = self.hist.model_number[::-1] 702 | _, mod_ind = np.unique(mod_rev, return_index=True) 703 | self.hist.data = self.hist.data[ 704 | np.size(self.hist.model_number) - mod_ind - 1 705 | ] 706 | 707 | def scrubHistory(self, f="", fileOut="LOGS/history.data.scrubbed"): 708 | self.loadHistory(f) 709 | with open(fileOut, "w") as f: 710 | print( 711 | " ".join([str(i) for i in range(1, np.size(self.hist.head_names) + 1)]), 712 | file=f, 713 | ) 714 | print(" ".join([str(i) for i in self.hist.head_names]), file=f) 715 | print( 716 | " ".join([str(self.hist.head[i]) for i in self.hist.head_names]), file=f 717 | ) 718 | print(" ", file=f) 719 | print( 720 | " ".join([str(i) for i in range(1, np.size(self.hist.data_names) + 1)]), 721 | file=f, 722 | ) 723 | print(" ".join([str(i) for i in self.hist.data_names]), file=f) 724 | for j in range(np.size(self.hist.data)): 725 | print( 726 | " ".join([str(self.hist.data[i][j]) for i in self.hist.data_names]), 727 | file=f, 728 | ) 729 | 730 | def loadProfile( 731 | self, 732 | f="", 733 | num=None, 734 | prof=None, 735 | mode="nearest", 736 | silent=False, 737 | cache=True, 738 | cols=[], 739 | use_pickle=True, 740 | reload_pickle=False, 741 | ): 742 | if num is None and prof is None: 743 | self._readProfile(f) # f is a filename 744 | return 745 | 746 | if len(f) == 0: 747 | if len(self.log_fold) == 0: 748 | self.log_fold = "LOGS/" 749 | f = self.log_fold 750 | else: 751 | self.log_fold = f 752 | 753 | self._loadProfileIndex(f) # Assume f is a folder 754 | prof_nums = np.atleast_1d(self.prof_ind["profile"]).astype("int") 755 | 756 | if prof is not None: 757 | pos = np.where(prof_nums == prof)[0][0] 758 | else: 759 | if np.count_nonzero(self.prof_ind) == 1: 760 | pos = 0 761 | else: 762 | if num <= 0: 763 | pos = num 764 | else: 765 | # Find profile with mode 'nearest','upper','lower','first','last' 766 | pos = bisect.bisect_left(self.prof_ind["model"], num) 767 | if pos == 0 or mode == "first": 768 | pos = 0 769 | elif pos == np.size(self.prof_ind["profile"]) or mode == "last": 770 | pos = -1 771 | elif mode == "lower": 772 | pos = pos - 1 773 | elif mode == "upper": 774 | pos = pos 775 | elif mode == "nearest": 776 | if ( 777 | self.prof_ind["model"][pos] - num 778 | < num - self.prof_ind["model"][pos - 1] 779 | ): 780 | pos = pos 781 | else: 782 | pos = pos - 1 783 | else: 784 | raise ValueError("Invalid mode") 785 | 786 | profile_num = np.atleast_1d(self.prof_ind["profile"])[pos] 787 | filename = f + "/profile" + str(int(profile_num)) + ".data" 788 | if not silent: 789 | print(filename) 790 | self._readProfile( 791 | filename, 792 | cache=cache, 793 | cols=cols, 794 | use_pickle=use_pickle, 795 | reload_pickle=reload_pickle, 796 | silent=silent, 797 | ) 798 | return 799 | 800 | def loadMod(self, filename=None): 801 | """ 802 | Read a MESA .mod file. 803 | """ 804 | self.mod = data() 805 | 806 | self.mod.loadFile(filename, is_mod=True) 807 | 808 | def iterateProfiles( 809 | self, f="", priority=None, rng=[-1.0, -1.0], step=1, cache=True, silent=False 810 | ): 811 | if len(f) == 0: 812 | if len(self.log_fold) == 0: 813 | self.log_fold = "LOGS/" 814 | f = self.log_fold 815 | else: 816 | self.log_fold = f 817 | # Load profiles index file 818 | self._loadProfileIndex(f) 819 | for x in self.prof_ind: 820 | if priority != None: 821 | if type(priority) is not list: 822 | priority = [priority] 823 | if x["priority"] in priority or 0 in priority: 824 | self.loadProfile( 825 | f=f + "/profile" + str(int(x["profile"])) + ".data", 826 | cache=cache, 827 | silent=silent, 828 | ) 829 | yield 830 | if len(rng) == 2 and rng[0] > 0: 831 | if ( 832 | x["model"] >= rng[0] 833 | and x["model"] <= rng[1] 834 | and np.remainder(x["model"] - rng[0], step) == 0 835 | ): 836 | self.loadProfile( 837 | f=f + "/profile" + str(int(x["profile"])) + ".data", 838 | cache=cache, 839 | silent=silent, 840 | ) 841 | yield 842 | elif x["model"] > rng[1]: 843 | return 844 | elif len(rng) > 2 and rng[0] > 0: 845 | if x["model"] in rng: 846 | self.loadProfile( 847 | f=f + "/profile" + str(int(x["profile"])) + ".data", 848 | cache=cache, 849 | silent=silent, 850 | ) 851 | yield 852 | else: 853 | self.loadProfile( 854 | f=f + "/profile" + str(int(x["profile"])) + ".data", 855 | cache=cache, 856 | silent=silent, 857 | ) 858 | yield 859 | return 860 | 861 | def _loadProfileIndex(self, f): 862 | self.prof_ind = np.genfromtxt( 863 | f + "/profiles.index", skip_header=1, names=["model", "priority", "profile"] 864 | ) 865 | 866 | def _readProfile( 867 | self, 868 | filename, 869 | cache=True, 870 | cols=[], 871 | use_pickle=True, 872 | reload_pickle=False, 873 | silent=False, 874 | ): 875 | """ 876 | Reads a MESA profile file. 877 | 878 | Required: 879 | filename: Path to profile to read 880 | 881 | Optional: 882 | cache: If true caches the profile data so multiple profile loads do not need to reread the data 883 | cols: cols: If none returns all columns, else if set as a list only storing those columns, it will always add zone to the list of columns 884 | 885 | Returns: 886 | self.prof.head: The header data in the profile as a structured dtype 887 | self.prof.data: The data in the main body of the profile file as a structured dtype 888 | self.prof.head_names: List of names of the header fields 889 | self.prof.data_names: List of names of the data fields 890 | """ 891 | 892 | # Handle cases where we change directories inside the python session 893 | if self._cache_wd != os.getcwd(): 894 | self.clearProfCache() 895 | self._cache_wd = os.getcwd() 896 | 897 | if filename in self._cache_prof_name and cache: 898 | self.prof = self._cache_prof[self._cache_prof_name.index(filename)] 899 | else: 900 | x = data() 901 | x.loadFile( 902 | filename, 903 | cols=cols, 904 | use_pickle=use_pickle, 905 | reload_pickle=reload_pickle, 906 | silent=silent, 907 | ) 908 | if cache: 909 | if len(self._cache_prof_name) == self.cache_limit: 910 | self._cache_prof.pop(0) 911 | self._cache_prof_name.pop(0) 912 | self._cache_prof.append(x) 913 | self._cache_prof_name.append(filename) 914 | self.prof = x 915 | 916 | def clearProfCache(self): 917 | self._cache_prof = [] 918 | self._cache_prof_name = [] 919 | 920 | def abun(self, element): 921 | xx = 0 922 | for ii in range(0, 1000): 923 | try: 924 | xx = xx + np.sum( 925 | self.prof.data[element + str(ii)] * 10 ** self.prof.logdq 926 | ) 927 | except: 928 | pass 929 | return xx 930 | 931 | def loadBinary( 932 | self, f="", filename_in=None, max_model=-1, max_num_lines=-1, cols=[] 933 | ): 934 | """ 935 | Reads a MESA binary history file. 936 | 937 | Optional: 938 | f: Folder in which binary_history.data exists, if not present uses self.log_fold, if that is 939 | not set try the current working directory. 940 | filename_in: Reads the file given by name 941 | max_model: Maximum model to read into, may help when having to clean files with many retries, backups and restarts by not processing data beyond max_model 942 | max_num_lines: Maximum number of lines to read from the file, maps ~maximum model number but not quite (retries, backups and restarts effect this) 943 | cols: If none returns all columns, else if set as a list only stores those columns, it will always add model_number to the list 944 | 945 | 946 | Returns: 947 | self.binary.head: The header data in the history file as a structured dtype 948 | self.binary.data: The data in the main body of the history file as a structured dtype 949 | self.binary.head_names: List of names of the header fields 950 | self.binary.data_names: List of names of the data fields 951 | 952 | Note it will clean the file up of backups, retries and restarts, preferring to use 953 | the newest data line. 954 | """ 955 | if len(f) == 0: 956 | if len(self.log_fold) == 0: 957 | self.log_fold = "./" 958 | f = self.log_fold 959 | else: 960 | self.log_fold = f + "/" 961 | 962 | if filename_in is None: 963 | filename = os.path.join(self.log_fold, "binary_history.data") 964 | else: 965 | filename = filename_in 966 | 967 | self.binary.loadFile(filename, max_num_lines, cols) 968 | 969 | if max_model > 0: 970 | self.binary.data = self.binary.data[self.binary.model_number <= max_model] 971 | 972 | # Reverse model numbers, we want the unique elements 973 | # but keeping the last not the first. 974 | 975 | # Fix case where we have at end of file numbers: 976 | # 1 2 3 4 5 3, without this we get the extra 4 and 5 977 | self.binary.data = self.binary.data[ 978 | self.binary.model_number <= self.binary.model_number[-1] 979 | ] 980 | 981 | mod_rev = self.binary.model_number[::-1] 982 | _, mod_ind = np.unique(mod_rev, return_index=True) 983 | self.binary.data = self.binary.data[ 984 | np.size(self.binary.model_number) - mod_ind - 1 985 | ] 986 | 987 | 988 | class inlist(object): 989 | def __init__(self): 990 | pass 991 | 992 | def read(self, filename): 993 | res = {} 994 | with open(filename, "r") as f: 995 | for l in f: 996 | l = l.strip() 997 | if l.startswith("!") or not len(l.strip()): 998 | continue 999 | if "=" in l: 1000 | line = l.split("=") 1001 | res[line[0].strip()] = line[1].strip() 1002 | return res 1003 | -------------------------------------------------------------------------------- /mesaPlot/version.py: -------------------------------------------------------------------------------- 1 | try: 2 | from importlib import metadata 3 | except ImportError: # for Python<3.8 4 | import importlib_metadata as metadata # type: ignore 5 | 6 | try: 7 | __version__ = metadata.version("mesaplot") 8 | except metadata.PackageNotFoundError: 9 | # package is not installed 10 | pass -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=64", "wheel", "setuptools_scm[toml]>=7.1.0"] 3 | # Python 3.7 doesnt go above 7.1.0 4 | 5 | [tool.pytest.ini_options] 6 | testpaths = [ 7 | "tests", 8 | ] 9 | addopts = "-s" 10 | 11 | [tool.setuptools_scm] 12 | 13 | 14 | [project] 15 | name = "mesaPlot" 16 | authors = [ 17 | {name="Robert Farmer", email="robert.j.farmer37@gmail.com"} 18 | ] 19 | description = "Library for reading and plotting MESA data" 20 | readme = "README.md" 21 | requires-python = ">=3.7" 22 | license = {text = "GPLv2+"} 23 | classifiers = [ 24 | "Programming Language :: Python :: 3", 25 | "Programming Language :: Python :: 3 :: Only", 26 | "Programming Language :: Python :: 3.7", 27 | "Programming Language :: Python :: 3.8", 28 | "Programming Language :: Python :: 3.9", 29 | "Programming Language :: Python :: 3.10", 30 | "Programming Language :: Python :: 3.11", 31 | "Programming Language :: Python :: 3.12", 32 | "Topic :: Scientific/Engineering :: Astronomy", 33 | "Intended Audience :: Science/Research", 34 | ] 35 | 36 | 37 | dependencies = [ 38 | "numpy", 39 | "matplotlib", 40 | "scipy", 41 | "pandas", 42 | "importlib_metadata" # Needed for python <3.8 43 | ] 44 | 45 | dynamic = ["version"] 46 | 47 | 48 | [project.optional-dependencies] 49 | test = ['pytest', 'tox'] 50 | dev = ['pre-commit','black'] -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup() 4 | 5 | -------------------------------------------------------------------------------- /tests/LOGS/profiles.index: -------------------------------------------------------------------------------- 1 | 6 models. lines hold model number, priority, and profile number. 2 | 1 2 1 3 | 10 1 2 4 | 20 1 3 5 | 30 1 4 6 | 40 1 5 7 | 50 1 6 8 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rjfarmer/mesaplot/324f142b8f941241db53c5a948c1ded62083f1cc/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_mesaplot.py: -------------------------------------------------------------------------------- 1 | 2 | import unittest as unittest 3 | 4 | 5 | import mesaPlot as mp 6 | import os 7 | import matplotlib.pyplot as plt 8 | 9 | os.chdir('tests') 10 | 11 | class TestFileReader(unittest.TestCase): 12 | def test_init(self): 13 | m=mp.MESA() 14 | 15 | def test_load_history1(self): 16 | m=mp.MESA() 17 | m.loadHistory() 18 | 19 | def test_load_history2(self): 20 | m=mp.MESA() 21 | m.log_fold='LOGS/' 22 | m.loadHistory() 23 | 24 | def test_load_profile1(self): 25 | m=mp.MESA() 26 | m.loadProfile(num=1) 27 | 28 | def test_load_profile2(self): 29 | m=mp.MESA() 30 | m.log_fold='LOGS/' 31 | m.loadProfile(num=-1) 32 | 33 | def test_load_profile3(self): 34 | m=mp.MESA() 35 | m.log_fold='LOGS/' 36 | m.loadProfile(num=-2) 37 | 38 | def test_load_profile3(self): 39 | m=mp.MESA() 40 | m.log_fold='LOGS/' 41 | m.loadProfile(f='LOGS/profile1.data') 42 | 43 | 44 | class TestPlot(unittest.TestCase): 45 | def setUp(self): 46 | self.m=mp.MESA() 47 | self.p=mp.plot() 48 | self.m.loadHistory() 49 | self.m.loadProfile(num=1) 50 | 51 | def tearDown(self): 52 | plt.close('all') 53 | 54 | def test_plotHR(self): 55 | self.p.plotHR(self.m,show=False) 56 | 57 | def test_plotNeu(self): 58 | self.p.plotNeu(self.m,show=False) 59 | 60 | def test_abun(self): 61 | self.p.plotAbun(self.m,show=False) 62 | 63 | def test_plotAbunByA(self): 64 | self.p.plotAbunByA(self.m,show=False) 65 | 66 | def test_plotAbunHist(self): 67 | self.p.plotAbunHist(self.m,show=False) 68 | 69 | def test_plotAbunPAndN(self): 70 | self.p.plotAbunPAndN(self.m,show=False) 71 | 72 | def test_plotAngMom(self): 73 | self.p.plotAngMom(self.m,show=False) 74 | 75 | def test_plotBurn(self): 76 | self.p.plotBurn(self.m,show=False) 77 | 78 | def test_plotBurnHist(self): 79 | self.p.plotBurnHist(self.m,show=False) 80 | 81 | def test_plotDynamo(self): 82 | self.p.plotDynamo(self.m,show=False) 83 | 84 | def test_plotHistory(self): 85 | self.p.plotHistory(self.m,show=False) 86 | 87 | def test_plotProfile(self): 88 | self.p.plotProfile(self.m,show=False) 89 | 90 | def test_plotKip(self): 91 | self.p.plotKip(self.m,show=False) 92 | 93 | def test_plotKip2(self): 94 | self.p.plotKip2(self.m,show=False) 95 | 96 | def test_plotKip3(self): 97 | self.p.plotKip3(self.m,show=False) 98 | 99 | def test_plotKip3(self): 100 | self.p.plotKip3(self.m,show=False,age_lookback=True,xaxis='star_age') 101 | 102 | def test_plotMix(self): 103 | self.p.plotMix(self.m,show=False) 104 | 105 | def test_plotTRho(self): 106 | self.p.plotTRho(self.m,show=False) 107 | 108 | def test_plotLdivM(self): 109 | self.p.plotLdivM(self.m,show=False) 110 | 111 | -------------------------------------------------------------------------------- /tests/work/history_columns.list: -------------------------------------------------------------------------------- 1 | ! history_columns.list -- determines the contents of star history logs 2 | ! you can use a non-standard version by setting history_columns_file in your inlist 3 | 4 | ! units are cgs unless otherwise noted. 5 | 6 | ! reorder the following names as desired to reorder columns. 7 | ! comment out the name to omit a column (fewer columns => less IO => faster running). 8 | ! remove '!' to restore a column. 9 | 10 | ! if you have a situation where you want a non-standard set of columns, 11 | ! make a copy of this file, edit as desired, and give the new filename in your inlist 12 | ! as history_columns_file. if you are just adding columns, you can 'include' this file, 13 | ! and just list the additions in your file. note: to include the standard default 14 | ! version, use include '' -- the 0 length string means include the default file. 15 | 16 | ! blank lines and comments can be used freely. 17 | ! if a column name appears more than once in the list, only the first occurrence is used. 18 | 19 | ! if you need to have something added to the list of options, let me know.... 20 | 21 | 22 | ! the first few lines of the log file contain a few items: 23 | 24 | ! version_number -- for the version of mesa being used 25 | ! burn_min1 -- 1st limit for reported burning, in erg/g/s 26 | ! burn_min2 -- 2nd limit for reported burning, in erg/g/s 27 | 28 | 29 | !# other files 30 | 31 | ! note: you can include another list by doing 32 | ! include 'filename' 33 | ! include '' means include the default standard list file 34 | 35 | ! the following lines of the log file contain info about 1 model per row 36 | 37 | !---------------------------------------------------------------------------------------------- 38 | 39 | !# general info about the model 40 | 41 | model_number ! counting from the start of the run 42 | num_zones ! number of zones in the model 43 | !version_number ! mesa version from file mesa/data/version_number 44 | 45 | !## age 46 | 47 | star_age ! elapsed simulated time in years since the start of the run 48 | !star_age_sec ! elapsed simulated time in seconds since the start of the run 49 | !star_age_min ! elapsed simulated time in minutes since the start of the run 50 | !star_age_hr ! elapsed simulated time in hours since the start of the run 51 | !star_age_day ! elapsed simulated time in days since the start of the run 52 | 53 | !log_star_age 54 | !log_star_age_sec 55 | 56 | !## timestep 57 | 58 | !time_step ! timestep in years since previous model 59 | !time_step_sec ! timestep in seconds since previous model 60 | log_dt ! log10 time_step in years 61 | !log_dt_sec ! log10 time_step in seconds 62 | 63 | !## mass 64 | 65 | star_mass ! in Msun units 66 | !log_star_mass 67 | 68 | !star_gravitational_mass ! star_mass is baryonic mass 69 | !star_mass_grav_div_mass 70 | 71 | !delta_mass ! star_mass - initial_mass in Msun units 72 | log_xmstar ! log10 mass exterior to M_center (grams) 73 | 74 | !## mass change 75 | 76 | !star_mdot ! d(star_mass)/dt (in msolar per year) 77 | log_abs_mdot ! log10(abs(star_mdot)) (in msolar per year) 78 | 79 | !## imposed surface conditions 80 | !Tsurf_factor 81 | !tau_factor 82 | !tau_surface 83 | !surface_extra_Pgas 84 | 85 | !## imposed center conditions 86 | m_center 87 | !m_center_gm 88 | r_center 89 | !r_center_cm 90 | L_center 91 | !log_L_center 92 | !log_L_center_ergs_s 93 | v_center 94 | 95 | !---------------------------------------------------------------------------------------------- 96 | 97 | !# mixing and convection 98 | 99 | !max_conv_vel_div_csound 100 | !max_gradT_div_grada 101 | !max_gradT_sub_grada 102 | !min_log_mlt_Gamma 103 | !max_conv_dP_term 104 | 105 | 106 | !## mixing regions 107 | 108 | mass_conv_core ! (Msun) mass coord of top of convective core. 0 if core is not convective 109 | 110 | ! mx1 refers to the largest (by mass) convective region. 111 | ! mx2 is the 2nd largest. 112 | 113 | ! conv_mx1_top and conv_mx1_bot are the region where mixing_type == convective_mixing. 114 | ! mx1_top and mx1_bot are the extent of all kinds of mixing, convective and other. 115 | 116 | ! values are m/Mstar 117 | conv_mx1_top 118 | conv_mx1_bot 119 | conv_mx2_top 120 | conv_mx2_bot 121 | mx1_top 122 | mx1_bot 123 | mx2_top 124 | mx2_bot 125 | 126 | ! radius -- values are radii in Rsun units 127 | !conv_mx1_top_r 128 | !conv_mx1_bot_r 129 | !conv_mx2_top_r 130 | !conv_mx2_bot_r 131 | !mx1_top_r 132 | !mx1_bot_r 133 | !mx2_top_r 134 | !mx2_bot_r 135 | 136 | ! you might want to get a more complete list of mixing regions by using the following 137 | 138 | !mixing_regions ! note: this includes regions where the mixing type is no_mixing. 139 | 140 | ! the is the number of regions to report 141 | ! there will be 2* columns for this in the log file, 2 for each region. 142 | ! the first column for a region gives the mixing type as defined in const/public/const_def.f90. 143 | 144 | ! the second column for a region gives the m/mstar location of the top of the region 145 | ! entries for extra columns after the last region in the star will have an invalid mixing_type value of -1. 146 | ! mstar is the total mass of the star, so these locations range from 0 to 1 147 | ! all regions are include starting from the center, so the bottom of one region 148 | ! is the top of the previous one. since we start at the center, the bottom of the 1st region is 0. 149 | 150 | ! the columns in the log file will have names like 'mix_type_1' and 'mix_qtop_1' 151 | 152 | ! if the star has too many regions to report them all, 153 | ! the smallest regions will be merged with neighbors for reporting purposes only. 154 | 155 | mixing_regions 20 156 | burning_regions 20 157 | !mix_relr_regions 158 | ! same as above, but locations given as r/rstar instead of m/mstar. 159 | ! the columns in the log file will have names like 'mix_relr_type_1' and 'mix_relr_top_1' 160 | 161 | 162 | !## conditions at base of largest convection zone (by mass) 163 | !cz_bot_mass ! mass coordinate of base (Msun) 164 | !cz_mass ! mass coordinate of base (Msun) -- same as cz_bot_mass 165 | !cz_log_xmass ! mass exterior to base (g) 166 | !cz_log_xmsun ! mass exterior to base (Msun) 167 | !cz_xm ! mass exterior to base (Msun) 168 | !cz_logT 169 | !cz_logRho 170 | !cz_logP 171 | !cz_bot_radius ! Rsun 172 | !cz_log_column_depth 173 | !cz_log_radial_depth 174 | !cz_luminosity ! Lsun 175 | !cz_opacity 176 | !cz_log_tau 177 | !cz_eta 178 | !cz_log_eps_nuc ! log10(ergs/g/s) 179 | !cz_t_heat ! Cp*T/eps_nuc (seconds) 180 | 181 | !cz_csound 182 | !cz_scale_height 183 | !cz_grav 184 | 185 | !cz_omega 186 | !cz_omega_div_omega_crit 187 | 188 | !cz_zone 189 | 190 | ! mass fractions at base of largest convection zone (by mass) 191 | !cz_log_xa h1 192 | !cz_log_xa he4 193 | 194 | !## conditions at top of largest convection zone (by mass) 195 | !cz_top_mass ! mass coordinate of top (Msun) 196 | !cz_top_log_xmass ! mass exterior to top (g) 197 | !cz_top_log_xmsun ! mass exterior to top (Msun) 198 | !cz_top_xm ! mass exterior to top (Msun) 199 | !cz_top_logT 200 | !cz_top_logRho 201 | !cz_top_logP 202 | !cz_top_radius ! Rsun 203 | !cz_top_log_column_depth 204 | !cz_top_log_radial_depth 205 | !cz_top_luminosity ! Lsun 206 | !cz_top_opacity 207 | !cz_top_log_tau 208 | !cz_top_eta 209 | !cz_top_log_eps_nuc ! log10(ergs/g/s) 210 | !cz_top_t_heat ! Cp*T/eps_nuc (seconds) 211 | 212 | !cz_top_csound 213 | !cz_top_scale_height 214 | !cz_top_grav 215 | 216 | !cz_top_omega 217 | !cz_top_omega_div_omega_crit 218 | 219 | !cz_top_zone 220 | !cz_top_zone_logdq 221 | 222 | ! mass fractions at top of largest convection zone (by mass) 223 | !cz_top_log_xa h1 224 | !cz_top_log_xa he4 225 | 226 | !---------------------------------------------------------------------------------------------- 227 | 228 | !# nuclear reactions 229 | 230 | !## integrated quantities 231 | 232 | !power_h_burn ! total thermal power from PP and CNO, excluding neutrinos (in Lsun units) 233 | !power_he_burn ! total thermal power from triple-alpha, excluding neutrinos (in Lsun units) 234 | !power_c_burn ! total thermal power from carbon burning, excluding neutrinos (in Lsun units) 235 | !log_power_nuc_burn ! total thermal power from all burning, excluding photodisintegrations 236 | log_LH ! log10 power_h_burn 237 | log_LHe ! log10 power_he_burn 238 | !log_LC ! log10 power_c_burn 239 | log_LZ ! log10 total burning power including LC, but excluding LH and LHe and photodisintegrations 240 | log_Lnuc ! log(LH + LHe + LZ) 241 | !log_Lnuc_ergs_s 242 | !log_Lnuc_sub_log_L 243 | 244 | !extra_L ! integral of extra_heat in Lsun units 245 | !log_extra_L ! log10 extra_L 246 | 247 | !## neutrino losses 248 | !log_Lneu ! log10 power emitted in neutrinos, nuclear and thermal (in Lsun units) 249 | !log_Lneu_nuc ! log10 power emitted in neutrinos, nuclear sources only (in Lsun units) 250 | !log_Lneu_nonnuc ! log10 power emitted in neutrinos, thermal sources only (in Lsun units) 251 | 252 | !mass_loc_of_max_eps_nuc ! (in Msun units) 253 | !mass_ext_to_max_eps_nuc ! (in Msun units) 254 | !eps_grav_integral ! (in Lsun units) 255 | !log_abs_Lgrav ! log10 abs(eps_grav_integral) (in Lsun units) 256 | 257 | !## information about reactions (by category) 258 | 259 | ! log10 total luminosity for reaction categories (Lsun units) 260 | 261 | pp 262 | cno 263 | tri_alfa 264 | burn_c 265 | burn_n 266 | burn_o 267 | burn_ne 268 | burn_na 269 | burn_mg 270 | burn_si 271 | burn_s 272 | burn_ar 273 | burn_ca 274 | burn_ti 275 | burn_cr 276 | burn_fe 277 | c12_c12 278 | c12_o16 279 | o16_o16 280 | photo 281 | pnhe4 282 | !other 283 | 284 | !## nuclear reactions at center 285 | 286 | ! center log10 burn erg/g/s for reaction categories 287 | 288 | !c_log_eps_burn cno 289 | !c_log_eps_burn tri_alfa 290 | 291 | ! center d_eps_nuc_dlnd for reaction categories 292 | 293 | !c_d_eps_dlnd cno 294 | !c_d_eps_dlnd tri_alfa 295 | 296 | ! center d_eps_nuc_dlnT for reaction categories 297 | 298 | !c_d_eps_dlnT cno 299 | !c_d_eps_dlnT tri_alfa 300 | 301 | !## regions of strong nuclear burning 302 | 303 | ! 2 zones where eps_nuc > burn_min1 erg/g/s 304 | ! for each zone have 4 numbers: start1, start2, end2, end1 305 | ! start1 is mass of inner edge where first goes > burn_min1 (or -20 if none such) 306 | ! start2 is mass of inner edge where first zone reaches burn_min2 erg/g/sec (or -20 if none such) 307 | ! end2 is mass of outer edge where first zone drops back below burn_min2 erg/g/s 308 | ! end1 is mass of outer edge where first zone ends (i.e. eps_nuc < burn_min1) 309 | ! similar for the second zone 310 | 311 | epsnuc_M_1 ! start1 for 1st zone 312 | epsnuc_M_2 ! start2 313 | epsnuc_M_3 ! end2 314 | epsnuc_M_4 ! end1 315 | 316 | epsnuc_M_5 ! start1 for 2nd zone 317 | epsnuc_M_6 ! start2 318 | epsnuc_M_7 ! end2 319 | epsnuc_M_8 ! end1 320 | 321 | 322 | ! you might want to get a more complete list of burning regions by using the following 323 | 324 | !burning_regions 325 | ! the is the number of regions to report 326 | ! there will be 2* columns for this in the log file, 2 for each region. 327 | ! the first column for a region gives int(sign(val)*log10(max(1,abs(val)))) 328 | ! where val = ergs/gm/sec nuclear energy minus all neutrino losses. 329 | ! the second column for a region gives the q location of the top of the region 330 | ! entries for extra columns after the last region in the star will have a value of -9999 331 | ! all regions are included starting from the center, so the bottom of one region 332 | ! is the top of the previous one. 333 | ! since we start at the center, the bottom of the 1st region is q=0 and top of last is q=1. 334 | 335 | ! the columns in the log file will have names like 'burn_type_1' and 'burn_qtop_1' 336 | 337 | 338 | ! if the star has too many regions to report them all, 339 | ! the smallest regions will be merged with neighbors for reporting purposes only. 340 | 341 | !---------------------------------------------------------------------------------------------- 342 | 343 | !# information about core and envelope 344 | 345 | !## helium core 346 | he_core_mass 347 | !he_core_radius 348 | !he_core_lgT 349 | !he_core_lgRho 350 | !he_core_L 351 | !he_core_v 352 | !he_core_omega 353 | !he_core_omega_div_omega_crit 354 | !he_core_k 355 | 356 | !## carbon core 357 | c_core_mass 358 | !c_core_radius 359 | !c_core_lgT 360 | !c_core_lgRho 361 | !c_core_L 362 | !c_core_v 363 | !c_core_omega 364 | !c_core_omega_div_omega_crit 365 | !c_core_k 366 | 367 | !## oxygen core 368 | o_core_mass 369 | !o_core_radius 370 | !o_core_lgT 371 | !o_core_lgRho 372 | !o_core_L 373 | !o_core_v 374 | !o_core_omega 375 | !o_core_omega_div_omega_crit 376 | !o_core_k 377 | 378 | !## silicon core 379 | si_core_mass 380 | !si_core_radius 381 | !si_core_lgT 382 | !si_core_lgRho 383 | !si_core_L 384 | !si_core_v 385 | !si_core_omega 386 | !si_core_omega_div_omega_crit 387 | !si_core_k 388 | 389 | !## iron core 390 | fe_core_mass 391 | !fe_core_radius 392 | !fe_core_lgT 393 | !fe_core_lgRho 394 | !fe_core_L 395 | !fe_core_v 396 | !fe_core_omega 397 | !fe_core_omega_div_omega_crit 398 | !fe_core_k 399 | 400 | !## neuton rich core 401 | neutron_rich_core_mass 402 | !neutron_rich_core_radius 403 | !neutron_rich_core_lgT 404 | !neutron_rich_core_lgRho 405 | !neutron_rich_core_L 406 | !neutron_rich_core_v 407 | !neutron_rich_core_omega 408 | !neutron_rich_core_omega_div_omega_crit 409 | !neutron_rich_core_k 410 | 411 | !## envelope 412 | 413 | !envelope_mass ! = star_mass - he_core_mass 414 | !envelope_fraction_left ! = envelope_mass / (initial_mass - he_core_mass) 415 | 416 | !h_rich_layer_mass ! = star_mass - he_core_mass 417 | !he_rich_layer_mass ! = he_core_mass - c_core_mass 418 | !c_rich_layer_mass ! = c_core_mass - o_core_mass 419 | !o_rich_layer_mass ! = o_core_mass - si_core_mass 420 | !si_rich_layer_mass ! = si_core_mass - fe_core_mass 421 | 422 | 423 | !---------------------------------------------------------------------------------------------- 424 | 425 | !# timescales 426 | 427 | !dynamic_timescale ! dynamic timescale (seconds) -- estimated by 2*pi*sqrt(r^3/(G*m)) 428 | !kh_timescale ! kelvin-helmholtz timescale (years) 429 | !mdot_timescale ! star_mass/abs(star_mdot) (years) 430 | !kh_div_mdot_timescales ! kh_timescale/mdot_timescale 431 | !nuc_timescale ! nuclear timescale (years) -- proportional to mass divided by luminosity 432 | !log_chem_timescale ! burn+mix timescale (years) 433 | ! approximately min over all cells k and species i of x(i,k)/abs(dxdt_mix + dxdt_burn) 434 | !log_chem_timescale_div_time_step 435 | !log_cell_collapse_timescale 436 | 437 | !dt_cell_collapse ! min time for any cell to collapse at current velocities 438 | !dt_div_dt_cell_collapse 439 | 440 | 441 | !min_dr_div_cs ! min over all cells of dr/csound (seconds) 442 | !min_dr_div_cs_k ! location of min 443 | !log_min_dr_div_cs ! log10 min dr_div_csound (seconds) 444 | !min_dr_div_cs_yr ! min over all cells of dr/csound (years) 445 | !log_min_dr_div_cs_yr ! log10 min dr_div_csound (years) 446 | !dt_div_min_dr_div_cs 447 | !log_dt_div_min_dr_div_cs 448 | 449 | !min_t_eddy ! minimum value of scale_height/conv_velocity 450 | 451 | !---------------------------------------------------------------------------------------------- 452 | 453 | !# conditions at or near the surface of the model 454 | 455 | !## conditions at the photosphere 456 | !effective_T 457 | log_Teff ! log10 effective temperature 458 | 459 | !photosphere_black_body_T 460 | !photosphere_cell_T 461 | !photosphere_cell_log_T 462 | !photosphere_cell_density 463 | !photosphere_cell_log_density 464 | !photosphere_cell_opacity 465 | !photosphere_cell_log_opacity 466 | !photosphere_L ! Lsun units 467 | !photosphere_log_L ! Lsun units 468 | !photosphere_r ! Rsun units 469 | !photosphere_log_r ! Rsun units 470 | !photosphere_m ! Msun units 471 | !photosphere_v_km_s 472 | !photosphere_cell_k 473 | !photosphere_column_density 474 | !photosphere_csound 475 | !photosphere_log_column_density 476 | !photosphere_opacity 477 | !photosphere_v_div_cs 478 | !photosphere_xm 479 | 480 | !## conditions at or near the surface of the model (outer edge of outer cell) 481 | 482 | !luminosity ! luminosity in Lsun units 483 | !luminosity_ergs_s ! luminosity in cgs units 484 | log_L ! log10 luminosity in Lsun units 485 | !log_L_ergs_s ! log10 luminosity in cgs units 486 | !radius ! Rsun 487 | log_R ! log10 radius in Rsun units 488 | !radius_cm 489 | !log_R_cm 490 | 491 | log_g ! log10 gravity 492 | !gravity 493 | !log_Ledd 494 | !log_L_div_Ledd ! log10(L/Leddington) 495 | !lum_div_Ledd 496 | !log_surf_optical_depth 497 | !surface_optical_depth 498 | 499 | !log_surf_cell_opacity ! old name was log_surf_opacity 500 | !log_surf_cell_P ! old name was log_surf_P 501 | !log_surf_cell_pressure ! old name was log_surf_pressure 502 | !log_surf_cell_density ! old name was log_surf_density 503 | !log_surf_cell_temperature ! old name was log_surf_temperature 504 | !surface_cell_temperature ! old name was surface_temperature 505 | !log_surf_cell_z ! old name was log_surf_z 506 | !surface_cell_entropy ! in units of kerg per baryon 507 | ! old name was surface_entropy 508 | 509 | !v_surf ! (cm/s) 510 | !v_surf_km_s ! (km/s) 511 | v_div_csound_surf ! velocity divided by sound speed at outermost grid point 512 | !v_div_csound_max ! max value of velocity divided by sound speed at face 513 | 514 | !v_surf_div_v_kh ! v_surf/(photosphere_r/kh_timescale) 515 | !surface_accel_div_grav ! (v - v_old)/dt divided by GM/R^2 at outermost grid point 516 | 517 | !surf_avg_j_rot 518 | !surf_avg_omega 519 | !surf_avg_omega_crit 520 | !surf_avg_omega_div_omega_crit 521 | !surf_avg_v_rot ! km/sec rotational velocity at equator 522 | !surf_avg_v_crit ! critical rotational velocity at equator 523 | !surf_avg_v_div_v_crit 524 | !surf_avg_Lrad_div_Ledd 525 | !surf_avg_logT 526 | !surf_avg_logRho 527 | !surf_avg_opacity 528 | 529 | !Gravity Darkening, reports the surface averaged L/Lsun and Teff (K) caused by 530 | !gravity darkening in rotating stars. Based on the model of Espinosa Lara & Rieutord (2011) 531 | !'polar' refers to the line of sight being directed along the rotation axis of the star 532 | !'equatorial' refers to the line of sight coincident with the stellar equator 533 | !grav_dark_L_polar !Lsun 534 | !grav_dark_Teff_polar !K 535 | !grav_dark_L_equatorial !Lsun 536 | !grav_dark_Teff_equatorial !K 537 | 538 | !surf_escape_v ! cm/s 539 | 540 | !v_wind_Km_per_s ! Km/s 541 | ! = 1d-5*s% opacity(1)*max(0d0,-s% mstar_dot)/ & 542 | ! (4*pi*s% photosphere_r*Rsun*s% tau_base) 543 | ! Lars says: 544 | ! wind_mdot = 4*pi*R^2*rho*v_wind 545 | ! tau = integral(opacity*rho*dr) from R to infinity 546 | ! so tau = opacity*wind_mdot/(4*pi*R*v_wind) at photosphere 547 | ! or v_wind = opacity*wind_mdot/(4*pi*R*tau) at photosphere 548 | 549 | !rotational_mdot_boost ! factor for increase in mass loss mdot due to rotation 550 | !log_rotational_mdot_boost ! log factor for increase in mass loss mdot due to rotation 551 | !surf_r_equatorial_div_r_polar 552 | !surf_r_equatorial_div_r 553 | !surf_r_polar_div_r 554 | 555 | !## info about location where optical depth is 10 556 | 557 | !tau10_mass ! mass in solar units where optical depth = 10 558 | !tau10_radius ! radius in solar units where optical depth = 10 559 | !tau10_lgP ! estimate for log10(P) at tau = 10 560 | !tau10_T ! estimate for T at tau = 10 561 | !tau10_lgT ! estimate for log10(T) at tau = 10 562 | !tau10_lgRho ! estimate for log10(density) at tau = 10 563 | !tau10_L ! estimate for L/Lsun at tau = 10 564 | 565 | !## info about location where optical depth is 100 566 | 567 | !tau100_mass ! location in solar units where optical depth = 100 568 | !tau100_radius ! location in solar units where optical depth = 100 569 | !tau100_lgP ! estimates for values at tau = 100 570 | !tau100_T 571 | !tau100_lgT 572 | !tau100_lgRho 573 | !tau100_L 574 | 575 | !---------------------------------------------------------------------------------------------- 576 | 577 | !# conditions near center 578 | 579 | log_center_T ! temperature 580 | log_center_Rho ! density 581 | !log_center_P ! pressure 582 | 583 | ! shorter names for above 584 | log_cntr_P 585 | log_cntr_Rho 586 | log_cntr_T 587 | 588 | !center_T ! temperature 589 | !center_Rho ! density 590 | !center_P ! pressure 591 | 592 | !center_degeneracy ! the electron chemical potential in units of k*T 593 | !center_gamma ! plasma interaction parameter 594 | center_mu 595 | center_ye 596 | center_abar 597 | !center_zbar 598 | 599 | !center_eps_grav 600 | !center_dL_dm 601 | !center_dlnT_dt 602 | !center_dlnd_dt 603 | !center_dlogRho 604 | !center_dlogT 605 | 606 | !center_non_nuc_neu 607 | !center_eps_nuc 608 | !d_center_eps_nuc_dlnT 609 | !d_center_eps_nuc_dlnd 610 | !log_center_eps_nuc 611 | 612 | !center_entropy ! in units of kerg per baryon 613 | !max_entropy ! in units of kerg per baryon 614 | !fe_core_infall 615 | !non_fe_core_infall 616 | !max_infall_speed_mass 617 | 618 | !compactness_parameter ! (m/Msun)/(R(m)/1000km) for m = 2.5 Msun 619 | 620 | !center_omega 621 | !center_omega_div_omega_crit 622 | 623 | !---------------------------------------------------------------------------------------------- 624 | 625 | !# abundances 626 | 627 | !species ! size of net 628 | 629 | !## mass fractions near center 630 | 631 | ! the following controls automatically add columns for all of the isos that are in the current net 632 | add_center_abundances 633 | !add_log_center_abundances 634 | 635 | ! individual central mass fractions (as many as desired) 636 | center h1 637 | center he4 638 | center c12 639 | center o16 640 | 641 | ! individual log10 central mass fractions (as many as desired) 642 | !log_center h1 643 | !log_center he4 644 | ! etc. 645 | 646 | 647 | !## mass fractions near surface 648 | 649 | ! the following controls automatically add columns for all of the isos that are in the current net 650 | !add_surface_abundances 651 | !add_log_surface_abundances 652 | 653 | ! individual surface mass fractions (as many as desired) 654 | !surface h1 655 | !surface he4 656 | surface c12 657 | surface o16 658 | ! etc. 659 | 660 | ! individual log10 surface mass fractions (as many as desired) 661 | 662 | !log_surface h1 663 | !log_surface he4 664 | 665 | 666 | !## mass fractions for entire star 667 | 668 | ! the following controls automatically add columns for all of the isos that are in the current net 669 | !add_average_abundances 670 | !add_log_average_abundances 671 | 672 | ! individual average mass fractions (as many as desired) 673 | !average h1 674 | !average he4 675 | ! etc. 676 | 677 | ! individual log10 average mass fractions (as many as desired) 678 | !log_average h1 679 | !log_average he4 680 | ! etc. 681 | 682 | 683 | !## mass totals for entire star (in Msun units) 684 | 685 | ! the following controls automatically add columns for all of the isos that are in the current net 686 | !add_total_mass 687 | !add_log_total_mass 688 | 689 | ! individual mass totals for entire star (as many as desired) 690 | total_mass h1 691 | total_mass he4 692 | ! etc. 693 | 694 | !individial log10 mass totals for entire star (in Msun units) 695 | !log_total_mass h1 696 | !log_total_mass he4 697 | ! etc. 698 | 699 | !---------------------------------------------------------------------------------------------- 700 | 701 | !# info at specific locations 702 | 703 | !## info at a specified mass coordinate (given by trace_mass_location) 704 | !trace_mass_location ! (Msun) 705 | !trace_mass_radius ! (Rsun) 706 | !trace_mass_lgT 707 | !trace_mass_lgRho 708 | !trace_mass_L ! (Lsun) 709 | !trace_mass_v 710 | 711 | !trace_mass_lgP 712 | !trace_mass_g 713 | !trace_mass_X 714 | !trace_mass_Y 715 | !trace_mass_edv_H 716 | !trace_mass_edv_He 717 | !trace_mass_scale_height 718 | !trace_mass_dlnX_dr 719 | !trace_mass_dlnY_dr 720 | !trace_mass_dlnRho_dr 721 | 722 | !trace_mass_omega 723 | !trace_mass_omega_div_omega_crit 724 | 725 | 726 | !## info at location of max temperature 727 | !max_T 728 | !log_max_T 729 | !max_T_lgT ! equivalent to above 730 | !max_T_mass ! (Msun) 731 | !max_T_radius ! (Rsun) 732 | !max_T_lgRho 733 | !max_T_lgP 734 | !max_T_entropy 735 | !max_T_L ! (Lsun) 736 | !max_T_eps_nuc ! (erg/g/s) 737 | !max_T_lgP_thin_shell ! log10(G*Mcore*Menv/(4*pi*Rcore^4)) 738 | ! Mcore = Msun*max_T_mass, 739 | ! Menv = Msun*(star_mass - max_T_mass), 740 | ! Rcore = Rsun*max_T_radius 741 | !max_T_shell_binding_energy ! integral from max_T out 742 | 743 | 744 | !## info about location where have max rate of hydrogen burning (PP and CNO) 745 | !max_eps_h ! erg/g/s 746 | !max_eps_h_lgT ! log10 temperature at location of max burn 747 | !max_eps_h_lgRho ! log10 density at location of max burn 748 | !max_eps_h_m ! mass coordinate at location of max burn (Msun units) 749 | !max_eps_h_xm ! mass exterior to location of max burn (Msun units) 750 | !max_eps_h_lgP ! log10 pressure at location of max burn 751 | !max_eps_h_lgR ! log10 radius at location of max burn 752 | !max_eps_h_opacity ! opacity at location of max burn 753 | 754 | !## info about location where have max rate of helium burning 755 | ! triple-alpha plus alpha capture on C12, N14, O16, and Ne20. 756 | !max_eps_he ! erg/g/s 757 | !max_eps_he_lgT ! log10 temperature at location of max_eps_he 758 | !max_eps_he_lgRho ! log10 density at location of max burn 759 | !max_eps_he_m ! mass coordinate at location of max burn (Msun units) 760 | !max_eps_he_xm ! mass exterior to location of max burn (Msun units) 761 | !max_eps_he_lgP ! log10 pressure at location of max burn 762 | !max_eps_he_lgR ! log10 radius at location of max burn 763 | !max_eps_he_opacity ! opacity at location of max burn 764 | 765 | !## info about location where have max rate of burning of metals 766 | ! alpha capture on heavy elements plus C+C, C+O, O+O, etc. 767 | !max_eps_z ! erg/g/s 768 | !max_eps_z_lgT ! log10 temperature at location of max burn 769 | !max_eps_z_lgRho ! log10 density at location of max burn 770 | !max_eps_z_m ! mass coordinate at location of max burn (Msun units) 771 | !max_eps_z_xm ! mass exterior to location of max burn (Msun units) 772 | !max_eps_z_lgP ! log10 pressure at location of max burn 773 | !max_eps_z_lgR ! log10 radius at location of max burn 774 | !max_eps_z_opacity ! opacity at location of max burn 775 | 776 | !## info about location where have max rate of burning of all types 777 | !max_eps_nuc ! erg/g/s 778 | !max_eps_nuc_lgT ! log10 temperature at location of max burn 779 | !max_eps_nuc_lgRho ! log10 density at location of max burn 780 | !max_eps_nuc_m ! mass coordinate at location of max burn (Msun units) 781 | !max_eps_nuc_xm ! mass exterior to location of max burn (Msun units) 782 | !max_eps_nuc_lgP ! log10 pressure at location of max burn 783 | !max_eps_nuc_lgR ! log10 radius at location of max burn 784 | !max_eps_nuc_opacity ! opacity at location of max burn 785 | !max_eps_nuc_cp ! Cp at location of max burn 786 | !max_eps_nuc_t_heat ! Cp*T/eps_nuc at location of max burn 787 | !max_eps_nuc_csound 788 | !max_eps_nuc_pi_r_div_cs 789 | !max_eps_nuc_H ! pressure scale height 790 | !max_eps_nuc_H_div_cs 791 | !max_eps_nuc_log_xa he4 ! any species 792 | 793 | !## info at location of max abs velocity 794 | ! note: can use control "min_tau_for_max_abs_v_location" to exclude surface 795 | !max_abs_v_velocity 796 | !max_abs_v_csound 797 | !max_abs_v_v_div_cs 798 | !max_abs_v_lgT 799 | !max_abs_v_lgRho 800 | !max_abs_v_lgP 801 | !max_abs_v_gamma1 802 | !max_abs_v_mass 803 | !max_abs_v_radius 804 | !max_abs_v_radius_cm 805 | !max_abs_v_lgR ! Rsun 806 | !max_abs_v_lgR_cm 807 | !max_abs_v_L ! Lsun 808 | !max_abs_v_entropy 809 | !max_abs_v_eps_nuc 810 | !max_abs_v_E0 ! 4/3 pi R^3 crad T^4 at max_abs_v_location 811 | 812 | !---------------------------------------------------------------------------------------------- 813 | 814 | !# information about shocks 815 | 816 | !## info about outermost outward moving shock 817 | ! excluding locations with q > max_q_for_outer_mach1_location 818 | ! returns values at location of max velocity 819 | !shock_mass ! baryonic (Msun) 820 | !shock_mass_gm ! baryonic (grams) 821 | !shock_q 822 | !shock_radius ! (Rsun) 823 | !shock_radius_cm ! (cm) 824 | !shock_velocity 825 | !shock_csound 826 | !shock_v_div_cs 827 | !shock_lgT 828 | !shock_lgRho 829 | !shock_lgP 830 | !shock_gamma1 831 | !shock_entropy 832 | !shock_tau 833 | !shock_E0 ! 4/3 pi R^3 crad T^4 at shock location 834 | !shock_k 835 | 836 | !## info at innermost mach 1 location 837 | ! excluding locations with q < min_q_for_inner_mach1_location 838 | !inner_mach1_mass ! baryonic (Msun) 839 | !inner_mach1_q 840 | !inner_mach1_radius ! (Rsun) 841 | !inner_mach1_velocity 842 | !inner_mach1_csound 843 | !inner_mach1_v_div_cs 844 | !inner_mach1_lgT 845 | !inner_mach1_lgRho 846 | !inner_mach1_lgP 847 | !inner_mach1_gamma1 848 | !inner_mach1_entropy 849 | !inner_mach1_tau 850 | !inner_mach1_k 851 | 852 | !## info at outermost mach 1 location 853 | ! excluding locations with q > max_q_for_outer_mach1_location 854 | !outer_mach1_mass ! baryonic (Msun) 855 | !outer_mach1_q 856 | !outer_mach1_radius ! (Rsun) 857 | !outer_mach1_velocity 858 | !outer_mach1_csound 859 | !outer_mach1_v_div_cs 860 | !outer_mach1_lgT 861 | !outer_mach1_lgRho 862 | !outer_mach1_lgP 863 | !outer_mach1_gamma1 864 | !outer_mach1_entropy 865 | !outer_mach1_tau 866 | !outer_mach1_k 867 | 868 | !---------------------------------------------------------------------------------------------- 869 | 870 | !# asteroseismology 871 | 872 | !delta_nu ! large frequency separation for p-modes (microHz) 873 | ! 1e6/(seconds for sound to cross diameter of star) 874 | !delta_Pg ! g-mode period spacing for l=1 (seconds) 875 | ! sqrt(2) pi^2/(integral of brunt_N/r dr) 876 | !log_delta_Pg 877 | !nu_max ! estimate from scaling relation (microHz) 878 | ! nu_max = nu_max_sun * M/Msun / ((R/Rsun)^3 (Teff/Teff_sun)^0.5) 879 | ! with nu_max_sun = 3100 microHz, Teff_sun = 5777 880 | !nu_max_3_4th_div_delta_nu ! nu_max^0.75/delta_nu 881 | !acoustic_cutoff ! 0.5*g*sqrt(gamma1*rho/P) at surface 882 | !acoustic_radius ! integral of dr/csound (seconds) 883 | !ng_for_nu_max ! = 1 / (nu_max*delta_Pg) 884 | ! period for g-mode with frequency nu_max = nu_max_ng*delta_Pg 885 | !gs_per_delta_nu ! delta_nu / (nu_max**2*delta_Pg) 886 | ! number of g-modes per delta_nu at nu_max 887 | 888 | !int_k_r_dr_nu_max_Sl1 ! integral of k_r*dr where nu < N < Sl for nu = nu_max, l=1 889 | !int_k_r_dr_2pt0_nu_max_Sl1 ! integral of k_r*dr where nu < N < Sl for nu = nu_max*2, l=1 890 | !int_k_r_dr_0pt5_nu_max_Sl1 ! integral of k_r*dr where nu < N < Sl for nu = nu_max/2, l=1 891 | !int_k_r_dr_nu_max_Sl2 ! integral of k_r*dr where nu < N < Sl for nu = nu_max, l=2 892 | !int_k_r_dr_2pt0_nu_max_Sl2 ! integral of k_r*dr where nu < N < Sl for nu = nu_max*2, l=2 893 | !int_k_r_dr_0pt5_nu_max_Sl2 ! integral of k_r*dr where nu < N < Sl for nu = nu_max/2, l=2 894 | !int_k_r_dr_nu_max_Sl3 ! integral of k_r*dr where nu < N < Sl for nu = nu_max, l=3 895 | !int_k_r_dr_2pt0_nu_max_Sl3 ! integral of k_r*dr where nu < N < Sl for nu = nu_max*2, l=3 896 | !int_k_r_dr_0pt5_nu_max_Sl3 ! integral of k_r*dr where nu < N < Sl for nu = nu_max/2, l=3 897 | 898 | !---------------------------------------------------------------------------------------------- 899 | 900 | !# energy information 901 | 902 | !total_energy ! at end of step 903 | !log_total_energy ! log(abs(total_energy)) 904 | !total_energy_start ! at start of step 905 | !total_energy_change ! end - start 906 | 907 | ! shorter versions of above 908 | !tot_E 909 | !log_tot_E 910 | !tot_E_change 911 | !tot_E_start 912 | 913 | 914 | !total_gravitational_energy 915 | !log_total_gravitational_energy ! log(abs(total_gravitational_energy)) 916 | !total_gravitational_energy_start 917 | !total_gravitational_energy_change 918 | 919 | ! shorter versions of above 920 | !tot_PE 921 | !log_tot_PE 922 | !tot_PE_start 923 | !tot_PE_change 924 | 925 | 926 | !total_internal_energy 927 | !log_total_internal_energy 928 | !total_internal_energy_start 929 | !total_internal_energy_change 930 | 931 | ! shorter versions of above 932 | !tot_IE 933 | !log_tot_IE 934 | !tot_IE_start 935 | !tot_IE_change 936 | 937 | 938 | !total_radial_kinetic_energy 939 | !log_total_radial_kinetic_energy 940 | !total_radial_kinetic_energy_start 941 | !total_radial_kinetic_energy_change 942 | 943 | ! shorter versions of above (does not include rot KE) 944 | !tot_KE 945 | !log_tot_KE 946 | !tot_KE_start 947 | !tot_KE_change 948 | 949 | 950 | !tot_IE_div_IE_plus_KE 951 | !total_IE_div_IE_plus_KE 952 | 953 | !total_IE_plus_KE 954 | !log_total_IE_plus_KE 955 | !total_IE_plus_KE_change 956 | !total_IE_plus_KE_start 957 | 958 | 959 | !total_energy_minus_sources_and_sinks 960 | !total_energy_plus_L_surf 961 | !total_entropy 962 | !total_eps_grav 963 | 964 | !total_energy_sources_and_sinks ! for this step 965 | !total_nuclear_heating 966 | !total_non_nuc_neu_cooling 967 | !total_irradiation_heating 968 | !total_extra_heating 969 | !total_Ne22_sedimentation_heating 970 | 971 | !run_deltaE 972 | !rel_run_E_err 973 | 974 | !rel_run_deltaE 975 | !log_rel_run_deltaE 976 | 977 | !rel_E_err 978 | !abs_rel_E_err 979 | !log_rel_E_err 980 | 981 | 982 | !error_in_energy_conservation ! for this step 983 | ! = total_energy - (total_energy_start + total_energy_sources_and_sinks) 984 | !cumulative_energy_error ! = sum over all steps of error_in_energy_conservation 985 | !rel_cumulative_energy_error ! = cumulative_energy_error/total_energy 986 | !log_rel_cumulative_energy_error ! = log10 of rel_cumulative_energy_error 987 | !log_rel_run_E_err ! shorter name for rel_cumulative_energy_error 988 | 989 | !rel_error_in_energy_conservation ! = error_in_energy_conservation/total_energy 990 | !log_rel_error_in_energy_conservation 991 | 992 | !total_energy_and_integrated_fluxes ! = total_energy + cumulative_sources_and_sinks 993 | 994 | !total_radiation 995 | !total_energy_plus_total_radiation 996 | 997 | 998 | !---------------------------------------------------------------------------------------------- 999 | 1000 | !# rotation 1001 | 1002 | !total_angular_momentum 1003 | !log_total_angular_momentum 1004 | 1005 | !total_rotational_kinetic_energy 1006 | !log_total_rotational_kinetic_energy 1007 | !total_rotational_kinetic_energy_start 1008 | !total_rotational_kinetic_energy_change 1009 | 1010 | !---------------------------------------------------------------------------------------------- 1011 | 1012 | !# velocities 1013 | 1014 | !avg_abs_v_div_cs 1015 | !log_avg_abs_v_div_cs 1016 | !max_abs_v_div_cs 1017 | !log_max_abs_v_div_cs 1018 | 1019 | !avg_abs_v 1020 | !log_avg_abs_v 1021 | !max_abs_v 1022 | !log_max_abs_v 1023 | 1024 | !u_surf 1025 | !u_surf_km_s 1026 | !u_div_csound_surf 1027 | !u_div_csound_max 1028 | 1029 | !---------------------------------------------------------------------------------------------- 1030 | 1031 | !# misc 1032 | 1033 | !e_thermal ! sum over all zones of Cp*T*dm 1034 | 1035 | !## eos 1036 | !logQ_max ! logQ = logRho - 2*logT + 12 1037 | !logQ_min 1038 | 1039 | !## core mixing 1040 | !core_overshoot_Hp 1041 | !core_overshoot_f 1042 | !core_overshoot_f0 1043 | !core_overshoot_hstep 1044 | !core_overshoot_r0 1045 | 1046 | !mass_bdy_core_overshooting 1047 | !radius_bdy_core_overshooting 1048 | 1049 | !mass_semiconv_core 1050 | 1051 | !## H-He boundary 1052 | 1053 | !diffusion_time_H_He_bdy 1054 | !temperature_H_He_bdy 1055 | 1056 | 1057 | !## optical depth and opacity 1058 | 1059 | !one_div_yphot 1060 | !log_one_div_yphot 1061 | 1062 | !min_kap_floor 1063 | !log_min_kap_floor 1064 | 1065 | !log_min_opacity 1066 | !min_opacity 1067 | 1068 | !log_tau_center 1069 | 1070 | 1071 | !## other 1072 | 1073 | !Lsurf_m 1074 | !dlnR_dlnM 1075 | !h1_czb_mass ! location (in Msun units) of base of 1st convection zone above he core 1076 | !kh_mdot_limit 1077 | !log_cntr_dr_cm 1078 | !min_L 1079 | !min_Pgas_div_P 1080 | !min_dL_dm 1081 | !min_dL_dm_m 1082 | !rms_dvdt_div_v 1083 | !split_mixing_choice 1084 | !surf_c12_minus_o16 ! this is useful for seeing effects of dredge up on AGB 1085 | !surf_num_c12_div_num_o16 1086 | 1087 | 1088 | 1089 | !## MLT++ 1090 | !gradT_excess_alpha 1091 | !gradT_excess_min_beta 1092 | !gradT_excess_max_lambda 1093 | 1094 | !max_L_rad_div_Ledd 1095 | !max_L_rad_div_Ledd_div_phi_Joss 1096 | 1097 | 1098 | !## RTI 1099 | !rti_regions 1100 | !alpha_RTI_avg_by_mass 1101 | 1102 | !## Ni & Co 1103 | !total_ni_co_56 1104 | !nico_escape_ergs_s 1105 | !log_nico_escape_ergs_s 1106 | 1107 | 1108 | !## internal structure constants 1109 | 1110 | ! this is evaluated assuming a spherical star and does not account for rotation 1111 | !apsidal_constant_k2 1112 | 1113 | 1114 | !---------------------------------------------------------------------------------------------- 1115 | 1116 | !# accretion 1117 | 1118 | !k_below_Eulerian_eps_grav 1119 | !q_below_Eulerian_eps_grav 1120 | !logxq_below_Eulerian_eps_grav 1121 | 1122 | !k_Lagrangian_eps_grav 1123 | !q_Lagrangian_eps_grav 1124 | !logxq_Lagrangian_eps_grav 1125 | 1126 | !k_below_const_q 1127 | !q_below_const_q 1128 | !logxq_below_const_q 1129 | 1130 | !k_const_mass 1131 | !q_const_mass 1132 | !logxq_const_mass 1133 | 1134 | !k_below_just_added 1135 | !q_below_just_added 1136 | !logxq_below_just_added 1137 | 1138 | !k_for_test_CpT_absMdot_div_L 1139 | !q_for_test_CpT_absMdot_div_L 1140 | !logxq_for_test_CpT_absMdot_div_L 1141 | 1142 | !k_CpTMdot_lt_L 1143 | !q_CpTMdot_lt_L 1144 | !logxq_CpTMdot_lt_L 1145 | 1146 | 1147 | !---------------------------------------------------------------------------------------------- 1148 | 1149 | !# Color output 1150 | 1151 | ! Outputs the bolometric correction (bc) for the star in filter band ``filter'' (case sensitive) 1152 | !bc filter 1153 | 1154 | ! Outputs the absolute magnitude for the star in filter band ``filter'' (case sensitive) 1155 | !abs_mag filter 1156 | 1157 | ! Adds all the bc's to the output 1158 | !add_bc 1159 | 1160 | ! Adds all the absolute magnitudes to the output 1161 | !add_abs_mag 1162 | 1163 | ! Outputs luminosity in filter band ``filter'' (lsun) (case sensitive) 1164 | ! lum_band filter 1165 | 1166 | ! Adds all the filter band luminosities to the output (lsun) 1167 | ! add_lum_band 1168 | 1169 | ! Outputs log luminosity in filter band ``filter'' (log lsun) (case sensitive) 1170 | ! log_lum_band filter 1171 | 1172 | ! Adds all the filter band luminosities to the output (log lsun) 1173 | ! add_log_lum_band 1174 | 1175 | !---------------------------------------------------------------------------------------------- 1176 | 1177 | !# debugging 1178 | 1179 | !## backups and retries 1180 | num_retries ! total during the run 1181 | num_backups ! total during the run 1182 | 1183 | !## solver iterations 1184 | 1185 | num_iters ! same as num_newton_iterations 1186 | !num_newton_iterations ! iterations at this step 1187 | !total_num_newton_iterations ! total iterations during the run 1188 | 1189 | !rotation_solver_steps 1190 | 1191 | !diffusion_solver_steps 1192 | !diffusion_solver_iters 1193 | 1194 | 1195 | !## maximum solver residuals 1196 | !log_max_abs_lgE_residual 1197 | !log_max_abs_v_residual 1198 | !log_max_dlnEdt_residual 1199 | !log_max_drdt_residual 1200 | !log_max_dvdt_residual 1201 | !log_max_lnd_residual 1202 | 1203 | !avg_lgE_residual 1204 | !avg_v_residual 1205 | 1206 | !log_avg_lgE_residual 1207 | !log_avg_v_residual 1208 | 1209 | !max_abs_lgE_residual 1210 | !max_abs_v_residual 1211 | 1212 | !## conservation during mesh adjust 1213 | !log_mesh_adjust_IE_conservation 1214 | !log_mesh_adjust_KE_conservation 1215 | !log_mesh_adjust_PE_conservation 1216 | 1217 | !## amr 1218 | !num_hydro_merges 1219 | !num_hydro_splits 1220 | 1221 | !## timing 1222 | !elapsed_time ! time since start of run (seconds) 1223 | -------------------------------------------------------------------------------- /tests/work/inlist: -------------------------------------------------------------------------------- 1 | ! this is the master inlist that MESA reads when it starts. 2 | 3 | ! This file tells MESA to go look elsewhere for its configuration 4 | ! info. This makes changing between different inlists easier, by 5 | ! allowing you to easily change the name of the file that gets read. 6 | 7 | &star_job 8 | 9 | read_extra_star_job_inlist1 = .true. 10 | extra_star_job_inlist1_name = 'inlist_project' 11 | 12 | / ! end of star_job namelist 13 | 14 | 15 | &controls 16 | 17 | read_extra_controls_inlist1 = .true. 18 | extra_controls_inlist1_name = 'inlist_project' 19 | 20 | / ! end of controls namelist 21 | 22 | 23 | &pgstar 24 | 25 | read_extra_pgstar_inlist1 = .true. 26 | extra_pgstar_inlist1_name = 'inlist_pgstar' 27 | 28 | / ! end of pgstar namelist 29 | -------------------------------------------------------------------------------- /tests/work/inlist_pgstar: -------------------------------------------------------------------------------- 1 | &pgstar 2 | 3 | ! MESA uses PGPLOT for live plotting and gives the user a tremendous 4 | ! amount of control of the presentation of the information. 5 | 6 | ! show HR diagram 7 | ! this plots the history of L,Teff over many timesteps 8 | HR_win_flag = .true. 9 | 10 | ! set static plot bounds 11 | HR_logT_min = 3.5 12 | HR_logT_max = 4.6 13 | HR_logL_min = 2.0 14 | HR_logL_max = 6.0 15 | 16 | ! set window size (aspect_ratio = height/width) 17 | HR_win_width = 6 18 | HR_win_aspect_ratio = 1.0 19 | 20 | 21 | ! show temperature/density profile 22 | ! this plots the internal structure at single timestep 23 | TRho_Profile_win_flag = .true. 24 | 25 | ! add legend explaining colors 26 | show_TRho_Profile_legend = .true. 27 | 28 | ! display numerical info about the star 29 | show_TRho_Profile_text_info = .true. 30 | 31 | ! set window size (aspect_ratio = height/width) 32 | TRho_Profile_win_width = 8 33 | TRho_Profile_win_aspect_ratio = 0.75 34 | 35 | / ! end of pgstar namelist 36 | -------------------------------------------------------------------------------- /tests/work/inlist_project: -------------------------------------------------------------------------------- 1 | ! inlist to evolve a 15 solar mass star 2 | 3 | ! For the sake of future readers of this file (yourself included), 4 | ! ONLY include the controls you are actually using. DO NOT include 5 | ! all of the other controls that simply have their default values. 6 | 7 | &star_job 8 | 9 | ! begin with a pre-main sequence model 10 | create_pre_main_sequence_model = .true. 11 | 12 | ! save a model at the end of the run 13 | save_model_when_terminate = .false. 14 | save_model_filename = '15M_at_TAMS.mod' 15 | 16 | ! display on-screen plots 17 | pgstar_flag = .true. 18 | 19 | / !end of star_job namelist 20 | 21 | 22 | &controls 23 | 24 | ! starting specifications 25 | initial_mass = 15 ! in Msun units 26 | 27 | ! stop when the star nears ZAMS (Lnuc/L > 0.99) 28 | Lnuc_div_L_zams_limit = 0.99d0 29 | stop_near_zams = .true. 30 | 31 | ! stop when the center mass fraction of h1 drops below this limit 32 | xa_central_lower_limit_species(1) = 'h1' 33 | xa_central_lower_limit(1) = 1d-3 34 | 35 | / ! end of controls namelist 36 | -------------------------------------------------------------------------------- /tests/work/profile_columns.list: -------------------------------------------------------------------------------- 1 | ! profile_columns.list -- determines the contents of star model profiles 2 | ! you can use a non-standard version by setting profile_columns_file in your inlist 3 | 4 | ! units are cgs unless otherwise noted. 5 | 6 | ! reorder the following names as desired to reorder columns. 7 | ! comment out the name to omit a column (fewer columns => less IO => faster running). 8 | ! remove '!' to restore a column. 9 | 10 | ! if you have a situation where you want a non-standard set of columns, 11 | ! make a copy of this file, edit as desired, and give the new filename in your inlist 12 | ! as profile_columns_file. if you are just adding columns, you can 'include' this file, 13 | ! and just list the additions in your file. note: to include the standard default 14 | ! version, use include '' -- the 0 length string means include the default file. 15 | 16 | ! if you need to have something added to the list of options, let me know.... 17 | 18 | ! the first few lines of the profile contain general info about the model. 19 | ! for completeness, those items are described at the end of this file. 20 | 21 | 22 | ! note: you can include another list by doing 23 | ! include 'filename' 24 | ! include '' means include the default standard list file 25 | 26 | 27 | ! the following lines of the profile contain info for 1 zone per row, surface to center. 28 | 29 | ! minimal set of enabled columns: 30 | 31 | zone ! numbers start with 1 at the surface 32 | mass ! m/Msun. mass coordinate of outer boundary of cell. 33 | logR ! log10(radius/Rsun) at outer boundary of zone 34 | logT ! log10(temperature) at center of zone 35 | logRho ! log10(density) at center of zone 36 | logP ! log10(pressure) at center of zone 37 | x_mass_fraction_H 38 | y_mass_fraction_He 39 | z_mass_fraction_metals 40 | 41 | 42 | ! everything below this line is deactived 43 | 44 | 45 | !# Structure 46 | !logM ! log10(m/Msun) 47 | !dm ! cell mass (grams) 48 | !dm_bar ! boundary mass (grams) average of adjacent dm's 49 | !logdq ! log10(dq) 50 | !dq_ratio ! dq(k-1)/dq(k) 51 | !q ! fraction of star mass interior to outer boundary of this zone 52 | !log_q ! log10(q) 53 | 54 | !grav ! gravitational acceleration (cm sec^2) 55 | !log_g ! log10 gravitational acceleration (cm sec^2) 56 | !g_div_r ! grav/radius (sec^2) 57 | !r_div_g ! radius/grav (sec^-2) 58 | !cgrav_factor ! = cgrav(k)/standard_cgrav 59 | !vel_km_per_s ! velocity at outer boundary of zone (km/s) -- 0 if no velocity variable 60 | 61 | !radius ! radius at outer boundary of zone (in Rsun units) 62 | !radius_cm ! radius at outer boundary of zone (in centimeters) 63 | !logR_cm ! log10 radius at outer boundary of zone (in centimeters) 64 | !rmid ! radius at center by mass of zone (in Rsun units) 65 | !r_div_R ! fraction of total radius 66 | 67 | velocity ! velocity at outer boundary of zone (cm/s) -- 0 if no velocity variable 68 | !v_div_r ! velocity divided by radius 69 | !v_times_t_div_r 70 | !rho_times_r3 ! at face 71 | !log_rho_times_r3 ! at face 72 | !scale_height ! in Rsun units 73 | !pressure_scale_height ! in Rsun units 74 | 75 | !accel_div_grav ! dv_dt/grav -- only if v_flag is true. 0 otherwise. 76 | !m_div_r ! gm/cm 77 | !dmbar_m_div_r 78 | !log_dmbar_m_div_r 79 | !mass_grams ! mass coordinate of outer boundary of cell in grams 80 | !mmid ! mass at midpoint of cell (average of mass coords of the cell boundaries) Msun units. 81 | 82 | !m_grav ! total enclosed gravitational mass. Msun units. 83 | !m_grav_div_m_baryonic ! mass_gravitational/mass at cell boundary 84 | !mass_correction_factor ! dm_gravitational/dm (dm is baryonic mass of cell) 85 | 86 | !xm ! mass exterior to point (Msun units) 87 | dq ! mass of zone as a fraction of total star mass 88 | !logxq ! log10(1-q) 89 | !logxm ! log10(xm) 90 | 91 | !xr ! radial distance from point to surface (Rsun) 92 | !xr_cm ! radial distance from point to surface (cm) 93 | !xr_div_R ! radial distance from point to surface in units of star radius 94 | !log_xr ! log10 radial distance from point to surface (Rsun) 95 | !log_xr_cm ! log10 radial distance from point to surface (cm) 96 | !log_xr_div_R ! log10 radial distance from point to surface in units of star radius 97 | 98 | !dr ! r(outer edge) - r(inner edge); radial extent of cell in cm. 99 | !log_dr ! log10 cell width (cm) 100 | !dv ! v(inner edge) - v(outer edge); rate at which delta_r is shrinking (cm/sec). 101 | 102 | !dt_dv_div_dr ! dt*dv/dr; need to have this << 1 for every cell 103 | !dr_div_R ! cell width divided by star R 104 | !log_dr_div_R ! log10 cell width divided by star R 105 | !dr_div_rmid ! cell width divided by rmid 106 | !log_dr_div_rmid ! log(dr_div_rmid) 107 | 108 | !dr_div_cs ! cell sound crossing time (sec) 109 | !log_dr_div_cs ! log10 cell sound crossing time (sec) 110 | !dr_div_cs_yr ! cell sound crossing time (years) 111 | !log_dr_div_cs_yr ! log10 cell sound crossing time (years) 112 | 113 | !acoustic_radius ! sound time from center to outer cell boundary (sec) 114 | !log_acoustic_radius ! log10(acoustic_radius) (sec) 115 | !acoustic_depth ! sound time from surface to outer cell boundary (sec) 116 | !log_acoustic_depth ! log10(acoustic_depth) (sec) 117 | !acoustic_r_div_R_phot 118 | 119 | !cell_collapse_time ! only set if doing explicit hydro 120 | ! time (seconds) for cell inner edge to catch cell outer edge at current velocities 121 | ! 0 if distance between inner and outer is increasing 122 | !log_cell_collapse_time ! log of cell_collapse_time 123 | 124 | !grav_gr_factor ! (1/sqrt(1 - 2Gm/(rc^2)) -- only important for neutron stars 125 | !log_grav_gr_factor ! log10(grav_gr_factor) 126 | 127 | 128 | 129 | 130 | 131 | !# Thermodynamics 132 | temperature ! temperature at center of zone 133 | !logT_face ! log10(temperature) at outer boundary of zone 134 | !logT_bb ! log10(black body temperature) at outer boundary of zone 135 | !logT_face_div_logT_bb 136 | 137 | !energy ! internal energy (ergs/g) 138 | !logE ! log10(specific internal energy) at center of zone 139 | !rho ! density 140 | !density ! rho 141 | 142 | !entropy ! specific entropy divided by (avo*kerg) 143 | !logS ! log10(specific entropy) 144 | !logS_per_baryon ! log10(specific entropy per baryon / kerg) 145 | !del_entropy ! entropy - entropy_start (includes change in entropy due to diffusion at beginning of step) 146 | 147 | !pressure ! total pressure at center of zone (pgas + prad) 148 | !prad ! radiation pressure at center of zone 149 | !pgas ! gas pressure at center of zone (electrons and ions) 150 | !logPgas ! log10(pgas) 151 | !pgas_div_ptotal ! pgas/pressure 152 | !pturb_div_pgas_plus_prad 153 | 154 | !eta ! electron degeneracy parameter (eta >> 1 for significant degeneracy) 155 | !mu ! mean molecular weight per gas particle (ions + free electrons) 156 | 157 | !grada ! dlnT_dlnP at constant S 158 | !dE_dRho ! at constant T 159 | !cv ! specific heat at constant volume 160 | !cp ! specific heat at constant total pressure 161 | 162 | !log_CpT 163 | !gamma1 ! dlnP_dlnRho at constant S 164 | !gamma3 ! gamma3 - 1 = dlnT_dlnRho at constant S 165 | !theta_e ! electron degeneracy factor for graboske screening 166 | !gam ! plasma interaction parameter (> 160 or so means starting crystallization) 167 | !free_e ! free_e is mean number of free electrons per nucleon 168 | !logfree_e ! log10(free_e), free_e is mean number of free electrons per nucleon 169 | !chiRho ! dlnP_dlnRho at constant T 170 | !chiT ! dlnP_dlnT at constant Rho 171 | !dlnRho_dlnT_const_Pgas 172 | !dlnRho_dlnPgas_const_T 173 | 174 | csound ! sound speed 175 | !csound_face ! sound speed (was previously called csound_at_face) 176 | !cs_at_cell_bdy ! sound speed at cell boundary (csound is at cell center) 177 | !v_div_cs ! velocity divided by sound speed 178 | v_div_csound ! velocity divided by sound speed 179 | 180 | !thermal_time_to_surface ! in seconds 181 | !log_thermal_time_to_surface 182 | 183 | 184 | 185 | 186 | !# Mass accretion 187 | !eps_grav ! -T*ds/dt (negative for expansion) 188 | !eps_grav_dm_term_const_q ! advection term, T*(ds/dm)*(dm/dt)_q 189 | !eps_grav_dt_term_const_q ! fixed relative mass time derivative term, -T*(ds/dt)_q 190 | !log_abs_eps_grav_dm_div_L 191 | !log_abs_v ! log10(abs(velocity)) (cm/s) 192 | !log_abs_dvdt_div_v 193 | 194 | !dlnd ! change of log(density) at fixed mass coordinate (Lagrangian) 195 | !dlnPgas ! change of log(Pgas) at fixed mass coordinate (Lagrangian) 196 | !dlnT ! change of log(temperature) at fixed mass coordinate (Lagrangian) 197 | !dlnR ! change of log(radius) at fixed mass coordinate (Lagrangian) 198 | 199 | !dlnd_dt ! time derivative of log(density) at fixed mass coordinate (Lagrangian) 200 | !dlnPgas_dt ! time derivative of log(Pgas) at fixed mass coordinate (Lagrangian) 201 | !dlnT_dt ! time derivative of log(temperature) at fixed mass coordinate (Lagrangian) 202 | !dlnR_dt ! time derivative of log(radius) at fixed mass coordinate (Lagrangian) 203 | !dr_dt ! time derivative of radius at fixed mass coordinate (Lagrangian) 204 | !dv_dt ! time derivative of velocity at fixed mass coordinate (Lagrangian) 205 | 206 | !ds_from_eps_grav ! -eps_grav/T/(avo*kerg) 207 | 208 | !dlnd_dt_const_q ! time derivative of log(density) at fixed q (for Eulerian eps_grav) 209 | !dlnPgas_dt_const_q ! time derivative of log(Pgas) at fixed q (for Eulerian eps_grav) 210 | !dlnT_dt_const_q ! time derivative of log(temperature) at fixed q (for Eulerian eps_grav) 211 | 212 | !signed_dlnd ! sign(dlnd)*log10(max(1,abs(1d6*dlnd))) 213 | !signed_dlnT ! sign(dlnT)*log10(max(1,abs(1d6*dlnT))) 214 | !dv_dt ! time derivative of velocity at fixed mass coordinate (Lagrangian) 215 | 216 | 217 | 218 | 219 | !# Nuclear energy generation 220 | !signed_log_eps_grav ! sign(eps_grav)*log10(max(1,abs(eps_grav))) 221 | net_nuclear_energy ! erg/gm/s from nuclear reactions minus all neutrino losses 222 | ! The value plotted is net_nuclear_energy = sign(val)*log10(max(1,abs(val))) 223 | ! where val = net nuclear energy minus all neutrino losses. 224 | !net_energy ! net_energy + eps_grav. 225 | ! The value plotted is net_energy = sign(val)*log10(max(1,abs(val))) 226 | ! where val = net nuclear energy plus eps_grav minus all neutrino losses. 227 | !eps_nuc_plus_nuc_neu 228 | 229 | !eps_nuc ! ergs/g/sec from nuclear reactions (reaction neutrinos subtracted) 230 | !log_abs_eps_nuc 231 | !d_lnepsnuc_dlnd 232 | !d_epsnuc_dlnd 233 | !deps_dlnd_face 234 | ! (was previously called deps_dlnd_at_face) 235 | !d_lnepsnuc_dlnT 236 | !d_epsnuc_dlnT 237 | !deps_dlnT_face 238 | ! (was previously called deps_dlnT_at_face) 239 | !eps_nuc_neu_total ! erg/gm/sec as neutrinos from nuclear reactions 240 | 241 | !non_nuc_neu ! non-nuclear-reaction neutrino losses 242 | !nonnucneu_plas ! plasmon neutrinos (for collective reactions like gamma_plasmon => nu_e + nubar_e) 243 | !nonnucneu_brem ! bremsstrahlung (for reactions like e- + (z,a) => e- + (z,a) + nu + nubar) 244 | !nonnucneu_phot ! photon neutrinos (for reactions like e- + gamma => e- + nu_e + nubar_e) 245 | !nonnucneu_pair ! pair production (for reactions like e+ + e- => nu_e + nubar_e) 246 | 247 | 248 | ! ergs/g/sec for reaction categories 249 | add_reaction_categories ! this adds all the reaction categories 250 | ! NOTE: you can list specific categories by giving their names (from net_def) 251 | ! This will generate columns labeled burn_ELEMENT 252 | ! i.e. burn_ar, burn_c, burn_fe etc and also c12_c12, c12_o16 etc 253 | !pp 254 | !cno 255 | !tri_alfa 256 | 257 | 258 | 259 | 260 | !# Composition 261 | !x_mass_fraction_H 262 | !y_mass_fraction_He 263 | !z_mass_fraction_metals 264 | !abar ! average atomic weight (g/mole) 265 | !zbar ! average charge 266 | !z2bar ! average charge^2 267 | !ye ! average charge per baryon = proton fraction 268 | 269 | !x ! hydrogen mass fraction 270 | !log_x 271 | !y ! helium mass fraction 272 | !log_y 273 | !z ! metallicity 274 | !log_z ! metallicity 275 | 276 | add_abundances ! this adds all of the isos that are in the current net 277 | ! NOTE: you can list specific isotopes by giving their names (from chem_def) 278 | !h1 279 | !he3 280 | !he4 281 | !c12 282 | !n14 283 | !o16 284 | 285 | add_log_abundances ! this adds log10 of all of the isos that are in the current net 286 | ! NOTE: you can list specific isotopes by giving their names (from chem_def) 287 | !log h1 288 | !log he3 289 | !log he4 290 | !log c12 291 | !log n14 292 | !log o16 293 | 294 | ! log concentration of species 295 | ! concentration = number density / number density of electrons 296 | ! Ci = (Xi/Ai) / sum(Zi*Xi/Ai) [see Thoul et al, ApJ 421:828-842, 1994] 297 | !log_concentration h1 298 | !log_concentration he4 299 | 300 | ! average charge from ionization module 301 | !avg_charge_H 302 | !avg_charge_He 303 | !avg_charge_C 304 | !avg_charge_N 305 | !avg_charge_O 306 | !avg_charge_Ne 307 | !avg_charge_Mg 308 | !avg_charge_Si 309 | !avg_charge_Fe 310 | 311 | ! average neutral fraction from ionization module 312 | !neutral_fraction_H 313 | !neutral_fraction_He 314 | !neutral_fraction_C 315 | !neutral_fraction_N 316 | !neutral_fraction_O 317 | !neutral_fraction_Ne 318 | !neutral_fraction_Mg 319 | !neutral_fraction_Si 320 | !neutral_fraction_Fe 321 | 322 | 323 | ! typical charge for given species 324 | !typical_charge he4 325 | !typical_charge c12 326 | !typical_charge fe52 327 | 328 | ! ionization state for given species 329 | !ionization he4 330 | !ionization c12 331 | !ionization fe52 332 | 333 | !cno_div_z ! abundance of c12, n14, and o16 as a fraction of total z 334 | 335 | 336 | 337 | 338 | !# Opacity 339 | !opacity ! opacity measured at center of zone 340 | !log_opacity ! log10(opacity) 341 | !dkap_dlnrho_face ! partial derivative of opacity wrt. ln rho (at T=const) at outer edge of cell 342 | ! (was previously called dkap_dlnrho_at_face) 343 | !dkap_dlnT_face ! partial derivative of opacity wrt. ln T (at rho=const) at outer edge of cell 344 | ! (was previously called dkap_dlnT_at_face) 345 | 346 | 347 | 348 | !# Luminosity 349 | !luminosity ! luminosity at outer boundary of zone (in Lsun units) 350 | !logL ! log10(max(1d-2,L/Lsun)) 351 | !log_Lrad 352 | !log_Ledd ! log10(Leddington/Lsun) -- local Ledd, 4 pi clight G m / kap 353 | !log_L_div_Ledd ! log10(max(1d-12,L/Leddington)) 354 | !log_Lrad_div_Ledd 355 | !log_Lrad_div_L 356 | !signed_log_power ! sign(L)*log10(max(1,abs(L))) 357 | 358 | 359 | 360 | !# Energetics 361 | !total_energy ! specific total energy of cell (ergs/g). internal+potential+kinetic+rotation. 362 | !total_energy_integral ! sum from surface inwards of cell dm * cell total_energy (ergs) 363 | !cell_specific_IE 364 | !cell_specific_KE 365 | !cell_IE_div_IE_plus_KE 366 | !cell_KE_div_IE_plus_KE 367 | 368 | 369 | 370 | 371 | !# Convection 372 | !mlt_mixing_length ! mixing length for mlt (cm) 373 | !mlt_mixing_type ! value returned by mlt 374 | !conv_dP_term ! P is increased by factor (1 + conv_dP_term) by inclusion of convective turbulence 375 | 376 | !conv_vel ! convection velocity (cm/sec) 377 | !log_conv_vel ! log10 convection velocity (cm/sec) 378 | !log_tau_conv_yrs ! timescale for change of conv velocity 379 | 380 | !conv_L_div_L 381 | !log_conv_L_div_L 382 | !lum_conv_div_lum_rad 383 | !lum_rad_div_L_Edd 384 | !lum_conv_div_lum_Edd 385 | !lum_conv_div_L 386 | !lum_rad_div_L 387 | !lum_rad_div_L_Edd_sub_fourPrad_div_PchiT ! density increases outward if this is > 0 388 | ! see Joss, Salpeter, and Ostriker, "Critical Luminosity", ApJ 181:429-438, 1973. 389 | 390 | !fourPrad_div_PchiT ! = phi, where 1/phi = 1 + (dPgas/dPrad)|rho 391 | ! if phi < Lrad/Ledd, then will get density inversion 392 | ! see Joss, Salpeter, Ostriker, "Critical Luminosity", ApJ 181: 429-438, 1973. 393 | 394 | !gradT ! mlt value for required temperature gradient dlnT/dlnP 395 | !d_gradT_dlnd00 396 | !d_gradT_dlnT00 397 | !d_gradT_dlndm1 398 | !d_gradT_dlnTm1 399 | !d_gradT_dlnR 400 | !d_gradT_dL 401 | 402 | !actual_gradT ! actual temperature gradient dlnT/dlnP in model 403 | !gradT_sub_actual_gradT 404 | 405 | !gradr ! dlnT/dlnP required for purely radiative transport 406 | !grad_temperature ! smoothed dlnT/dlnP at cell boundary 407 | !grad_density ! smoothed dlnRho/dlnP at cell boundary 408 | 409 | !gradL ! gradient for Ledoux criterion for convection 410 | !sch_stable ! 1 if grada > gradr, 0 otherwise 411 | !ledoux_stable ! 1 if gradL > gradr, 0 otherwise 412 | 413 | !grada_sub_gradT 414 | !gradT_sub_grada ! gradT-grada at cell boundary 415 | !gradT_div_grada ! gradT/grada at cell boundary 416 | 417 | !gradr_sub_gradT 418 | !gradT_sub_gradr ! gradT-gradr at cell boundary 419 | !gradT_div_gradr ! gradT/gradr at cell boundary 420 | 421 | !log_gradT_div_gradr ! log10 gradT/gradr at cell boundary 422 | !log_mlt_Gamma ! convective efficiency 423 | !super_ad ! max(0,gradT-grada) at cell boundary 424 | !newly_nonconvective 425 | !conv_vel_div_csound ! convection velocity divided by sound speed 426 | !conv_vel_div_L_vel ! L_vel is velocity needed to carry L by convection; L = 4*pi*r^2*rho*vel**3 427 | !log_mlt_D_mix ! log10 diffusion coefficient for mixing from mlt (cm^2/sec) 428 | 429 | !gradr_div_grada ! gradr/grada_face; > 1 => Schwarzschild unstable for convection 430 | !gradr_sub_grada ! gradr - grada_face; > 0 => Schwarzschild unstable for convection 431 | 432 | 433 | 434 | 435 | 436 | !# Mixing 437 | mixing_type ! mixing types are defined in mesa/const/public/const_def 438 | log_D_mix ! log10 diffusion coefficient for mixing in units of cm^2/second (Eulerian) 439 | log_D_mix_non_rotation 440 | 441 | log_D_conv ! D_mix for regions where mix_type = convective_mixing 442 | log_D_soft ! D_mix for regions where mix_type = softened_convective_mixing 443 | log_D_semi ! D_mix for regions where mix_type = semiconvective_mixing 444 | log_D_ovr ! D_mix for regions where mix_type = overshoot_mixing 445 | log_D_thrm ! D_mix for regions where mix_type = thermohaline_mixing 446 | log_D_minimum ! D_mix for regions where mix_type = minimum_mixing 447 | log_D_rayleigh_taylor ! D_mix for regions where mix_type = rayleigh_taylor_mixing 448 | log_D_anon ! D_mix for regions where mix_type = anonymous_mixing 449 | 450 | !log_sig_mix ! sig(k) is mixing flow across face k in (gm sec^1) 451 | ! sig(k) = D_mix*(4*pi*r(k)**2*rho_face)**2/dmavg 452 | 453 | !dominant_isoA_for_thermohaline 454 | !dominant_isoZ_for_thermohaline 455 | !gradL_composition_term 456 | 457 | 458 | 459 | !# Optical Depth 460 | !tau ! optical depth 461 | !log_column_depth ! log10 column depth, exterior mass / area (g cm^-2) 462 | !log_radial_depth ! log10 radial distance to surface (cm) 463 | !logtau ! log10(optical depth) at center of zone 464 | !tau_eff ! tau that gives the local P == P_atm if this location at surface 465 | ! tau_eff = kap*(P/g - Pextra_factor*(L/M)/(6*pi*clight*cgrav)) 466 | !tau_eff_div_tau 467 | 468 | 469 | 470 | !# Rotation 471 | omega ! angular velocity = j_rot/i_rot 472 | !log_omega 473 | log_j_rot 474 | !log_J_div_M53 ! J is j*1e-15 integrated from center; M53 is m^(5/3) 475 | !log_J_inside ! J_inside is j_rot integrated from center 476 | !shear ! -dlnomega/dlnR 477 | !log_abs_shear ! log10(abs(dlnomega/dlnR)) 478 | !richardson_number 479 | i_rot ! specific moment of inertia at cell boundary 480 | j_rot ! specific angular momentum at cell boundary 481 | !v_rot ! rotation velocity at cell boundary (km/sec) 482 | !w_div_w_crit_roche !ratio of rotational velocity to keplerian at the equator 483 | !without the contribution from the Eddington factor 484 | !fp_rot ! rotation factor for pressure 485 | !ft_rot ! rotation factor for temperature 486 | !ft_rot_div_fp_rot ! gradr factor 487 | 488 | !log_am_nu_non_rot ! log10(am_nu_non_rot) 489 | !log_am_nu_rot ! log10(am_nu_rot) 490 | !log_am_nu ! log10(am_nu_non_rot + am_nu_rot) 491 | 492 | !r_polar ! (Rsun) 493 | !log_r_polar ! log10 (Rsun) 494 | !r_equatorial ! (Rsun) 495 | !log_r_equatorial ! log10 (Rsun) 496 | !r_e_div_r_p ! equatorial/r_polar 497 | !omega_crit ! breakup angular velocity = sqrt(G M / equatorial^3) 498 | !omega_div_omega_crit 499 | 500 | am_log_nu_omega ! for diffusion of omega 501 | am_log_nu_j ! for diffusion of angular momentum 502 | 503 | am_log_nu_rot ! diffusion of angular momentum driven by rotation 504 | am_log_nu_non_rot ! diffusion driven by other sources, e.g. convection 505 | 506 | am_log_sig_omega ! for diffusion of omega 507 | am_log_sig_j ! for diffusion of angular momentum 508 | am_log_sig ! == am_log_sig_omega 509 | 510 | am_log_D_visc ! diffusion coeff for kinematic viscosity 511 | am_log_D_DSI ! diffusion coeff for dynamical shear instability 512 | am_log_D_SH ! diffusion coeff for Solberg-Hoiland instability 513 | am_log_D_SSI ! diffusion coeff for secular shear instability 514 | am_log_D_ES ! diffusion coeff for Eddington-Sweet circulation 515 | am_log_D_GSF ! diffusion coeff for Goldreich-Schubert-Fricke instability 516 | am_log_D_ST ! Spruit dynamo mixing diffusivity 517 | am_log_nu_ST ! Spruit dynamo effective viscosity 518 | 519 | dynamo_log_B_r ! (Gauss) 520 | dynamo_log_B_phi ! (Gauss) 521 | 522 | 523 | 524 | !# Diffusion 525 | ! electric field from element diffusion calculation 526 | !e_field 527 | !log_e_field 528 | 529 | ! gravitational field from element diffusion calculation 530 | !g_field_element_diffusion 531 | !log_g_field_element_diffusion 532 | 533 | !eE_div_mg_element_diffusion 534 | !log_eE_div_mg_element_diffusion 535 | 536 | ! element diffusion velocity for species 537 | !edv h1 538 | !edv he4 539 | !edv o16 540 | 541 | ! Energy generated by Ne22 sedimentation. 542 | !eps_Ne22_sedimentation 543 | !log_eps_Ne22_sedimentation 544 | 545 | !diffusion_D h1 ! self diffusion coeff 546 | !diffusion_dX h1 ! change in h1 mass fraction from diffusion 547 | !diffusion_dX he4 ! change in he4 mass fraction from diffusion 548 | !diffusion_dX n20 ! change in n20 mass fraction from diffusion 549 | 550 | !v_rad h1 ! velocity from radiative levitation 551 | !v_rad he4 ! velocity from radiative levitation 552 | !v_rad ne20 ! velocity from radiative levitation 553 | 554 | !log_g_rad h1 ! log10 acceleration from radiative levitation 555 | !log_g_rad he4 ! log10 acceleration from radiative levitation 556 | !log_g_rad ne20 ! log10 acceleration from radiative levitation 557 | 558 | 559 | 560 | !# Oscillations 561 | !brunt_N2 ! brunt-vaisala frequency squared 562 | !brunt_N2_structure_term 563 | !brunt_N2_composition_term 564 | !log_brunt_N2_structure_term 565 | !log_brunt_N2_composition_term 566 | !brunt_A ! = N^2*r/g 567 | !brunt_A_div_x2 ! x = r(k)/r(1) 568 | !brunt_N2_dimensionless ! N2 in units of 3GM/R^3 569 | !brunt_N_dimensionless ! N in units of sqrt(3GM/R^3) 570 | !brunt_frequency ! cycles per day 571 | !brunt_N ! sqrt(abs(brunt_N2)) 572 | !log_brunt_N ! log10(brunt_N) 573 | !log_brunt_N2 ! log10(brunt_N2) 574 | !log_brunt_N2_dimensionless ! log10(brunt_N2_dimensionless) 575 | 576 | !brunt_B ! smoothed numerical difference 577 | !brunt_nonB ! = grada - gradT 578 | !log_brunt_B ! smoothed numerical difference 579 | !log_brunt_nonB ! = grada - gradT 580 | 581 | !sign_brunt_N2 ! sign of brunt_N2 (+1 for Ledoux stable; -1 for Ledoux unstable) 582 | !lamb_S2 ! for l=1: S = 2*(csound/r)^2 583 | !lamb_S ! for l=1: S = sqrt(2)*csound/r 584 | !brunt_nu ! brunt_frequency in microHz 585 | 586 | !lamb_Sl1 ! for l=1; = sqrt(2)*csound/r (microHz) 587 | !lamb_Sl2 ! for l=2; = sqrt(6)*csound/r (microHz) 588 | !lamb_Sl3 ! for l=3; = sqrt(12)*csound/r (microHz) 589 | 590 | !log_brunt_nu ! brunt_frequency in microHz 591 | !log_lamb_Sl1 ! for l=1; = sqrt(2)*csound/r (microHz) 592 | !log_lamb_Sl2 ! for l=2; = sqrt(6)*csound/r (microHz) 593 | !log_lamb_Sl3 ! for l=3; = sqrt(12)*csound/r (microHz) 594 | !log_lamb_Sl10 595 | 596 | !brunt_N_div_r_integral ! integral from center of N*dr/r 597 | !k_r_integral ! integral from center of k_r*dr 598 | !brunt_N2_sub_omega2 599 | !sl2_sub_omega2 600 | 601 | 602 | 603 | !# Extras 604 | !extra_heat 605 | !extra_dPdm 606 | !extra_L ! extra_heat integrated from center (Lsun) 607 | !log_extra_L ! log10 integrated from center (Lsun) 608 | !log_irradiation_heat 609 | 610 | !extra_jdot ! set in other_torque routine 611 | !extra_omegadot ! set in other_torque routine 612 | 613 | !extra_opacity_factor ! set in other_opacity_factor routine 614 | 615 | 616 | 617 | !# Miscellaneous 618 | !v_residual 619 | !lnd_residual 620 | !lnR_residual 621 | !log_v_residual 622 | !log_lnd_residual 623 | !log_lnR_residual 624 | 625 | !dlog_h1_dlogP ! (log(h1(k)) - log(h1(k-1)))/(log(P(k)) - log(P(k-1))) 626 | !dlog_he3_dlogP 627 | !dlog_he4_dlogP 628 | !dlog_c12_dlogP 629 | !dlog_c13_dlogP 630 | !dlog_n14_dlogP 631 | !dlog_o16_dlogP 632 | !dlog_ne20_dlogP 633 | !dlog_mg24_dlogP 634 | !dlog_si28_dlogP 635 | 636 | !dlog_pp_dlogP 637 | !dlog_cno_dlogP 638 | !dlog_3alf_dlogP 639 | 640 | !dlog_burn_c_dlogP 641 | !dlog_burn_n_dlogP 642 | !dlog_burn_o_dlogP 643 | 644 | !dlog_burn_ne_dlogP 645 | !dlog_burn_na_dlogP 646 | !dlog_burn_mg_dlogP 647 | 648 | !dlog_cc_dlogP 649 | !dlog_co_dlogP 650 | !dlog_oo_dlogP 651 | 652 | !dlog_burn_si_dlogP 653 | !dlog_burn_s_dlogP 654 | !dlog_burn_ar_dlogP 655 | !dlog_burn_ca_dlogP 656 | !dlog_burn_ti_dlogP 657 | !dlog_burn_cr_dlogP 658 | !dlog_burn_fe_dlogP 659 | 660 | !dlog_pnhe4_dlogP 661 | !dlog_photo_dlogP 662 | !dlog_other_dlogP 663 | 664 | !logQ ! logQ = logRho - 2*logT + 12 665 | !logV ! logV = logRho - 0.7*logE + 20 666 | 667 | !log_CpT_absMdot_div_L ! log10(s% Cp(k)*s% T(k)*abs(s% mstar_dot)/s% L(k)) 668 | 669 | !delta_r ! r - r_start, change during step 670 | !delta_L ! L - L_start, change during step 671 | !delta_cell_vol ! cell_vol - cell_vol_start, change during step 672 | !delta_entropy ! entropy - entropy_start, change during step (does not include effects of diffusion) 673 | !delta_T ! T - T_start, change during step 674 | !delta_rho ! rho - rho_start, change during step 675 | !delta_eps_nuc ! eps_nuc - eps_nuc_start, change during step 676 | !delta_mu ! mu - mu_start, change during step 677 | 678 | !zFe ! mass fraction of "Fe" = Fe+Co+Ni 679 | !log_zFe 680 | !u_residual 681 | !log_u_residual 682 | !u 683 | !u_face 684 | !dPdr_dRhodr_info 685 | !flux_limit_lambda 686 | !flux_limit_R 687 | !signed_log_ergs_err 688 | 689 | 690 | 691 | ! the first few lines of the profile contain general info about the model. 692 | ! for completeness, those items are described here. 693 | 694 | ! initial mass and Z 695 | ! initial_mass 696 | ! initial_z 697 | ! general properties of the current state 698 | ! model_number 699 | ! num_zones 700 | ! star_age 701 | ! time_step 702 | ! properties at the photosphere 703 | ! Teff 704 | ! photosphere_L 705 | ! photosphere_r 706 | ! properties at the outermost zone of the model 707 | ! log_surface_L 708 | ! log_surface_radius 709 | ! log_surface_temp 710 | ! properties near the center of the model 711 | ! log_center_temp 712 | ! log_center_density 713 | ! log_center_P 714 | ! center_eta 715 | ! abundances near the center 716 | ! center_h1 717 | ! center_he3 718 | ! center_he4 719 | ! center_c12 720 | ! center_n14 721 | ! center_o16 722 | ! center_ne20 723 | ! information about total mass 724 | ! star_mass 725 | ! star_mdot 726 | ! star_mass_h1 727 | ! star_mass_he3 728 | ! star_mass_he4 729 | ! star_mass_c12 730 | ! star_mass_n14 731 | ! star_mass_o16 732 | ! star_mass_ne20 733 | ! locations of abundance transitions 734 | ! he_core_mass 735 | ! c_core_mass 736 | ! o_core_mass 737 | ! si_core_mass 738 | ! fe_core_mass 739 | ! location of optical depths 10 and 100 740 | ! tau10_mass 741 | ! tau10_radius 742 | ! tau100_mass 743 | ! tau100_radius 744 | ! time scales 745 | ! dynamic_time 746 | ! kh_timescale 747 | ! nuc_timescale 748 | ! various kinds of total power 749 | ! power_nuc_burn 750 | ! power_h_burn 751 | ! power_he_burn 752 | ! power_neu 753 | ! a few control parameter values 754 | ! h1_boundary_limit 755 | ! he4_boundary_limit 756 | ! c12_boundary_limit 757 | ! burn_min1 758 | ! burn_min2 759 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | minversion = 3.12.0 3 | envlist = py3{7,8,9,10,11,12} 4 | isolated_build = true 5 | 6 | [testenv] 7 | setenv = 8 | PYTHONPATH = {toxinidir} 9 | commands = 10 | pytest --basetemp={envtmpdir} 11 | allowlist_externals = pytest --------------------------------------------------------------------------------