├── LICENSE.txt ├── README.md ├── prog_workshop1 ├── numpy_indexing.png └── prog_workshop1.ipynb ├── prog_workshop2 └── prog_workshop2.ipynb ├── prog_workshop3 ├── fatty_acids.svg ├── fibofact.py └── prog_workshop3.ipynb └── prog_workshop4 ├── Ar.out ├── Ar2.out ├── H2S.xyz ├── He.out ├── He2.out ├── Kr.out ├── Kr2.out ├── Ne.out ├── Ne2.out ├── molecule_angle.svg ├── prog_workshop4.ipynb └── test.out /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public licenses. 379 | Notwithstanding, Creative Commons may elect to apply one of its public 380 | licenses to material it publishes and in those instances will be 381 | considered the "Licensor." Except for the limited purpose of indicating 382 | that material is shared under a Creative Commons public license or as 383 | otherwise permitted by the Creative Commons policies published at 384 | creativecommons.org/policies, Creative Commons does not authorize the 385 | use of the trademark "Creative Commons" or any other trademark or logo 386 | of Creative Commons without its prior written consent including, 387 | without limitation, in connection with any unauthorized modifications 388 | to any of its public licenses or any other arrangements, 389 | understandings, or agreements concerning use of licensed material. For 390 | the avoidance of doubt, this paragraph does not form part of the public 391 | licenses. 392 | 393 | Creative Commons may be contacted at creativecommons.org. 394 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # An introduction to computer programming using Python 2 | 3 | This collection of Jupyter notebooks and accompanying material form the basis of an interactive introduction to computer 4 | programming taught to chemistry undergraduate students at Imperial College London. It benefits from an earlier 5 | [course focussed on data analysis](https://github.com/imperialchem/python-data-viz-intro), 6 | but does not build upon and does not depend on it. 7 | 8 | As the name of the course suggests, the goal is not exactly to teach Python, but rather to use Python to teach 9 | features and constructs that are common in many imperative programming languages. Object-oriented features in 10 | Python are not covered, and therefore object specific methods are not used (in workshop 4, the convenience of some methods 11 | when processing strings lead to deviations from this principle). These choices may seem odd to Python programmers 12 | who will find more elegant ways of solving problems, but they keep the course shorter and more consistent, and hopefully 13 | more approachable to beginner programmers. Still, it is expected that the students will develop a good basis to start reading 14 | and working with Python code. 15 | 16 | The structure of the course is as follows: 17 | 18 | ### [Workshop 1](https://github.com/imperialchem/python-prog-intro/blob/master/prog_workshop1/prog_workshop1.ipynb) 19 | 20 | * Basic data types ---numbers (integers, floating point, complex), strings, booleans--- and their operations. 21 | * Conditional statements 22 | * Variables 23 | * Lists 24 | * Other data structures 25 | 26 | ### [Workshop 2](https://github.com/imperialchem/python-prog-intro/blob/master/prog_workshop2/prog_workshop2.ipynb) 27 | 28 | * *For* and *While* loops 29 | * Defining functions (and a how to invoke methods) 30 | 31 | ### [Workshop 3](https://github.com/imperialchem/python-prog-intro/blob/master/prog_workshop3/prog_workshop3.ipynb) 32 | 33 | * Using loops to do work; nested loop structures. 34 | * Using external modules. 35 | * Standalone scripts and prompting for input. 36 | 37 | ### [Workshop 4](https://github.com/imperialchem/python-prog-intro/blob/master/prog_workshop4/prog_workshop4.ipynb) 38 | 39 | * Dealing with files: writing, reading, parsing. 40 | 41 | The notebooks and related materials are made available under the [Creative Commons Attribution 4.0 (CC-by) license](https://creativecommons.org/licenses/by/4.0/), 42 | and can be downloaded as a [zip archive](https://github.com/imperialchem/python-prog-intro/archive/master.zip). 43 | In order to use the notebooks interactively in your computer you will need to have a python interpreter (version 3.x) 44 | and the Jupyter notebook installed, both can be obtained, for example, by installing the 45 | [Anaconda](https://www.continuum.io/downloads) distribution. 46 | 47 | We are interested in your [feedback](mailto:chemistry-git@imperial.ac.uk) and to hear about other ways this material is being used. 48 | -------------------------------------------------------------------------------- /prog_workshop1/numpy_indexing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imperialchem/python-prog-intro/15d3bb673d5b4ac1ed085714b8fb306505fb83d0/prog_workshop1/numpy_indexing.png -------------------------------------------------------------------------------- /prog_workshop3/fatty_acids.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 31 | 55 | 57 | Created with Chemtool 1.6.13 from file /home/joao/ensino/imperial/python_workshops/python-prog/pyprog_workshop3/fatty_acids.svg 58 | 59 | 62 | 69 | 76 | 83 | 90 | 97 | 104 | 111 | 118 | 125 | 132 | 139 | 146 | 153 | 160 | 167 | 174 | 181 | 188 | 195 | 202 | 209 | O 215 | HO 221 | O 227 | HO 233 | O 239 | HO 245 | 246 | 249 | 256 | 263 | 270 | 277 | 284 | 291 | 298 | 305 | 312 | 319 | 326 | 333 | 340 | 347 | 354 | 361 | 368 | 375 | 382 | 389 | 396 | O 402 | HO 408 | 409 | 412 | Oleic acid 418 | 419 | 422 | Elaidic acid 428 | 429 | 432 | OC(=O)CCCCCCC/C=C\CCCCCCCC 440 | 441 | 444 | OC(=O)CCCCCCC/C=C/CCCCCCCC 450 | 451 | 452 | -------------------------------------------------------------------------------- /prog_workshop3/fibofact.py: -------------------------------------------------------------------------------- 1 | def fibonacci(sequence_length): 2 | """Return the Fibonacci sequence of length *sequence_length*.""" 3 | sequence = [0,1] 4 | if sequence_length < 1: 5 | print("Fibonacci sequence only defined for length 1 or greater") 6 | return 7 | elif sequence_length >=3: 8 | for i in range(2,sequence_length): 9 | sequence=sequence+[sequence[i-1]+sequence[i-2]] 10 | return sequence 11 | 12 | def factorial(n): 13 | """Return the factorial of number *n*.""" 14 | num = 1 15 | while n >= 1: 16 | num = num * n 17 | n = n - 1 18 | return num 19 | -------------------------------------------------------------------------------- /prog_workshop3/prog_workshop3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Introduction to programming 3" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "João Pedro Malhado and Clyde Fare, Imperial College London (contact: [chemistry-git@imperial.ac.uk](mailto:chemistry-git@imperial.ac.uk))\n", 15 | "\n", 16 | "This notebook is licensed under a [Creative Commons Attribution 4.0 (CC-by) license](http://creativecommons.org/licenses/by/4.0/), except this section which is adapted from Erle Robotics S.L. book and is licensed under [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 (CC-by-NC-SA) license](http://creativecommons.org/licenses/by-nc-sa/4.0/)." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "## Overview" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "In the last workshop of this series we finished covering the most important building blocks of the Python programming language, which are indeed common to many other programming languages (with only syntactic variations). We are thus now equipped to tackle all sorts of problems, and the major challenge in programming is to break down a given problem into simple steps using this language we have learned. The best way to achieve proficiency at doing this is by actual practice.\n", 31 | "\n", 32 | "In the first part of this workshop we shall not be introducing new language elements, and instead focus on a few examples and problem some common themes that appear in attempting to solve them.\n", 33 | "\n", 34 | "We will also look at how to use pieces of code built by others, in the form of modules.\n", 35 | "\n", 36 | "In the second part of the workshop, we will see how to ask for user input and how to run python programs outside of the notebook. We will end by programming a very simple computer game. In doing so we will be touching some aspects of program design." 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "## Workshop content\n", 44 | "\n", 45 | "#### Part 1\n", 46 | "* [Nested loops](#nested)\n", 47 | "* [Sorting a list of numbers - exercise](#sort)\n", 48 | "* [Distilling alcohols - exercise](#distill)\n", 49 | "\n", 50 | "#### Part 2\n", 51 | "* [Importing external code](#import)\n", 52 | "* [Stand-alone scripts](#scripts)\n", 53 | "* [Extra: video game](#battleship)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "## Warm up" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "In the last workshop we learned how loops work, how they introduce repetition in the program, and how by repeating relatively simple operations a complex result can be achieved. We have also seen how to use functions to encapsulate functionality to be reused in different parts of the program.\n", 68 | "\n", 69 | "To review both of these notions we will now create a function *reverse_string()* which given a string will return another string with the characters of the argument string in the reverse order. An example of the function result is\n", 70 | "\n", 71 | " reverse_string('Rewarder') -> 'redraweR'\n", 72 | " \n", 73 | "In the cell below we provide an outline of the function (note it doesn't yet work!). You should fill in the gaps to make it functional." 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "def reverse_string(input_string):\n", 83 | " \"\"\"Reverses the order of the characters in input_string.\"\"\"\n", 84 | " \n", 85 | " rev=''\n", 86 | " for\n", 87 | " rev=rev+\n", 88 | " return rev" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "Note how the function is set up, with *input_string* as an argument of the function, and *rev* as a local variable that will be returned.\n", 96 | "\n", 97 | "Also note the common structure of the loop: we define a result variable (here called *rev*), and update it's value in the loop body. In this case, the function output is directly the result variable.\n", 98 | "\n", 99 | "The great advantage of defining a function is that we can now apply it to many different cases without rewriting the same code again and again. Let's use it then\n", 100 | "\n", 101 | " reverse_string('0123')" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | " reverse_string('Noon')" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": null, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | " reverse_string('stressed')" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "## Nested loops " 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "Data will often take the form of lists of lists (which can be seen as 2D or higher dimension lists), and we might be interested in doing operations on, or using every element of these lists. Such operations often require running more than one loop simultaneously. Let us look at the example case of the following table\n", 151 | "\n", 152 | " table=[[1,1.2,'a'],\n", 153 | " [2,2.3,'b'],\n", 154 | " [3,3.4,'c']]" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": null, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [] 163 | }, 164 | { 165 | "cell_type": "markdown", 166 | "metadata": {}, 167 | "source": [ 168 | "First, we will print *x*2* for every *x* element of *table* (note that this operation exist for both numbers and strings but with different effects). To do this we need 2 loops:\n", 169 | "\n", 170 | "* The first will loop through the elements of *table*: i.e. each of the inner lists.\n", 171 | "* The second will loop through the elements of the inner lists.\n", 172 | "\n", 173 | "It will look like the following:\n", 174 | "\n", 175 | " for row in table:\n", 176 | " for x in row:\n", 177 | " print(2*x)" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "We are using loop variable names that are indicative of what these variables are in the algorithm. The first for loop is \"picking out\" the rows of the table. For each value of *row*, the second loop is \"picking out\" individual elements of *row*.\n", 192 | "\n", 193 | "It is perhaps helpful to introduce some print functions to better understand what the code is doing. It is important to note indentation and which print statement belongs to which loop body to understand when it is being executed\n", 194 | "\n", 195 | " for row in table:\n", 196 | " print('row=',row)\n", 197 | " for x in row:\n", 198 | " print('x=',x)\n", 199 | " print(2*x)" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": null, 205 | "metadata": {}, 206 | "outputs": [], 207 | "source": [] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": {}, 212 | "source": [ 213 | "If it is not clear how the nested loops are working, please ask a demonstrator.\n", 214 | "\n", 215 | "We could obtain exactly the same results by using indexes to extract the elements of *table*.\n", 216 | "\n", 217 | " for i in range(3):\n", 218 | " for j in range(3):\n", 219 | " print(2*table[i][j])" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "metadata": {}, 226 | "outputs": [], 227 | "source": [] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "Adding some print statements to make things clearer\n", 234 | "\n", 235 | " for i in range(3):\n", 236 | " print(\"i=\",i)\n", 237 | " for j in range(3):\n", 238 | " print(\"j=\",j)\n", 239 | " print(\"table[i][j]=\",table[i][j])\n", 240 | " print(2*table[i][j])" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": {}, 247 | "outputs": [], 248 | "source": [] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "Note that the variables we are looping over are integers running from 0 to 2. In this case we know the shape of the array and can explicitly set the loop bounds with range(3). In cases when we don't know, or don't want to know, the size of the table we are dealing with, we can write a more generic form\n", 255 | "\n", 256 | " for i in range(len(table)):\n", 257 | " for j in range(len(table[i])):\n", 258 | " print(2*table[i][j])" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": null, 264 | "metadata": {}, 265 | "outputs": [], 266 | "source": [] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "We have just shown that we can loop over list elements or list indexes to obtain the same result. The first way is often simpler and more natural in Python, while the second way is more common in most other programming languages.\n", 273 | "\n", 274 | "There are some cases when using indexes can be handy. For example, until now we have been printing the result of the operations following each row \"horizontally\", and moving to the next row \"below\" it. Write some code using indexes that will perform the same operation but following down the columns of *table*." 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "metadata": {}, 287 | "source": [ 288 | "So far we have been performing operations on every element of the list and printing the result to the screen. This is not a particularly useful operation, and we often want to make a transformation to the full table and keep it. We can do this by building a new table *table2*\n", 289 | "\n", 290 | " table2=[]\n", 291 | " for row in table:\n", 292 | " new_row=[]\n", 293 | " for x in row:\n", 294 | " new_row=new_row+[2*x]\n", 295 | " table2=table2+[new_row]\n", 296 | " \n", 297 | " table2" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": null, 303 | "metadata": {}, 304 | "outputs": [], 305 | "source": [] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": {}, 310 | "source": [ 311 | "Note that we have defined 2 result variables, *table2* and *new_row*, each updated on a different loop. *table2* is initialized to an empty list and is updated at the end of the body of the first loop. *new_row* is initialized to an empty list **in each cycle** of the first loop, build up inside the second loop, and appended to *table2* after the second loop has finished.\n", 312 | "\n", 313 | "This is a common construction when building new tables, it is important that you understand how it works. If it is not completely clear, try adding some print statements to the code above." 314 | ] 315 | }, 316 | { 317 | "cell_type": "markdown", 318 | "metadata": {}, 319 | "source": [ 320 | "Although very common in 2D lists, nested loops also occur in other contexts.\n", 321 | "As an example, we will now consider how to generate a list of all the prime numbers below 100. We will approach the problem in the simplest, albeit not very efficient, way: we will loop through every number between 1 and 100 and test if each of them is a prime number. To test if each number is a prime we need a second loop where we test if the number is divisible by any of the numbers smaller than itself.\n", 322 | "\n", 323 | "We will provide the outline of the code and let you fill the gaps to make it functional." 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": {}, 330 | "outputs": [], 331 | "source": [ 332 | "primes=[]\n", 333 | "for test_number in range(1,100):\n", 334 | " is_prime=True\n", 335 | " for divisor in range():\n", 336 | " if % ==0:\n", 337 | " is_prime=\n", 338 | " if :\n", 339 | " primes=\n", 340 | " \n", 341 | "primes" 342 | ] 343 | }, 344 | { 345 | "cell_type": "markdown", 346 | "metadata": {}, 347 | "source": [ 348 | "Although common, this type of nested loops can get relatively complicated to read and understand. It is often possible to avoid them by defining a function that will do the work being done in the inner loop separately.\n", 349 | "\n", 350 | "In the case of the list of prime numbers, we could make our lives easier if we define a function *isprime()* that will return a boolean indicating if the argument is a prime number. Define such a function below.\n", 351 | "\n", 352 | "(If you are feeling confident, you can define your function using a while loop instead of a for loop. Note that if a number is divisible, for example by 2, we already know the number is not a prime, so no need to test division by other numbers. This will make the program more efficient as it will do fewer loop steps.)" 353 | ] 354 | }, 355 | { 356 | "cell_type": "code", 357 | "execution_count": null, 358 | "metadata": {}, 359 | "outputs": [], 360 | "source": [] 361 | }, 362 | { 363 | "cell_type": "markdown", 364 | "metadata": {}, 365 | "source": [ 366 | "Use the function isprime() to retrieve the list of the prime numbers below 100" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": null, 372 | "metadata": {}, 373 | "outputs": [], 374 | "source": [] 375 | }, 376 | { 377 | "cell_type": "markdown", 378 | "metadata": {}, 379 | "source": [ 380 | "### Sorting " 381 | ] 382 | }, 383 | { 384 | "cell_type": "markdown", 385 | "metadata": {}, 386 | "source": [ 387 | "Sorting the elements of a list is another operation that requires the use of nested loops. This is an important operation in many contexts and although simple to state, there are [many different algorithms](https://en.wikipedia.org/wiki/Sorting_algorithm) to achieve this task (performance can be a concern for big or frequent operations, think about sorting Twitter message by time).\n", 388 | "\n", 389 | "Although Python has the built-in function *sorted()* and the list method *.sort()* to do this operation, we will be looking at a variation of the simple Insert Sort algorithm in order to practice more general implementations.\n", 390 | "\n", 391 | "We will build a new ordered list by taking elements of the original list and inserting them into the new ordered list in such a way that our new list is always in the right order. Let us try to picture how it would work:\n", 392 | "\n", 393 | "*Step 0:* initial state\n", 394 | "\n", 395 | " original_list=[3,1,2]\n", 396 | " ordered_list=[]\n", 397 | " \n", 398 | "*Step 1:* we pick the first element of the original_list and place it in the ordered_list\n", 399 | "\n", 400 | " |\n", 401 | " original_list=[3,1,2]\n", 402 | " ordered_list=[3]\n", 403 | "\n", 404 | "*Step 2:* select the second element of original_list and place it in position 0 of the ordered_list\n", 405 | "\n", 406 | " |\n", 407 | " original_list=[3,1,2]\n", 408 | " ordered_list=[1,3]\n", 409 | "\n", 410 | "*Step 3:* select the third element of the original_list and place it in position 1 of the ordered_list\n", 411 | "\n", 412 | " |\n", 413 | " original_list[3,1,2]\n", 414 | " ordered_list[1,2,3]" 415 | ] 416 | }, 417 | { 418 | "cell_type": "markdown", 419 | "metadata": {}, 420 | "source": [ 421 | "Perhaps it is already apparent where the nested loop structure is coming from in the algorithm above:\n", 422 | "\n", 423 | "* First loop to select the elements of the original list in turn.\n", 424 | "* Second loop to check in which position to insert the new element in the ordered list.\n", 425 | "\n", 426 | "Instead of trying to implement the algorithm all in one piece of code, we will split out the task of inserting elements in the correct position of an ordered list.\n", 427 | "\n", 428 | "First, recall from the first workshop how to insert an element in a list in a specific position. (This can also be done with the *.insert()* list method.)\n", 429 | "\n", 430 | " ordered_list=[1,2,4,5,6]\n", 431 | " ordered_list[2:2]=[3]" 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": null, 437 | "metadata": {}, 438 | "outputs": [], 439 | "source": [] 440 | }, 441 | { 442 | "cell_type": "markdown", 443 | "metadata": {}, 444 | "source": [ 445 | "Now define the function *insert_in_order(num,ordered_list)* which will receive as arguments a number and an ordered list, and will return an ordered list where the number passed will be in the correct position. \n", 446 | "\n", 447 | "E.g. executing insert_in_order with arguments 3, [1,2,4,5] will return [1,2,3,4,5]" 448 | ] 449 | }, 450 | { 451 | "cell_type": "code", 452 | "execution_count": null, 453 | "metadata": {}, 454 | "outputs": [], 455 | "source": [] 456 | }, 457 | { 458 | "cell_type": "markdown", 459 | "metadata": {}, 460 | "source": [ 461 | "Test is your insert_in_order() function\n", 462 | "\n", 463 | " olist=list(range(0,20,3))\n", 464 | " insert_in_order(8,olist) " 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": null, 470 | "metadata": {}, 471 | "outputs": [], 472 | "source": [] 473 | }, 474 | { 475 | "cell_type": "markdown", 476 | "metadata": {}, 477 | "source": [ 478 | "Now define a function *insert_sort(unordered_list)* that receives an unordered list as argument and returns an ordered list with the same elements, that uses the *insert_in_order()* function defined above." 479 | ] 480 | }, 481 | { 482 | "cell_type": "code", 483 | "execution_count": null, 484 | "metadata": {}, 485 | "outputs": [], 486 | "source": [] 487 | }, 488 | { 489 | "cell_type": "markdown", 490 | "metadata": {}, 491 | "source": [ 492 | "Does it work?\n", 493 | "\n", 494 | " insert_sort([91, 80, 34, 97, 9, 93, 50, 49, 6, 46])" 495 | ] 496 | }, 497 | { 498 | "cell_type": "code", 499 | "execution_count": null, 500 | "metadata": {}, 501 | "outputs": [], 502 | "source": [] 503 | }, 504 | { 505 | "cell_type": "markdown", 506 | "metadata": {}, 507 | "source": [ 508 | "## Distilling alcohols " 509 | ] 510 | }, 511 | { 512 | "cell_type": "markdown", 513 | "metadata": {}, 514 | "source": [ 515 | "The list *organic_mix* defined below groups a bunch of strings with chemical fomulae for simple organic molecules" 516 | ] 517 | }, 518 | { 519 | "cell_type": "code", 520 | "execution_count": null, 521 | "metadata": {}, 522 | "outputs": [], 523 | "source": [ 524 | "organic_mix=['CH2CH2','CH3CHCH2','(NH2)2CO','CH2ClCH2Cl','CH2CHCl','C6H6','C6H5CH2CH3','CH3O(CH3)3',\n", 525 | " 'C6H5CHCH2','CH3OH','CH2O','C6H4(CH3)2','CH3CH2OH','C6H5OH','C6H3(OH)2Br','CH2OHCH2OH',\n", 526 | " 'CH3CHCH3CHOHCH3','C6H3(OH)2CH2CHNH2CO2H','CH3CHOHCH2CH2OH','C6H8(OH)2','CHCl3,CH3CO2H',\n", 527 | " 'CH3OCH3','CH3COCH3','CH3CH2CH2CH2OH']" 528 | ] 529 | }, 530 | { 531 | "cell_type": "markdown", 532 | "metadata": {}, 533 | "source": [ 534 | "The first goal is to create a function *distill()*. This function will take as an argument a list of chemical formulae. It will return a list containing the alcohols present in the original list.\n", 535 | "\n", 536 | "(Note that in the chemical formulae above, carboxylic acid groups are written as 'CO2H'. If you want a more challenging problem you can change the chemical formulae of acids in the list to read like 'COOH')\n", 537 | "\n", 538 | "Before writing your function, think about:\n", 539 | "\n", 540 | "* What type of result should your function return?\n", 541 | "* How do you \"build\" such result?\n", 542 | "* Do you need a loop? What should the loop variable be?\n", 543 | "* What kind of tests (*if* statements) do you need to do while building your result?" 544 | ] 545 | }, 546 | { 547 | "cell_type": "code", 548 | "execution_count": null, 549 | "metadata": {}, 550 | "outputs": [], 551 | "source": [] 552 | }, 553 | { 554 | "cell_type": "markdown", 555 | "metadata": {}, 556 | "source": [ 557 | "We will go further in defining a function called *frac_distill()*, that will return a list of two lists. The first of such lists will contain the formulae of simple alcohols, while the second list will contain the diols.\n", 558 | "\n", 559 | "One way to approach this problem is:\n", 560 | "\n", 561 | "* First, define an auxiliary function *isdiol()* which will identify if a given single formula is a diol.\n", 562 | "* In *frac_distill()* use the function *distill()* to generate an intermediary list with all alcohols.\n", 563 | "* In *frac_distill()* use the function *isdiol()* to create two lists for simple alcohols and diols.\n", 564 | "\n", 565 | "(In identifying diols we also want to look for the cases written as '(OH)2'. In terms of the implementation of isdiol() you will probably want to use indexes and check 2 characters in the string at a time.)" 566 | ] 567 | }, 568 | { 569 | "cell_type": "code", 570 | "execution_count": null, 571 | "metadata": {}, 572 | "outputs": [], 573 | "source": [] 574 | }, 575 | { 576 | "cell_type": "markdown", 577 | "metadata": {}, 578 | "source": [ 579 | "## Summary" 580 | ] 581 | }, 582 | { 583 | "cell_type": "markdown", 584 | "metadata": {}, 585 | "source": [ 586 | "In the first part of this workshop we have looked at slightly more complex structures in programming, in particular nested loops. We have seen that nested loops often occur in operations with lists and can often be \"decomposed\" by separating the inner loops into an auxiliary function." 587 | ] 588 | }, 589 | { 590 | "cell_type": "markdown", 591 | "metadata": {}, 592 | "source": [ 593 | "# Part 2" 594 | ] 595 | }, 596 | { 597 | "cell_type": "markdown", 598 | "metadata": {}, 599 | "source": [ 600 | "## External modules: [Standing on the shoulders of giants](https://en.wikiquote.org/wiki/Isaac_Newton) " 601 | ] 602 | }, 603 | { 604 | "cell_type": "markdown", 605 | "metadata": {}, 606 | "source": [ 607 | "We have seen that the components of a programming language are rather simple, and that by combining simple operations one achieves more complex results. We can further write functions to perform a given task and use these to build more complex programs. However,\n", 608 | "it quickly becomes cumbersome if every time we want to use a function that is not part of Python we have to explicitly write it out in our notebook. Luckily there is a way to import pre-existing code in the form of modules.\n", 609 | "\n", 610 | "Inside your notebook directory you have a file called fibofact.py which contains two functions [*fibonacci()*](https://en.wikipedia.org/wiki/Fibonacci_number) and *factorial()* which we want to use in our current notebook.\n", 611 | "This is a simple text file with the extension .py, take a look at it in a text editor and note the functions are defined in the same way we have done before. (Do you understand what they are doing?). There are several ways we can import and use them.\n", 612 | "\n", 613 | "We can import the whole module and call functions within, via a dot and the name of the function we want:\n", 614 | "\n", 615 | " import fibofact\n", 616 | " \n", 617 | " fibofact.fibonacci(10)" 618 | ] 619 | }, 620 | { 621 | "cell_type": "code", 622 | "execution_count": null, 623 | "metadata": {}, 624 | "outputs": [], 625 | "source": [] 626 | }, 627 | { 628 | "cell_type": "markdown", 629 | "metadata": {}, 630 | "source": [ 631 | " fibofact.factorial(10)" 632 | ] 633 | }, 634 | { 635 | "cell_type": "code", 636 | "execution_count": null, 637 | "metadata": {}, 638 | "outputs": [], 639 | "source": [] 640 | }, 641 | { 642 | "cell_type": "markdown", 643 | "metadata": {}, 644 | "source": [ 645 | "We can do the same thing but choosing to refer to the module by a different (usually shorter) name: \n", 646 | " \n", 647 | " import fibofact as ff\n", 648 | "\n", 649 | " ff.fibonacci(10)" 650 | ] 651 | }, 652 | { 653 | "cell_type": "code", 654 | "execution_count": null, 655 | "metadata": {}, 656 | "outputs": [], 657 | "source": [] 658 | }, 659 | { 660 | "cell_type": "markdown", 661 | "metadata": {}, 662 | "source": [ 663 | "We can choose to extract one (or more) of the functions directly\n", 664 | "\n", 665 | " from fibofact import factorial\n", 666 | "\n", 667 | " factorial(10)\n" 668 | ] 669 | }, 670 | { 671 | "cell_type": "code", 672 | "execution_count": null, 673 | "metadata": {}, 674 | "outputs": [], 675 | "source": [] 676 | }, 677 | { 678 | "cell_type": "markdown", 679 | "metadata": {}, 680 | "source": [ 681 | "Or extract all functions contained in the module\n", 682 | "\n", 683 | " from fibofact import *\n", 684 | " \n", 685 | " fibonacci(10)" 686 | ] 687 | }, 688 | { 689 | "cell_type": "code", 690 | "execution_count": null, 691 | "metadata": {}, 692 | "outputs": [], 693 | "source": [] 694 | }, 695 | { 696 | "cell_type": "markdown", 697 | "metadata": {}, 698 | "source": [ 699 | "The downside of options 3 and particularly 4 is that we might accidentally import a function that has the same name as another variable or function being used. Option 2 is generally considered best practice." 700 | ] 701 | }, 702 | { 703 | "cell_type": "markdown", 704 | "metadata": {}, 705 | "source": [ 706 | "Even if we can construct our own functions and store them in a module for use at a later time, writing any medium piece of software would appear as a daunting task if we were to build every needed function from scratch using bare *if* statements and *for* loops. Much of the work in programming builds on the work of others, this work is available in the form of function and method libraries implementing useful functionality and that we can import as modules.\n", 707 | "\n", 708 | "There are a number of popular scientific modules directly made available by the [Anaconda distribution](http://docs.continuum.io/anaconda/pkg-docs), but as Python is a very popular language there are numerous other modules freely available for us to use.\n", 709 | "\n", 710 | "Important packages that you may be using often are [SciPy](http://www.scipy.org) and [NumPy](http://docs.scipy.org/doc/numpy/user/index.html)\n", 711 | "\n", 712 | " import numpy as np\n", 713 | " \n", 714 | " np.mean([1,2,3])" 715 | ] 716 | }, 717 | { 718 | "cell_type": "code", 719 | "execution_count": null, 720 | "metadata": {}, 721 | "outputs": [], 722 | "source": [] 723 | }, 724 | { 725 | "cell_type": "markdown", 726 | "metadata": {}, 727 | "source": [ 728 | "Large modules like scipy often further divide into sub-modules. The sub-module [scipy.constants](https://docs.scipy.org/doc/scipy/reference/constants.html) provides values for useful physical constants. We can import a submodule directly:\n", 729 | "\n", 730 | " import scipy.constants as physcons\n", 731 | " physcons.k" 732 | ] 733 | }, 734 | { 735 | "cell_type": "code", 736 | "execution_count": null, 737 | "metadata": {}, 738 | "outputs": [], 739 | "source": [] 740 | }, 741 | { 742 | "cell_type": "markdown", 743 | "metadata": {}, 744 | "source": [ 745 | "or import functions (in this case variables) from within the submodule via:\n", 746 | " \n", 747 | " from scipy.constants import h\n", 748 | " h" 749 | ] 750 | }, 751 | { 752 | "cell_type": "code", 753 | "execution_count": null, 754 | "metadata": {}, 755 | "outputs": [], 756 | "source": [] 757 | }, 758 | { 759 | "cell_type": "markdown", 760 | "metadata": {}, 761 | "source": [ 762 | "If a function or variable is imported once in a notebook it is accessible from all the cells." 763 | ] 764 | }, 765 | { 766 | "cell_type": "markdown", 767 | "metadata": {}, 768 | "source": [ 769 | "When writing scripts, we almost always put the import statements at the beginning of the file. That way it is immediately clear what the code we are using depends upon." 770 | ] 771 | }, 772 | { 773 | "cell_type": "markdown", 774 | "metadata": {}, 775 | "source": [ 776 | "One last example\n", 777 | "\n", 778 | " from IPython.display import YouTubeVideo\n", 779 | " YouTubeVideo('T3jIE3b-bhY')" 780 | ] 781 | }, 782 | { 783 | "cell_type": "code", 784 | "execution_count": null, 785 | "metadata": {}, 786 | "outputs": [], 787 | "source": [] 788 | }, 789 | { 790 | "cell_type": "markdown", 791 | "metadata": {}, 792 | "source": [ 793 | "## Going beyond the notebook: stand-alone scripts " 794 | ] 795 | }, 796 | { 797 | "cell_type": "markdown", 798 | "metadata": {}, 799 | "source": [ 800 | "In these workshops we have been writing and running all our code within the notebook interface. The notebook is very useful to write and test small pieces of code, or when the output of our code involves plotting. All that we have learned can however be transposed to stand-alone Python programs, which are nothing but code written on text files saved with the extension .py.\n", 801 | "\n", 802 | "We will be looking at two examples, but will first do some preliminary work within the notebook." 803 | ] 804 | }, 805 | { 806 | "cell_type": "markdown", 807 | "metadata": {}, 808 | "source": [ 809 | "### Interactivity: reading user input" 810 | ] 811 | }, 812 | { 813 | "cell_type": "markdown", 814 | "metadata": {}, 815 | "source": [ 816 | "One important aspect when running a program outside of the notebook, where the user cannot see or change variable values easily, is to provide a way to prompt the user for input. The function *input()* prompts the user and collects input typed on the keyboard. This is the simplest way to create interactive programs.\n", 817 | "\n", 818 | " keys=input(\"I will collect what you type: \")\n", 819 | " print(\"What you typed was:\",keys)" 820 | ] 821 | }, 822 | { 823 | "cell_type": "code", 824 | "execution_count": null, 825 | "metadata": {}, 826 | "outputs": [], 827 | "source": [] 828 | }, 829 | { 830 | "cell_type": "markdown", 831 | "metadata": {}, 832 | "source": [ 833 | "The first line of code will present the user with a string, and in the notebook a text box where whatever you type on the keyboard until you hit return is \"collected\" (outside of the notebook this text box does not appear, but we will have the chance to check the behaviour later on). Whatever you type is stored as a string in variable *keys* in this case.\n", 834 | "\n", 835 | "If we expect numerical input from the user, the string needs to be converted.\n", 836 | "\n", 837 | " number_string=input(\"How many carbon atoms are there in butene?\")\n", 838 | " number_number=int(number_string)\n", 839 | " if number_number == 4:\n", 840 | " print(\"Obviously!\")\n", 841 | " else:\n", 842 | " print(\"Are you a physicist, or what?!\")" 843 | ] 844 | }, 845 | { 846 | "cell_type": "code", 847 | "execution_count": null, 848 | "metadata": {}, 849 | "outputs": [], 850 | "source": [] 851 | }, 852 | { 853 | "cell_type": "markdown", 854 | "metadata": {}, 855 | "source": [ 856 | "### SMILES generator" 857 | ] 858 | }, 859 | { 860 | "cell_type": "markdown", 861 | "metadata": {}, 862 | "source": [ 863 | "In the exercise above we were working with strings of chemical formulas, but chemical formulas can be ambiguous with respect to chemical structure. [SMILES codes](http://www.daylight.com/dayhtml/doc/theory/theory.smiles.html) is a much less ambiguous way of representing a chemical structure with a single string. The image below shows the structure and respective SMILES codes for two mono-unsaturated fatty acids which differ on the configuration of the double bond.\n", 864 | "\n", 865 | "\n", 866 | "\n", 867 | "We note that an aliphatic chain can be written as a succession of 'C' characters, with double bonds represented by '='. We can use the forward and backward slash to determine double bond configuration, or we can leave them out if we want to leave it unspecified. No need to include hydrogens. We will not say much more about it, but you can follow the link to [know more about SMILES](http://www.daylight.com/meetings/summerschool98/course/dave/smiles-intro.html).\n", 868 | "\n", 869 | "In this section we will be writing a program to write SMILES strings for mono-unsaturated fatty acids, by prompting the user for the total chain length, the position of the double bond, and the orientation of the double bond.\n", 870 | "\n", 871 | "While completing this task, we will be need to manipulate the backslash character '\\\\' and there are some details we need to worry about." 872 | ] 873 | }, 874 | { 875 | "cell_type": "markdown", 876 | "metadata": {}, 877 | "source": [ 878 | "#### A side note on backslashes ('\\\\') \n", 879 | "\n", 880 | "The backslash is a special character that has some [specific uses](https://docs.python.org/2.0/ref/strings.html) in Python. In specifying a string with a backslash we can use two backslashes\n", 881 | "\n", 882 | " butene='C/C=C\\\\C'\n", 883 | " butene" 884 | ] 885 | }, 886 | { 887 | "cell_type": "code", 888 | "execution_count": null, 889 | "metadata": {}, 890 | "outputs": [], 891 | "source": [] 892 | }, 893 | { 894 | "cell_type": "markdown", 895 | "metadata": {}, 896 | "source": [ 897 | "When using a notebook, the string will be displayed in an output cell in Python's \"internal representation\" with '\\\\\\\\'.\n", 898 | "But if we use print(), Python will \"translate\" from its internal representation and display a single backslash\n", 899 | "\n", 900 | " print(butene)" 901 | ] 902 | }, 903 | { 904 | "cell_type": "code", 905 | "execution_count": null, 906 | "metadata": {}, 907 | "outputs": [], 908 | "source": [] 909 | }, 910 | { 911 | "cell_type": "markdown", 912 | "metadata": {}, 913 | "source": [ 914 | "The function we will be defining below should return a string, and its results will be displayed with '\\\\\\\\' on an output cell." 915 | ] 916 | }, 917 | { 918 | "cell_type": "markdown", 919 | "metadata": {}, 920 | "source": [ 921 | "#### Back to the smiles generator task\n", 922 | "\n", 923 | "The core of our program is going to be the function *fatty_gen()*, that receives 3 arguments: chain length, double bond position, and a string specifying orientation. The string can have the values 'Z' or 'E', any other string would count as an unspecified orientation, and should give a result accordingly. The output of the function should be a string with the SMILES code of the fatty acid. Write such a function below" 924 | ] 925 | }, 926 | { 927 | "cell_type": "code", 928 | "execution_count": null, 929 | "metadata": {}, 930 | "outputs": [], 931 | "source": [] 932 | }, 933 | { 934 | "cell_type": "markdown", 935 | "metadata": {}, 936 | "source": [ 937 | "In order to test your function, you can insert the resulting string into the program Avogadro and observe the generated structure. (In the program main window select Build > Insert > SMILES...).\n", 938 | "\n", 939 | "\n", 940 | "#### Taking it outside the notebook\n", 941 | "\n", 942 | "Once you are convinced your function is doing the right thing, let us move to build our stand-alone program.\n", 943 | "A Python stand-alone program is a simple text file with the Python code in it and an extension .py. Two simple ways of creating such a text file would be to open up a text editor (on Windows the default text editor is **Notepad**), or use the text editor inbuilt in Jupyter (on the dashboard, on the top right click New > Text File). *It is important to note that in the latter case, although you are using Jupyter, the file you are working on is not a Notebook --- note no cells --- but a simple text file.*\n", 944 | "\n", 945 | "Copy the function fatty_gen() you defined above, from the notebook to the text editor, and save the file as fatty_gen.py. We have just created a Python program, but our program at the moment defines the function fatty_gen() but never actually calls it, so if we run the program nothing happens. To complete the script we need to do 3 more things:\n", 946 | "\n", 947 | "* Ask the user for input to get the 3 arguments needed to run fatty_gen().\n", 948 | "* Run fatty_gen() with the input given.\n", 949 | "* Print the output of fatty_gen().\n", 950 | "\n", 951 | "The last step is actually important when running code outside of the notebook. In the notebook the output of a function is returned in an Out[] cell, but when running on the console cells don't exist, and we must write specific code to print to the screen.\n", 952 | "\n", 953 | "Once you finished writing your code on the text editor, save the file. Depending on your setup, you may be able to run your program by double-clicking on the file. However, in a default Anaconda installation you may get an alert message stating that the operating system doesn't know how to open the fatty_gen.py file. Select to open the file with the Python interpreter which on Windows should be in C:\\User\\\\<your username>\\Anaconda3\\python.exe. \n", 954 | "If this does not work, open the anaconda-prompt, type \"python\" and with the mouse drag the file with your program from the File Explorer or the Desktop into the terminal window. It should read something like:\n", 955 | "\n", 956 | " python C:\\path\\to\\your\\file\\fatty_gen.py\n", 957 | " \n", 958 | "*Ask a demonstrator for help if you are struggling with this step.*\n", 959 | "\n", 960 | "If you manage to run the program by double-clicking on it, you will see the terminal window closing before you have a chance to look at the result of the program. This is because the window is closing as soon as the program ends after the last print() statement. A small trick that we can use to keep the window open, is to add another prompt at the very end of the program, so it waits until the user presses return.\n", 961 | "\n", 962 | " input(\"Press return to close the window.\")\n", 963 | "\n", 964 | "When your program contains an error, the terminal window may close immediately, even if you include the input statement at the end, thus preventing you from seeing the error messages and correct the error. In this case, open the anaconda-prompt and run the program directly from the open terminal window as described above." 965 | ] 966 | }, 967 | { 968 | "cell_type": "markdown", 969 | "metadata": {}, 970 | "source": [ 971 | "### Extra: Battleship" 972 | ] 973 | }, 974 | { 975 | "cell_type": "markdown", 976 | "metadata": {}, 977 | "source": [ 978 | "#### The game" 979 | ] 980 | }, 981 | { 982 | "cell_type": "markdown", 983 | "metadata": {}, 984 | "source": [ 985 | "In this section we will be writing a computer game which is a simplified version of the pencil and paper game [Battleship](https://en.wikipedia.org/wiki/Battleship_(game)). The game will work as follows:\n", 986 | "\n", 987 | "* We define a square grid with 5×5 elements.\n", 988 | "* The computer randomly assigns one of the elements of the grid to represent a hidden ship. All other grid elements are the ocean.\n", 989 | "* The player has 5 shots to sink the ship: guess where the ship is." 990 | ] 991 | }, 992 | { 993 | "cell_type": "markdown", 994 | "metadata": {}, 995 | "source": [ 996 | "#### What should the program do?" 997 | ] 998 | }, 999 | { 1000 | "cell_type": "markdown", 1001 | "metadata": {}, 1002 | "source": [ 1003 | "We want to write a stand-alone program that:\n", 1004 | "\n", 1005 | "1. Sets up the grid by hiding the ship in one of the grid elements.\n", 1006 | "2. Shows the grid to the player (not showing the hidden ship, but including any shots made).\n", 1007 | "3. Asks the player for a guess position.\n", 1008 | "4. Checks whether the choice is a hit.\n", 1009 | "5. Inform the user of success, or update the grid with the guess shot and go back to point 2." 1010 | ] 1011 | }, 1012 | { 1013 | "cell_type": "markdown", 1014 | "metadata": {}, 1015 | "source": [ 1016 | "#### Designing a solution" 1017 | ] 1018 | }, 1019 | { 1020 | "cell_type": "markdown", 1021 | "metadata": {}, 1022 | "source": [ 1023 | "How to go about solving this problem? This is the design phase, and it is not a bad idea to get a pencil and paper out and draw a diagram of how to break down the different tasks.\n", 1024 | "\n", 1025 | "A second stage of design is to define what data we need to keep track of (what are our global variables) and what operations need to occur during the program that use or change this data (what functions need to be defined, along with what their arguments and output should be). If we go through in detail what the program needs to do as suggested in the section above, the task of determining what functions to define can be greatly simplified.\n", 1026 | "\n", 1027 | "What follows is one suggestion for the program design, you can choose a different route if you wish." 1028 | ] 1029 | }, 1030 | { 1031 | "cell_type": "markdown", 1032 | "metadata": {}, 1033 | "source": [ 1034 | "##### Variables" 1035 | ] 1036 | }, 1037 | { 1038 | "cell_type": "markdown", 1039 | "metadata": {}, 1040 | "source": [ 1041 | "One crucial variable of the program is the position of the hidden ship. This could be defined by the two coordinates on the grid and stored as a 2 element list with the variable name *hidden_ship*.\n", 1042 | "\n", 1043 | "Another piece of information important to keep track of is the shots already made. This will be a list of 2 element lists. This list will start empty, and will be added to during the game. We will call this list *shots*.\n", 1044 | "\n", 1045 | "These are the 2 pieces of information that we need to keep. Note that although we could have decided differently, we are choosing not to keep track of the full grid. We can build this grid with information from *shots* at any one time." 1046 | ] 1047 | }, 1048 | { 1049 | "cell_type": "markdown", 1050 | "metadata": {}, 1051 | "source": [ 1052 | "##### Functions" 1053 | ] 1054 | }, 1055 | { 1056 | "cell_type": "markdown", 1057 | "metadata": {}, 1058 | "source": [ 1059 | "To establish the needed functions, we can follow the outline of the program given above. We will discuss the outline of the functions first, and worry about the details of the implementation in a subsequent section below.\n", 1060 | "\n", 1061 | "We will need a function to generate the random position *hidden_ship* (we will see how to do this below). We will call this function *hide()*. This function does not need any input, and should output a list with the two coordinates.\n", 1062 | "\n", 1063 | "We will need a function that displays the current grid to the player. We can represent the grid as a 5×5 list of lists. We will use the string 'O' to represent positions not yet tried, and 'X', for previous shots.\n", 1064 | "Our initial grid will thus look like:\n", 1065 | "\n", 1066 | " [['O','O','O','O','O'],\n", 1067 | " ['O','O','O','O','O'],\n", 1068 | " ['O','O','O','O','O'],\n", 1069 | " ['O','O','O','O','O'],\n", 1070 | " ['O','O','O','O','O']]\n", 1071 | " \n", 1072 | "And when the player aims at the position [1,3] (**we will be using Python list indexing numbering in the game**) it will look like:\n", 1073 | "\n", 1074 | " [['O','O','O','O','O'],\n", 1075 | " ['O','O','O','X','O'],\n", 1076 | " ['O','O','O','O','O'],\n", 1077 | " ['O','O','O','O','O'],\n", 1078 | " ['O','O','O','O','O']]\n", 1079 | " \n", 1080 | "We will separate the task of presenting the grid to the player into two functions. *build_grid()* will construct the 5×5 2D list as above, and *print_grid()* will print the grid for the user to see. *build_grid* should receive the *shots* list as input, and output a 5×5 2D list.\n", 1081 | "*print_grid()* should receive a 5×5 2D list and output nothing (only print to the screen).\n", 1082 | "\n", 1083 | "We will need a function that asks the player for a guess position, and it should do a few checks to see if the choice is valid: within the grid and not repeated. This function should add the guess to the list *shots*. Let us call this function *aim()*. This function should receive as argument the list *shots*, and should output an updated *shots* list.\n", 1084 | "\n", 1085 | "We should have a function *check()* which will check and inform the user if the shot was successful, if there are more tries or if the game is over. This function should receive the lists *hidden_ship* *shots* as arguments, and returns no output (only prints to screen). " 1086 | ] 1087 | }, 1088 | { 1089 | "cell_type": "markdown", 1090 | "metadata": {}, 1091 | "source": [ 1092 | "##### Putting it together" 1093 | ] 1094 | }, 1095 | { 1096 | "cell_type": "markdown", 1097 | "metadata": {}, 1098 | "source": [ 1099 | "Once we have defined our functions, writing the program is relatively simple.\n", 1100 | "\n", 1101 | " hidden_ship=hide()\n", 1102 | " shots=[]\n", 1103 | " \n", 1104 | " while hidden_ship not in shots and len(shots)<5:\n", 1105 | " grid=build_grid(shots)\n", 1106 | " print_grid(grid)\n", 1107 | " shots=aim(shots)\n", 1108 | " check(hidden_ship,shots)\n", 1109 | " \n", 1110 | "It is normal that there are still unclear aspects about the design of the program, and things should become clearer once we start the implementation phase below. Nevertheless you are welcome to discuss with a demonstrator any aspects of this solution.\n", 1111 | "\n", 1112 | "We will implement the individual functions inside the notebook and make sure they work as expected, and then write them down in a stand-alone program." 1113 | ] 1114 | }, 1115 | { 1116 | "cell_type": "markdown", 1117 | "metadata": {}, 1118 | "source": [ 1119 | "#### Implementation" 1120 | ] 1121 | }, 1122 | { 1123 | "cell_type": "markdown", 1124 | "metadata": {}, 1125 | "source": [ 1126 | "Here we will implement the different functions we have specified above.\n", 1127 | "\n", 1128 | "The function *hide()* needs to output a list with two random integers between 0 and 4. In order to generate integer random numbers we can use the function *randint()* of the numpy module.\n", 1129 | "\n", 1130 | " from numpy.random import randint\n", 1131 | " randint(0,100)" 1132 | ] 1133 | }, 1134 | { 1135 | "cell_type": "code", 1136 | "execution_count": null, 1137 | "metadata": {}, 1138 | "outputs": [], 1139 | "source": [] 1140 | }, 1141 | { 1142 | "cell_type": "markdown", 1143 | "metadata": {}, 1144 | "source": [ 1145 | "The code above generates a random integer between 0 and 100. Note that if you run the cell again you will obtain a different number.\n", 1146 | "\n", 1147 | "Define the function *hide()* below." 1148 | ] 1149 | }, 1150 | { 1151 | "cell_type": "code", 1152 | "execution_count": null, 1153 | "metadata": {}, 1154 | "outputs": [], 1155 | "source": [] 1156 | }, 1157 | { 1158 | "cell_type": "markdown", 1159 | "metadata": {}, 1160 | "source": [ 1161 | "We now want to define the function *build_grid()* which receives a list *shots* as an argument, and returns a 5×5 2D list of 'O' everywhere and 'X' at the positions *shots*. It is probably easier to first build a grid with 'O' everywhere, and then loop through *shots* and redefine the positions of the grid accordingly." 1162 | ] 1163 | }, 1164 | { 1165 | "cell_type": "code", 1166 | "execution_count": null, 1167 | "metadata": {}, 1168 | "outputs": [], 1169 | "source": [] 1170 | }, 1171 | { 1172 | "cell_type": "markdown", 1173 | "metadata": {}, 1174 | "source": [ 1175 | "The function *print_grid()* should receive as input the output of *build_grid()* and print it in a convenient fashion to the screen. Note that simply using the function print on a list does not convey the idea of a grid.\n", 1176 | "\n", 1177 | " print([['O','O','O'],['O','O','X'],['O','O','O']])" 1178 | ] 1179 | }, 1180 | { 1181 | "cell_type": "code", 1182 | "execution_count": null, 1183 | "metadata": {}, 1184 | "outputs": [], 1185 | "source": [] 1186 | }, 1187 | { 1188 | "cell_type": "markdown", 1189 | "metadata": {}, 1190 | "source": [ 1191 | "A nicer output would look like:\n", 1192 | "\n", 1193 | " O O O\n", 1194 | " O O X\n", 1195 | " O O O\n", 1196 | " \n", 1197 | "This could be done by looping through the rows of the grid, building a convenient string and printing it out.\n", 1198 | "\n", 1199 | "Define the function *print_grid()* below." 1200 | ] 1201 | }, 1202 | { 1203 | "cell_type": "code", 1204 | "execution_count": null, 1205 | "metadata": {}, 1206 | "outputs": [], 1207 | "source": [] 1208 | }, 1209 | { 1210 | "cell_type": "markdown", 1211 | "metadata": {}, 1212 | "source": [ 1213 | "The function *aim()*, should receive the list *shots* as input, ask the user for the row and column guess, and output the list *shots* updated. A first implementation can be quite simple.\n", 1214 | "\n", 1215 | "If you are feeling comfortable, you should implements some checks, since the wrong player input can cause errors in the program later on. We should use a loop and keep on prompting the user for input until the guess is sensible, informing them of what the problem with input is at each stage. We should check if the guess is in the range of the grid, and if the entered guess is a repeat and is already in *shots*." 1216 | ] 1217 | }, 1218 | { 1219 | "cell_type": "code", 1220 | "execution_count": null, 1221 | "metadata": {}, 1222 | "outputs": [], 1223 | "source": [] 1224 | }, 1225 | { 1226 | "cell_type": "markdown", 1227 | "metadata": {}, 1228 | "source": [ 1229 | "The function *check()* receives the list *hidden_ship* and *shots*, and it should check whether the last element of *shots* matches *hidden_ship* and inform the player of what happens. It does not have to output anything, just print things to the screen.\n", 1230 | "\n", 1231 | "There are three possibilities: ship sunk; tell the player how many shots are still available (determined by the current length of *shots*); or game over." 1232 | ] 1233 | }, 1234 | { 1235 | "cell_type": "code", 1236 | "execution_count": null, 1237 | "metadata": {}, 1238 | "outputs": [], 1239 | "source": [] 1240 | }, 1241 | { 1242 | "cell_type": "markdown", 1243 | "metadata": {}, 1244 | "source": [ 1245 | "When you are convinced that your functions are doing the right thing, you can copy them to a text file, and the main code structure above. Don't forget to import any module that you are using. Run the program, and have fun!\n", 1246 | "\n", 1247 | "If there is anything in your program that you want to improve, just change your functions accordingly." 1248 | ] 1249 | }, 1250 | { 1251 | "cell_type": "markdown", 1252 | "metadata": {}, 1253 | "source": [ 1254 | "## Summary" 1255 | ] 1256 | }, 1257 | { 1258 | "cell_type": "markdown", 1259 | "metadata": {}, 1260 | "source": [ 1261 | "In building complex programs we can draw upon code written by others importing external modules, thus increasing the functionality available in the standard Python language. \n", 1262 | "\n", 1263 | "We have also seen how to run programs outside of the notebook and how to provide a mechanism for user input.\n", 1264 | "\n", 1265 | "We wrote a program to generate SMILES codes for mono-unsaturated fatty acids, and wrote a simple computer game. In doing so we've illustrated how to use functions to breakdown a more complex problems into simpler parts." 1266 | ] 1267 | } 1268 | ], 1269 | "metadata": { 1270 | "kernelspec": { 1271 | "display_name": "Python 3 (ipykernel)", 1272 | "language": "python", 1273 | "name": "python3" 1274 | }, 1275 | "language_info": { 1276 | "codemirror_mode": { 1277 | "name": "ipython", 1278 | "version": 3 1279 | }, 1280 | "file_extension": ".py", 1281 | "mimetype": "text/x-python", 1282 | "name": "python", 1283 | "nbconvert_exporter": "python", 1284 | "pygments_lexer": "ipython3", 1285 | "version": "3.11.2" 1286 | } 1287 | }, 1288 | "nbformat": 4, 1289 | "nbformat_minor": 1 1290 | } 1291 | -------------------------------------------------------------------------------- /prog_workshop4/Ar.out: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------- 2 | PSI4: An Open-Source Ab Initio Electronic Structure Package 3 | PSI 4.0.0-beta5+ Driver 4 | 5 | Git: Rev {master} eab4c2bf53d0cfe2fa7ff775dfb81b740d89e238 6 | 7 | J. M. Turney, A. C. Simmonett, R. M. Parrish, E. G. Hohenstein, 8 | F. A. Evangelista, J. T. Fermann, B. J. Mintz, L. A. Burns, J. J. Wilke, 9 | M. L. Abrams, N. J. Russ, M. L. Leininger, C. L. Janssen, E. T. Seidl, 10 | W. D. Allen, H. F. Schaefer, R. A. King, E. F. Valeev, C. D. Sherrill, 11 | and T. D. Crawford, WIREs Comput. Mol. Sci. 2, 556-565 (2012) 12 | (doi: 10.1002/wcms.93) 13 | 14 | Additional Contributions by 15 | A. E. DePrince, M. Saitow, U. Bozkaya, A. Yu. Sokolov 16 | ----------------------------------------------------------------------- 17 | 18 | Process ID: 31067 19 | PSI4DATADIR: /home/wv111/local/share/psi/ 20 | 21 | Using LocalCommunicator (Number of processes = 1) 22 | 23 | Memory level set to 256.000 MB 24 | 25 | ==> Input File <== 26 | 27 | -------------------------------------------------------------------------- 28 | memory 3000 mb 29 | 30 | molecule dimer { 31 | Ar 32 | } 33 | 34 | 35 | set basis cc-pVDZ 36 | set reference uhf 37 | 38 | # Initialize a blank dictionary of counterpoise corrected energies 39 | # (Need this for the syntax below to work) 40 | ecp = {} 41 | energy('mp2') 42 | -------------------------------------------------------------------------- 43 | 44 | Memory set to 3.000 GiB by Python script. 45 | 46 | No DF_BASIS_SCF auxiliary basis selected, defaulting to cc-pvdz-jkfit 47 | 48 | 49 | *** tstart() called on cx1-50-4-16.cx1.hpc.ic.ac.uk 50 | *** at Mon Feb 3 22:22:49 2014 51 | 52 | There are an even number of electrons - assuming singlet. 53 | Specify the multiplicity with the MULTP option in the 54 | input if this is incorrect 55 | 56 | 57 | --------------------------------------------------------- 58 | SCF 59 | by Justin Turney, Rob Parrish, and Andy Simmonett 60 | UHF Reference 61 | 1 Threads, 3000 MiB Core 62 | --------------------------------------------------------- 63 | 64 | ==> Geometry <== 65 | 66 | Molecular point group: d2h 67 | Geometry (in Angstrom), charge = 0, multiplicity = 1: 68 | 69 | Center X Y Z 70 | ------------ ----------------- ----------------- ----------------- 71 | AR 0.000000000000 0.000000000000 0.000000000000 72 | 73 | Running in d2h symmetry. 74 | 75 | 76 | Rotational constants (cm^-1): 77 | A = ********** B = ********** C = ********** 78 | 79 | Rotational constants (MHz): 80 | A = ********** B = ********** C = ********** 81 | Nuclear repulsion = 0.000000000000000 82 | 83 | Charge = 0 84 | Multiplicity = 1 85 | Electrons = 18 86 | Nalpha = 9 87 | Nbeta = 9 88 | 89 | ==> Algorithm <== 90 | 91 | SCF Algorithm Type is DF. 92 | DIIS enabled. 93 | MOM disabled. 94 | Fractional occupation disabled. 95 | Guess Type is CORE. 96 | Energy threshold = 1.00e-08 97 | Density threshold = 1.00e-08 98 | Integral threshold = 0.00e+00 99 | 100 | ==> Primary Basis <== 101 | 102 | Basis Set: CC-PVDZ 103 | Number of shells: 8 104 | Number of basis function: 18 105 | Number of Cartesian functions: 19 106 | Spherical Harmonics?: true 107 | Max angular momentum: 2 108 | 109 | ==> Pre-Iterations <== 110 | 111 | ------------------------------------------------------- 112 | Irrep Nso Nmo Nalpha Nbeta Ndocc Nsocc 113 | ------------------------------------------------------- 114 | Ag 6 6 0 0 0 0 115 | B1g 1 1 0 0 0 0 116 | B2g 1 1 0 0 0 0 117 | B3g 1 1 0 0 0 0 118 | Au 0 0 0 0 0 0 119 | B1u 3 3 0 0 0 0 120 | B2u 3 3 0 0 0 0 121 | B3u 3 3 0 0 0 0 122 | ------------------------------------------------------- 123 | Total 18 18 9 9 9 0 124 | ------------------------------------------------------- 125 | 126 | OEINTS: Wrapper to libmints. 127 | by Justin Turney 128 | 129 | Calculation information: 130 | Number of atoms: 1 131 | Number of AO shells: 8 132 | Number of SO shells: 8 133 | Number of primitives: 50 134 | Number of atomic orbitals: 19 135 | Number of basis functions: 18 136 | 137 | Number of irreps: 8 138 | Number of functions per irrep: [ 6 1 1 1 0 3 3 3 ] 139 | 140 | Overlap, kinetic, potential, dipole, and quadrupole integrals 141 | stored in file 35. 142 | 143 | ==> Integral Setup <== 144 | 145 | ==> DFJK: Density-Fitted J/K Matrices <== 146 | 147 | J tasked: Yes 148 | K tasked: Yes 149 | wK tasked: No 150 | OpenMP threads: 1 151 | Integrals threads: 1 152 | Memory (MB): 2145 153 | Algorithm: Core 154 | Integral Cache: NONE 155 | Schwarz Cutoff: 1E-12 156 | Fitting Condition: 1E-12 157 | 158 | => Auxiliary Basis Set <= 159 | 160 | Basis Set: cc-pvdz-jkfit 161 | Number of shells: 36 162 | Number of basis function: 112 163 | Number of Cartesian functions: 130 164 | Spherical Harmonics?: true 165 | Max angular momentum: 3 166 | 167 | Minimum eigenvalue in the overlap matrix is 1.1016109502E-01. 168 | Using Symmetric Orthogonalization. 169 | SCF Guess: Core (One-Electron) Hamiltonian. 170 | 171 | ==> Iterations <== 172 | 173 | Total Energy Delta E RMS |[F,P]| 174 | 175 | @DF-UHF iter 1: -523.38229308648260 -5.23382e+02 2.06743e-01 176 | @DF-UHF iter 2: -526.68798296484920 -3.30569e+00 6.85353e-02 DIIS 177 | @DF-UHF iter 3: -526.79853916161483 -1.10556e-01 6.77350e-03 DIIS 178 | @DF-UHF iter 4: -526.79985534241837 -1.31618e-03 7.83609e-04 DIIS 179 | @DF-UHF iter 5: -526.79986787621533 -1.25338e-05 1.26119e-04 DIIS 180 | @DF-UHF iter 6: -526.79986827914593 -4.02931e-07 1.02173e-06 DIIS 181 | @DF-UHF iter 7: -526.79986827915286 -6.93490e-12 1.49831e-08 DIIS 182 | @DF-UHF iter 8: -526.79986827915263 2.27374e-13 7.24451e-11 DIIS 183 | 184 | ==> Post-Iterations <== 185 | 186 | @Spin Contamination Metric: 1.065814104E-14 187 | @S^2 Expected: 0.000000000E+00 188 | @S^2 Observed: 1.065814104E-14 189 | @S Expected: 0.000000000E+00 190 | @S Observed: 0.000000000E+00 191 | 192 | Orbital Energies (a.u.) 193 | ----------------------- 194 | 195 | Alpha Occupied: 196 | 197 | 1Ag -118.606289 2Ag -12.317786 1B2u -9.566314 198 | 1B3u -9.566314 1B1u -9.566314 3Ag -1.274392 199 | 2B2u -0.588024 2B1u -0.588024 2B3u -0.588024 200 | 201 | Alpha Virtual: 202 | 203 | 3B1u 0.797264 3B2u 0.797264 3B3u 0.797264 204 | 4Ag 0.959750 1B1g 1.108403 1B2g 1.108403 205 | 1B3g 1.108403 5Ag 1.108403 6Ag 1.108403 206 | 207 | Beta Occupied: 208 | 209 | 1Ag -118.606289 2Ag -12.317786 1B2u -9.566314 210 | 1B3u -9.566314 1B1u -9.566314 3Ag -1.274392 211 | 2B2u -0.588024 2B1u -0.588024 2B3u -0.588024 212 | 213 | Beta Virtual: 214 | 215 | 3B1u 0.797264 3B2u 0.797264 3B3u 0.797264 216 | 4Ag 0.959750 1B1g 1.108403 1B2g 1.108403 217 | 1B3g 1.108403 5Ag 1.108403 6Ag 1.108403 218 | 219 | Final Occupation by Irrep: 220 | Ag B1g B2g B3g Au B1u B2u B3u 221 | DOCC [ 3, 0, 0, 0, 0, 2, 2, 2 ] 222 | SOCC [ 0, 0, 0, 0, 0, 0, 0, 0 ] 223 | 224 | Energy converged. 225 | 226 | @DF-UHF Final Energy: -526.79986827915263 227 | 228 | => Energetics <= 229 | 230 | Nuclear Repulsion Energy = 0.0000000000000000 231 | One-Electron Energy = -728.2767716859010534 232 | Two-Electron Energy = 201.4769034067483915 233 | DFT Exchange-Correlation Energy = 0.0000000000000000 234 | Empirical Dispersion Energy = 0.0000000000000000 235 | Total Energy = -526.7998682791526335 236 | 237 | 238 | 239 | Properties will be evaluated at 0.000000, 0.000000, 0.000000 Bohr 240 | ==> Properties <== 241 | 242 | 243 | Properties computed using the SCF density density matrix 244 | Nuclear Dipole Moment: (a.u.) 245 | X: 0.0000 Y: 0.0000 Z: 0.0000 246 | 247 | Electronic Dipole Moment: (a.u.) 248 | X: 0.0000 Y: 0.0000 Z: 0.0000 249 | 250 | Dipole Moment: (a.u.) 251 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 252 | 253 | Dipole Moment: (Debye) 254 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 255 | 256 | 257 | Saving occupied orbitals to File 180. 258 | 259 | *** tstop() called on cx1-50-4-16.cx1.hpc.ic.ac.uk at Mon Feb 3 22:22:52 2014 260 | Module time: 261 | user time = 0.14 seconds = 0.00 minutes 262 | system time = 0.01 seconds = 0.00 minutes 263 | total time = 3 seconds = 0.05 minutes 264 | Total time: 265 | user time = 0.14 seconds = 0.00 minutes 266 | system time = 0.01 seconds = 0.00 minutes 267 | total time = 3 seconds = 0.05 minutes 268 | 269 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>// 270 | // DFMP2 // 271 | //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DF-MP2 Energies <=================== 297 | ---------------------------------------------------------- 298 | Reference Energy = -526.7998682791526335 [H] 299 | Singles Energy = -0.0000000000000000 [H] 300 | Same-Spin Energy = -0.0403021427261389 [H] 301 | Opposite-Spin Energy = -0.1052838436972492 [H] 302 | Correlation Energy = -0.1455859864233881 [H] 303 | Total Energy = -526.9454542655760179 [H] 304 | ---------------------------------------------------------- 305 | ================> DF-SCS-MP2 Energies <================= 306 | ---------------------------------------------------------- 307 | SCS Same-Spin Scale = 0.3333333333333333 [-] 308 | SCS Opposite-Spin Scale = 1.2000000000000000 [-] 309 | SCS Same-Spin Energy = -0.0134340475753796 [H] 310 | SCS Opposite-Spin Energy = -0.1263406124366990 [H] 311 | SCS Correlation Energy = -0.1397746600120787 [H] 312 | SCS Total Energy = -526.9396429391647416 [H] 313 | ---------------------------------------------------------- 314 | 315 | 316 | *** tstop() called on cx1-50-4-16.cx1.hpc.ic.ac.uk at Mon Feb 3 22:22:53 2014 317 | Module time: 318 | user time = 0.10 seconds = 0.00 minutes 319 | system time = 0.01 seconds = 0.00 minutes 320 | total time = 1 seconds = 0.02 minutes 321 | Total time: 322 | user time = 0.24 seconds = 0.00 minutes 323 | system time = 0.02 seconds = 0.00 minutes 324 | total time = 4 seconds = 0.07 minutes 325 | 326 | *** PSI4 exiting successfully. Buy a developer a beer! 327 | -------------------------------------------------------------------------------- /prog_workshop4/H2S.xyz: -------------------------------------------------------------------------------- 1 | 3 2 | XYZ file of the hydrogen sulphide molecule 3 | S 0.00000000 0.00000000 0.10224900 4 | H 0.00000000 0.96805900 -0.81799200 5 | H 0.00000000 -0.96805900 -0.81799200 6 | -------------------------------------------------------------------------------- /prog_workshop4/He.out: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------- 2 | PSI4: An Open-Source Ab Initio Electronic Structure Package 3 | PSI 4.0.0-beta5+ Driver 4 | 5 | Git: Rev {master} eab4c2bf53d0cfe2fa7ff775dfb81b740d89e238 6 | 7 | J. M. Turney, A. C. Simmonett, R. M. Parrish, E. G. Hohenstein, 8 | F. A. Evangelista, J. T. Fermann, B. J. Mintz, L. A. Burns, J. J. Wilke, 9 | M. L. Abrams, N. J. Russ, M. L. Leininger, C. L. Janssen, E. T. Seidl, 10 | W. D. Allen, H. F. Schaefer, R. A. King, E. F. Valeev, C. D. Sherrill, 11 | and T. D. Crawford, WIREs Comput. Mol. Sci. 2, 556-565 (2012) 12 | (doi: 10.1002/wcms.93) 13 | 14 | Additional Contributions by 15 | A. E. DePrince, M. Saitow, U. Bozkaya, A. Yu. Sokolov 16 | ----------------------------------------------------------------------- 17 | 18 | Process ID: 6699 19 | PSI4DATADIR: /home/wv111/local/share/psi/ 20 | 21 | Using LocalCommunicator (Number of processes = 1) 22 | 23 | Memory level set to 256.000 MB 24 | 25 | ==> Input File <== 26 | 27 | -------------------------------------------------------------------------- 28 | memory 3000 mb 29 | 30 | molecule dimer { 31 | He 32 | } 33 | 34 | 35 | set basis cc-pVDZ 36 | set reference uhf 37 | 38 | # Initialize a blank dictionary of counterpoise corrected energies 39 | # (Need this for the syntax below to work) 40 | ecp = {} 41 | energy('mp2') 42 | -------------------------------------------------------------------------- 43 | 44 | Memory set to 3.000 GiB by Python script. 45 | 46 | No DF_BASIS_SCF auxiliary basis selected, defaulting to cc-pvdz-jkfit 47 | 48 | 49 | *** tstart() called on cx1-12-6-2.cx1.hpc.ic.ac.uk 50 | *** at Tue Feb 4 14:53:44 2014 51 | 52 | There are an even number of electrons - assuming singlet. 53 | Specify the multiplicity with the MULTP option in the 54 | input if this is incorrect 55 | 56 | 57 | --------------------------------------------------------- 58 | SCF 59 | by Justin Turney, Rob Parrish, and Andy Simmonett 60 | UHF Reference 61 | 1 Threads, 3000 MiB Core 62 | --------------------------------------------------------- 63 | 64 | ==> Geometry <== 65 | 66 | Molecular point group: d2h 67 | Geometry (in Angstrom), charge = 0, multiplicity = 1: 68 | 69 | Center X Y Z 70 | ------------ ----------------- ----------------- ----------------- 71 | HE 0.000000000000 0.000000000000 0.000000000000 72 | 73 | Running in d2h symmetry. 74 | 75 | 76 | Rotational constants (cm^-1): 77 | A = ********** B = ********** C = ********** 78 | 79 | Rotational constants (MHz): 80 | A = ********** B = ********** C = ********** 81 | Nuclear repulsion = 0.000000000000000 82 | 83 | Charge = 0 84 | Multiplicity = 1 85 | Electrons = 2 86 | Nalpha = 1 87 | Nbeta = 1 88 | 89 | ==> Algorithm <== 90 | 91 | SCF Algorithm Type is DF. 92 | DIIS enabled. 93 | MOM disabled. 94 | Fractional occupation disabled. 95 | Guess Type is CORE. 96 | Energy threshold = 1.00e-08 97 | Density threshold = 1.00e-08 98 | Integral threshold = 0.00e+00 99 | 100 | ==> Primary Basis <== 101 | 102 | Basis Set: CC-PVDZ 103 | Number of shells: 3 104 | Number of basis function: 5 105 | Number of Cartesian functions: 5 106 | Spherical Harmonics?: true 107 | Max angular momentum: 1 108 | 109 | ==> Pre-Iterations <== 110 | 111 | ------------------------------------------------------- 112 | Irrep Nso Nmo Nalpha Nbeta Ndocc Nsocc 113 | ------------------------------------------------------- 114 | Ag 2 2 0 0 0 0 115 | B1g 0 0 0 0 0 0 116 | B2g 0 0 0 0 0 0 117 | B3g 0 0 0 0 0 0 118 | Au 0 0 0 0 0 0 119 | B1u 1 1 0 0 0 0 120 | B2u 1 1 0 0 0 0 121 | B3u 1 1 0 0 0 0 122 | ------------------------------------------------------- 123 | Total 5 5 1 1 1 0 124 | ------------------------------------------------------- 125 | 126 | OEINTS: Wrapper to libmints. 127 | by Justin Turney 128 | 129 | Calculation information: 130 | Number of atoms: 1 131 | Number of AO shells: 3 132 | Number of SO shells: 3 133 | Number of primitives: 5 134 | Number of atomic orbitals: 5 135 | Number of basis functions: 5 136 | 137 | Number of irreps: 8 138 | Number of functions per irrep: [ 2 0 0 0 0 1 1 1 ] 139 | 140 | Overlap, kinetic, potential, dipole, and quadrupole integrals 141 | stored in file 35. 142 | 143 | ==> Integral Setup <== 144 | 145 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 146 | sanity check failed! Gaussian94BasisSetParser::parser: Unable to find the basis set for HE in /home/wv111/local/share/psi//basis/cc-pvdz-jkfit.gbs 147 | file: /home/wv111/psi4release/src/lib/libmints/basisset_parser.cc 148 | line: 362 149 | Turning off DF and switching to PK method. 150 | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 151 | MINTS: Wrapper to libmints. 152 | by Justin Turney 153 | 154 | Calculation information: 155 | Number of atoms: 1 156 | Number of AO shells: 3 157 | Number of SO shells: 3 158 | Number of primitives: 5 159 | Number of atomic orbitals: 5 160 | Number of basis functions: 5 161 | 162 | Number of irreps: 8 163 | Integral cutoff 0.00e+00 164 | Number of functions per irrep: [ 2 0 0 0 0 1 1 1 ] 165 | 166 | Overlap, kinetic, potential, dipole, and quadrupole integrals 167 | stored in file 35. 168 | 169 | Computing two-electron integrals...done 170 | Computed 33 non-zero two-electron integrals. 171 | Stored in file 33. 172 | 173 | Batch 1 pq = [ 0, 6] index = [ 0,21] 174 | ==> DiskJK: Disk-Based J/K Matrices <== 175 | 176 | J tasked: Yes 177 | K tasked: Yes 178 | wK tasked: No 179 | Memory (MB): 2145 180 | Schwarz Cutoff: 1E-12 181 | 182 | Minimum eigenvalue in the overlap matrix is 3.6583226831E-01. 183 | Using Symmetric Orthogonalization. 184 | SCF Guess: Core (One-Electron) Hamiltonian. 185 | 186 | ==> Iterations <== 187 | 188 | Total Energy Delta E RMS |[F,P]| 189 | 190 | @UHF iter 1: -2.74189680632999 -2.74190e+00 1.80274e-01 191 | @UHF iter 2: -2.85440990349123 -1.12513e-01 1.51220e-02 DIIS 192 | @UHF iter 3: -2.85516044565469 -7.50542e-04 9.81900e-05 DIIS 193 | @UHF iter 4: -2.85516047724238 -3.15877e-08 3.32428e-07 DIIS 194 | @UHF iter 5: -2.85516047724274 -3.62821e-13 7.53620e-10 DIIS 195 | 196 | ==> Post-Iterations <== 197 | 198 | @Spin Contamination Metric: 2.220446049E-16 199 | @S^2 Expected: 0.000000000E+00 200 | @S^2 Observed: 2.220446049E-16 201 | @S Expected: 0.000000000E+00 202 | @S Observed: 0.000000000E+00 203 | 204 | Orbital Energies (a.u.) 205 | ----------------------- 206 | 207 | Alpha Occupied: 208 | 209 | 1Ag -0.914148 210 | 211 | Alpha Virtual: 212 | 213 | 2Ag 1.397442 1B1u 2.524372 1B3u 2.524372 214 | 1B2u 2.524372 215 | 216 | Beta Occupied: 217 | 218 | 1Ag -0.914148 219 | 220 | Beta Virtual: 221 | 222 | 2Ag 1.397442 1B1u 2.524372 1B3u 2.524372 223 | 1B2u 2.524372 224 | 225 | Final Occupation by Irrep: 226 | Ag B1g B2g B3g Au B1u B2u B3u 227 | DOCC [ 1, 0, 0, 0, 0, 0, 0, 0 ] 228 | SOCC [ 0, 0, 0, 0, 0, 0, 0, 0 ] 229 | 230 | Energy converged. 231 | 232 | @UHF Final Energy: -2.85516047724274 233 | 234 | => Energetics <= 235 | 236 | Nuclear Repulsion Energy = 0.0000000000000000 237 | One-Electron Energy = -3.8820251017722445 238 | Two-Electron Energy = 1.0268646245295039 239 | DFT Exchange-Correlation Energy = 0.0000000000000000 240 | Empirical Dispersion Energy = 0.0000000000000000 241 | Total Energy = -2.8551604772427406 242 | 243 | 244 | 245 | Properties will be evaluated at 0.000000, 0.000000, 0.000000 Bohr 246 | ==> Properties <== 247 | 248 | 249 | Properties computed using the SCF density density matrix 250 | Nuclear Dipole Moment: (a.u.) 251 | X: 0.0000 Y: 0.0000 Z: 0.0000 252 | 253 | Electronic Dipole Moment: (a.u.) 254 | X: 0.0000 Y: 0.0000 Z: 0.0000 255 | 256 | Dipole Moment: (a.u.) 257 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 258 | 259 | Dipole Moment: (Debye) 260 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 261 | 262 | 263 | Saving occupied orbitals to File 180. 264 | 265 | *** tstop() called on cx1-12-6-2.cx1.hpc.ic.ac.uk at Tue Feb 4 14:53:46 2014 266 | Module time: 267 | user time = 0.05 seconds = 0.00 minutes 268 | system time = 0.01 seconds = 0.00 minutes 269 | total time = 2 seconds = 0.03 minutes 270 | Total time: 271 | user time = 0.05 seconds = 0.00 minutes 272 | system time = 0.01 seconds = 0.00 minutes 273 | total time = 2 seconds = 0.03 minutes 274 | 275 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>// 276 | // DFMP2 // 277 | //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DF-MP2 Energies <=================== 303 | ---------------------------------------------------------- 304 | Reference Energy = -2.8551604772427410 [H] 305 | Singles Energy = -0.0000000000000000 [H] 306 | Same-Spin Energy = 0.0000000000000000 [H] 307 | Opposite-Spin Energy = -0.0258244934942787 [H] 308 | Correlation Energy = -0.0258244934942787 [H] 309 | Total Energy = -2.8809849707370199 [H] 310 | ---------------------------------------------------------- 311 | ================> DF-SCS-MP2 Energies <================= 312 | ---------------------------------------------------------- 313 | SCS Same-Spin Scale = 0.3333333333333333 [-] 314 | SCS Opposite-Spin Scale = 1.2000000000000000 [-] 315 | SCS Same-Spin Energy = 0.0000000000000000 [H] 316 | SCS Opposite-Spin Energy = -0.0309893921931345 [H] 317 | SCS Correlation Energy = -0.0309893921931345 [H] 318 | SCS Total Energy = -2.8861498694358754 [H] 319 | ---------------------------------------------------------- 320 | 321 | 322 | *** tstop() called on cx1-12-6-2.cx1.hpc.ic.ac.uk at Tue Feb 4 14:53:46 2014 323 | Module time: 324 | user time = 0.07 seconds = 0.00 minutes 325 | system time = 0.00 seconds = 0.00 minutes 326 | total time = 0 seconds = 0.00 minutes 327 | Total time: 328 | user time = 0.12 seconds = 0.00 minutes 329 | system time = 0.01 seconds = 0.00 minutes 330 | total time = 2 seconds = 0.03 minutes 331 | 332 | *** PSI4 exiting successfully. Buy a developer a beer! 333 | -------------------------------------------------------------------------------- /prog_workshop4/Kr.out: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------- 2 | PSI4: An Open-Source Ab Initio Electronic Structure Package 3 | PSI 4.0.0-beta5+ Driver 4 | 5 | Git: Rev {master} eab4c2bf53d0cfe2fa7ff775dfb81b740d89e238 6 | 7 | J. M. Turney, A. C. Simmonett, R. M. Parrish, E. G. Hohenstein, 8 | F. A. Evangelista, J. T. Fermann, B. J. Mintz, L. A. Burns, J. J. Wilke, 9 | M. L. Abrams, N. J. Russ, M. L. Leininger, C. L. Janssen, E. T. Seidl, 10 | W. D. Allen, H. F. Schaefer, R. A. King, E. F. Valeev, C. D. Sherrill, 11 | and T. D. Crawford, WIREs Comput. Mol. Sci. 2, 556-565 (2012) 12 | (doi: 10.1002/wcms.93) 13 | 14 | Additional Contributions by 15 | A. E. DePrince, M. Saitow, U. Bozkaya, A. Yu. Sokolov 16 | ----------------------------------------------------------------------- 17 | 18 | Process ID: 2572 19 | PSI4DATADIR: /home/wv111/local/share/psi/ 20 | 21 | Using LocalCommunicator (Number of processes = 1) 22 | 23 | Memory level set to 256.000 MB 24 | 25 | ==> Input File <== 26 | 27 | -------------------------------------------------------------------------- 28 | memory 3000 mb 29 | 30 | molecule dimer { 31 | Kr 32 | } 33 | 34 | 35 | set basis cc-pVDZ 36 | set reference uhf 37 | 38 | # Initialize a blank dictionary of counterpoise corrected energies 39 | # (Need this for the syntax below to work) 40 | ecp = {} 41 | energy('mp2') 42 | -------------------------------------------------------------------------- 43 | 44 | Memory set to 3.000 GiB by Python script. 45 | 46 | No DF_BASIS_SCF auxiliary basis selected, defaulting to cc-pvdz-jkfit 47 | 48 | 49 | *** tstart() called on cx1-12-6-2.cx1.hpc.ic.ac.uk 50 | *** at Tue Feb 4 14:26:15 2014 51 | 52 | There are an even number of electrons - assuming singlet. 53 | Specify the multiplicity with the MULTP option in the 54 | input if this is incorrect 55 | 56 | 57 | --------------------------------------------------------- 58 | SCF 59 | by Justin Turney, Rob Parrish, and Andy Simmonett 60 | UHF Reference 61 | 1 Threads, 3000 MiB Core 62 | --------------------------------------------------------- 63 | 64 | ==> Geometry <== 65 | 66 | Molecular point group: d2h 67 | Geometry (in Angstrom), charge = 0, multiplicity = 1: 68 | 69 | Center X Y Z 70 | ------------ ----------------- ----------------- ----------------- 71 | KR 0.000000000000 0.000000000000 0.000000000000 72 | 73 | Running in d2h symmetry. 74 | 75 | 76 | Rotational constants (cm^-1): 77 | A = ********** B = ********** C = ********** 78 | 79 | Rotational constants (MHz): 80 | A = ********** B = ********** C = ********** 81 | Nuclear repulsion = 0.000000000000000 82 | 83 | Charge = 0 84 | Multiplicity = 1 85 | Electrons = 36 86 | Nalpha = 18 87 | Nbeta = 18 88 | 89 | ==> Algorithm <== 90 | 91 | SCF Algorithm Type is DF. 92 | DIIS enabled. 93 | MOM disabled. 94 | Fractional occupation disabled. 95 | Guess Type is CORE. 96 | Energy threshold = 1.00e-08 97 | Density threshold = 1.00e-08 98 | Integral threshold = 0.00e+00 99 | 100 | ==> Primary Basis <== 101 | 102 | Basis Set: CC-PVDZ 103 | Number of shells: 11 104 | Number of basis function: 27 105 | Number of Cartesian functions: 29 106 | Spherical Harmonics?: true 107 | Max angular momentum: 2 108 | 109 | ==> Pre-Iterations <== 110 | 111 | ------------------------------------------------------- 112 | Irrep Nso Nmo Nalpha Nbeta Ndocc Nsocc 113 | ------------------------------------------------------- 114 | Ag 9 9 0 0 0 0 115 | B1g 2 2 0 0 0 0 116 | B2g 2 2 0 0 0 0 117 | B3g 2 2 0 0 0 0 118 | Au 0 0 0 0 0 0 119 | B1u 4 4 0 0 0 0 120 | B2u 4 4 0 0 0 0 121 | B3u 4 4 0 0 0 0 122 | ------------------------------------------------------- 123 | Total 27 27 18 18 18 0 124 | ------------------------------------------------------- 125 | 126 | OEINTS: Wrapper to libmints. 127 | by Justin Turney 128 | 129 | Calculation information: 130 | Number of atoms: 1 131 | Number of AO shells: 11 132 | Number of SO shells: 11 133 | Number of primitives: 90 134 | Number of atomic orbitals: 29 135 | Number of basis functions: 27 136 | 137 | Number of irreps: 8 138 | Number of functions per irrep: [ 9 2 2 2 0 4 4 4 ] 139 | 140 | Overlap, kinetic, potential, dipole, and quadrupole integrals 141 | stored in file 35. 142 | 143 | ==> Integral Setup <== 144 | 145 | ==> DFJK: Density-Fitted J/K Matrices <== 146 | 147 | J tasked: Yes 148 | K tasked: Yes 149 | wK tasked: No 150 | OpenMP threads: 1 151 | Integrals threads: 1 152 | Memory (MB): 2145 153 | Algorithm: Core 154 | Integral Cache: NONE 155 | Schwarz Cutoff: 1E-12 156 | Fitting Condition: 1E-12 157 | 158 | => Auxiliary Basis Set <= 159 | 160 | Basis Set: cc-pvdz-jkfit 161 | Number of shells: 52 162 | Number of basis function: 188 163 | Number of Cartesian functions: 230 164 | Spherical Harmonics?: true 165 | Max angular momentum: 3 166 | 167 | Minimum eigenvalue in the overlap matrix is 9.4122781015E-02. 168 | Using Symmetric Orthogonalization. 169 | SCF Guess: Core (One-Electron) Hamiltonian. 170 | 171 | ==> Iterations <== 172 | 173 | Total Energy Delta E RMS |[F,P]| 174 | 175 | @DF-UHF iter 1: -2746.34444728974131 -2.74634e+03 2.19097e-01 176 | @DF-UHF iter 2: -2751.08957337878292 -4.74513e+00 7.32040e-02 DIIS 177 | @DF-UHF iter 3: -2751.25383439639972 -1.64261e-01 5.03020e-03 DIIS 178 | @DF-UHF iter 4: -2751.25562875034529 -1.79435e-03 7.86067e-04 DIIS 179 | @DF-UHF iter 5: -2751.25567363314667 -4.48828e-05 1.14934e-04 DIIS 180 | @DF-UHF iter 6: -2751.25567460287402 -9.69727e-07 1.04208e-06 DIIS 181 | @DF-UHF iter 7: -2751.25567460291813 -4.41105e-11 2.69903e-08 DIIS 182 | @DF-UHF iter 8: -2751.25567460291904 -9.09495e-13 9.25278e-10 DIIS 183 | 184 | ==> Post-Iterations <== 185 | 186 | @Spin Contamination Metric: -1.421085472E-14 187 | @S^2 Expected: 0.000000000E+00 188 | @S^2 Observed: -1.421085472E-14 189 | @S Expected: 0.000000000E+00 190 | @S Observed: 0.000000000E+00 191 | 192 | Orbital Energies (a.u.) 193 | ----------------------- 194 | 195 | Alpha Occupied: 196 | 197 | 1Ag -520.244133 2Ag -69.974765 1B2u -63.083594 198 | 1B3u -63.083594 1B1u -63.083594 3Ag -10.880531 199 | 2B3u -8.362563 2B1u -8.362563 2B2u -8.362563 200 | 4Ag -3.705192 5Ag -3.705192 1B1g -3.705192 201 | 1B3g -3.705192 1B2g -3.705192 6Ag -1.151755 202 | 3B1u -0.521274 3B3u -0.521274 3B2u -0.521274 203 | 204 | Alpha Virtual: 205 | 206 | 7Ag 0.723237 4B1u 0.772564 4B3u 0.772564 207 | 4B2u 0.772564 8Ag 0.864898 9Ag 0.864898 208 | 2B1g 0.864898 2B3g 0.864898 2B2g 0.864898 209 | 210 | Beta Occupied: 211 | 212 | 1Ag -520.244133 2Ag -69.974765 1B2u -63.083594 213 | 1B3u -63.083594 1B1u -63.083594 3Ag -10.880531 214 | 2B3u -8.362563 2B1u -8.362563 2B2u -8.362563 215 | 4Ag -3.705192 5Ag -3.705192 1B1g -3.705192 216 | 1B3g -3.705192 1B2g -3.705192 6Ag -1.151755 217 | 3B1u -0.521274 3B3u -0.521274 3B2u -0.521274 218 | 219 | Beta Virtual: 220 | 221 | 7Ag 0.723237 4B1u 0.772564 4B3u 0.772564 222 | 4B2u 0.772564 8Ag 0.864898 9Ag 0.864898 223 | 2B1g 0.864898 2B3g 0.864898 2B2g 0.864898 224 | 225 | Final Occupation by Irrep: 226 | Ag B1g B2g B3g Au B1u B2u B3u 227 | DOCC [ 6, 1, 1, 1, 0, 3, 3, 3 ] 228 | SOCC [ 0, 0, 0, 0, 0, 0, 0, 0 ] 229 | 230 | Energy converged. 231 | 232 | @DF-UHF Final Energy: -2751.25567460291904 233 | 234 | => Energetics <= 235 | 236 | Nuclear Repulsion Energy = 0.0000000000000000 237 | One-Electron Energy = -3829.1524743590935032 238 | Two-Electron Energy = 1077.8967997561744596 239 | DFT Exchange-Correlation Energy = 0.0000000000000000 240 | Empirical Dispersion Energy = 0.0000000000000000 241 | Total Energy = -2751.2556746029190435 242 | 243 | 244 | 245 | Properties will be evaluated at 0.000000, 0.000000, 0.000000 Bohr 246 | ==> Properties <== 247 | 248 | 249 | Properties computed using the SCF density density matrix 250 | Nuclear Dipole Moment: (a.u.) 251 | X: 0.0000 Y: 0.0000 Z: 0.0000 252 | 253 | Electronic Dipole Moment: (a.u.) 254 | X: 0.0000 Y: 0.0000 Z: 0.0000 255 | 256 | Dipole Moment: (a.u.) 257 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 258 | 259 | Dipole Moment: (Debye) 260 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 261 | 262 | 263 | Saving occupied orbitals to File 180. 264 | 265 | *** tstop() called on cx1-12-6-2.cx1.hpc.ic.ac.uk at Tue Feb 4 14:26:18 2014 266 | Module time: 267 | user time = 0.51 seconds = 0.01 minutes 268 | system time = 0.01 seconds = 0.00 minutes 269 | total time = 3 seconds = 0.05 minutes 270 | Total time: 271 | user time = 0.51 seconds = 0.01 minutes 272 | system time = 0.01 seconds = 0.00 minutes 273 | total time = 3 seconds = 0.05 minutes 274 | 275 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>// 276 | // DFMP2 // 277 | //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DF-MP2 Energies <=================== 303 | ---------------------------------------------------------- 304 | Reference Energy = -2751.2556746029190435 [H] 305 | Singles Energy = -0.0000000000000000 [H] 306 | Same-Spin Energy = -0.0422227428831926 [H] 307 | Opposite-Spin Energy = -0.0970738491056196 [H] 308 | Correlation Energy = -0.1392965919888122 [H] 309 | Total Energy = -2751.3949711949080665 [H] 310 | ---------------------------------------------------------- 311 | ================> DF-SCS-MP2 Energies <================= 312 | ---------------------------------------------------------- 313 | SCS Same-Spin Scale = 0.3333333333333333 [-] 314 | SCS Opposite-Spin Scale = 1.2000000000000000 [-] 315 | SCS Same-Spin Energy = -0.0140742476277309 [H] 316 | SCS Opposite-Spin Energy = -0.1164886189267435 [H] 317 | SCS Correlation Energy = -0.1305628665544743 [H] 318 | SCS Total Energy = -2751.3862374694735990 [H] 319 | ---------------------------------------------------------- 320 | 321 | 322 | *** tstop() called on cx1-12-6-2.cx1.hpc.ic.ac.uk at Tue Feb 4 14:26:30 2014 323 | Module time: 324 | user time = 0.40 seconds = 0.01 minutes 325 | system time = 0.01 seconds = 0.00 minutes 326 | total time = 12 seconds = 0.20 minutes 327 | Total time: 328 | user time = 0.91 seconds = 0.02 minutes 329 | system time = 0.02 seconds = 0.00 minutes 330 | total time = 15 seconds = 0.25 minutes 331 | 332 | *** PSI4 exiting successfully. Buy a developer a beer! 333 | -------------------------------------------------------------------------------- /prog_workshop4/Ne.out: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------- 2 | PSI4: An Open-Source Ab Initio Electronic Structure Package 3 | PSI 4.0.0-beta5+ Driver 4 | 5 | Git: Rev {master} eab4c2bf53d0cfe2fa7ff775dfb81b740d89e238 6 | 7 | J. M. Turney, A. C. Simmonett, R. M. Parrish, E. G. Hohenstein, 8 | F. A. Evangelista, J. T. Fermann, B. J. Mintz, L. A. Burns, J. J. Wilke, 9 | M. L. Abrams, N. J. Russ, M. L. Leininger, C. L. Janssen, E. T. Seidl, 10 | W. D. Allen, H. F. Schaefer, R. A. King, E. F. Valeev, C. D. Sherrill, 11 | and T. D. Crawford, WIREs Comput. Mol. Sci. 2, 556-565 (2012) 12 | (doi: 10.1002/wcms.93) 13 | 14 | Additional Contributions by 15 | A. E. DePrince, M. Saitow, U. Bozkaya, A. Yu. Sokolov 16 | ----------------------------------------------------------------------- 17 | 18 | Process ID: 18719 19 | PSI4DATADIR: /home/wv111/local/share/psi/ 20 | 21 | Using LocalCommunicator (Number of processes = 1) 22 | 23 | Memory level set to 256.000 MB 24 | 25 | ==> Input File <== 26 | 27 | -------------------------------------------------------------------------- 28 | memory 3000 mb 29 | 30 | molecule dimer { 31 | Ne 32 | } 33 | 34 | 35 | set basis cc-pVDZ 36 | set reference uhf 37 | 38 | # Initialize a blank dictionary of counterpoise corrected energies 39 | # (Need this for the syntax below to work) 40 | ecp = {} 41 | energy('mp2') 42 | -------------------------------------------------------------------------- 43 | 44 | Memory set to 3.000 GiB by Python script. 45 | 46 | No DF_BASIS_SCF auxiliary basis selected, defaulting to cc-pvdz-jkfit 47 | 48 | 49 | *** tstart() called on cx1-12-6-9.cx1.hpc.ic.ac.uk 50 | *** at Wed Feb 5 14:32:24 2014 51 | 52 | There are an even number of electrons - assuming singlet. 53 | Specify the multiplicity with the MULTP option in the 54 | input if this is incorrect 55 | 56 | 57 | --------------------------------------------------------- 58 | SCF 59 | by Justin Turney, Rob Parrish, and Andy Simmonett 60 | UHF Reference 61 | 1 Threads, 3000 MiB Core 62 | --------------------------------------------------------- 63 | 64 | ==> Geometry <== 65 | 66 | Molecular point group: d2h 67 | Geometry (in Angstrom), charge = 0, multiplicity = 1: 68 | 69 | Center X Y Z 70 | ------------ ----------------- ----------------- ----------------- 71 | NE 0.000000000000 0.000000000000 0.000000000000 72 | 73 | Running in d2h symmetry. 74 | 75 | 76 | Rotational constants (cm^-1): 77 | A = ********** B = ********** C = ********** 78 | 79 | Rotational constants (MHz): 80 | A = ********** B = ********** C = ********** 81 | Nuclear repulsion = 0.000000000000000 82 | 83 | Charge = 0 84 | Multiplicity = 1 85 | Electrons = 10 86 | Nalpha = 5 87 | Nbeta = 5 88 | 89 | ==> Algorithm <== 90 | 91 | SCF Algorithm Type is DF. 92 | DIIS enabled. 93 | MOM disabled. 94 | Fractional occupation disabled. 95 | Guess Type is CORE. 96 | Energy threshold = 1.00e-08 97 | Density threshold = 1.00e-08 98 | Integral threshold = 0.00e+00 99 | 100 | ==> Primary Basis <== 101 | 102 | Basis Set: CC-PVDZ 103 | Number of shells: 6 104 | Number of basis function: 14 105 | Number of Cartesian functions: 15 106 | Spherical Harmonics?: true 107 | Max angular momentum: 2 108 | 109 | ==> Pre-Iterations <== 110 | 111 | ------------------------------------------------------- 112 | Irrep Nso Nmo Nalpha Nbeta Ndocc Nsocc 113 | ------------------------------------------------------- 114 | Ag 5 5 0 0 0 0 115 | B1g 1 1 0 0 0 0 116 | B2g 1 1 0 0 0 0 117 | B3g 1 1 0 0 0 0 118 | Au 0 0 0 0 0 0 119 | B1u 2 2 0 0 0 0 120 | B2u 2 2 0 0 0 0 121 | B3u 2 2 0 0 0 0 122 | ------------------------------------------------------- 123 | Total 14 14 5 5 5 0 124 | ------------------------------------------------------- 125 | 126 | OEINTS: Wrapper to libmints. 127 | by Justin Turney 128 | 129 | Calculation information: 130 | Number of atoms: 1 131 | Number of AO shells: 6 132 | Number of SO shells: 6 133 | Number of primitives: 22 134 | Number of atomic orbitals: 15 135 | Number of basis functions: 14 136 | 137 | Number of irreps: 8 138 | Number of functions per irrep: [ 5 1 1 1 0 2 2 2 ] 139 | 140 | Overlap, kinetic, potential, dipole, and quadrupole integrals 141 | stored in file 35. 142 | 143 | ==> Integral Setup <== 144 | 145 | ==> DFJK: Density-Fitted J/K Matrices <== 146 | 147 | J tasked: Yes 148 | K tasked: Yes 149 | wK tasked: No 150 | OpenMP threads: 1 151 | Integrals threads: 1 152 | Memory (MB): 2145 153 | Algorithm: Core 154 | Integral Cache: NONE 155 | Schwarz Cutoff: 1E-12 156 | Fitting Condition: 1E-12 157 | 158 | => Auxiliary Basis Set <= 159 | 160 | Basis Set: cc-pvdz-jkfit 161 | Number of shells: 24 162 | Number of basis function: 70 163 | Number of Cartesian functions: 81 164 | Spherical Harmonics?: true 165 | Max angular momentum: 3 166 | 167 | Minimum eigenvalue in the overlap matrix is 1.9330486283E-01. 168 | Using Symmetric Orthogonalization. 169 | SCF Guess: Core (One-Electron) Hamiltonian. 170 | 171 | ==> Iterations <== 172 | 173 | Total Energy Delta E RMS |[F,P]| 174 | 175 | @DF-UHF iter 1: -122.77299660256577 -1.22773e+02 5.12050e-01 176 | @DF-UHF iter 2: -127.36748844384414 -4.59449e+00 3.37057e-01 DIIS 177 | @DF-UHF iter 3: -128.48680374857301 -1.11932e+00 1.37187e-02 DIIS 178 | @DF-UHF iter 4: -128.48873838767653 -1.93464e-03 2.89397e-03 DIIS 179 | @DF-UHF iter 5: -128.48879298914659 -5.46015e-05 6.98271e-04 DIIS 180 | @DF-UHF iter 6: -128.48879661006694 -3.62092e-06 4.95326e-06 DIIS 181 | @DF-UHF iter 7: -128.48879661029596 -2.29022e-10 1.64551e-07 DIIS 182 | @DF-UHF iter 8: -128.48879661029613 -1.70530e-13 3.80094e-09 DIIS 183 | 184 | ==> Post-Iterations <== 185 | 186 | @Spin Contamination Metric: 3.552713679E-15 187 | @S^2 Expected: 0.000000000E+00 188 | @S^2 Observed: 3.552713679E-15 189 | @S Expected: 0.000000000E+00 190 | @S Observed: 0.000000000E+00 191 | 192 | Orbital Energies (a.u.) 193 | ----------------------- 194 | 195 | Alpha Occupied: 196 | 197 | 1Ag -32.765665 2Ag -1.918810 1B3u -0.832115 198 | 1B1u -0.832115 1B2u -0.832115 199 | 200 | Alpha Virtual: 201 | 202 | 2B1u 1.694660 2B3u 1.694660 2B2u 1.694660 203 | 3Ag 2.159507 1B1g 5.197106 4Ag 5.197106 204 | 5Ag 5.197106 1B2g 5.197106 1B3g 5.197106 205 | 206 | Beta Occupied: 207 | 208 | 1Ag -32.765665 2Ag -1.918810 1B3u -0.832115 209 | 1B1u -0.832115 1B2u -0.832115 210 | 211 | Beta Virtual: 212 | 213 | 2B1u 1.694660 2B3u 1.694660 2B2u 1.694660 214 | 3Ag 2.159507 1B1g 5.197106 4Ag 5.197106 215 | 5Ag 5.197106 1B2g 5.197106 1B3g 5.197106 216 | 217 | Final Occupation by Irrep: 218 | Ag B1g B2g B3g Au B1u B2u B3u 219 | DOCC [ 2, 0, 0, 0, 0, 1, 1, 1 ] 220 | SOCC [ 0, 0, 0, 0, 0, 0, 0, 0 ] 221 | 222 | Energy converged. 223 | 224 | @DF-UHF Final Energy: -128.48879661029613 225 | 226 | => Energetics <= 227 | 228 | Nuclear Repulsion Energy = 0.0000000000000000 229 | One-Electron Energy = -182.6159553194615910 230 | Two-Electron Energy = 54.1271587091654567 231 | DFT Exchange-Correlation Energy = 0.0000000000000000 232 | Empirical Dispersion Energy = 0.0000000000000000 233 | Total Energy = -128.4887966102961343 234 | 235 | 236 | 237 | Properties will be evaluated at 0.000000, 0.000000, 0.000000 Bohr 238 | ==> Properties <== 239 | 240 | 241 | Properties computed using the SCF density density matrix 242 | Nuclear Dipole Moment: (a.u.) 243 | X: 0.0000 Y: 0.0000 Z: 0.0000 244 | 245 | Electronic Dipole Moment: (a.u.) 246 | X: 0.0000 Y: 0.0000 Z: 0.0000 247 | 248 | Dipole Moment: (a.u.) 249 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 250 | 251 | Dipole Moment: (Debye) 252 | X: 0.0000 Y: 0.0000 Z: 0.0000 Total: 0.0000 253 | 254 | 255 | Saving occupied orbitals to File 180. 256 | 257 | *** tstop() called on cx1-12-6-9.cx1.hpc.ic.ac.uk at Wed Feb 5 14:32:25 2014 258 | Module time: 259 | user time = 0.13 seconds = 0.00 minutes 260 | system time = 0.01 seconds = 0.00 minutes 261 | total time = 1 seconds = 0.02 minutes 262 | Total time: 263 | user time = 0.13 seconds = 0.00 minutes 264 | system time = 0.01 seconds = 0.00 minutes 265 | total time = 1 seconds = 0.02 minutes 266 | 267 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>// 268 | // DFMP2 // 269 | //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DF-MP2 Energies <=================== 295 | ---------------------------------------------------------- 296 | Reference Energy = -128.4887966102961343 [H] 297 | Singles Energy = -0.0000000000000000 [H] 298 | Same-Spin Energy = -0.0515581170495575 [H] 299 | Opposite-Spin Energy = -0.1359986877719555 [H] 300 | Correlation Energy = -0.1875568048215131 [H] 301 | Total Energy = -128.6763534151176600 [H] 302 | ---------------------------------------------------------- 303 | ================> DF-SCS-MP2 Energies <================= 304 | ---------------------------------------------------------- 305 | SCS Same-Spin Scale = 0.3333333333333333 [-] 306 | SCS Opposite-Spin Scale = 1.2000000000000000 [-] 307 | SCS Same-Spin Energy = -0.0171860390165192 [H] 308 | SCS Opposite-Spin Energy = -0.1631984253263466 [H] 309 | SCS Correlation Energy = -0.1803844643428658 [H] 310 | SCS Total Energy = -128.6691810746389990 [H] 311 | ---------------------------------------------------------- 312 | 313 | 314 | *** tstop() called on cx1-12-6-9.cx1.hpc.ic.ac.uk at Wed Feb 5 14:32:25 2014 315 | Module time: 316 | user time = 0.11 seconds = 0.00 minutes 317 | system time = 0.00 seconds = 0.00 minutes 318 | total time = 0 seconds = 0.00 minutes 319 | Total time: 320 | user time = 0.24 seconds = 0.00 minutes 321 | system time = 0.01 seconds = 0.00 minutes 322 | total time = 1 seconds = 0.02 minutes 323 | 324 | *** PSI4 exiting successfully. Buy a developer a beer! 325 | -------------------------------------------------------------------------------- /prog_workshop4/prog_workshop4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Introduction to programming 4" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "William Vigor, Clyde Fare and João Pedro Malhado, Imperial College London (contact: [chemistry-git@imperial.ac.uk](mailto:chemistry-git@imperial.ac.uk))\n", 15 | "\n", 16 | "Notebook is licensed under a [Creative Commons Attribution 4.0 (CC-by) license](http://creativecommons.org/licenses/by/4.0/)." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "## Overview" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "Up to now all our programs have run in their little bubble: they define the variable values they use and after they finish they leave little trace that they were ever run. Things changed a little in the last workshop where we introduced the possibility of the user passing on some information for the program to process. We will go a step further in seeing how we can interact with files.\n", 31 | "\n", 32 | "Dealing and interacting with files is a very common way of processing information stored in a computer, and is something that your programs might often do. When we deal with files and our programs go beyond their \"logical bubble\", is when we can start doing some damage: delete information on files, delete files all together, fill up the hard disk, damage your installation (the operating system should actually have safeguards for this). This should not intimidate you, it is just that with power it comes responsibility.\n", 33 | "\n", 34 | "In this workshop we will first go over the basic operations on files. Then we will look at a case study of a common scenario where we want to process a file to extract information in a useful format." 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## Workshop content\n", 42 | "\n", 43 | "#### Part 1\n", 44 | "* [Dealing with files](#files)\n", 45 | "* [Parsing a simple XYZ file - exercise](#xyz)\n", 46 | "\n", 47 | "#### Part 2\n", 48 | "* [Parsing a complex file - guided exercise](#dimers)" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "## Dealing with files " 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "In any computer hard-disk there are typically two types of files: text files and binary files. Text files are those you can read with a text editor program (think of Notepad, not Microsoft Word), and do not necessarily contain prose. (If you open this notebook, which has an extension \\*.ipynb, on a text editor you will see that it is text in some form. The Jupyter notebook is a text file.) Binary files on the other end cannot be opened on a text editor, or when they do open they show up as ununderstandable characters. (Picture files like PNG or JPEG, music files like MP3, video files, Word DOC files, are all binary files.)\n", 63 | "\n", 64 | "We will only be looking at manipulating text files. Although Python can also manipulate binary files, the caveat of such files is that the programmer needs to know *a priori* how the content of the file is structured, and since one cannot just look at the file on a text editor, this task is harder. Binary files further require knowledge of some low level computer architecture which is beyond the scope of this course. Manipulating text files will however illustrate the process, and most instruments and computer programs are able to write data in some form of text file." 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "We will start by loading the content of the file test.out (you can open the file to look at its content). First we need to open a stream to the file content and set it to a variable. This is done with function `open()`\n", 72 | "\n", 73 | " stream1=open('test.out','r')" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "This takes a string containing the name of our file (including the full path if the file is not in the same directory as the notebook/script) and as a second argument a flag telling Python whether we are going to read or write to the file. ('r' for reading and 'w' for writing).\n", 88 | "\n", 89 | "Via the variable *stream1* we now have direct access to the content of the file. We can for example read one line from the file using\n", 90 | "\n", 91 | " stream1.readline()" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "If we repeat the same command we will now read the second line in the file, since the process of reading the file is sequential\n", 106 | "\n", 107 | " stream1.readline()" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "Note at the end of the line you see the linebreak represented by '\\n' which counts as a single character.\n", 122 | "\n", 123 | "We may now consider that we finished working on the file, close the stream and leave the file in peace\n", 124 | "\n", 125 | " stream1.close()" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "Since the process of reading the file is sequential, using a loop is a practical way of accessing the content of a file. We could use the `.readline()` method in the body of the loop, or indeed loop over the file stream itself to access each line in the file\n", 140 | "\n", 141 | " stream2=open('test.out','r')\n", 142 | " for line in stream2:\n", 143 | " print(line)\n", 144 | " steam2.close()" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "If we are interested in a list with every line in the file we could build a list with a loop, or simply operate with the function *list()* on the stream\n", 159 | "\n", 160 | " stream3=open('test.out','r')\n", 161 | " list_content=list(stream3)\n", 162 | " stream3.close()\n", 163 | " list_content" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "We should be slightly careful when performing this operations as it puts all the content of the file into a list, which will be unmanageable if the file is several gigabytes in size.\n", 178 | "\n", 179 | "The house keeping step of closing the stream can be a bit tedious an easily forgotten. The following construct will close the stream for us when we are done\n", 180 | "\n", 181 | " with open('test.out','r') as stream:\n", 182 | " for i in range(2):\n", 183 | " autumn=stream.readline()\n", 184 | " print(autumn)" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "metadata": {}, 191 | "outputs": [], 192 | "source": [] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "If we are just interested in some specific information in the file we can search for it as we read it.\n", 199 | "\n", 200 | "The following code looks for the line with the substring 'leaves' and extracts the colour of the leaves in the text." 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": {}, 207 | "outputs": [], 208 | "source": [ 209 | "with open('test.out','r') as stream:\n", 210 | " for line in stream:\n", 211 | " if 'leaves' in line:\n", 212 | " leaf_colour = line.split()[4]\n", 213 | " \n", 214 | "leaf_colour[:-1]" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "metadata": {}, 220 | "source": [ 221 | "Note that the variable *line* is a string with each line in the file. If we are interested in individual words, we can form a list from a string with the `.split()` method.\n", 222 | "\n", 223 | " \"Read my words. One by one.\".split()" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": null, 229 | "metadata": {}, 230 | "outputs": [], 231 | "source": [] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": {}, 236 | "source": [ 237 | "By default `.split()` separates the string on the blank spaces (space or tab characters), but we can choose any other character\n", 238 | "\n", 239 | " \"Read my words. One by one.\".split(\".\")" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": null, 245 | "metadata": {}, 246 | "outputs": [], 247 | "source": [] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "For completeness, the opposite operation to `.split()` is performed by `.join()`\n", 254 | "\n", 255 | " \"--\".join(['three','two','one','go'])" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": {}, 262 | "outputs": [], 263 | "source": [] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": {}, 268 | "source": [ 269 | "Is it clear how we are obtaining the colour of the leaves? Write some code below that extracts the colour of the sky instead knowing that it is the second word after 'sky'." 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": {}, 282 | "source": [ 283 | "The authors of those words were probably not in their best mood. So we are going to change the text to make it more cheerful (even if slightly psychedelic). The goal is thus to construct a list of the verses in the lyrics, but with *blue* leaves, a *bay* sky and a *glorious* day. Let us call this list *cheerful*.\n", 284 | "\n", 285 | "This can be done with two nested loops: one looping over the lines in the file, the other over the words of each line; and a combination of both `.split()` and `.join()`." 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": null, 291 | "metadata": {}, 292 | "outputs": [], 293 | "source": [] 294 | }, 295 | { 296 | "cell_type": "markdown", 297 | "metadata": {}, 298 | "source": [ 299 | "If we want to write our cheerful version to a file, we just do\n", 300 | "\n", 301 | " with open('cheerful.out','w') as stream:\n", 302 | " stream.writelines(cheerful)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": null, 308 | "metadata": {}, 309 | "outputs": [], 310 | "source": [] 311 | }, 312 | { 313 | "cell_type": "markdown", 314 | "metadata": {}, 315 | "source": [ 316 | "Note that if you open a file for writing you **will overwrite whatever was initially in the file**.\n", 317 | "\n", 318 | "The [os module](https://docs.python.org/3/library/os.html\") provides many functions for interaction with the operating system, including the file system. We can get the list of the files in the current directory and see if our new created file is in place\n", 319 | "\n", 320 | " import os\n", 321 | " os.listdir()" 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": null, 327 | "metadata": {}, 328 | "outputs": [], 329 | "source": [] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "metadata": {}, 334 | "source": [ 335 | "### XYZ molecular structure files " 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": {}, 341 | "source": [ 342 | "A very common type of text file used in chemistry is the XYZ file to represent chemical structures. The H2S.xyz file, present in the same directory as the notebook, is an example of such file (you can open it using a molecular viewer program such as Avogadro). If we open the H2S.xyz file on a text editor, we can clearly note the general structure of such files:\n", 343 | "\n", 344 | "* The first line of the file is formed by a single integer number *n* indicating the number atoms present in the chemical structure in the file.\n", 345 | "* The second line is a string containing a comment about the file. It is often left blank, but this line must be present.\n", 346 | "* It follows *n* lines with the chemical symbol of each atom and its position in space in Cartesian coordinates in Ångström.\n", 347 | "\n", 348 | "In this exercise, we will want to determine what is the bond angle of the H2S molecule represented in the H2S.xyz.\n", 349 | "\n", 350 | "First, write some code to extract the position of each atom in the molecule, in the form of a list where each element is another list with the atom coordinates." 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": null, 356 | "metadata": {}, 357 | "outputs": [], 358 | "source": [] 359 | }, 360 | { 361 | "cell_type": "markdown", 362 | "metadata": {}, 363 | "source": [ 364 | "Note that the bond angle can be determined with relative ease, by thinking of the vectors that connect the atom positions:\n", 365 | "\n", 366 | "\n", 367 | "\n", 368 | "Using arrays from the Numpy module, obtain the two relevant vectors from the atoms' coordinates previously taken from the file." 369 | ] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "execution_count": null, 374 | "metadata": {}, 375 | "outputs": [], 376 | "source": [] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "Using the dot() and norm() functions from the Numpy module, determine the bond angle on the H2S molecule." 383 | ] 384 | }, 385 | { 386 | "cell_type": "code", 387 | "execution_count": null, 388 | "metadata": {}, 389 | "outputs": [], 390 | "source": [] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": {}, 395 | "source": [ 396 | "# Part 2" 397 | ] 398 | }, 399 | { 400 | "cell_type": "markdown", 401 | "metadata": {}, 402 | "source": [ 403 | "## Ne2 dissociation: extracting information from files " 404 | ] 405 | }, 406 | { 407 | "cell_type": "markdown", 408 | "metadata": {}, 409 | "source": [ 410 | "In this mini-project we will be looking at the dissociation curve of two neon atoms, i.e. how their electronic energy varies with the distance between the two atoms. By analysing this curve, beyond other quantities, it is possible to determine the equilibrium distance between atoms at low temperature.\n", 411 | "\n", 412 | "This task will involve extracting the relevant information from the output file of a quantum chemistry calculation. The file Ne.out is a fairly typical log file of an electronic structure calculation program, in this case from the Psi4 program, and corresponds to a calculation of the electronic energy of a single neon atom. By looking at the file one notices that a lot of detail is given about the electronic structure of neon and about the calculation itself. We want to write a program that extracts from the file the relevant information to accomplish the task in hand.\n", 413 | "\n", 414 | "The situation where we have a text file generated by a program or an instrument, and wish to extract some relevant information (for example to make a plot), is a fairly common one both when working in an experimental or computational setting. We will look at how to address this problem." 415 | ] 416 | }, 417 | { 418 | "cell_type": "markdown", 419 | "metadata": {}, 420 | "source": [ 421 | "We will first focus our attention on the energy of an isolated neon atom. We can find this energy expressed in Hartrees towards the end of the Ne.out file on the line\n", 422 | "\n", 423 | " Total Energy = -128.6763534151176600 [H]\n", 424 | "\n", 425 | "Note that the substring \"Total Energies\" shows up several times in the file, so it is important to search for a substring with the correct number of spaces.\n", 426 | "In the cell below remove 'pass' and in its place write some code that will read the log file and set a variable named 'energy_str' to the string with the energy of the neon atom" 427 | ] 428 | }, 429 | { 430 | "cell_type": "code", 431 | "execution_count": null, 432 | "metadata": {}, 433 | "outputs": [], 434 | "source": [ 435 | "with open('Ne.out', 'r') as f:\n", 436 | " for line in f:\n", 437 | " pass" 438 | ] 439 | }, 440 | { 441 | "cell_type": "markdown", 442 | "metadata": {}, 443 | "source": [ 444 | "Now we have extracted the energy as a string, modify the code to generate a new variable named 'ne_energy' which contains the energy as a floating point number." 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "execution_count": null, 450 | "metadata": {}, 451 | "outputs": [], 452 | "source": [ 453 | "with open('Ne.out', 'r') as f:\n", 454 | " for line in f:\n", 455 | " pass" 456 | ] 457 | }, 458 | { 459 | "cell_type": "markdown", 460 | "metadata": {}, 461 | "source": [ 462 | "Based on the code above, define a function *get_atom_energy()* which receives a string with the name of a file of an atom electronic structure calculation and returns the MP2 total energy from that file." 463 | ] 464 | }, 465 | { 466 | "cell_type": "code", 467 | "execution_count": null, 468 | "metadata": {}, 469 | "outputs": [], 470 | "source": [] 471 | }, 472 | { 473 | "cell_type": "markdown", 474 | "metadata": {}, 475 | "source": [ 476 | "We now have a way to extract the energy of a single atom, but we are interested in the energy of 2 atoms as a function of the energy. The file Ne2.out contains energies for a neon dimer for different positions of the two atoms.\n", 477 | "\n", 478 | "You can open the file and note that is has the following format:" 479 | ] 480 | }, 481 | { 482 | "cell_type": "raw", 483 | "metadata": {}, 484 | "source": [ 485 | ".\n", 486 | ".\n", 487 | ". Some irrelevant stuff\n", 488 | ".\n", 489 | ".\n", 490 | "\n", 491 | " Center X Y Z\n", 492 | "------------ ----------------- ----------------- -----------------\n", 493 | " NE 0.000000000000 0.000000000000 -0.250000000000\n", 494 | " NE 0.000000000000 0.000000000000 0.250000000000\n", 495 | "\n", 496 | ".\n", 497 | ".\n", 498 | ". Some more irrelevant stuff\n", 499 | ".\n", 500 | ".\n", 501 | " ==================> DF-MP2 Energies <===================\n", 502 | " ----------------------------------------------------------\n", 503 | " Reference Energy = -256.9755260598059294 [H]\n", 504 | " Singles Energy = -0.0000000000000000 [H]\n", 505 | " Same-Spin Energy = -0.1032374376641407 [H]\n", 506 | " Opposite-Spin Energy = -0.2721124831543129 [H]\n", 507 | " Correlation Energy = -0.3753499208184536 [H]\n", 508 | " Total Energy = -257.3508759806243802 [H]\n", 509 | "\n", 510 | ".\n", 511 | ".\n", 512 | ". Some more irrelevant stuff\n", 513 | ".\n", 514 | "." 515 | ] 516 | }, 517 | { 518 | "cell_type": "markdown", 519 | "metadata": {}, 520 | "source": [ 521 | "This format is then repeated giving data for several different coordinates of neon atom pairs. Our task is to extract both the information about atom position (from which we will obtain the distance) and the energy. We will tackle these two problems separately at first." 522 | ] 523 | }, 524 | { 525 | "cell_type": "markdown", 526 | "metadata": {}, 527 | "source": [ 528 | "The coordinates of the two Ne atoms are specified in Å:\n", 529 | "\n", 530 | " Center X Y Z\n", 531 | " ------------ ----------------- ----------------- -----------------\n", 532 | " NE 0.000000000000 0.000000000000 -0.250000000000\n", 533 | " NE 0.000000000000 0.000000000000 0.250000000000\n", 534 | "\n", 535 | "Unfortunately the two lines have the same format so it is not quite as easy as before to distinguish between lines and extract the data. But we do know that whenever we find a 'Ne' symbol on the line we want to extract the coordinates, but we need a mechanism to distinguish between atom 1 and atom 2.\n", 536 | "\n", 537 | "Study the following cell. In it the code goes through the file line by line, and prints out the neon coordinates specifying which neon atom the coordinates refer to:" 538 | ] 539 | }, 540 | { 541 | "cell_type": "code", 542 | "execution_count": null, 543 | "metadata": {}, 544 | "outputs": [], 545 | "source": [ 546 | "#we use the variable first_Ne as a flag to indicate whether the next line with an 'Ne' in it\n", 547 | "#will be the first or the second Neon atom. It is initiated to True\n", 548 | "first_Ne = True\n", 549 | "\n", 550 | "with open('Ne2.out', 'r') as f:\n", 551 | " for line in f:\n", 552 | " #if we are on the line with the first Ne\n", 553 | " if 'NE' in line.split() and first_Ne:\n", 554 | " print('1: ' + line)\n", 555 | " \n", 556 | " #set the flag to false because the next line with Ne on will be the second Ne\n", 557 | " first_Ne=False\n", 558 | " \n", 559 | " #we are on the line with second Ne\n", 560 | " elif 'NE' in line.split() and not first_Ne:\n", 561 | " print('2: ' + line)\n", 562 | "\n", 563 | " #set the flag to true because the next line will Ne on with be the first Ne\n", 564 | " first_Ne=True" 565 | ] 566 | }, 567 | { 568 | "cell_type": "markdown", 569 | "metadata": {}, 570 | "source": [ 571 | "Modify the cell below so that instead of printing the whole line out every time we find Neon coordinates, instead we just print out a list with the x,y and z coordinates." 572 | ] 573 | }, 574 | { 575 | "cell_type": "code", 576 | "execution_count": null, 577 | "metadata": {}, 578 | "outputs": [], 579 | "source": [ 580 | "first_Ne= True\n", 581 | "\n", 582 | "with open('Ne2.out','r') as f:\n", 583 | " for line in f:\n", 584 | " #we are on the line with the first Ne\n", 585 | " if 'NE' in line.split() and first_Ne:\n", 586 | "\n", 587 | " #set the flag to false because the next line with Ne on will be the second Ne\n", 588 | " first_Ne=False\n", 589 | " \n", 590 | " #we are on the line with second Ne\n", 591 | " elif 'NE' in line.split() and not first_Ne:\n", 592 | "\n", 593 | " #set the flag to true because the next line with Ne on will be the first Ne\n", 594 | " first_Ne=True" 595 | ] 596 | }, 597 | { 598 | "cell_type": "markdown", 599 | "metadata": {}, 600 | "source": [ 601 | "OK, the task now is to generate a list of distances between the Neon atoms in the dimers. Above you have found a method for distinguishing between the first and second atoms in each dimer and have used it to print out the coordinates of each atom. Below, the function *vect_dist()* calculates the distance between two atoms given the coordinates of each in Cartesian coordinates. (This function could have been defined using arrays, but here we take a more explicit approach)" 602 | ] 603 | }, 604 | { 605 | "cell_type": "code", 606 | "execution_count": null, 607 | "metadata": {}, 608 | "outputs": [], 609 | "source": [ 610 | "def vect_dist(x1, y1, z1, x2, y2, z2):\n", 611 | " distance = ( (x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2 )**0.5\n", 612 | " return(distance)" 613 | ] 614 | }, 615 | { 616 | "cell_type": "markdown", 617 | "metadata": {}, 618 | "source": [ 619 | "Adapt the code we wrote before such that we call the *vect_dist()* every time we find the second neon atom, and in this way build a list *dist* with all distances between neon atoms." 620 | ] 621 | }, 622 | { 623 | "cell_type": "code", 624 | "execution_count": null, 625 | "metadata": {}, 626 | "outputs": [], 627 | "source": [ 628 | "dist=[]\n" 629 | ] 630 | }, 631 | { 632 | "cell_type": "markdown", 633 | "metadata": {}, 634 | "source": [ 635 | "Here is a good point to check your answer. The function *check_float()* checks if two numbers are equal with a tolerance of 1×10-8." 636 | ] 637 | }, 638 | { 639 | "cell_type": "code", 640 | "execution_count": null, 641 | "metadata": {}, 642 | "outputs": [], 643 | "source": [ 644 | "def check_float(float_number, exact_answer):\n", 645 | " tol = 1e-8\n", 646 | " return abs(float_number - exact_answer) < tol" 647 | ] 648 | }, 649 | { 650 | "cell_type": "markdown", 651 | "metadata": {}, 652 | "source": [ 653 | "Run the cell bellow and check the output is the same:" 654 | ] 655 | }, 656 | { 657 | "cell_type": "code", 658 | "execution_count": null, 659 | "metadata": {}, 660 | "outputs": [], 661 | "source": [ 662 | "correct_answer = [2.3, 2.35, 2.40, 2.45, 2.5, 2.55, 2.60, 2.65, 2.70, 2.75, 2.80, 2.95, 3.00, 3.05 , 3.10, 3.15, 3.20, 3.25, 3.3, 3.35]\n", 663 | "\n", 664 | "for i,d in enumerate(dist):\n", 665 | " if check_float(d, correct_answer[i]):\n", 666 | " print('Success')\n", 667 | " else:\n", 668 | " print(\"The lists don't match, check your above solutions.\")" 669 | ] 670 | }, 671 | { 672 | "cell_type": "markdown", 673 | "metadata": {}, 674 | "source": [ 675 | "We have now successfully extracted the distances between neon atoms from the log file. The next step is to also extract the energies (we already addressed this problem when extracting the energy of a single neon).\n", 676 | "\n", 677 | "Adapt the code you wrote before such that you build both the *dist* and *energies* lists with a single loop through the file." 678 | ] 679 | }, 680 | { 681 | "cell_type": "code", 682 | "execution_count": null, 683 | "metadata": {}, 684 | "outputs": [], 685 | "source": [ 686 | "dist=[]\n", 687 | "energies=[]\n", 688 | "\n" 689 | ] 690 | }, 691 | { 692 | "cell_type": "markdown", 693 | "metadata": {}, 694 | "source": [ 695 | "Again here is a good point to check you answer. Run the cell below and check the output is the same:" 696 | ] 697 | }, 698 | { 699 | "cell_type": "code", 700 | "execution_count": null, 701 | "metadata": {}, 702 | "outputs": [], 703 | "source": [ 704 | "correct_answer = [-257.3508759806243802,-257.3515014203481996,-257.3519632198754152,-257.3522960563400943,-257.3525285912639902,-257.3526844311371633,-257.3527828598416818,-257.3528394280590987,-257.3528664678370887,-257.3528735535761029,-257.3528679338846814,-257.3528206560993112,-257.3528035490451771,-257.3527879372218194,-257.3527742712665258,-257.3527626771479504,-257.3527530774693446,-257.3527452802550215,-257.3527390409376494,-257.3527341032995537]\n", 705 | "\n", 706 | "for i,d in enumerate(energies):\n", 707 | " if check_float(d, correct_answer[i]):\n", 708 | " print('Success')\n", 709 | " else:\n", 710 | " print(\"The lists don't match, check your above solutions.\")\n", 711 | "\n", 712 | " \n", 713 | "correct_answer = [2.3, 2.35, 2.40, 2.45, 2.5, 2.55, 2.60, 2.65, 2.70, 2.75, 2.80, 2.95, 3.00, 3.05 , 3.10, 3.15, 3.20, 3.25, 3.3, 3.35]\n", 714 | "\n", 715 | "for i,d in enumerate(dist):\n", 716 | " if check_float(d, correct_answer[i]):\n", 717 | " print('Success')\n", 718 | " else:\n", 719 | " print(\"The lists don't match, check your above solutions.\")" 720 | ] 721 | }, 722 | { 723 | "cell_type": "markdown", 724 | "metadata": {}, 725 | "source": [ 726 | "Let us now make our solution reusable by defining a function *get_dimer_distance_energy()*, that should receive two strings as arguments: a file name, chemical symbol search pattern. The function should return a list where the first element is a list of distances and the second element a list of energies." 727 | ] 728 | }, 729 | { 730 | "cell_type": "code", 731 | "execution_count": null, 732 | "metadata": {}, 733 | "outputs": [], 734 | "source": [] 735 | }, 736 | { 737 | "cell_type": "markdown", 738 | "metadata": {}, 739 | "source": [ 740 | "## Ne2 dissociation: analysing the result" 741 | ] 742 | }, 743 | { 744 | "cell_type": "markdown", 745 | "metadata": {}, 746 | "source": [ 747 | "Now that we created a mechanism for extracting the data from the text file, let us use it to do some interesting things. First we will plot the data, using the standard [matplotlib](https://matplotlib.org/users/pyplot_tutorial.html) python plotting module, to find the characteristic diatomic energy pattern." 748 | ] 749 | }, 750 | { 751 | "cell_type": "code", 752 | "execution_count": null, 753 | "metadata": {}, 754 | "outputs": [], 755 | "source": [ 756 | "from matplotlib.pyplot import *\n", 757 | "\n", 758 | "ne2_data=get_dimer_distance_energy('Ne2.out','NE')\n", 759 | "dist=ne2_data[0]\n", 760 | "energy=ne2_data[1]\n", 761 | "\n", 762 | "plot(dist, energy, marker='+')\n", 763 | "xlabel('Ne - Ne Bond Distance ($\\\\AA$)')\n", 764 | "ylabel('Energy (Hartree)')\n", 765 | "show()" 766 | ] 767 | }, 768 | { 769 | "cell_type": "markdown", 770 | "metadata": {}, 771 | "source": [ 772 | "In chemistry we are more interested in the interaction energy of the two atoms, i.e. the relative energy with respect to 2 separate atoms in space. Subtract twice the energy of a free Ne atom (which we can obtain via the get_atom_energy() function) and plot how interaction energy varies with distance. (It is convenient here to work with arrays instead of lists)." 773 | ] 774 | }, 775 | { 776 | "cell_type": "code", 777 | "execution_count": null, 778 | "metadata": {}, 779 | "outputs": [], 780 | "source": [] 781 | }, 782 | { 783 | "cell_type": "markdown", 784 | "metadata": {}, 785 | "source": [ 786 | "This shape of dissociation curve can be modeled mathematically by the Morse potential:\n", 787 | "\n", 788 | "$$V(r) = d ((1 - e^{-a(r - r_e)})^2 - 1),$$\n", 789 | "\n", 790 | "where *re* is the equilibrium distance, *d* is the dissociation energy, and the *a* is related to the frequency of the potential well.\n", 791 | "\n", 792 | "Write a function to compute the Morse potential with *r*, *re*, *d* and *a* as arguments to the function, making sure the arguments are defined in this order." 793 | ] 794 | }, 795 | { 796 | "cell_type": "code", 797 | "execution_count": null, 798 | "metadata": {}, 799 | "outputs": [], 800 | "source": [] 801 | }, 802 | { 803 | "cell_type": "markdown", 804 | "metadata": {}, 805 | "source": [ 806 | "Run the cell below to check if your function is defined correctly." 807 | ] 808 | }, 809 | { 810 | "cell_type": "code", 811 | "execution_count": null, 812 | "metadata": {}, 813 | "outputs": [], 814 | "source": [ 815 | "if check_float(morse(2.5, 1.0, 3.2, 5.2) , -0.002621766640661 ):\n", 816 | " print('Well Done your Morse function works.')\n", 817 | "else:\n", 818 | " print('Your Morse function is wrong!')" 819 | ] 820 | }, 821 | { 822 | "cell_type": "markdown", 823 | "metadata": {}, 824 | "source": [ 825 | "We are interested on the equilibrium distance and dissociation energy of the neon dimer. In order to obtain these we can use the function *curve_fit()* from the scipy.optimize module. (You may want to revise how to do this from you 1st year course notebooks: if you don't have them in an accessible place you can get them from here).\n", 826 | "\n", 827 | "In the process of fitting you will want to pay attention to the initial parameter guess. How can you extract good guesses for *re* and *d* from the data?" 828 | ] 829 | }, 830 | { 831 | "cell_type": "code", 832 | "execution_count": null, 833 | "metadata": {}, 834 | "outputs": [], 835 | "source": [ 836 | "from scipy.optimize import curve_fit\n", 837 | "\n" 838 | ] 839 | }, 840 | { 841 | "cell_type": "markdown", 842 | "metadata": {}, 843 | "source": [ 844 | "To check that the fit makes sense. Plot the fitted curve along with original data (to get a smooth curve we should use the function linspace() to plot the fitted curve)." 845 | ] 846 | }, 847 | { 848 | "cell_type": "code", 849 | "execution_count": null, 850 | "metadata": {}, 851 | "outputs": [], 852 | "source": [] 853 | }, 854 | { 855 | "cell_type": "markdown", 856 | "metadata": {}, 857 | "source": [ 858 | "## Extra: Trends along the group" 859 | ] 860 | }, 861 | { 862 | "cell_type": "markdown", 863 | "metadata": {}, 864 | "source": [ 865 | "You will find on the same directory as the notebook, besides the log file for the Ne dimer, also log files for He, Ar and Kr. It is interesting to observe the trend of equilibrium distance and dissociation energy along the group. In order to do this it is useful that we automatise the analysis done above.\n", 866 | "\n", 867 | "We shall define two functions, *eqdist_dissenergy()* and *disscurve()* both receiving three string arguments: the file name with the energy of a single atom, the file name for a file containing data for the dimer at different distances, and a chemical element search string. The *eqdist_dissenergy()* should call *get_dimer_distance_energy()* and *get_atom_energy()*, fit the data to a Morse potential (it should provide adequate guesses for the fit), and return the values of the equilibrium distance and dissociation energy." 868 | ] 869 | }, 870 | { 871 | "cell_type": "code", 872 | "execution_count": null, 873 | "metadata": {}, 874 | "outputs": [], 875 | "source": [] 876 | }, 877 | { 878 | "cell_type": "markdown", 879 | "metadata": {}, 880 | "source": [ 881 | "Because fitting blindly is a dangerous thing to do, we should define *disscurve()* which should do most of the same work as *eqdist_dissenergy()* but show us instead the plot of the fitted dissociation curve and original data." 882 | ] 883 | }, 884 | { 885 | "cell_type": "code", 886 | "execution_count": null, 887 | "metadata": {}, 888 | "outputs": [], 889 | "source": [] 890 | }, 891 | { 892 | "cell_type": "markdown", 893 | "metadata": {}, 894 | "source": [ 895 | "Use the functions defined above to plot the variation of dimer equilibrium distance and dissociation energy along the noble gas group." 896 | ] 897 | }, 898 | { 899 | "cell_type": "code", 900 | "execution_count": null, 901 | "metadata": {}, 902 | "outputs": [], 903 | "source": [] 904 | }, 905 | { 906 | "cell_type": "code", 907 | "execution_count": null, 908 | "metadata": {}, 909 | "outputs": [], 910 | "source": [] 911 | }, 912 | { 913 | "cell_type": "markdown", 914 | "metadata": {}, 915 | "source": [ 916 | "## Summary" 917 | ] 918 | }, 919 | { 920 | "cell_type": "markdown", 921 | "metadata": {}, 922 | "source": [ 923 | "Files are an important way of permanent storage of data. Handling files is important not only for processing data generated by instruments or other programs, but also to store results generated by your own programs.\n", 924 | "\n", 925 | "In this workshop we have seen how to access data in files files. The function *open()* creates a stream to access the file content, which can be looped line by line. Each line is retrieved as a string, in which context the string method *.split()* becomes useful for further processing.\n", 926 | "\n", 927 | "We used file processing techniques to extract the data of the dissociation curve of a dimer from a complex file. We further analysed this data to obtain the dissociation energy and equilibrium distance of the dimer." 928 | ] 929 | }, 930 | { 931 | "cell_type": "markdown", 932 | "metadata": {}, 933 | "source": [ 934 | "# If you want to go further\n", 935 | "\n", 936 | "In these four workshops we covered most of the basic concepts in computer programming which are common to many programming languages. You can go a long way with just what is covered here, but if you want to go further there is a lot to look towards to. The following is a brief list of online resources.\n", 937 | "\n", 938 | "* [The Official Python Documentation](http://docs.python.org), including\n", 939 | " * [Python Tutorial](http://docs.python.org/3/tutorial),\n", 940 | " * [Python Language Reference](http://docs.python.org/3/reference) with documentation on all commands and features of the Python language.\n", 941 | "* [The Code Academy Python course](http://www.codecademy.com/en/tracks/python)\n", 942 | "* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)\n", 943 | "* [Dive Into Python](http://www.diveintopython.net/)" 944 | ] 945 | } 946 | ], 947 | "metadata": { 948 | "kernelspec": { 949 | "display_name": "Python 3 (ipykernel)", 950 | "language": "python", 951 | "name": "python3" 952 | }, 953 | "language_info": { 954 | "codemirror_mode": { 955 | "name": "ipython", 956 | "version": 3 957 | }, 958 | "file_extension": ".py", 959 | "mimetype": "text/x-python", 960 | "name": "python", 961 | "nbconvert_exporter": "python", 962 | "pygments_lexer": "ipython3", 963 | "version": "3.11.2" 964 | } 965 | }, 966 | "nbformat": 4, 967 | "nbformat_minor": 1 968 | } 969 | -------------------------------------------------------------------------------- /prog_workshop4/test.out: -------------------------------------------------------------------------------- 1 | All the leaves are brown, 2 | and the sky is grey, 3 | I went for a walk on a winter's day. 4 | --------------------------------------------------------------------------------