├── .gitignore ├── LICENSE ├── README.md ├── installation_instructions.docx ├── python_cheatsheet.ipynb ├── week01 ├── practice │ ├── exercise_1.ipynb │ └── exercise_2.ipynb └── theory │ ├── 1_introduction.ipynb │ ├── 2_hello_world.ipynb │ ├── 3_statements.ipynb │ ├── 4_control_flow.ipynb │ └── images │ ├── Flow_chart.png │ ├── Python-if-elif-else-statement.png │ └── spoiler.jpg ├── week02 ├── practice │ ├── exercise_1.ipynb │ └── packed_column_2.csv └── theory │ ├── 1_dictionaries_and_sets.ipynb │ ├── 2_dataframes.ipynb │ ├── 3_numpy_arrays.ipynb │ ├── 4_data_visualizations.ipynb │ ├── packed_column.csv │ └── sets.png ├── week03 ├── practice │ ├── additional_exercises_previous_weeks.ipynb │ └── week03_exercise_1.ipynb └── theory │ ├── 1_operations.ipynb │ └── 2_linear_regression.ipynb ├── week04 ├── practice │ ├── assignment_1.ipynb │ ├── week04_exercise_1.ipynb │ └── week04_exercise_1_solution.ipynb └── theory │ └── 1_reactors_in_python.ipynb ├── week05 ├── practice │ └── week05_exercise_1_solution.ipynb └── theory │ └── week05_exercise_1.ipynb ├── week06 ├── practice │ └── 1_stoichiometry_solution.ipynb └── theory │ ├── 1_stoichiometry.ipynb │ └── 2_stoichiometry_pt2.ipynb └── week07 ├── practice ├── assignment_2.ipynb └── assignment_2_system.png └── theory └── 28342 E2022 Chemical Reaction Engineeering Assignment 2 draft.docx /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints 2 | */.ipynb_checkpoints/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Fiammetta Caccavale 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chemical-Reaction-Engineering-in-Python :ear_of_rice: 2 | 3 | ## TL;DR 4 | This is a practical course designed for chemical engineers that want to learn how to program in Python. The course is very practical and will cover various topics, such as basic Python syntax, solving ODEs, stoichiometry, data visualization and basic data analysis. 5 | 6 | ## Introduction 7 | Recently, more and more chemical engineering students have expressed the desire to acquire basic programming skills early on in their career, with Python being the most requested language by far. For this reason, we decided to support the regular material taught in the Chemical Reaction Engineering (28342) with an introductory Python course. Therefore, we aim to provide material and practical tutorials to learn Python, so that you have the opportunity to use Python to solve the exercises and assignments. 8 | 9 | This course is designed to be very practical, since the best way to learn how to program is by programming. You will start writing and executing code from day 1, through carefully designed exercises. The target of this course is students and professionals in Chemical Engineering that want to learn how to program in Python. 10 | 11 | The course may be challenging and overwhelming at the beginning, but don't worry if you don't manage to complete everything. Each week, there will be a mandatory notebook of exercises 01-Exercises and an additional, optional, notebook containing more challenging exercises, for learners that want to test themselves and like to crack the code (pun intended). 12 | 13 | ## :snake: Why Python? 14 | Python is one of the most popular languages in use today, thanks to its easy syntax, readability, libraries available and broad documentation. It is open-source, unlike other very popular programs such as MATLAB, which require a license. It has a big community, meaning that other people have probably already asked any possible question you might be having right now. Some forums where to ask and look for questions: StackOverflow (for practical questions about code), StackExchange (for more theoretical questions). It is the to-go language for data analysis and data science, both in academia and industry. 15 | 16 | ## :wrench: Installation 17 | Here you can find instructions [how to install Python](https://github.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/blob/main/installation_instructions.docx). 18 | 19 | Or watch the [video tutorial](https://drive.google.com/file/d/1JD-xaiPfCqbrU8kEEFfMyCaTrEYbSyWb/view?usp=sharing). 20 | 21 | For more video tutorial, check this [folder](https://drive.google.com/drive/folders/1eIRsWmd1AKE1qkJ5ubGg0JA-cXQcsjtq?usp=sharing). 22 | 23 | ## Helpful tips and tricks before starting 24 | "The most effective debugging tool is still careful thought, coupled with judiciously placed print statements." 25 | 26 | — Brian Kernighan, "Unix for Beginners" (1979) 27 | 28 | 1. **The best way to learn how to program is by programming**. It's normal that you cannot solve everything and you are overwhelmed at the beginning. Don't give up and just practice. 29 | 2. **Write, test and improve code**. Do not expect to write a full program in one sitting: most programmers write, test and rewrite code many times before their program works, so do not get discouraged! 30 | 3. **Brainstorm first**. Instead of reading a problem and looking for a solution on the Internet, try to think about it yourself. Re-read the problem, brainstorm possible solutions and try to write some code. Make sure that you actually understand what it is asked. Only after you have spent sufficient time on this, look for hints elsewhere. 31 | 4. **Learn to comment your code early on**. Before coding, visualize what you plan to do and describe is in plan, non-technical text on paper. Try to be as detailed as possible and include all the steps, even the smallest ones. This will be helpful at the beginning of your coding experience to guide you through the process and ensure you do not forget important steps. Later on, when you are more comfortable coding, it will be helpful for reference for you or other teammates. Remember that just because something seems easy for you, it does not mean your colleague can read your code and understand it right away. This is a very important principle for code deployment. 32 | 5. **Understand what the program is doing**. It is important that you understand what your program is doing. Often, it is useful to simply print what you are doing, this is an easy way to visualize, and therefore better understand, the output. This approach is called tracing or printf() debugging, after the print function name in the C language). 33 | 34 | ## Other courses 35 | We are created other Python courses tailored for Chemical Engineers, such as [AI for Chemical Engineers](https://github.com/FiammettaC/AI-for-Chemical-Engineers). 36 | 37 | ## Contacts 38 | If you have any questions regarding the exercises or any feedback on the course, feel free to contact Fiammetta Caccavale (fiacac@kt.dtu.dk). 39 | 40 | ## Feedback 41 | Please fill in our [online survey](https://forms.gle/xJ1uJc94G9c7YUtJ7) if you have any feedback. We really appreciate your suggestions and we will try to use them to improve the course. 42 | 43 | ## 🤝 Contributing 44 | Contributions, issues, and feature requests are welcome! 45 | 46 | ## Show your support 47 | Give a ⭐️ if you like this project! 48 | 49 | ## 📝 License 50 | This project is [MIT](https://opensource.org/licenses/MIT) licensed. 51 | 52 | ## Cite this work 53 | If you would like to cite this work, please reference our paper: **SPyCE: A structured and tailored series of Python courses for (bio)chemical engineers**. 54 | ```bibtex 55 | @article{CACCAVALE202390, 56 | title = {SPyCE: A structured and tailored series of Python courses for (bio)chemical engineers}, 57 | journal = {Education for Chemical Engineers}, 58 | volume = {45}, 59 | pages = {90-103}, 60 | year = {2023}, 61 | issn = {1749-7728}, 62 | doi = {https://doi.org/10.1016/j.ece.2023.08.003}, 63 | url = {https://www.sciencedirect.com/science/article/pii/S1749772823000404}, 64 | author = {Fiammetta Caccavale and Carina L. Gargalo and Krist V. Gernaey and Ulrich Krühne}, 65 | keywords = {Python in engineering education, Digital education, Programming in engineering curriculum, Artificial Intelligence}, 66 | abstract = {In times of educational disruption, significant advances in adopting digitalization strategies have been accelerated. In this transformation climate, engineers should be adequately educated to face the challenges and acquire the new skills imposed by Industry 4.0. Among these, one of the most highly requested tools is Python. To tackle these aspects, this work establishes a pedagogical framework to teach Python to chemical engineers. This is achieved through a hands-on series of Python courses (sPyCE), covering topics as chemical reaction engineering and machine learning. Part of the series has been embedded in the curriculum of a Bachelor’s-level course at the Technical University of Denmark (DTU). Overall, students found the course to be useful; using Python, they solved systems of differential equations, mass and energy balances, set stoichiometric tables, regressions, simulations and more. Motivated by the large applicability and relevance of the covered topics, sPyCE is made publicly available on GitHub.} 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /installation_instructions.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/f37542b41215bc162a766559f25f32e2a245bbea/installation_instructions.docx -------------------------------------------------------------------------------- /week01/practice/exercise_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "62e6b376-ef5c-4c10-a52c-6c3b0040e2c2", 6 | "metadata": {}, 7 | "source": [ 8 | "# Exercises about statements, assignments, lists and generators, control flow and packaging" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "268c0e1d-74de-4783-8cb3-220f8053a500", 14 | "metadata": {}, 15 | "source": [ 16 | "## 1. Statements" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "4aa08f81-c9a1-4c24-b396-66cfd33dd1c2", 22 | "metadata": {}, 23 | "source": [ 24 | "**Exercise**: Print your favorite kind of enzyme.\n", 25 | "*Hint*: enzyme kind should be printed as a string.\n", 26 | "\n", 27 | "Level: Easy." 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "id": "ffc8b0d1-d695-4699-937c-7a8072300d21", 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "# Your code here" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "id": "24ab2e03-26a6-43b3-b12c-245a0061771c", 43 | "metadata": {}, 44 | "source": [ 45 | "**Exercise**: Sum 4 and 5 and divide the result by 2. *Hint*: don't forget the parenthesis.\n", 46 | "\n", 47 | "Level: Easy." 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "id": "5de43d1c-ae54-45d7-be44-be906b3fe559", 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "# Your code here" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "id": "bdf7e44c-4626-4bd4-8b5e-bb89f85805af", 63 | "metadata": {}, 64 | "source": [ 65 | "**Exercise**: Print your age as an integer.\n", 66 | "\n", 67 | "Level: Easy." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "id": "ce94c559-96ac-4970-888c-d65985004fb3", 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "# Your code here" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "id": "69314384-2ea7-4038-8e25-91e01fc61e69", 83 | "metadata": {}, 84 | "source": [ 85 | "**Exercise**: Print your age as a string.\n", 86 | "\n", 87 | "Level: Medium." 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "id": "2dd3554c-29e6-470f-89c4-5d28eab608b0", 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "# Your code here" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "id": "b19afb00-e0cd-4550-960b-14daa6554574", 103 | "metadata": {}, 104 | "source": [ 105 | "**Exercise**: Calculate the square of 16, then divide the result by the square of 3. Only return 2 decimal points.\n", 106 | "\n", 107 | "Level: Medium." 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "id": "8442e157-624a-4acd-be3e-96c5ba1e962d", 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "# Your code here" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "id": "7fae92b1-2ff4-4a2e-b873-15ed69c85493", 123 | "metadata": {}, 124 | "source": [ 125 | "## 2. Assignments" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "id": "3e7dcab1-19c2-4ee3-ab7b-9f806513d967", 131 | "metadata": {}, 132 | "source": [ 133 | "**Exercise**: Bind your favorite enzyme to a variable. Choose a descriptive name for your variable.\n", 134 | "\n", 135 | "Level: Easy." 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "id": "f6dd4862-2fe2-47f9-83d0-5cdf3d2e9d30", 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "# Your code here" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "id": "5d7a2639-8a4d-4189-a5d5-2d32a208d658", 151 | "metadata": {}, 152 | "source": [ 153 | "**Exercise**: Create a variable called `total`, which is the result of the following calculation:\n", 154 | "- your_birth_year * your_birth_day / your_birth_month - your_current_age\n", 155 | "\n", 156 | "Level: Easy." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "id": "2a24d3b0-95c8-455e-aee6-c0259d33d1e7", 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "# Your code here" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "id": "a63bffed-d241-4840-af18-873ff24cee60", 172 | "metadata": {}, 173 | "source": [ 174 | "**Exercise**: Given the following variables, create two lists containing all possible combinations (sum) of the *allowed* pairs. *Hint*: Remember that you cannot add a `string` and an `integer`. Don't do it manually, try to use a loop.\n", 175 | "\n", 176 | "Level: Hard." 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": null, 182 | "id": "b30b475a-7d44-4d63-82c4-c4ec2cdc9a0e", 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [ 186 | "string_a = 'a'\n", 187 | "string_b = 'b'\n", 188 | "integer_1 = 1\n", 189 | "integer_2 = 2\n", 190 | "string_4 = '4'\n", 191 | "float_1 = 1.0\n", 192 | "float_2_5 = 2.5" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "id": "41bd40fc-f717-4d05-8edb-b08f9caf5645", 198 | "metadata": {}, 199 | "source": [ 200 | "Expected results, order does not matter:\n", 201 | "- list_a = ['ab', 'a4', 'ba', 'b4', '4a', '4b']\n", 202 | "- list_b = [3, 2.0, 3.5, 3, 3.0, 4.5, 3.0, 2.0, 3.5, 3.5, 4.5, 3.5]" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "id": "f8e25341-702a-42fc-ab9e-ad7b8fec961a", 209 | "metadata": {}, 210 | "outputs": [], 211 | "source": [ 212 | "# Your code here" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "id": "a59c40f9-ca09-4e24-b952-177294ca8940", 218 | "metadata": {}, 219 | "source": [ 220 | "*Possible solution in Notebook Exercise 2.ipynb" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "id": "4d0ff0f6-c648-4d94-89e0-1390ec026e10", 226 | "metadata": {}, 227 | "source": [ 228 | "## 3. Lists and generators" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": null, 234 | "id": "64d5c9c9-a399-48ae-baf2-bcf3a689af16", 235 | "metadata": {}, 236 | "outputs": [], 237 | "source": [ 238 | "multiple_5 = [5, 10, 15, 20]" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "id": "3d4afe4e-6292-47ad-a347-c972f293ad74", 244 | "metadata": {}, 245 | "source": [ 246 | "**Exercise**: Given `multiple_5`, create a list **MANUALLY** containing each element in `multiple_5` summed by 2.\n", 247 | "\n", 248 | "Level: Easy." 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": null, 254 | "id": "02247da5-d5b9-409b-b64c-6b8466f59b5a", 255 | "metadata": {}, 256 | "outputs": [], 257 | "source": [ 258 | "# Your code here" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "id": "4c69527c-5a16-471a-8d14-a522b907e59c", 264 | "metadata": {}, 265 | "source": [ 266 | "**Exercise**: Given `multiple_5`, create a list **USING A FOR LOOP** containing each element in `multiple_5` summed by 2.\n", 267 | "\n", 268 | "Level: Easy." 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": null, 274 | "id": "f1ec653a-d144-4d07-a702-a5e18bd17a0a", 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [ 278 | "# Your code here" 279 | ] 280 | }, 281 | { 282 | "cell_type": "markdown", 283 | "id": "5f59e673-4a31-4fef-9800-871971ae06b6", 284 | "metadata": {}, 285 | "source": [ 286 | "**Exercise**: Given `multiple_5`, create a list **USING A LIST COMPREHENSION** containing each element in `multiple_5` summed by 2.\n", 287 | "\n", 288 | "Level: Medium." 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": null, 294 | "id": "936fae1a-726a-49df-a911-5099b59ae8d3", 295 | "metadata": {}, 296 | "outputs": [], 297 | "source": [ 298 | "# Your code here" 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "id": "419d2d16-4e87-41b6-b8ba-4ba8dcbfca60", 304 | "metadata": {}, 305 | "source": [ 306 | "**Exercise**: Given `multiple_5`, create a generator containing each element in `multiple_5` summed by 2.\n", 307 | "\n", 308 | "Level: Easy." 309 | ] 310 | }, 311 | { 312 | "cell_type": "code", 313 | "execution_count": null, 314 | "id": "b2eaaa1b-af45-4324-acf9-d7aa59a6fc24", 315 | "metadata": {}, 316 | "outputs": [], 317 | "source": [ 318 | "# Your code here" 319 | ] 320 | }, 321 | { 322 | "cell_type": "markdown", 323 | "id": "b144e00a-281a-4535-87d7-2123bc6e9c75", 324 | "metadata": {}, 325 | "source": [ 326 | "## 4. Compound statements" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "id": "6d5a2df0-0c65-424c-865d-b8fc3f15bdee", 332 | "metadata": {}, 333 | "source": [ 334 | "**Exercise**: Translate the following flow chart to check why the unit for the *hydrodynamics condition in packed tower* experiment is not working.\n", 335 | "\n", 336 | "Level: Easy.\n", 337 | "\n", 338 | "![alt text](../theory/images/Flow_chart.png)" 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": null, 344 | "id": "3db9f5b9-fb14-4eba-8414-10d15ee7045f", 345 | "metadata": {}, 346 | "outputs": [], 347 | "source": [ 348 | "# Your code here" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "id": "56ba5b55-9393-4dd4-aaae-3cd15ee70243", 354 | "metadata": {}, 355 | "source": [ 356 | "**Exercise**: Calculate the 10th element *F10* in the Fibonacci sequence, where F0 = 0, F1 = 1 and Fn = (Fn-1) + (Fn -2) for n > 1.\n", 357 | "\n", 358 | "Level: Medium." 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": null, 364 | "id": "b1b7f8a3-e934-4874-bc11-a5e8534eb4bd", 365 | "metadata": {}, 366 | "outputs": [], 367 | "source": [ 368 | "# Your code here" 369 | ] 370 | }, 371 | { 372 | "cell_type": "markdown", 373 | "id": "d0076c11-576c-42bb-a702-f04c192fad99", 374 | "metadata": {}, 375 | "source": [ 376 | "## 5. Packaging" 377 | ] 378 | }, 379 | { 380 | "cell_type": "markdown", 381 | "id": "9f3cb9d8-c35b-4572-afcd-ab2f6380912d", 382 | "metadata": {}, 383 | "source": [ 384 | "**Exercise**: Write four functions for:\n", 385 | "- **Summing** two numbers\n", 386 | "- **Subtracting** two numbers\n", 387 | "- **Multiplying** two numbers\n", 388 | "- **Dividing** two numbers\n", 389 | "\n", 390 | "Level: Easy" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": null, 396 | "id": "a35b80fb-5b84-45e1-b88c-a134ffa3b935", 397 | "metadata": {}, 398 | "outputs": [], 399 | "source": [ 400 | "def plus(a, b):\n", 401 | " # Your code here\n", 402 | " return\n", 403 | "\n", 404 | "def minus(a, b):\n", 405 | " # Your code here\n", 406 | " return\n", 407 | "\n", 408 | "def multiply(a, b):\n", 409 | " # Your code here\n", 410 | " return\n", 411 | "\n", 412 | "def divide(a, b):\n", 413 | " # Your code here\n", 414 | " return" 415 | ] 416 | }, 417 | { 418 | "cell_type": "markdown", 419 | "id": "95f32c20-c019-483f-bd79-b143d7c51438", 420 | "metadata": {}, 421 | "source": [ 422 | "**Example**: We compute 1 + 3 - 2" 423 | ] 424 | }, 425 | { 426 | "cell_type": "code", 427 | "execution_count": null, 428 | "id": "32d8b41d-8285-4b86-9668-9cd0443b00b8", 429 | "metadata": {}, 430 | "outputs": [], 431 | "source": [ 432 | "minus(plus(1, 3), 2)" 433 | ] 434 | }, 435 | { 436 | "cell_type": "markdown", 437 | "id": "eb2739ee-f8db-49f8-8d08-9fcfc77c48ef", 438 | "metadata": {}, 439 | "source": [ 440 | "**Exercise**: Use the functions implemented above to compute the following:\n", 441 | "- (((2 + 7) * 5) / 3) - 4\n", 442 | "- 6 / 3 * 6 - 1\n", 443 | "- 3 + 4 + 7 - 2 * 7 / 2\n", 444 | "\n", 445 | "Level: Medium" 446 | ] 447 | }, 448 | { 449 | "cell_type": "code", 450 | "execution_count": null, 451 | "id": "7fda45f1-85dd-4c27-8ffd-a22658a91d8b", 452 | "metadata": {}, 453 | "outputs": [], 454 | "source": [ 455 | "# Your code here" 456 | ] 457 | } 458 | ], 459 | "metadata": { 460 | "kernelspec": { 461 | "display_name": "Python 3 (ipykernel)", 462 | "language": "python", 463 | "name": "python3" 464 | }, 465 | "language_info": { 466 | "codemirror_mode": { 467 | "name": "ipython", 468 | "version": 3 469 | }, 470 | "file_extension": ".py", 471 | "mimetype": "text/x-python", 472 | "name": "python", 473 | "nbconvert_exporter": "python", 474 | "pygments_lexer": "ipython3", 475 | "version": "3.9.7" 476 | } 477 | }, 478 | "nbformat": 4, 479 | "nbformat_minor": 5 480 | } 481 | -------------------------------------------------------------------------------- /week01/practice/exercise_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "0fa8b164-98ee-4aed-9b66-00b98efc308f", 6 | "metadata": {}, 7 | "source": [ 8 | "# Hard exercises and solutions" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "5c66aeb4-b91f-46c8-9f5a-f155cc3da0ed", 14 | "metadata": {}, 15 | "source": [ 16 | "### Exercise: Remove all outliers\n", 17 | "\n", 18 | "Remove **all** possible outliers from the given array, based on the cutoff (given cutoff value multiplied by standard deviation).\n", 19 | "Here, we want to remove all values that are more than three standard deviations from the mean.\n", 20 | "So, \n", 21 | "``` python\n", 22 | "abs(data_point - data_mean) > cutoff\n", 23 | "```\n", 24 | "\n", 25 | "*Hint*: Once you remove the first outlier(s), make sure that the resulting array does not have other outliers (e.g., use a loop).\n", 26 | "\n", 27 | "Level: Medium." 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "id": "9b20d763-c522-4208-939e-f84a7670a1b3", 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "import numpy as np\n", 38 | "data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000])\n", 39 | "cut_off = 3 * np.std(data)\n", 40 | "\n", 41 | "# Your code here" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "id": "e8d94308-bbe9-497b-9a22-623225a5be03", 47 | "metadata": {}, 48 | "source": [ 49 | "### Exercise: Binary to English translation\n", 50 | "\n", 51 | "You are provided with an English-to-binary code translation table and messages in binary code. \n", 52 | "You have to decode the given messages to find out what Chemistry Cat says.\n", 53 | "\n", 54 | "Note that \n", 55 | "- the letters in the code are space delimited \n", 56 | "- the words are delimited by '/'\n", 57 | "\n", 58 | "Level: Hard." 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "id": "ecb87dc1-18ee-41b9-933c-5bf4088316ef", 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# we provide the translation table binary to english\n", 69 | "binary_to_english = {\n", 70 | " \"a\" : \"01100001\", \"b\" : \"01100010\", \"c\" : \"01100011\", \"d\" : \"01100100\", \"e\" : \"01100101\", \"f\" : \"01100110\", \"g\" : \"01100111\", \"h\" : \"01101000\",\n", 71 | " \"i\" : \"01101001\", \"j\" : \"01101010\", \"k\" : \"01101011\", \"l\" : \"01101100\", \"m\" : \"01101101\", \"n\" : \"01101110\", \"o\" : \"01101111\", \"p\" : \"01110000\",\n", 72 | " \"q\" : \"01110001\", \"r\" : \"01110010\", \"s\" : \"01110011\", \"t\" : \"01110100\", \"u\" : \"01110101\", \"v\" : \"01110110\", \"w\" : \"01110111\", \"x\" : \"01111000\",\n", 73 | " \"y\" : \"01111001\", \"z\" : \"01111010\", \"A\" : \"01000001\", \"B\" : \"01000010\", \"C\" : \"01000011\", \"D\" : \"01000100\", \"E\" : \"01000101\", \"F\" : \"01000110\",\n", 74 | " \"G\" : \"01000111\", \"H\" : \"01001000\", \"I\" : \"01001001\", \"J\" : \"01001010\", \"K\" : \"01001011\", \"L\" : \"01001100\", \"M\" : \"01001101\", \"N\" : \"01001110\",\n", 75 | " \"O\" : \"01001111\", \"P\" : \"01010000\", \"Q\" : \"01010001\", \"R\" : \"01010010\", \"S\" : \"01010011\", \"T\" : \"01010100\", \"U\" : \"01010101\", \"V\" : \"01010110\",\n", 76 | " \"W\" : \"01010111\", \"X\" : \"01011000\", \"Y\" : \"01011001\", \"Z\" : \"01011010\", \",\": \"00101100\", \".\": \"00101110\", \"'\": \"00100111\", \"?\": \"00111111\"}\n", 77 | "\n", 78 | "# to translate the sentences, you need to define a reversed table\n", 79 | "# Your code here\n", 80 | "\n", 81 | "# sentences to decode\n", 82 | "sentences = [\"01001001 / 01110111 01101111 01110101 01101100 01100100 / 01110100 01100101 01101100 01101100 / 01111001 01101111 01110101 / 01100001 / 01100011 01101000 01100101 01101101 01101001 01110011 01110100 01110010 01111001 / 01101010 01101111 01101011 01100101 / 00101100 / 01100010 01110101 01110100 / 01100001 01101100 01101100 / 01110100 01101000 01100101 / 01100111 01101111 01101111 01100100 / 01101111 01101110 01100101 01110011 / 01000001 01110010 01100111 01101111 01101110\",\n", 83 | " \"01001001 01100110 / 01111001 01101111 01110101 / 01100001 01110010 01100101 / 01101110 01101111 01110100 / 01110000 01100001 01110010 01110100 / 01101111 01100110 / 01110100 01101000 01100101 / 01110011 01101111 01101100 01110101 01110100 01101001 01101111 01101110 / 00101100 / 01111001 01101111 01110101 / 01100001 01110010 01100101 / 01110000 01100001 01110010 01110100 / 01101111 01100110 / 01110100 01101000 01100101 / 01110000 01110010 01100101 01100011 01101001 01110000 01101001 01110100 01100001 01110100 01100101\",\n", 84 | " \"01000001 / 01101110 01100101 01110101 01110100 01110010 01101111 01101110 / 01110111 01100001 01101100 01101011 01110011 / 01101001 01101110 01110100 01101111 / 01100001 / 01100010 01100001 01110010 / 01100001 01101110 01100100 / 01100001 01110011 01101011 01110011 / 00101100 / 00100111 / 01101000 01101111 01110111 / 01101101 01110101 01100011 01101000 / 01100110 01101111 01110010 / 01100001 / 01100010 01100101 01100101 01110010 / 00111111 / 00100111 / 01100001 01101110 01100100 / 01110100 01101000 01100101 / 01100010 01100001 01110010 01110100 01100101 01101110 01100100 01100101 01110010 / 01110011 01100001 01111001 01110011 / 00101100 / 00100111 / 01100110 01101111 01110010 / 01111001 01101111 01110101 / 00101100 / 01101110 01101111 / 01100011 01101000 01100001 01110010 01100111 01100101\",\n", 85 | " \"01001111 01101110 01100011 01100101 / 01001001 / 01110100 01101111 01101100 01100100 / 01100001 / 01100011 01101000 01100101 01101101 01101001 01110011 01110100 01110010 01111001 / 01101010 01101111 01101011 01100101 / 00101100 / 01110100 01101000 01100101 01110010 01100101 / 01110111 01100001 01110011 / 01101110 01101111 / 01110010 01100101 01100001 01100011 01110100 01101001 01101111 01101110\"]\n", 86 | "\n", 87 | "# decoding the sentences and printing the output\n", 88 | "for sentence in sentences:\n", 89 | " words = sentence.split(' / ')\n", 90 | " for word in words:\n", 91 | " # Your code here\n", 92 | " # remove the next line to run your code\n", 93 | " pass \n", 94 | " #print()" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "id": "b833cc03-42ef-4073-abb7-6ec9986e31e0", 100 | "metadata": {}, 101 | "source": [ 102 | "## Possible solutions" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "id": "f1f8c0d9-4dcc-4a8c-bc34-e9a20ad23c79", 108 | "metadata": {}, 109 | "source": [ 110 | "!!! Do not scroll down if you don't want to see the solutions...you have been warned!." 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "id": "c0a7449f-3051-4629-887e-b0cda88a27da", 116 | "metadata": {}, 117 | "source": [ 118 | "![alt text](../theory/images/spoiler.jpg)" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 1, 124 | "id": "369cacef-b826-426c-9e3a-1474e8c00a0c", 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "string_a = 'a'\n", 129 | "string_b = 'b'\n", 130 | "integer_1 = 1\n", 131 | "integer_2 = 2\n", 132 | "string_4 = '4'\n", 133 | "float_1 = 1.0\n", 134 | "float_2_5 = 2.5\n", 135 | "\n", 136 | "list_strings = [string_a, string_b, string_4]\n", 137 | "list_numbers = [integer_1, integer_2, float_1, float_2_5]\n", 138 | "\n", 139 | "def combinations(list_elements):\n", 140 | " list_combinations = []\n", 141 | " for element in list_elements:\n", 142 | " copy_list = list_elements.copy()\n", 143 | " copy_list.remove(element)\n", 144 | " for item in copy_list:\n", 145 | " list_combinations.append((element + item))\n", 146 | " return list_combinations\n", 147 | "\n", 148 | "# print(combinations(list_strings))\n", 149 | "# print(combinations(list_numbers))" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 6, 155 | "id": "a053c162-bfef-40eb-9557-2617c02ee7c6", 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "data": { 160 | "text/plain": [ 161 | "array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])" 162 | ] 163 | }, 164 | "execution_count": 6, 165 | "metadata": {}, 166 | "output_type": "execute_result" 167 | } 168 | ], 169 | "source": [ 170 | "import numpy as np\n", 171 | "data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000])\n", 172 | "cut_off = 3 * np.std(data)\n", 173 | "\n", 174 | "def outliers(list_data):\n", 175 | " cut_off = 3 * np.std(list_data)\n", 176 | " no_outliers = [(abs(x - list_data.mean()) < cut_off) for x in list_data]\n", 177 | " list_data = list_data[no_outliers]\n", 178 | " while len(list_data) != len(no_outliers):\n", 179 | " cut_off = 3 * np.std(list_data)\n", 180 | " no_outliers = [(abs(x - list_data.mean()) < cut_off) for x in list_data]\n", 181 | " list_data = list_data[no_outliers]\n", 182 | " return list_data\n", 183 | "\n", 184 | "outliers(data)" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "id": "d55f6dd9-0afc-4aaf-8064-8022fd1360b7", 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "english_to_binary = {v: k for k, v in binary_to_english.items()}\n", 195 | "\n", 196 | "for sentence in sentences:\n", 197 | " words = sentence.split(\" / \")\n", 198 | " temp = []\n", 199 | " for word in words:\n", 200 | " # your code here\n", 201 | " letters = word.split()\n", 202 | " list_lett = [english_to_binary[letter] for letter in letters]\n", 203 | " #print(''.join(list_lett))\n", 204 | " temp.append(''.join(list_lett))\n", 205 | " print(' '.join(temp))" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": null, 211 | "id": "c012f729-82aa-43ab-922b-9a35e909af94", 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [] 215 | } 216 | ], 217 | "metadata": { 218 | "kernelspec": { 219 | "display_name": "Python 3 (ipykernel)", 220 | "language": "python", 221 | "name": "python3" 222 | }, 223 | "language_info": { 224 | "codemirror_mode": { 225 | "name": "ipython", 226 | "version": 3 227 | }, 228 | "file_extension": ".py", 229 | "mimetype": "text/x-python", 230 | "name": "python", 231 | "nbconvert_exporter": "python", 232 | "pygments_lexer": "ipython3", 233 | "version": "3.9.7" 234 | } 235 | }, 236 | "nbformat": 4, 237 | "nbformat_minor": 5 238 | } 239 | -------------------------------------------------------------------------------- /week01/theory/1_introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "763dae41-9cf9-46ef-b082-378801c0e7f8", 6 | "metadata": {}, 7 | "source": [ 8 | "# Chemical Reaction Engineering in Python" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "fc42db5c-bb0c-4a6e-822e-df80c74b7ee6", 14 | "metadata": { 15 | "tags": [] 16 | }, 17 | "source": [ 18 | "## TL;DR" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "id": "acaa6657-edfd-473d-88c7-1e975fc4d0d9", 24 | "metadata": {}, 25 | "source": [ 26 | "This is a practical course designed for chemical engineers that want to learn how to program in Python. \n", 27 | "The course is very practical and will cover various topics, such as basic Python syntax, solving ODEs, stoichiometry, data visualization and basic data analysis." 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "id": "8522383e-8d8a-439e-aa80-879dbe18aa40", 33 | "metadata": {}, 34 | "source": [ 35 | "## Introduction" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "id": "3525e27b-804b-4065-b003-ef5237c2c7f9", 41 | "metadata": {}, 42 | "source": [ 43 | "Recently, more and more chemical engineering students have expressed the desire to acquire basic programming skills early on in their career, with Python being the most requested language by far.\n", 44 | "For this reason, we decided to support the regular material taught in Chemical Reaction Engineering (28342) with an introductory Python course.\n", 45 | "Therefore, we aim to provide material and practical tutorials to learn Python, so that you have the opportunity to use Python to solve the exercises and assignments.\n", 46 | "\n", 47 | "This course is designed to be very practical since the best way to learn how to program is by programming. You will start writing and executing code from day 1, through carefully designed exercises.\n", 48 | "The target of this course is students and professionals in Chemical Engineering that want to learn how to program in Python.\n", 49 | "\n", 50 | "The course may be challenging and overwhelming at the beginning, but don't worry if you don't manage to complete everything.\n", 51 | "Each week, there will be a mandatory notebook of exercises `01-Exercises` and an additional, optional, notebook containing more challenging exercises, for learners that want to test themselves and like to *crack the code* (pun intended)." 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "id": "f18424c8-070a-450d-bff2-4154ccb71503", 57 | "metadata": {}, 58 | "source": [ 59 | "## Why Python?" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "id": "240510b5-fdb2-4b15-b5b2-3ccf89fd1368", 65 | "metadata": {}, 66 | "source": [ 67 | "Python is one of the most popular languages in use today, thanks to its easy syntax, readability, libraries available and broad documentation. \n", 68 | "It is open-source, unlike other very popular programs such as MATLAB, which require a license.\n", 69 | "It has a big community, meaning that other people have probably already asked any possible question you might be having right now.\n", 70 | "Some forums where to ask and look for questions: [StackOverflow](https://stackoverflow.com/) (for practical questions about code), [StackExchange](https://stackexchange.com/) (for more theoretical questions).\n", 71 | "It is the to-go language for data analysis and data science, both in academia and industry.\n", 72 | "\n", 73 | "In this course, we will use Python 3.8." 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "id": "5b489271-a3ce-44b6-9aed-573baf52bdc2", 79 | "metadata": {}, 80 | "source": [ 81 | "## Schedule" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "id": "98f42d9a-53d3-463b-8ea1-3f6cbe57d904", 87 | "metadata": {}, 88 | "source": [ 89 | "The course follows the regular 13 weeks period and provides material and exercises to support the lectures. Some of the topics:\n", 90 | "- **Introduction to the course**. Introduction, motivation, tips and tricks, package installation. General syntax: indentation, for loop, while loop, functions and classes.\n", 91 | "- **Data structures**. Data structures: lists, arrays, strings, dictionaries, pandas dataframe.\n", 92 | "- **Data visualization**. Plotting with matplotlib library\n", 93 | "- **Solvers**. Solving systems of equations and stoichiometry.\n", 94 | "- **Data analysis**. Data loading, extraction, cleaning, preprocessing, analysis.\n", 95 | "- **Balances**. Mass balance, energy balance." 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "id": "b8b4f06e-87b0-4af4-886f-34debecb0b6f", 101 | "metadata": {}, 102 | "source": [ 103 | "## Learning Objectives" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "id": "cb038214-b40b-431a-aa03-649d2d10eba8", 109 | "metadata": {}, 110 | "source": [ 111 | "- Master the Python's syntax, familiarize with arithmetic operations, assignment and compound statements.\n", 112 | "- Learn reusing Python code efficiently through functions and classes.\n", 113 | "- Master the usage of main data structures used in Python, such as lists, generators, dictionaries, sets, dataframes and arrays.\n", 114 | "- Effectively visualize and analyze data.\n", 115 | "- Operate the reactor based on kinetics for elementary and non-elementary reactions.\n", 116 | "- Understand the ideal reaction models: batch, continuous-stirred tank and plug flow.\n", 117 | "- Understand the mathematical models for the three ideal types of reactor under isothermal conditions.\n", 118 | "- Understand the mass balances for the three ideal reactor systems.\n", 119 | "- Measure the reaction kinetics to obtain a rate expression.\n", 120 | "- Carry out energy balances for the reactor types for a single reaction." 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "id": "62ede4ae-8c80-48c5-9492-b27b15157797", 126 | "metadata": {}, 127 | "source": [ 128 | "## Helpful tips and tricks before starting" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "id": "894a3fdc-e451-4d15-989e-74a88438e9f9", 134 | "metadata": {}, 135 | "source": [ 136 | "\"The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.\"\n", 137 | "\n", 138 | "— Brian Kernighan, \"Unix for Beginners\" (1979)" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "id": "7ebb7000-3cd7-4d9b-9671-83910d0afe94", 144 | "metadata": {}, 145 | "source": [ 146 | "1. **The best way to learn how to program is by programming**. It's normal that you cannot solve everything and you are overwhelmed at the beginning. Don't give up and just practice.\n", 147 | "1. **Write, test and improve code.** Do not expect to write a full program in one sitting: most programmers write, test and rewrite code many times before their program works, so do not get discouraged!\n", 148 | "2. **Brainstorm first.** Instead of reading a problem and looking for a solution on the Internet, try to think about it yourself. Re-read the problem, brainstorm possible solutions and try to write some code. Make sure that you actually understand what is asked. Only after you have spent sufficient time on this, look for hints elsewhere.\n", 149 | "3. **Learn to comment your code early on.** Before coding, visualize what you plan to do and describe it in plain, non-technical text on paper. Try to be as detailed as possible and include all the steps, even the smallest ones. This will be helpful at the beginning of your coding experience to guide you through the process and ensure you do not forget important steps. Later on, when you are more comfortable coding, it will be helpful for reference for you or other teammates. Remember that just because something seems easy for you, it does not mean your colleague can read your code and understand it right away. This is a very important principle for code deployment.\n", 150 | "4. **Understand what the program is doing.** It is important that you understand what your program is doing. Often, it is useful to simply *print* what you are doing, this is an easy way to visualize, and therefore better understand, the output. This approach is called tracing or printf() debugging, after the print function name in the C language)." 151 | ] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "id": "461bedd4-1244-4c2c-8420-18f588278d82", 156 | "metadata": {}, 157 | "source": [ 158 | "## Contacts\n", 159 | "If you have any questions regarding the exercises or any feedback on the course, feel free to contact Fiammetta Caccavale (fiacac@kt.dtu.dk)." 160 | ] 161 | } 162 | ], 163 | "metadata": { 164 | "kernelspec": { 165 | "display_name": "Python 3 (ipykernel)", 166 | "language": "python", 167 | "name": "python3" 168 | }, 169 | "language_info": { 170 | "codemirror_mode": { 171 | "name": "ipython", 172 | "version": 3 173 | }, 174 | "file_extension": ".py", 175 | "mimetype": "text/x-python", 176 | "name": "python", 177 | "nbconvert_exporter": "python", 178 | "pygments_lexer": "ipython3", 179 | "version": "3.8.10" 180 | } 181 | }, 182 | "nbformat": 4, 183 | "nbformat_minor": 5 184 | } 185 | -------------------------------------------------------------------------------- /week01/theory/2_hello_world.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "3fde4216-5be3-418e-93d3-5b0ab6efd536", 6 | "metadata": {}, 7 | "source": [ 8 | "# Hello, World!" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "7688b9ae-77cc-4a9f-9684-1e25950be8af", 14 | "metadata": {}, 15 | "source": [ 16 | "Traditionally, Hello World programs are used to illustrate how coding works, as well as to verify that the system is operating correctly.\n", 17 | "Greeting the user is considered the first step in learning to code, and it even has its own Wikipedia page!\n", 18 | "So, let's do that." 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "id": "d83589d7-923a-427b-b9d4-9d8f21901218", 25 | "metadata": {}, 26 | "outputs": [ 27 | { 28 | "name": "stdout", 29 | "output_type": "stream", 30 | "text": [ 31 | "Hello, World!\n" 32 | ] 33 | } 34 | ], 35 | "source": [ 36 | "print(\"Hello, World!\")" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "id": "445b7814-ac70-4938-90d3-f21a16beb2fe", 42 | "metadata": {}, 43 | "source": [ 44 | "## Syntax, Semantics and Pragmatics of a programming language" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "id": "037e30c6-d994-4b78-a276-52ada867cb34", 50 | "metadata": {}, 51 | "source": [ 52 | "Before starting to code, there are some notions that we need to understand.\n", 53 | "\n", 54 | "First of all, Python is regarded as a *programming language*. \n", 55 | "But what does that mean? \n", 56 | "How is a programming language different from a natural language?\n", 57 | "\n", 58 | "Let's start with what they have in common: **language**. A language is a system of communication, a means for individuals belonging to the same group to express themselves and understand each other.\n", 59 | "A language, in order to be successful in enabling communication and understanding, has to be based on conventions, rules that are agreed upon by the members of the group. \n", 60 | "\n", 61 | "The three main categories we will compare here are: **Syntax**, **Semantics** and **Pragmatics**.\n", 62 | "- **Syntax**: grammatical structure of sentences. It defines the rules of what is considered to be grammatical in a language. For example, in a natural language such as English, syntax determines the order of the components of a sentence (Subject-Verb-Object). Programming languages (e.g., Python) have a highly non-flexible notion of grammaticality, meaning that a structure is either correctly implemented or it raises an error An example of a very common syntactic error raised in Python is wrong indentation.\n", 63 | "- **Semantics**: meaning of a sentence. Sometimes, the program we are writing is syntactically correct, but it raises an error for other reasons. So while the computer may understand the commands, carrying them out leads to errors. An example of this is division by zero, combining incompatible types of variables (Python is a *weakly-typed* language) or calling an undefined function.\n", 64 | "- **Pragmatics**: defines how context contributes to the meaning of a sentence. Humans are able to infer much information from the context, enabling them to infer the meaning from a set of shared assumptions, even though not all details are explicit. Computer programs are unable to do the same, and can only do what instructed. But this is not necessarily a bad attribute, since it means that there is no ambiguity: a piece of code can have one and only one interpretation, while natural language can often be ambiguous. If a program encounters potentially ambiguous statements, preference rules are employed to select a single interpretation. An example of this is given by mathematical operations." 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "id": "43ec185d-c7be-406a-bfa5-200dda7aa65b", 70 | "metadata": {}, 71 | "source": [ 72 | "### Syntax" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 2, 78 | "id": "db5c80ca-0e1e-4181-9a2d-52bf3ad3da9f", 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "metre\n", 86 | "gram\n", 87 | "second\n" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "# Example of a correct statement\n", 93 | "for unit in ['metre', 'gram', 'second']:\n", 94 | " print(unit)" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 3, 100 | "id": "b218b066-dd30-4131-b20a-55b19c36aec3", 101 | "metadata": {}, 102 | "outputs": [ 103 | { 104 | "ename": "IndentationError", 105 | "evalue": "expected an indented block (Temp/ipykernel_18948/1821972305.py, line 3)", 106 | "output_type": "error", 107 | "traceback": [ 108 | "\u001b[1;36m File \u001b[1;32m\"C:\\Users\\fiacac\\AppData\\Local\\Temp/ipykernel_18948/1821972305.py\"\u001b[1;36m, line \u001b[1;32m3\u001b[0m\n\u001b[1;33m print(unit)\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mIndentationError\u001b[0m\u001b[1;31m:\u001b[0m expected an indented block\n" 109 | ] 110 | } 111 | ], 112 | "source": [ 113 | "# Example of error\n", 114 | "for unit in ['metre', 'gram', 'second']:\n", 115 | "print(unit)" 116 | ] 117 | }, 118 | { 119 | "cell_type": "markdown", 120 | "id": "99a4eca3-c013-4624-a8b9-41ba0af0cef5", 121 | "metadata": {}, 122 | "source": [ 123 | "### Semantics" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 4, 129 | "id": "3ac98ba7-8614-40f3-b5be-5d43088ee993", 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "ename": "ZeroDivisionError", 134 | "evalue": "division by zero", 135 | "output_type": "error", 136 | "traceback": [ 137 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 138 | "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 139 | "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_18948/2436706066.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m5\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mx\u001b[0m \u001b[1;33m/\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 140 | "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" 141 | ] 142 | } 143 | ], 144 | "source": [ 145 | "# Division by zero\n", 146 | "x = 5\n", 147 | "y = 0\n", 148 | "x / y" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "id": "99666ffe-eaf3-43d6-93af-6ab8c6648701", 154 | "metadata": {}, 155 | "source": [ 156 | "Although the syntax of the above cell is correct, the code returns an error due to the fact that division by zero is not possible." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 5, 162 | "id": "3352a202-b657-4639-9388-a4a57f40378a", 163 | "metadata": {}, 164 | "outputs": [ 165 | { 166 | "ename": "TypeError", 167 | "evalue": "unsupported operand type(s) for +: 'int' and 'str'", 168 | "output_type": "error", 169 | "traceback": [ 170 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 171 | "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", 172 | "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_18948/425070858.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mnumber\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mletter\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'a'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mnumber\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mletter\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 173 | "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'str'" 174 | ] 175 | } 176 | ], 177 | "source": [ 178 | "# Incompatible type\n", 179 | "number = 1\n", 180 | "letter = 'a'\n", 181 | "number + letter" 182 | ] 183 | }, 184 | { 185 | "cell_type": "markdown", 186 | "id": "9cf9c5c2-3c53-410a-a891-7302e7ff8353", 187 | "metadata": {}, 188 | "source": [ 189 | "Here the error indicates that you cannot add a `number` and a `letter` because the first is cast as an integer (`int`) and the second as a string (`str`). \n", 190 | "\n", 191 | "We will learn more about strings in week 2." 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": 6, 197 | "id": "80eae59f-d05f-417e-98a7-e53267f98439", 198 | "metadata": {}, 199 | "outputs": [ 200 | { 201 | "ename": "AttributeError", 202 | "evalue": "'list' object has no attribute 'my_function'", 203 | "output_type": "error", 204 | "traceback": [ 205 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 206 | "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", 207 | "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_18948/1423563681.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# Calling undefined function\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;33m[\u001b[0m\u001b[1;34m'metre'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'gram'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'second'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmy_function\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 208 | "\u001b[1;31mAttributeError\u001b[0m: 'list' object has no attribute 'my_function'" 209 | ] 210 | } 211 | ], 212 | "source": [ 213 | "# Calling undefined function\n", 214 | "['metre', 'gram', 'second'].my_function()" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "id": "6639a9a1-1a8e-4e65-bf9f-44c6613f2b0c", 220 | "metadata": {}, 221 | "source": [ 222 | "The error above indicates that `my_function()` is not defined." 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "id": "41215200-f013-424d-addf-cec9dd9363c0", 228 | "metadata": {}, 229 | "source": [ 230 | "### Pragmatics" 231 | ] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "id": "ea79ae7e-1235-4ba0-b306-d8d1236e27aa", 236 | "metadata": {}, 237 | "source": [ 238 | "Before running the following cell, can you guess what operation will be done first?" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": 7, 244 | "id": "7c7acdbd-0260-4513-adde-a192223475c4", 245 | "metadata": {}, 246 | "outputs": [ 247 | { 248 | "data": { 249 | "text/plain": [ 250 | "69" 251 | ] 252 | }, 253 | "execution_count": 7, 254 | "metadata": {}, 255 | "output_type": "execute_result" 256 | } 257 | ], 258 | "source": [ 259 | "# Mathematical operations are handled by preference rules \n", 260 | "6 + 7 * 9" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "id": "8b005d7b-ec0d-4822-88d8-6e6d39e35df0", 266 | "metadata": {}, 267 | "source": [ 268 | "If you meant to first add and then multiply, you can use parenthesis!" 269 | ] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "id": "00c54a4b-6273-4550-854d-f9f9336873a8", 274 | "metadata": {}, 275 | "source": [ 276 | "(6 + 7) * 9" 277 | ] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "id": "0071a226-6f0b-4829-a773-ce19ee17fad9", 282 | "metadata": {}, 283 | "source": [ 284 | "## \"A Foolish Consistency is the Hobgoblin of Little Minds\" \n", 285 | "-Ralph Waldo Emerson, Self-Reliance" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "id": "a615a9e5-2e92-4b57-80a4-623f5fe702f6", 291 | "metadata": {}, 292 | "source": [ 293 | "Programmers are very opinionated people, which means that they will probably have a strong preference for how to define variables, functions and classes, and so on.\n", 294 | "\n", 295 | "[Here](https://www.python.org/dev/peps/pep-0008/) you can find the Holy Grail of Python formatting style." 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "id": "12701bd5-0856-4fd8-8a77-bbdaff8305c7", 301 | "metadata": {}, 302 | "source": [ 303 | "If you need a laugh after all this hard work, here is a video from the TV series *Silicon Valley* regarding **Tabs vs Spaces**:" 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": 2, 309 | "id": "0a0e84d8-f360-4bd1-87e2-9930428544f4", 310 | "metadata": {}, 311 | "outputs": [ 312 | { 313 | "data": { 314 | "image/jpeg": "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\n", 315 | "text/html": [ 316 | "\n", 317 | " \n", 325 | " " 326 | ], 327 | "text/plain": [ 328 | "" 329 | ] 330 | }, 331 | "execution_count": 2, 332 | "metadata": {}, 333 | "output_type": "execute_result" 334 | } 335 | ], 336 | "source": [ 337 | "from IPython.display import YouTubeVideo\n", 338 | "YouTubeVideo('cowtgmZuai0', width=800, height=300)" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "id": "5858004a-9fc8-4f89-a825-b39b4145bef5", 344 | "metadata": {}, 345 | "source": [ 346 | "Although we really like Richard, the PEP-8 guidelines say that \n", 347 | "**\"Spaces are the preferred indentation method.\"**" 348 | ] 349 | } 350 | ], 351 | "metadata": { 352 | "kernelspec": { 353 | "display_name": "Python 3 (ipykernel)", 354 | "language": "python", 355 | "name": "python3" 356 | }, 357 | "language_info": { 358 | "codemirror_mode": { 359 | "name": "ipython", 360 | "version": 3 361 | }, 362 | "file_extension": ".py", 363 | "mimetype": "text/x-python", 364 | "name": "python", 365 | "nbconvert_exporter": "python", 366 | "pygments_lexer": "ipython3", 367 | "version": "3.10.10" 368 | } 369 | }, 370 | "nbformat": 4, 371 | "nbformat_minor": 5 372 | } 373 | -------------------------------------------------------------------------------- /week01/theory/4_control_flow.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "bcfb1a44-abdb-44b6-a59f-90684ce8322a", 6 | "metadata": {}, 7 | "source": [ 8 | "# Conditionality and Repetition" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "5fed5f05-ce90-4074-b918-01f32d208d8f", 14 | "metadata": {}, 15 | "source": [ 16 | "You will quickly find out that in your programming experience, you will spend quite some time writing conditional statements or *looping* through items. Therefore, it's very important that you understand what these statements do and how to properly use them.\n" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "f965f4f2-32da-4ce1-bbfc-ff3d16ffd521", 22 | "metadata": {}, 23 | "source": [ 24 | "## Conditionality" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "id": "4c907a86-3c74-47e5-be66-c1d9167c4926", 30 | "metadata": {}, 31 | "source": [ 32 | "The `if` statement is based on a **boolean** operation: if the first condition is executed it means that *the condition is* `True`, otherwise, the program moves on to the next statements *until either a `True` statement or the end of the flow* (else, if included). The flow chart below illustrates the conditional process with one if, two elif and one else statements.\n", 33 | "\n", 34 | "![alt text](images/Python-if-elif-else-statement.png)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "id": "b698e201-d46f-49aa-b6e2-6558e29eccc7", 40 | "metadata": {}, 41 | "source": [ 42 | "Let's see some examples." 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 1, 48 | "id": "f630a56c-0024-4660-ab8b-2251255d48ab", 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "True\n", 56 | "False\n" 57 | ] 58 | } 59 | ], 60 | "source": [ 61 | "# Simple if statement\n", 62 | "if True == 1:\n", 63 | " print('True')\n", 64 | " \n", 65 | "if False == 0:\n", 66 | " print('False')" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 2, 72 | "id": "5927935b-294c-4a83-be9c-b9d21b4b455e", 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "# Now let's execute this cell...do you know why the cell is not printing anything?\n", 77 | "if ():\n", 78 | " print('This condition is not True')" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": 3, 84 | "id": "767f3f48-e362-4482-9c0c-1dcf5978b8b9", 85 | "metadata": {}, 86 | "outputs": [ 87 | { 88 | "name": "stdout", 89 | "output_type": "stream", 90 | "text": [ 91 | "This condition is True\n" 92 | ] 93 | } 94 | ], 95 | "source": [ 96 | "# But this cell does return something\n", 97 | "if not ():\n", 98 | " print('This condition is True')" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "id": "75062093-7425-48d6-9ff8-3cc6fcd20911", 104 | "metadata": {}, 105 | "source": [ 106 | "As you might have guessed, Python casts *boolean* values in different ways. \n", 107 | "Note that in Python 3, `True` and `False` are keywords and cannot be reassigned to another value, e.g., False = 5 will raise an error.\n", 108 | "\n", 109 | "Here are values that are built-in objects considered `False`:\n", 110 | "``` python\n", 111 | "- constants defined to be false: None and False.\n", 112 | "- zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)\n", 113 | "- empty sequences and collections: '', (), [], {}, set(), range(0)\n", 114 | "```\n", 115 | "\n", 116 | "Read more about Truth Value Testing [here](https://docs.python.org/3/library/stdtypes.html)." 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 4, 122 | "id": "548b0e62-9299-4250-99b8-f9e39d0f4ca6", 123 | "metadata": {}, 124 | "outputs": [ 125 | { 126 | "name": "stdout", 127 | "output_type": "stream", 128 | "text": [ 129 | "a is divisible by 5\n" 130 | ] 131 | } 132 | ], 133 | "source": [ 134 | "# Note: the 'else' statement is optional and may not be specified\n", 135 | "a = 50 \n", 136 | "# the % is the modulo operator finding the remainder after the division\n", 137 | "# in this case, a divided by 5 leaves 0\n", 138 | "if a%5==0:\n", 139 | " print('a is divisible by 5')" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 5, 145 | "id": "ffbe241f-cd2c-435b-8de0-bf3da99fda63", 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "name": "stdout", 150 | "output_type": "stream", 151 | "text": [ 152 | "You failed the exam!\n" 153 | ] 154 | } 155 | ], 156 | "source": [ 157 | "# Now let's see more complex statements\n", 158 | "# Change the values of exam_score and assignment to see how the outcome changes\n", 159 | "\n", 160 | "exam_score = 30\n", 161 | "assignment = 'C'\n", 162 | "\n", 163 | "if exam_score >= 80:\n", 164 | " if assignment == 'A':\n", 165 | " print('You passed the exam with the highest grade.')\n", 166 | " elif assignment =='B':\n", 167 | " print('You passed the exam with the second highest grade')\n", 168 | " else:\n", 169 | " print('You passed the exam with the third highest grade')\n", 170 | "elif 40 <= exam_score < 80:\n", 171 | " if assignment == 'A' or assignment == 'B':\n", 172 | " print('You did well in the assignment but not in the exam, you have a second attempt in 30 days')\n", 173 | " else:\n", 174 | " print('You barely passed the exam')\n", 175 | "else:\n", 176 | " print('You failed the exam!')" 177 | ] 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "id": "50c3026a-f4ae-43b5-b68d-d9cf70bf6a2f", 182 | "metadata": {}, 183 | "source": [ 184 | "**Exercise**: Change the previous code so that if a student receives an exam score between 35 and 40 (not included) and assignment grade A, the code returns \"You almost passed\". " 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 6, 190 | "id": "45858adf-3d2e-4adb-affa-1ded20c53efb", 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "# Your code here" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "id": "fcb86283-0d14-4289-8150-461afbae25f2", 200 | "metadata": {}, 201 | "source": [ 202 | "## Repetition" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "id": "bd73c3d2-1455-4f45-b3ec-439840710381", 208 | "metadata": {}, 209 | "source": [ 210 | "The `for` loop is used to iterate through items, which could be stored in a tuple, list, dictionary and so on (we will get familiar with all of these data structures in week 2, so if you don't know these terms don't worry).\n", 211 | "These kinds of loops are helpful in a multitude of operations, for example when encountering a nested loop, where list comprehensions would make the code less transparent and harder to read. Remember that, particularly when working in a team, code readability is very important.\n", 212 | "\n", 213 | "Here we also introduce a new, very useful, function: the `zip` function.\n", 214 | "This function is used to simultaneously loop through multiple elements, for example through two lists." 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 6, 220 | "id": "8ea05cc0-c4b9-4564-b1cb-c908b5456158", 221 | "metadata": {}, 222 | "outputs": [ 223 | { 224 | "name": "stdout", 225 | "output_type": "stream", 226 | "text": [ 227 | "Anna is not Mary\n", 228 | "Mary\n", 229 | "Thomas is not Mary\n" 230 | ] 231 | } 232 | ], 233 | "source": [ 234 | "# loop through students and grades in the two given lists through the 'zip' function\n", 235 | "for student, grade in zip(['Anna', 'Mary', 'Thomas'], [7, 12, 10]):\n", 236 | " # if the student's initial is M and their grade is 12\n", 237 | " if student.startswith('M') and grade == 12:\n", 238 | " # print the name of the student\n", 239 | " print(student)\n", 240 | " else:\n", 241 | " # otherwise print that it is not Mary\n", 242 | " print(student, 'is not Mary')" 243 | ] 244 | }, 245 | { 246 | "cell_type": "code", 247 | "execution_count": 7, 248 | "id": "188b369a-6e23-4baa-a188-b5203ac029f5", 249 | "metadata": {}, 250 | "outputs": [ 251 | { 252 | "name": "stdout", 253 | "output_type": "stream", 254 | "text": [ 255 | "Row [0.90852788 0.2487985 0.85072772]\n", 256 | "Element 0.9085278793247539\n", 257 | "Element 0.24879849782046126\n", 258 | "Element 0.850727718969466\n", 259 | "\n", 260 | "Row [0.45354185 0.76613525 0.84683081]\n", 261 | "Element 0.4535418487717926\n", 262 | "Element 0.7661352543565969\n", 263 | "Element 0.8468308065135864\n", 264 | "\n" 265 | ] 266 | } 267 | ], 268 | "source": [ 269 | "# In this example we will use a library called Numpy\n", 270 | "import numpy as np\n", 271 | "\n", 272 | "# we initialize a matrix with random samples from a uniform distribution [0, 1) of shape 2x3 (rowsxcolumns)\n", 273 | "matrix = np.random.rand(2,3)\n", 274 | "\n", 275 | "# uncomment the following lines to investigate the data\n", 276 | "# print(matrix.shape)\n", 277 | "# print(matrix)\n", 278 | "\n", 279 | "# loop through the elements of the matrix\n", 280 | "for row in matrix:\n", 281 | " print('Row', row)\n", 282 | " # loop through each element in the row\n", 283 | " for elem in row:\n", 284 | " print('Element', elem)\n", 285 | " print()" 286 | ] 287 | }, 288 | { 289 | "cell_type": "markdown", 290 | "id": "9204950e-7907-46c6-9425-d4d69d1a0b12", 291 | "metadata": {}, 292 | "source": [ 293 | "The `while` loop is used to iterate through elements for as long as a certain condition is valid." 294 | ] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "execution_count": 8, 299 | "id": "db5a8549-3326-42cf-81ac-30ddca05d190", 300 | "metadata": {}, 301 | "outputs": [ 302 | { 303 | "name": "stdout", 304 | "output_type": "stream", 305 | "text": [ 306 | "Our total amount c is: 1, so the condition is within the limit\n", 307 | "Our total amount c is: 2, so the condition is within the limit\n", 308 | "Our total amount c is: 3, so the condition is within the limit\n", 309 | "Our total amount c is: 4, so the condition is within the limit\n", 310 | "Our total amount c is: 5, so the condition is within the limit\n", 311 | "Our total amount c is: 6, so the condition is within the limit\n", 312 | "Our total amount c is: 7, so the condition is within the limit\n", 313 | "Our total amount c is: 8, so the condition is within the limit\n", 314 | "Our total amount c is: 9, so the condition is within the limit\n", 315 | "Our total amount c is: 10, so the condition is within the limit\n", 316 | "Our total amount c is: 11, so the condition is within the limit\n" 317 | ] 318 | } 319 | ], 320 | "source": [ 321 | "# set a condition\n", 322 | "limit = 10\n", 323 | "\n", 324 | "c = 0\n", 325 | "while c <= limit:\n", 326 | " c+=1\n", 327 | " print(f\"Our total amount c is: {c}, so the condition is within the limit\")" 328 | ] 329 | }, 330 | { 331 | "cell_type": "markdown", 332 | "id": "238b6839-c41a-40ba-84f9-059ea94cc592", 333 | "metadata": {}, 334 | "source": [ 335 | "But be careful about infinite loops!" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": null, 341 | "id": "76abbc06-0b84-41a4-86bd-ee4c45223d07", 342 | "metadata": { 343 | "scrolled": true, 344 | "tags": [] 345 | }, 346 | "outputs": [], 347 | "source": [ 348 | "# infinite loop: interrupt execution!\n", 349 | "\n", 350 | "while True:\n", 351 | " print('This will keep running...')" 352 | ] 353 | }, 354 | { 355 | "cell_type": "markdown", 356 | "id": "336f2e77-f049-437e-b659-d9a323788c7b", 357 | "metadata": {}, 358 | "source": [ 359 | "## Continue and Break" 360 | ] 361 | }, 362 | { 363 | "cell_type": "markdown", 364 | "id": "a2dbb49a-86d8-49f2-b9eb-609992a1617a", 365 | "metadata": {}, 366 | "source": [ 367 | "Sometimes, it can be useful to ignore certain conditions or parts of the code. \n", 368 | "In this case, you can use the `continue` and `break` commands. \n", 369 | "Depending on what you want to achieve, you may use either of these commands.\n", 370 | "\n", 371 | "For example, \n", 372 | "- `continue` can be used to skip a certain condition in a loop and move to the next\n", 373 | "- `break` exits the current execution (e.g., in a loop) and moves to the next code block." 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": 9, 379 | "id": "584dde7b-4b20-4686-a988-54eb3188297e", 380 | "metadata": {}, 381 | "outputs": [ 382 | { 383 | "name": "stdout", 384 | "output_type": "stream", 385 | "text": [ 386 | "8\n", 387 | "9\n", 388 | "10\n", 389 | "11\n", 390 | "12\n", 391 | "13\n", 392 | "14\n" 393 | ] 394 | } 395 | ], 396 | "source": [ 397 | "# let's investigate what 'continue' does\n", 398 | "for i in range(15):\n", 399 | " if i > 7:\n", 400 | " print(i)\n", 401 | " else:\n", 402 | " #if this condition is True, we continue to the next iteration\n", 403 | " continue" 404 | ] 405 | }, 406 | { 407 | "cell_type": "code", 408 | "execution_count": 10, 409 | "id": "7509cfe2-2d44-4cb8-85a5-c385341e122a", 410 | "metadata": {}, 411 | "outputs": [ 412 | { 413 | "name": "stdout", 414 | "output_type": "stream", 415 | "text": [ 416 | "['batch', 'continuous stirred tank']\n" 417 | ] 418 | } 419 | ], 420 | "source": [ 421 | "# create a list of reactors\n", 422 | "reactors = ['batch', 'continuous stirred tank', 'plug flow']\n", 423 | "\n", 424 | "# create a new list, we will add items to this list until a certain element is reached, then we break the loop\n", 425 | "new_reactors = [] \n", 426 | "for reactor in reactors:\n", 427 | " # append items\n", 428 | " new_reactors.append(reactor)\n", 429 | " if reactor == 'continuous stirred tank':\n", 430 | " # if the condition is met, break the loop\n", 431 | " break\n", 432 | "\n", 433 | "if 'batch' in new_reactors:\n", 434 | " # print the new list\n", 435 | " print(new_reactors)" 436 | ] 437 | }, 438 | { 439 | "cell_type": "markdown", 440 | "id": "50ca5a36-7ed9-40eb-bab7-1986435acd7c", 441 | "metadata": {}, 442 | "source": [ 443 | "Here you can see that we used the `break` command to exit the loop once we reached our goal, which was to terminate the loop once 'continuous stirred tank' was added to new_reactors list." 444 | ] 445 | }, 446 | { 447 | "cell_type": "markdown", 448 | "id": "9a3d4edf-39a4-4c53-834b-677682ade757", 449 | "metadata": {}, 450 | "source": [ 451 | "References:\n", 452 | "- If elif else image: https://www.pythontutorial.net/python-basics/python-if/" 453 | ] 454 | } 455 | ], 456 | "metadata": { 457 | "kernelspec": { 458 | "display_name": "Python 3 (ipykernel)", 459 | "language": "python", 460 | "name": "python3" 461 | }, 462 | "language_info": { 463 | "codemirror_mode": { 464 | "name": "ipython", 465 | "version": 3 466 | }, 467 | "file_extension": ".py", 468 | "mimetype": "text/x-python", 469 | "name": "python", 470 | "nbconvert_exporter": "python", 471 | "pygments_lexer": "ipython3", 472 | "version": "3.10.10" 473 | } 474 | }, 475 | "nbformat": 4, 476 | "nbformat_minor": 5 477 | } 478 | -------------------------------------------------------------------------------- /week01/theory/images/Flow_chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/f37542b41215bc162a766559f25f32e2a245bbea/week01/theory/images/Flow_chart.png -------------------------------------------------------------------------------- /week01/theory/images/Python-if-elif-else-statement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/f37542b41215bc162a766559f25f32e2a245bbea/week01/theory/images/Python-if-elif-else-statement.png -------------------------------------------------------------------------------- /week01/theory/images/spoiler.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/f37542b41215bc162a766559f25f32e2a245bbea/week01/theory/images/spoiler.jpg -------------------------------------------------------------------------------- /week02/practice/exercise_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "1ab533bc-63d7-4c28-9482-176cb447ac54", 6 | "metadata": {}, 7 | "source": [ 8 | "# Exercises about dictionaries, sets, dataframes, arrays and visualizations" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "39ef4c7d-6ddc-4119-b2b8-54088051d957", 14 | "metadata": {}, 15 | "source": [ 16 | "## Dictionaries and sets" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "7149dfaa-0417-4c7d-95c3-8e7d3e12e5ff", 22 | "metadata": {}, 23 | "source": [ 24 | "**Exercise**: Take the list of reactors below and create a dictionary where the keys are the elements in the list (the reactors), and the values are the indexes of the elements in the list.\n", 25 | "You can do this by using both a for loop or a list comprehension.\n", 26 | "\n", 27 | "Your result should look like this:\n", 28 | "- dict_reactors = {'batch': 0, 'continuous stirred tank': 1, 'plug flow': 2}\n", 29 | "\n", 30 | "\n", 31 | "Level: Easy." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "id": "ca455779-70dd-44da-a827-a85eeef8c594", 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "list_reactors = ['batch', 'continuous stirred tank', 'plug flow']\n", 42 | "\n", 43 | "# Your code here" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "id": "048c509f-df22-4781-9cf7-6638b2d036ee", 49 | "metadata": {}, 50 | "source": [ 51 | "Now do the same exercise as above, but instead of the index, the values should be properties of the various reactors!\n", 52 | "\n", 53 | "\n", 54 | "Level: Easy." 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "id": "6ebfcbc9-50c3-44c1-b972-19dc01e5c59d", 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "# Your code here" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "id": "ea036b2d-2573-4ea9-8350-f17de29f212a", 70 | "metadata": {}, 71 | "source": [ 72 | "**Exercise**: find the set of the list below.\n", 73 | "\n", 74 | "Level: Easy." 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "id": "3c7f1f9d-6f4a-481b-950e-b3bd91dd6f0a", 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [ 84 | "list_reactors = ['batch', 'continuous stirred tank', 'plug flow', 'batch']\n", 85 | "\n", 86 | "# Your code here" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "id": "609c2fa8-9c9c-4f8b-9cea-27570dba301e", 92 | "metadata": {}, 93 | "source": [ 94 | "**Exercise**: Find the (i) intersection and (ii) union of the lists given below.\n", 95 | "\n", 96 | "Level: Easy." 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 1, 102 | "id": "961477f9-d4a8-4994-985e-a69b315635f7", 103 | "metadata": {}, 104 | "outputs": [ 105 | { 106 | "data": { 107 | "text/plain": [ 108 | "['batch']" 109 | ] 110 | }, 111 | "execution_count": 1, 112 | "metadata": {}, 113 | "output_type": "execute_result" 114 | } 115 | ], 116 | "source": [ 117 | "reactors1 = ['batch', 'continuous stirred tank']\n", 118 | "reactors2 = ['plug flow', 'batch']\n", 119 | "\n", 120 | "# Your code here\n", 121 | "\n", 122 | "list(set(reactors1).intersection(set(reactors2)))" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 4, 128 | "id": "703372f3-0f81-4403-be43-e730d5b17205", 129 | "metadata": {}, 130 | "outputs": [ 131 | { 132 | "data": { 133 | "text/plain": [ 134 | "['batch']" 135 | ] 136 | }, 137 | "execution_count": 4, 138 | "metadata": {}, 139 | "output_type": "execute_result" 140 | } 141 | ], 142 | "source": [ 143 | "list(set(reactors1) & set(reactors2))" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "id": "a41492a0-37a4-4227-922f-c05a5901571c", 149 | "metadata": {}, 150 | "source": [ 151 | "## DataFrames, arrays and plotting" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "id": "f926889e-b7f0-4d5f-af6c-a6261dc4b7dc", 157 | "metadata": {}, 158 | "source": [ 159 | "In the folder, you can load the .csv file 'packed_column_2.csv'.\n", 160 | "\n", 161 | "**Exercise**: load the data in `pandas`, visualize the top 7 rows of the DataFrame, calculate mean, sum, median of the columns and describe the DataFrame.\n", 162 | "\n", 163 | "Level: Easy." 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "id": "7fc4a022-6567-4ddb-83e0-05b70cbe3a0b", 170 | "metadata": {}, 171 | "outputs": [], 172 | "source": [ 173 | "import pandas as pd\n", 174 | "\n", 175 | "# Your code here" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "id": "beed64aa-6e1f-431d-84ac-1f0271162cb6", 181 | "metadata": {}, 182 | "source": [ 183 | "**Exercise**: plot the data, remembering to add a title, axis labels and the legend. Try to make your plot as informative (and pretty) as possible.\n", 184 | "\n", 185 | "Level: Easy." 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "id": "3a9bf1c8-224b-4514-b272-ecc0705d2486", 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "%matplotlib inline\n", 196 | "import matplotlib.pyplot as plt\n", 197 | "\n", 198 | "# Your code here" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "id": "56197752-e6da-4ba8-b8fa-fdf80c11872a", 204 | "metadata": {}, 205 | "source": [ 206 | "**Exercise**: import the data we worked with in the theory ('week02/htory/packed_column.csv') and compare the two DataFrames using `pandas` functions. Create a plot (plot can be done with matplotlib) for each water flow in the two dataframes (e.g., one plot with 0 kg/h water flow in column 1 and in column 2).\n", 207 | "\n", 208 | "Level: Medium." 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "id": "f58b607e-c50f-4335-acfd-482360c8691e", 215 | "metadata": {}, 216 | "outputs": [], 217 | "source": [ 218 | "# Your code here" 219 | ] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "id": "8bf0f902-c4cd-4538-bfb9-eabff06fc482", 224 | "metadata": {}, 225 | "source": [ 226 | "**Exercise**: convert the two DataFrames to numpy arrays and compare them (e.g., calculate the mean, sum, etc).\n", 227 | "\n", 228 | "Level: Easy." 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": null, 234 | "id": "af3d38a5-fd34-487a-9ac5-3ba714bd14a1", 235 | "metadata": {}, 236 | "outputs": [], 237 | "source": [ 238 | "# Your code here" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "id": "1769e5b4-d43a-4c10-b2cc-29402006e5cc", 244 | "metadata": {}, 245 | "source": [ 246 | "**Exercise**: what can you conclude from comparing the flow in the two packed columns? Write some text in markdown." 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": null, 252 | "id": "ab7a6a1c-949b-422d-8e0d-4057269f6360", 253 | "metadata": {}, 254 | "outputs": [], 255 | "source": [ 256 | "# write here\n", 257 | "# remember to make this a markdown cell" 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "id": "18a4fd51-3734-4e54-bd40-0052ed1d001a", 263 | "metadata": {}, 264 | "source": [ 265 | "**Exercise**: explore the data as you want, plot it, investigate it, have fun with it!" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": null, 271 | "id": "c4d4eba8-896a-4120-a8ef-a4276981a8c2", 272 | "metadata": {}, 273 | "outputs": [], 274 | "source": [ 275 | "# Your code here" 276 | ] 277 | } 278 | ], 279 | "metadata": { 280 | "kernelspec": { 281 | "display_name": "Python 3 (ipykernel)", 282 | "language": "python", 283 | "name": "python3" 284 | }, 285 | "language_info": { 286 | "codemirror_mode": { 287 | "name": "ipython", 288 | "version": 3 289 | }, 290 | "file_extension": ".py", 291 | "mimetype": "text/x-python", 292 | "name": "python", 293 | "nbconvert_exporter": "python", 294 | "pygments_lexer": "ipython3", 295 | "version": "3.10.10" 296 | } 297 | }, 298 | "nbformat": 4, 299 | "nbformat_minor": 5 300 | } 301 | -------------------------------------------------------------------------------- /week02/practice/packed_column_2.csv: -------------------------------------------------------------------------------- 1 | flow type;water flow / air flow;0 kg/h;100 kg/h;200 kg/h;300 kg/h 2 | small;15;0.1;1;1;1 3 | small;30;2;1;1;2 4 | small;50;2;1;2;5 5 | small;80;3;3;5;8 6 | small;100;4;6;8;13 7 | big;40;5;10;14;27 8 | big;50;7;16;21;48 9 | big;60;9;21;31;117 10 | big;70;13;31;47;300 11 | big;80;17;37;93; 12 | -------------------------------------------------------------------------------- /week02/theory/1_dictionaries_and_sets.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f1a4ce39-43b4-4096-9110-87b9f582130d", 6 | "metadata": {}, 7 | "source": [ 8 | "# Dictionaries and Sets" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "416c6905-7ded-4c6e-bfd5-b448a04f6968", 14 | "metadata": {}, 15 | "source": [ 16 | "## Dictionaries" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "89706cd5-444e-48ea-abcc-b81668ed247f", 22 | "metadata": {}, 23 | "source": [ 24 | "Just like the physical dictionaries used to look up the meaning of a word, *dictionaries* in Python are data structures that associate keys to values. In other programming languages, they are also known as hash tables, hash maps or associative arrays.\n", 25 | "\n", 26 | "Dictionaries are ordered in Python 3.7 and higher, in Python 3.6 and lower they are an unordered collection of key:value pairs.\n", 27 | "They are changeable, meaning that a dictionary can be updated, and values can be added, removed and overwritten.\n", 28 | "\n", 29 | "Note: Keys in a dictionary are unique (duplicates are not allowed), this means that the values can be overwritten.\n", 30 | "\n", 31 | "They are written in curly brackets." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 1, 37 | "id": "bf2767e0-78ec-4f75-8486-e19918953c1a", 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "name": "stdout", 42 | "output_type": "stream", 43 | "text": [ 44 | "{'temperature': 30, 'pH': 6.9, 'pressure': 1.0}\n" 45 | ] 46 | } 47 | ], 48 | "source": [ 49 | "dict_conditions = {\n", 50 | " \"temperature\": 30,\n", 51 | " \"pH\": 7.0,\n", 52 | " \"pressure\": 1.0,\n", 53 | " \"pH\": 6.9\n", 54 | "}\n", 55 | "\n", 56 | "print(dict_conditions)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "id": "8cd20e60-d22b-488d-ab3c-38738aeb45a0", 62 | "metadata": {}, 63 | "source": [ 64 | "As you can see, the pH was overwritten!\n", 65 | "\n", 66 | "But you can also have a list of values corresponding to each key." 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 2, 72 | "id": "6ab48b41-81e3-4b49-b989-950702cb199b", 73 | "metadata": {}, 74 | "outputs": [ 75 | { 76 | "name": "stdout", 77 | "output_type": "stream", 78 | "text": [ 79 | "{'temperature': [30, 29, 28], 'pH': [7.0, 6.9, 6.8], 'pressure': [1.0, 1.5, 2.0]}\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "dict_conditions = {\n", 85 | " \"temperature\": [30, 29, 28],\n", 86 | " \"pH\": [7.0, 6.9, 6.8],\n", 87 | " \"pressure\": [1.0, 1.5, 2.0]\n", 88 | "}\n", 89 | "\n", 90 | "print(dict_conditions)" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "id": "940b7663-55cf-4237-8979-fcc35d765b8f", 96 | "metadata": {}, 97 | "source": [ 98 | "Let's see how to extract information from dictionaries below" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 3, 104 | "id": "375c77ff-fc59-4fbe-999e-6c179b2cddb9", 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "name": "stdout", 109 | "output_type": "stream", 110 | "text": [ 111 | "[30, 29, 28]\n", 112 | "[30, 29, 28]\n", 113 | "True\n", 114 | "False\n", 115 | "{'temperature': 30, 'pH': [7.0, 6.9, 6.8], 'pressure': [1.0, 1.5, 2.0]}\n" 116 | ] 117 | } 118 | ], 119 | "source": [ 120 | "# Print the values of temperature\n", 121 | "print(dict_conditions[\"temperature\"])\n", 122 | "# or\n", 123 | "print(dict_conditions.get(\"temperature\"))\n", 124 | "\n", 125 | "# Look if a key is in the dictionary\n", 126 | "print(\"pressure\" in dict_conditions)\n", 127 | "print(\"air pressure\" in dict_conditions)\n", 128 | "\n", 129 | "# Update a certain condition\n", 130 | "dict_conditions[\"temperature\"] = 30\n", 131 | "print(dict_conditions)" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "id": "ff5788f2-0aba-40f8-bf94-7ff6f613ad95", 137 | "metadata": {}, 138 | "source": [ 139 | "Let's now extract all keys, values and items in the dictionary." 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 4, 145 | "id": "31f07c2c-6dec-4b6b-8b81-349229d59c2f", 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "name": "stdout", 150 | "output_type": "stream", 151 | "text": [ 152 | "dict_keys(['temperature', 'pH', 'pressure'])\n", 153 | "dict_values([30, [7.0, 6.9, 6.8], [1.0, 1.5, 2.0]])\n", 154 | "dict_items([('temperature', 30), ('pH', [7.0, 6.9, 6.8]), ('pressure', [1.0, 1.5, 2.0])])\n" 155 | ] 156 | } 157 | ], 158 | "source": [ 159 | "# Extrct the keys\n", 160 | "print(dict_conditions.keys())\n", 161 | "\n", 162 | "# Extrct the values\n", 163 | "print(dict_conditions.values())\n", 164 | "\n", 165 | "# Extrct the items to get the tuple of keys and values\n", 166 | "print(dict_conditions.items())" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "id": "a5bf8d25-aec3-42dc-9d26-e04ea1ce98df", 172 | "metadata": {}, 173 | "source": [ 174 | "### Creating a dictionary" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "id": "fc5038d1-8ea8-4a27-866f-b3f1930f5fa1", 180 | "metadata": {}, 181 | "source": [ 182 | "Dictionaries can be created in many ways. We can manually create a collection of keys and values, as seen above, or we can create them through iteration.\n", 183 | "\n", 184 | "Let's see other ways of creating a dictionary." 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 5, 190 | "id": "8d8b691c-b3d2-4e49-997d-8cd011a2f3f7", 191 | "metadata": {}, 192 | "outputs": [ 193 | { 194 | "name": "stdout", 195 | "output_type": "stream", 196 | "text": [ 197 | "{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}\n" 198 | ] 199 | } 200 | ], 201 | "source": [ 202 | "# Create a dictionary in a loop\n", 203 | "list_numbers = ['zero', 'one', 'two', 'three', 'four', 'five']\n", 204 | "\n", 205 | "my_dictonary = {}\n", 206 | "for key, value in enumerate(list_numbers): #enumerate is a function used to get a counter \n", 207 | " #and the value of an iterable (in our case a list)\n", 208 | " my_dictonary[key] = value\n", 209 | " \n", 210 | "print(my_dictonary)" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "id": "784d6dbd-df5c-4a01-98a5-83ba460a9bfe", 216 | "metadata": {}, 217 | "source": [ 218 | "Or we can do it in a one-liner." 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": 6, 224 | "id": "3bf64c3d-b3e6-4483-9d98-c745776c78a0", 225 | "metadata": {}, 226 | "outputs": [ 227 | { 228 | "name": "stdout", 229 | "output_type": "stream", 230 | "text": [ 231 | "{0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}\n" 232 | ] 233 | } 234 | ], 235 | "source": [ 236 | "my_dictonary = {key:value for key, value in enumerate(list_numbers)}\n", 237 | "print(my_dictonary)" 238 | ] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "id": "071541b2-5f1b-49b3-a25a-271de9e01bcf", 243 | "metadata": {}, 244 | "source": [ 245 | "## Sets" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "id": "8d394b97-62b4-49ce-be17-fb8f9d3021be", 251 | "metadata": {}, 252 | "source": [ 253 | "A *set* is a unique and unordered collection of items.\n", 254 | "The order of the items in a set does not matter.\n", 255 | "\n", 256 | "Items in a set cannot be changed, but they can be removed and new items can be added to the set.\n", 257 | "\n", 258 | "Let's see how to define a set below." 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": 7, 264 | "id": "2dd989d0-4f30-435d-8275-2ca0682e69ad", 265 | "metadata": {}, 266 | "outputs": [ 267 | { 268 | "name": "stdout", 269 | "output_type": "stream", 270 | "text": [ 271 | "{'Ion exchange', 'Crystallization', 'Fluid bed', 'Solid-liquid extraction', 'Bubble column'}\n" 272 | ] 273 | } 274 | ], 275 | "source": [ 276 | "experiments = ['Bubble column', 'Fluid bed', 'Crystallization', 'Ion exchange', \n", 277 | " 'Solid-liquid extraction', 'Crystallization']\n", 278 | "\n", 279 | "set_experiments = set(experiments)\n", 280 | "print(set_experiments)" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "id": "06120de3-ed06-4dbb-a26e-ad7f53bd0d9a", 286 | "metadata": {}, 287 | "source": [ 288 | "But remember that items in a set cannot be indexed!" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": 8, 294 | "id": "3c928f8e-7068-49d4-ad55-5ab4eb49f5c8", 295 | "metadata": {}, 296 | "outputs": [ 297 | { 298 | "ename": "TypeError", 299 | "evalue": "'set' object is not subscriptable", 300 | "output_type": "error", 301 | "traceback": [ 302 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 303 | "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", 304 | "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_18812/2900422087.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mset_experiments\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 305 | "\u001b[1;31mTypeError\u001b[0m: 'set' object is not subscriptable" 306 | ] 307 | } 308 | ], 309 | "source": [ 310 | "print(set_experiments[0])" 311 | ] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "id": "d12fe0ac-666d-4226-a7ad-0b7739d10ed9", 316 | "metadata": {}, 317 | "source": [ 318 | "### Sets operations\n", 319 | "\n", 320 | "Sets allow different operations, like intersection, union and difference between two collections." 321 | ] 322 | }, 323 | { 324 | "cell_type": "markdown", 325 | "id": "d75cecb4-ae49-4c34-b41f-07d1a06a15c2", 326 | "metadata": {}, 327 | "source": [ 328 | "" 329 | ] 330 | }, 331 | { 332 | "cell_type": "code", 333 | "execution_count": 9, 334 | "id": "c1c14f49-35eb-41e7-aa6e-599e298192e9", 335 | "metadata": {}, 336 | "outputs": [ 337 | { 338 | "name": "stdout", 339 | "output_type": "stream", 340 | "text": [ 341 | "{18, 12, 6}\n", 342 | "{2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 27, 30}\n", 343 | "{3, 9, 15, 21, 24, 27, 30}\n", 344 | "True\n" 345 | ] 346 | } 347 | ], 348 | "source": [ 349 | "multiples_three = {3, 6, 9, 12, 15, 18, 21, 24, 27, 30}\n", 350 | "even_numbers = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}\n", 351 | "\n", 352 | "# Intersection\n", 353 | "intersection = set(multiples_three & even_numbers) # or multiples_three.intersection(even_numbers)\n", 354 | "print(intersection)\n", 355 | "\n", 356 | "# Union\n", 357 | "union = set(multiples_three | even_numbers) # or multiples_three.union(even_numbers)\n", 358 | "print(union)\n", 359 | "\n", 360 | "# A-B: note that B-A will lead to a different result\n", 361 | "difference = multiples_three - even_numbers\n", 362 | "print(difference)\n", 363 | "\n", 364 | "# Subsets contained in a set (if all elements in 'multiples_three' are in 'union'\n", 365 | "subset = multiples_three.issubset(union)\n", 366 | "print(subset)" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "id": "a1ad2c50-3d71-4184-ad70-6e0c04e6fa47", 372 | "metadata": {}, 373 | "source": [ 374 | "Let's now try to remove elements" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": 10, 380 | "id": "d1b7779d-1707-433f-b817-b115ddbabd76", 381 | "metadata": {}, 382 | "outputs": [ 383 | { 384 | "name": "stdout", 385 | "output_type": "stream", 386 | "text": [ 387 | "{3, 9, 15, 21, 24, 27, 30}\n" 388 | ] 389 | }, 390 | { 391 | "data": { 392 | "text/plain": [ 393 | "{9, 15, 21, 24, 27, 30}" 394 | ] 395 | }, 396 | "execution_count": 10, 397 | "metadata": {}, 398 | "output_type": "execute_result" 399 | } 400 | ], 401 | "source": [ 402 | "print(difference)\n", 403 | "difference.remove(3)\n", 404 | "difference" 405 | ] 406 | }, 407 | { 408 | "cell_type": "code", 409 | "execution_count": 11, 410 | "id": "9444a640-3076-4775-9804-b8274190aacb", 411 | "metadata": {}, 412 | "outputs": [ 413 | { 414 | "data": { 415 | "text/plain": [ 416 | "9" 417 | ] 418 | }, 419 | "execution_count": 11, 420 | "metadata": {}, 421 | "output_type": "execute_result" 422 | } 423 | ], 424 | "source": [ 425 | "difference.pop()" 426 | ] 427 | } 428 | ], 429 | "metadata": { 430 | "kernelspec": { 431 | "display_name": "Python 3 (ipykernel)", 432 | "language": "python", 433 | "name": "python3" 434 | }, 435 | "language_info": { 436 | "codemirror_mode": { 437 | "name": "ipython", 438 | "version": 3 439 | }, 440 | "file_extension": ".py", 441 | "mimetype": "text/x-python", 442 | "name": "python", 443 | "nbconvert_exporter": "python", 444 | "pygments_lexer": "ipython3", 445 | "version": "3.9.7" 446 | } 447 | }, 448 | "nbformat": 4, 449 | "nbformat_minor": 5 450 | } 451 | -------------------------------------------------------------------------------- /week02/theory/3_numpy_arrays.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "8fdcfb01-e741-4248-b214-9b66050351b4", 6 | "metadata": {}, 7 | "source": [ 8 | "# Numpy arrays" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "42e9ae57-e294-494c-9b03-39b7264643ce", 14 | "metadata": {}, 15 | "source": [ 16 | "Another very popular library is [NumPy](https://numpy.org/), which allows users to work with vectors and matrices and perform mathematical operations with them.\n", 17 | "It offers comprehensive mathematical functions, random number generations, data distributions and more.\n", 18 | "\n", 19 | "For more information on what is an array and why NumPy is so widely used, read [here](https://numpy.org/doc/stable/user/absolute_beginners.html)." 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "id": "ae95f2f4-afd0-46ea-a7ed-fcfd50cc6406", 25 | "metadata": {}, 26 | "source": [ 27 | "### Create a NumPy array\n", 28 | "Let's now try to see how to create arrays!" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 1, 34 | "id": "0d473ebc-bbde-4f6e-9605-aee13a127683", 35 | "metadata": {}, 36 | "outputs": [ 37 | { 38 | "data": { 39 | "text/plain": [ 40 | "array([ 3.14159265, 6.28318531, 12.56637061])" 41 | ] 42 | }, 43 | "execution_count": 1, 44 | "metadata": {}, 45 | "output_type": "execute_result" 46 | } 47 | ], 48 | "source": [ 49 | "import numpy as np\n", 50 | "from math import pi\n", 51 | "\n", 52 | "# create a one-dimensional array\n", 53 | "array_1d = np.array([pi, pi*2, pi*4])\n", 54 | "array_1d" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "id": "9e12bb6e-8e74-4ed5-9957-c8c34323c2ef", 60 | "metadata": {}, 61 | "source": [ 62 | "Investigate the array" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 2, 68 | "id": "f229b4fb-46d8-452d-bf16-b75c288e2223", 69 | "metadata": {}, 70 | "outputs": [ 71 | { 72 | "data": { 73 | "text/plain": [ 74 | "3" 75 | ] 76 | }, 77 | "execution_count": 2, 78 | "metadata": {}, 79 | "output_type": "execute_result" 80 | } 81 | ], 82 | "source": [ 83 | "# creck the size of the array\n", 84 | "array_1d.size" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": 3, 90 | "id": "17551e56-5dbf-40fe-807d-ba62f8e542f3", 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "(3,)" 97 | ] 98 | }, 99 | "execution_count": 3, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "# creck the shape of the array\n", 106 | "array_1d.shape" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 4, 112 | "id": "1e9d154f-0b86-437f-8782-79015666cdd9", 113 | "metadata": {}, 114 | "outputs": [ 115 | { 116 | "data": { 117 | "text/plain": [ 118 | "1" 119 | ] 120 | }, 121 | "execution_count": 4, 122 | "metadata": {}, 123 | "output_type": "execute_result" 124 | } 125 | ], 126 | "source": [ 127 | "# creck the dimension of the array\n", 128 | "array_1d.ndim" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 5, 134 | "id": "a22449fd-0cca-4d52-a662-5ae3f805d4e1", 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "data": { 139 | "text/plain": [ 140 | "dtype('float64')" 141 | ] 142 | }, 143 | "execution_count": 5, 144 | "metadata": {}, 145 | "output_type": "execute_result" 146 | } 147 | ], 148 | "source": [ 149 | "# creck the type of the array\n", 150 | "array_1d.dtype" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 6, 156 | "id": "84f5d908-6f9b-42f5-b762-d4118ce1f2e7", 157 | "metadata": {}, 158 | "outputs": [ 159 | { 160 | "data": { 161 | "text/plain": [ 162 | "array([[ 3.14159265, 6.28318531, 12.56637061],\n", 163 | " [ 5.9 , 7. , 3. ],\n", 164 | " [ 4.39822972, 0.62831853, 20.10619298]])" 165 | ] 166 | }, 167 | "execution_count": 6, 168 | "metadata": {}, 169 | "output_type": "execute_result" 170 | } 171 | ], 172 | "source": [ 173 | "# create a one-dimensional array\n", 174 | "array_2d = np.array([[pi, pi*2, pi*4], [5.9, 7.0, 3], [pi*1.4, pi*0.2, pi*6.4]])\n", 175 | "array_2d" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 7, 181 | "id": "7ea6af20-9b94-44aa-9396-36f8d8c4a3ce", 182 | "metadata": {}, 183 | "outputs": [ 184 | { 185 | "name": "stdout", 186 | "output_type": "stream", 187 | "text": [ 188 | "Size of the array: 9\n", 189 | "Shape of the array: (3, 3)\n", 190 | "Dimensionality of the array: 2\n", 191 | "Type of the array: float64\n" 192 | ] 193 | } 194 | ], 195 | "source": [ 196 | "print('Size of the array: ', array_2d.size)\n", 197 | "print('Shape of the array: ', array_2d.shape)\n", 198 | "print('Dimensionality of the array: ', array_2d.ndim)\n", 199 | "print('Type of the array: ', array_2d.dtype)" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "id": "cc10263c-903c-4761-a027-b29b62b37ded", 205 | "metadata": {}, 206 | "source": [ 207 | "### Create an array according to a distribution" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": 8, 213 | "id": "78428db4-84e4-4ac0-b71c-3cbba9ec62dd", 214 | "metadata": {}, 215 | "outputs": [ 216 | { 217 | "data": { 218 | "text/plain": [ 219 | "array([1.74908024, 2.90142861, 2.46398788, 2.19731697, 1.31203728,\n", 220 | " 1.31198904, 1.11616722, 2.73235229, 2.20223002, 2.41614516,\n", 221 | " 1.04116899, 2.9398197 , 2.66488528, 1.42467822, 1.36364993,\n", 222 | " 1.36680902, 1.60848449, 2.04951286, 1.86389004, 1.58245828,\n", 223 | " 2.22370579, 1.27898772, 1.5842893 , 1.73272369, 1.91213997,\n", 224 | " 2.57035192, 1.39934756, 2.02846888, 2.18482914, 1.09290083,\n", 225 | " 2.2150897 , 1.34104825, 1.13010319, 2.89777107, 2.93126407,\n", 226 | " 2.6167947 , 1.60922754, 1.19534423, 2.36846605, 1.88030499,\n", 227 | " 1.24407647, 1.99035382, 1.06877704, 2.8186408 , 1.51755996,\n", 228 | " 2.32504457, 1.62342215, 2.04013604, 2.09342056, 1.36970891,\n", 229 | " 2.93916926, 2.55026565, 2.87899788, 2.7896547 , 2.19579996,\n", 230 | " 2.84374847, 1.176985 , 1.39196572, 1.09045458, 1.65066066,\n", 231 | " 1.77735458, 1.54269806, 2.65747502, 1.71350665, 1.56186902,\n", 232 | " 2.08539217, 1.28184845, 2.60439396, 1.14910129, 2.97377387,\n", 233 | " 2.54448954, 1.39743136, 1.01104423, 2.63092286, 2.41371469,\n", 234 | " 2.45801434, 2.54254069, 1.1480893 , 1.71693146, 1.23173812,\n", 235 | " 2.72620685, 2.24659625, 1.66179605, 1.1271167 , 1.62196464,\n", 236 | " 1.65036664, 2.45921236, 2.27511494, 2.77442549, 1.94442985,\n", 237 | " 1.23918849, 2.42648957, 2.5215701 , 2.1225544 , 2.54193436,\n", 238 | " 1.98759119, 2.04546566, 1.85508204, 1.05083825, 1.21578285,\n", 239 | " 1.06285837, 2.27282082, 1.62871196, 2.01714138, 2.81513295,\n", 240 | " 1.49858446, 1.82076585, 2.51110228, 1.45759633, 1.15395982,\n", 241 | " 1.57950291, 1.32244257, 2.8593953 , 2.61624076, 2.26680751,\n", 242 | " 2.74292118, 2.60734415, 1.37314012, 2.785118 , 2.07868448,\n", 243 | " 2.61488031, 2.7921826 , 1.63600695, 1.22010385, 1.45587033,\n", 244 | " 1.85421558, 2.63602953, 2.72146117, 1.01390426, 2.02149461,\n", 245 | " 1.83482201, 1.44421562, 1.23973073, 1.67523034, 2.88581941,\n", 246 | " 1.64640586, 2.03758124, 2.40603792, 1.7272592 , 2.94356417,\n", 247 | " 2.92489459, 1.50356459, 1.99449701, 1.60175662, 1.56968099,\n", 248 | " 1.07377389, 2.21912867, 2.00535805, 1.1029575 , 1.55729293,\n", 249 | " 2.81653177, 1.47912378, 1.28978974, 1.97890552, 2.97130091,\n", 250 | " 1.48411054, 2.34427109, 2.52323923, 1.47527509, 2.4564327 ,\n", 251 | " 1.73556627, 2.26461166, 2.26705942, 2.07154937, 1.18057954,\n", 252 | " 2.67060499, 1.64156013, 1.37303702, 1.08155028, 2.18178589,\n", 253 | " 2.35512872, 1.03317566, 2.02418612, 1.45299155, 2.29034558,\n", 254 | " 1.34873286, 2.38187548, 1.77347069, 2.87345998, 1.27504189,\n", 255 | " 1.6821327 , 1.22694704, 2.84938724, 2.75467871, 1.51588326,\n", 256 | " 2.31996809, 2.6344444 , 2.11040162, 2.05930116, 1.48370458,\n", 257 | " 1.18620554, 2.79443152, 2.80083611, 2.26620291, 1.67805958,\n", 258 | " 1.69841915, 2.45191136, 2.79422052, 2.77417285, 2.55975109])" 259 | ] 260 | }, 261 | "execution_count": 8, 262 | "metadata": {}, 263 | "output_type": "execute_result" 264 | } 265 | ], 266 | "source": [ 267 | "np.random.seed(42) # fix random seed to get the same set of values every time\n", 268 | "uniform = np.random.uniform(1, 3, 200) # arguments are the lower boundary, upper boundary, output shape\n", 269 | "uniform" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": 9, 275 | "id": "4becf82b-bf63-4ac4-838c-0e9423143eaf", 276 | "metadata": {}, 277 | "outputs": [ 278 | { 279 | "data": { 280 | "image/png": "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\n", 281 | "text/plain": [ 282 | "
" 283 | ] 284 | }, 285 | "metadata": { 286 | "needs_background": "light" 287 | }, 288 | "output_type": "display_data" 289 | } 290 | ], 291 | "source": [ 292 | "%matplotlib inline\n", 293 | "import matplotlib.pyplot as plt\n", 294 | "\n", 295 | "plt.hist(uniform, bins=50)\n", 296 | "plt.show()" 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": 10, 302 | "id": "de9b8c81-5c30-4986-b23b-6bb2d10f9491", 303 | "metadata": {}, 304 | "outputs": [], 305 | "source": [ 306 | "# create a normal distribution\n", 307 | "normal = np.random.normal(1, 3, 200) # arguments are the lower boundary, upper boundary, output shape" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 11, 313 | "id": "d77aa616-a5f4-4e9c-9a92-6a9b84664933", 314 | "metadata": {}, 315 | "outputs": [ 316 | { 317 | "data": { 318 | "image/png": "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\n", 319 | "text/plain": [ 320 | "
" 321 | ] 322 | }, 323 | "metadata": { 324 | "needs_background": "light" 325 | }, 326 | "output_type": "display_data" 327 | } 328 | ], 329 | "source": [ 330 | "plt.hist(normal, bins=50)\n", 331 | "plt.show()" 332 | ] 333 | }, 334 | { 335 | "cell_type": "markdown", 336 | "id": "6fd060e5-d477-4651-b79a-9e9c88c85f22", 337 | "metadata": {}, 338 | "source": [ 339 | "### Operations" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": 12, 345 | "id": "bf8fc55e-6fd6-40e8-8de6-2a5815ee32d7", 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [ 349 | "uniform = np.random.uniform(0, 1, 20)\n", 350 | "normal = np.random.normal(0, 1, 20)" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": 13, 356 | "id": "05483f45-0529-4dcf-b2af-851fe5db39ce", 357 | "metadata": {}, 358 | "outputs": [ 359 | { 360 | "name": "stdout", 361 | "output_type": "stream", 362 | "text": [ 363 | "[ 0.64831449 0.91894679 0.20887358 -0.28038468 0.03586382 0.96665893\n", 364 | " 1.50744688 1.07808874 2.2707087 -0.11813726 1.61836552 0.76671077\n", 365 | " 3.15197548 -0.43342771 -0.55400976 0.26920648 -1.90029989 0.43746752\n", 366 | " -0.74697819 1.12027261]\n" 367 | ] 368 | } 369 | ], 370 | "source": [ 371 | "# sum\n", 372 | "print(uniform + normal)" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": 14, 378 | "id": "f7b7597a-6395-4c4e-91d8-559711edb48b", 379 | "metadata": {}, 380 | "outputs": [ 381 | { 382 | "name": "stdout", 383 | "output_type": "stream", 384 | "text": [ 385 | "[ 9.50649629e-02 1.14131777e-02 1.08613362e-02 -3.80804025e-01\n", 386 | " 2.78279812e-04 2.33392199e-01 8.17041386e-02 1.13978561e-01\n", 387 | " 2.53055453e-01 -4.98169943e-01 6.50790344e-01 1.06955999e-01\n", 388 | " 2.10696827e+00 -3.03007247e-01 -2.39918679e-01 -5.20631929e-01\n", 389 | " -4.74894245e-01 -5.06419087e-01 -9.22685872e-03 1.45863749e-01]\n" 390 | ] 391 | } 392 | ], 393 | "source": [ 394 | "# product\n", 395 | "print(uniform * normal)" 396 | ] 397 | }, 398 | { 399 | "cell_type": "code", 400 | "execution_count": 15, 401 | "id": "78c6b576-d4d9-467b-a92f-4b4d6b30012f", 402 | "metadata": {}, 403 | "outputs": [ 404 | { 405 | "name": "stdout", 406 | "output_type": "stream", 407 | "text": [ 408 | "[ 0.20012953 0.89376198 0.01352138 1.26563489 -0.01315653 -0.02933765\n", 409 | " -1.39484033 -0.84045291 -2.03565621 1.41655787 -0.12627576 0.40002676\n", 410 | " -1.22763038 1.18316886 1.12543393 1.46799177 2.34749156 1.48897756\n", 411 | " 0.77128714 0.81948504]\n" 412 | ] 413 | } 414 | ], 415 | "source": [ 416 | "# difference\n", 417 | "print(uniform - normal)" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": 16, 423 | "id": "246ff948-5fab-48df-bda6-2e055f106078", 424 | "metadata": {}, 425 | "outputs": [ 426 | { 427 | "name": "stdout", 428 | "output_type": "stream", 429 | "text": [ 430 | "[ 1.89306667e+00 7.19762975e+01 1.13843083e+00 -6.37281849e-01\n", 431 | " 4.63221707e-01 9.41088856e-01 3.87992445e-02 1.23862743e-01\n", 432 | " 5.45825768e-02 -8.46044652e-01 8.55241580e-01 3.18186093e+00\n", 433 | " 4.39387734e-01 -4.63777527e-01 -3.40246105e-01 -1.44913211e+00\n", 434 | " -1.05276279e-01 -1.83207483e+00 -1.60110022e-02 6.44892884e+00]\n" 435 | ] 436 | } 437 | ], 438 | "source": [ 439 | "# ratio\n", 440 | "print(uniform / normal)" 441 | ] 442 | }, 443 | { 444 | "cell_type": "code", 445 | "execution_count": 17, 446 | "id": "09ab2d86-4b20-455b-8a74-277511a371e5", 447 | "metadata": {}, 448 | "outputs": [ 449 | { 450 | "name": "stdout", 451 | "output_type": "stream", 452 | "text": [ 453 | "0.8772544542002486\n" 454 | ] 455 | } 456 | ], 457 | "source": [ 458 | "# inner product of vectors\n", 459 | "print(np.dot(uniform, normal))" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": 18, 465 | "id": "d5374224-96e1-476d-815a-f868144f61b1", 466 | "metadata": {}, 467 | "outputs": [ 468 | { 469 | "data": { 470 | "text/plain": [ 471 | "array([[68, 31],\n", 472 | " [71, 28]])" 473 | ] 474 | }, 475 | "execution_count": 18, 476 | "metadata": {}, 477 | "output_type": "execute_result" 478 | } 479 | ], 480 | "source": [ 481 | "# matrix multiplication\n", 482 | "matrix_1 = np.array([[3, 8], [2, 9]])\n", 483 | "matrix_2 = np.array([[4, 5], [7, 2]])\n", 484 | "np.dot(matrix_1, matrix_2)" 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": 19, 490 | "id": "5112d056-2fea-4311-a6d1-7edc8dcd79de", 491 | "metadata": {}, 492 | "outputs": [ 493 | { 494 | "name": "stdout", 495 | "output_type": "stream", 496 | "text": [ 497 | "[[3 8]\n", 498 | " [2 9]]\n", 499 | "Summing over rows [ 5 17]\n", 500 | "Summing over columns [11 11]\n" 501 | ] 502 | } 503 | ], 504 | "source": [ 505 | "# More on the sum\n", 506 | "print(matrix_1)\n", 507 | "print('Summing over rows', np.sum(matrix_1, axis=0))\n", 508 | "print('Summing over columns', np.sum(matrix_1, axis=1))" 509 | ] 510 | }, 511 | { 512 | "cell_type": "code", 513 | "execution_count": 20, 514 | "id": "bf34f658-298c-4a71-b016-a729ce814aca", 515 | "metadata": {}, 516 | "outputs": [ 517 | { 518 | "data": { 519 | "text/plain": [ 520 | "array([[1.73205081, 2.82842712],\n", 521 | " [1.41421356, 3. ]])" 522 | ] 523 | }, 524 | "execution_count": 20, 525 | "metadata": {}, 526 | "output_type": "execute_result" 527 | } 528 | ], 529 | "source": [ 530 | "# square root \n", 531 | "np.sqrt(matrix_1)" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": 21, 537 | "id": "5d63a000-b023-473e-b25b-49e776233932", 538 | "metadata": {}, 539 | "outputs": [ 540 | { 541 | "data": { 542 | "text/plain": [ 543 | "array([[2.00855369e+01, 2.98095799e+03],\n", 544 | " [7.38905610e+00, 8.10308393e+03]])" 545 | ] 546 | }, 547 | "execution_count": 21, 548 | "metadata": {}, 549 | "output_type": "execute_result" 550 | } 551 | ], 552 | "source": [ 553 | "# exponential\n", 554 | "np.exp(matrix_1)" 555 | ] 556 | }, 557 | { 558 | "cell_type": "code", 559 | "execution_count": 22, 560 | "id": "b2744ae8-e471-4dd6-8bbf-2abaac6ff89c", 561 | "metadata": {}, 562 | "outputs": [ 563 | { 564 | "data": { 565 | "text/plain": [ 566 | "array([[ 9, 64],\n", 567 | " [ 4, 81]])" 568 | ] 569 | }, 570 | "execution_count": 22, 571 | "metadata": {}, 572 | "output_type": "execute_result" 573 | } 574 | ], 575 | "source": [ 576 | "# matrix to the power of 2\n", 577 | "matrix_1**2" 578 | ] 579 | }, 580 | { 581 | "cell_type": "code", 582 | "execution_count": 23, 583 | "id": "2898f8d0-50ee-4dac-9d6a-4b85b36b60fd", 584 | "metadata": {}, 585 | "outputs": [ 586 | { 587 | "name": "stdout", 588 | "output_type": "stream", 589 | "text": [ 590 | "[[3 8]\n", 591 | " [2 9]]\n" 592 | ] 593 | }, 594 | { 595 | "data": { 596 | "text/plain": [ 597 | "array([3, 8, 2, 9])" 598 | ] 599 | }, 600 | "execution_count": 23, 601 | "metadata": {}, 602 | "output_type": "execute_result" 603 | } 604 | ], 605 | "source": [ 606 | "# flatten array\n", 607 | "print(matrix_1)\n", 608 | "matrix_1.flatten()" 609 | ] 610 | }, 611 | { 612 | "cell_type": "code", 613 | "execution_count": 24, 614 | "id": "79d7cc1a-2b5a-4c4e-94e7-d59e9f589be0", 615 | "metadata": {}, 616 | "outputs": [ 617 | { 618 | "data": { 619 | "text/plain": [ 620 | "3" 621 | ] 622 | }, 623 | "execution_count": 24, 624 | "metadata": {}, 625 | "output_type": "execute_result" 626 | } 627 | ], 628 | "source": [ 629 | "# indexing a matrix\n", 630 | "matrix_1[0, 0]" 631 | ] 632 | }, 633 | { 634 | "cell_type": "code", 635 | "execution_count": 25, 636 | "id": "31ad072d-7568-47ea-9a33-971eebb1770a", 637 | "metadata": {}, 638 | "outputs": [ 639 | { 640 | "data": { 641 | "text/plain": [ 642 | "array([[3, 2],\n", 643 | " [8, 9]])" 644 | ] 645 | }, 646 | "execution_count": 25, 647 | "metadata": {}, 648 | "output_type": "execute_result" 649 | } 650 | ], 651 | "source": [ 652 | "# transposing a matrix\n", 653 | "matrix_1.T" 654 | ] 655 | } 656 | ], 657 | "metadata": { 658 | "kernelspec": { 659 | "display_name": "Python 3 (ipykernel)", 660 | "language": "python", 661 | "name": "python3" 662 | }, 663 | "language_info": { 664 | "codemirror_mode": { 665 | "name": "ipython", 666 | "version": 3 667 | }, 668 | "file_extension": ".py", 669 | "mimetype": "text/x-python", 670 | "name": "python", 671 | "nbconvert_exporter": "python", 672 | "pygments_lexer": "ipython3", 673 | "version": "3.9.7" 674 | } 675 | }, 676 | "nbformat": 4, 677 | "nbformat_minor": 5 678 | } 679 | -------------------------------------------------------------------------------- /week02/theory/packed_column.csv: -------------------------------------------------------------------------------- 1 | flow type;water flow / air flow;0 kg/h;100 kg/h;200 kg/h;300 kg/h 2 | small;15;1;2;3;3 3 | small;30;2;2;5;3 4 | small;50;2;3;6;5 5 | small;80;3;4;9;9 6 | small;100;3;5;13;13 7 | big;40;5;9;14;25 8 | big;50;7;14;22;39 9 | big;60;10;19;32;161 10 | big;70;13;27;46;224 11 | big;80;15;34;57;0 12 | -------------------------------------------------------------------------------- /week02/theory/sets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/f37542b41215bc162a766559f25f32e2a245bbea/week02/theory/sets.png -------------------------------------------------------------------------------- /week03/practice/additional_exercises_previous_weeks.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "a484f318-2fa1-4057-8989-3e75607b338d", 6 | "metadata": {}, 7 | "source": [ 8 | "## Here are some additional exercises to proactice for loops and if statements." 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "af1d6265-c0d0-4c69-b903-fea9d0d1e6e7", 14 | "metadata": {}, 15 | "source": [ 16 | "### For loops" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "id": "9abc3a7f-f67f-4a6b-afb9-a58f7e81ca73", 22 | "metadata": {}, 23 | "source": [ 24 | "**Exercise**: Create a for loop that loops through every number in the range [0, 20) and multiplies that by pi. Plot the values using `matplotlib`.\n", 25 | "\n", 26 | "Level: Easy." 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "id": "0e460abd-3f12-4ac2-a439-813862943c39", 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "# your code here" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "id": "6faf4da6-1f2b-4e9c-80ce-b5be767f52e1", 42 | "metadata": {}, 43 | "source": [ 44 | "**Exercise**: Create a dictionary through a list comprehension, where the keys are the indices of the elements in list_temperatures, the values the actual elements in the list. \n", 45 | "Plot the values using `matplotlib`.\n", 46 | "\n", 47 | "Level: Easy." 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "id": "2be6dd3b-c6dc-4b92-af31-ebe432fc139a", 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "list_temperatures = [20, 25, 30, 35, 40]\n", 58 | "\n", 59 | "# your code here" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "id": "32e178f9-039e-4f57-9eeb-00578be5d277", 65 | "metadata": {}, 66 | "source": [ 67 | "**Exercise**: Below you are given a list of lists. Loop through the list and print each element (hint, each element is a list), then loop through each of these elements (lists) and print each element.\n", 68 | "\n", 69 | "Level: Easy." 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "id": "b0783be8-d209-41fc-9884-3db98898a06b", 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "subjects = [[\"chemical reaction engineering\", \"process control\"], \n", 80 | " [\"uncertainty\", \"good manufacturing practice\"]]\n", 81 | "\n", 82 | "# your code here" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "id": "64fd167d-9c8f-42be-96ef-07ef3e595363", 88 | "metadata": {}, 89 | "source": [ 90 | "### If statements" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "id": "c5682b73-6889-4cc3-96bb-2e230088797c", 96 | "metadata": {}, 97 | "source": [ 98 | "**Exercise**: Create an if clause with the following conditions:\n", 99 | "- If variable **a** is equal to 0, variable **b** is equal to 1;\n", 100 | "- If variable **a** is between 1 and 10, variable **b** is equal to 50;\n", 101 | "- If variable **a** is bigger than 10, variable **b** is equal to 100;\n", 102 | "- Otherwise, variable b is equal to 0.\n", 103 | "\n", 104 | "Level: Easy." 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "id": "ebc0b771-db17-4e26-8f09-fd274ef96ea2", 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "# your code here" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "id": "374cf422-839e-4f63-8e6e-8459eb7c0547", 120 | "metadata": {}, 121 | "source": [ 122 | "**Exercise**: Create a nested if statement, where you have at least three condition for each level.\n", 123 | "\n", 124 | "Level: Medium." 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "id": "382ed31e-c823-4a14-bccf-5f459f211def", 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [ 134 | "# your code here" 135 | ] 136 | } 137 | ], 138 | "metadata": { 139 | "kernelspec": { 140 | "display_name": "Python 3 (ipykernel)", 141 | "language": "python", 142 | "name": "python3" 143 | }, 144 | "language_info": { 145 | "codemirror_mode": { 146 | "name": "ipython", 147 | "version": 3 148 | }, 149 | "file_extension": ".py", 150 | "mimetype": "text/x-python", 151 | "name": "python", 152 | "nbconvert_exporter": "python", 153 | "pygments_lexer": "ipython3", 154 | "version": "3.8.10" 155 | } 156 | }, 157 | "nbformat": 4, 158 | "nbformat_minor": 5 159 | } 160 | -------------------------------------------------------------------------------- /week03/practice/week03_exercise_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "eb7ad2bd-ac91-45a3-ae1a-1d06841efe70", 6 | "metadata": {}, 7 | "source": [ 8 | "# Operations with SciPy" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "4990aa38-96f3-4fbd-a398-7d9d2ab7d596", 14 | "metadata": {}, 15 | "source": [ 16 | "**Exercise**: Compare NumPy and SciPy on different operations, such as exponential functions and similar (choose at least 3).\n", 17 | "\n", 18 | "Level: Easy." 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "id": "56a424b1-489f-4d25-9075-34401604d43d", 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "# Your code here" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "id": "68068e1d-a091-4d80-a567-2d9b86cabbb5", 34 | "metadata": {}, 35 | "source": [ 36 | "**Exercise**: Can you find a way to print how long did it take for the two libraries to solve the same task? *Hint*: there are different libraries that you can use, try to search for \"time execution in Python\".\n", 37 | "\n", 38 | "Level: Easy." 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "id": "0c083440-d7b2-4624-963d-9f42e56303cf", 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "# Your code here" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "id": "ef06d89b-f363-4cc9-8928-3d64e247f45e", 54 | "metadata": {}, 55 | "source": [ 56 | "**Exercise**: Let's have some fun solving equations! Write an equation and give it to one of your peers to solve.\n", 57 | "\n", 58 | "Level: Easy." 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "id": "4e6b5b3f-ac13-463d-a36c-297228548042", 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# Your code here" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "id": "9815e69f-abe6-4637-aebe-df38680add86", 74 | "metadata": {}, 75 | "source": [ 76 | "**Exercise**: Now solve the same equation yourself.\n", 77 | "\n", 78 | "Level: Easy." 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "id": "ab95a603-17f7-4ad7-b0a8-b46db416f6b1", 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [ 88 | "# Your code here" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "id": "f610d609-ba62-4507-a62f-16dc97c8e04b", 94 | "metadata": {}, 95 | "source": [ 96 | "**Exercise**: How did it go? Were they able to solve it? Did you notice any difference between the code? Reflect on it.\n", 97 | "\n", 98 | "Level: Easy." 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "id": "626e5b39-c8e1-4010-b7ed-f00b1d306eb3", 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "# Your code here" 109 | ] 110 | } 111 | ], 112 | "metadata": { 113 | "kernelspec": { 114 | "display_name": "Python 3 (ipykernel)", 115 | "language": "python", 116 | "name": "python3" 117 | }, 118 | "language_info": { 119 | "codemirror_mode": { 120 | "name": "ipython", 121 | "version": 3 122 | }, 123 | "file_extension": ".py", 124 | "mimetype": "text/x-python", 125 | "name": "python", 126 | "nbconvert_exporter": "python", 127 | "pygments_lexer": "ipython3", 128 | "version": "3.8.10" 129 | } 130 | }, 131 | "nbformat": 4, 132 | "nbformat_minor": 5 133 | } 134 | -------------------------------------------------------------------------------- /week04/practice/assignment_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "402dcf15-9b0f-4ad7-9a2c-389cfb30ee4b", 6 | "metadata": {}, 7 | "source": [ 8 | "# Chemical Reaction Engineering - Assignment 1" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "1c5dec20-84bc-4e95-92d2-8f7215005806", 14 | "metadata": { 15 | "jp-MarkdownHeadingCollapsed": true, 16 | "tags": [] 17 | }, 18 | "source": [ 19 | "## Instructions \n", 20 | "\n", 21 | "Please use Python to solve the exercises below. \n", 22 | "\n", 23 | "You should hand in a Jupyter Notebook with your answers.\n", 24 | "When handing in, you are welcome to submit additional material you may have used, such as a scan of the paper to solve parts of the equations, Word and PDF documents and similar.\n", 25 | "\n", 26 | "The exercises sum up to a total of 12 points, but you only need **10 points** to get top marks.\n", 27 | "\n", 28 | "You will also get partial points for trying to solve the different exercises." 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "id": "2ce87203-6ab7-4d20-9f23-b9db25d79dd0", 34 | "metadata": {}, 35 | "source": [ 36 | "## Assignment 1" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "id": "c8acebd2-423e-4ec7-801a-6040394e2f9b", 42 | "metadata": {}, 43 | "source": [ 44 | "In your company, you need to evaluate the composition of the feed stream (containing only A and B) of an isothermal gas-phase reaction expressed as:\n", 45 | "\n", 46 | "$A+\\frac{1}{12}B→\\frac{1}{6}C+\\frac{1}{2}D$\n", 47 | "\n", 48 | "1. First, set up the stoichiometric table for the reaction for a flow reactor with constant pressure **(2 points)**. Afterward, write the concentrations of A, B, C and D as function of the conversion X **(1 point)**.\n" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "id": "d52dd8f0-acad-4669-a27f-501d13053a2a", 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "# Set up the stoichiometric table for the reaction for a flow reactor with constant pressure\n", 59 | "\n", 60 | "# Your code here" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "id": "ff0bfade-b70a-4a69-8dd2-8b56387f3047", 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "# Write the concentrations of A, B, C and D as function of the conversion X \n", 71 | "\n", 72 | "# Your code here" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "id": "153a67c6-e0c3-4225-b844-65f6d4262290", 78 | "metadata": {}, 79 | "source": [ 80 | "During a laboratory experiment, you measure in a batch reactor with constant volume:\n", 81 | " \n", 82 | "| $$ Time (h) $$| $$ Cc (mol \\cdot m^{-3}) $$ |\n", 83 | "| :------- | :------------------------- |\n", 84 | "| 0 | 0 |\n", 85 | "|2|2,5|\n", 86 | "|4|3,13|\n", 87 | "|6|3,41|\n", 88 | "|8|3,57|\n", 89 | "|10|3,68|\n", 90 | "|12|3,75|\n", 91 | "|14|3,81|\n", 92 | "|16|3,85|\n", 93 | "|18|3,88|\n", 94 | "|20|3,91|\n", 95 | "\n", 96 | "2. First of all, create a `pandas dataframe` of the data in the table below **(0,2 points)**." 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": null, 102 | "id": "d161dc33-7ec2-4001-8292-25777c9b75f2", 103 | "metadata": {}, 104 | "outputs": [], 105 | "source": [ 106 | "# Create pandas dataframe\n", 107 | "\n", 108 | "# Your code here\n", 109 | "df = pd.DataFrame()\n", 110 | "df['Time'] = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]\n", 111 | "df['Cc'] = [0, 2.5, 3.13, 3.41, 3.57, 3.68, 3.75, 3.81, 3.85, 3.88, 3.91]\n", 112 | "df['Ca'] = [c*2 for c in df['Cc']]" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "id": "bf1653e6-337f-4232-ba31-c2a948cfd001", 118 | "metadata": {}, 119 | "source": [ 120 | "3. Calculate the rate of the reaction, which follows the expression:\n", 121 | "\n", 122 | "$-\\frac{dC_A}{dt} = k{C_{A}}^n$\n", 123 | "\n", 124 | "To do so, consider that this data is obtained with a constant volume reactor and the initial concentration of $C_A$ is 25 $mol \\cdot m^{-3}$. \n", 125 | "Choose between using the differential or the integral method **(2 points)**.\n", 126 | "\n", 127 | "Back up your answer with the other method **(0,8 points)**." 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "id": "bb2a25f6-f4b7-4ed4-b43e-972364dc22e5", 133 | "metadata": {}, 134 | "source": [ 135 | "*Hint*: [linear regression](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html)" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "id": "d0e4ad3b-8058-4285-b0af-384d4eb75c4e", 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "# Calculate the rate of the reaction\n", 146 | "\n", 147 | "# Your code here" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "id": "f5e21779-e4df-4dec-a90b-e337f7c96e08", 153 | "metadata": {}, 154 | "source": [ 155 | "4. Plot the concentrations of A, B, C and D versus time. Explain the assumption you have made **(1 point)**." 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": null, 161 | "id": "a11ada77-13a0-49e9-9805-ee82f0f95083", 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "# Plot the concentrations of A, B, C and D versus time\n", 166 | "\n", 167 | "# Your code here" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "id": "c4d96ecc-6e1f-4f75-95e7-e04ac183865f", 173 | "metadata": {}, 174 | "source": [ 175 | "5. Finally, correlate the rate constant k with the temperature through the Arrhenius expression. Calculate the activation energy **(0,75 point)** and the Arrhenius constant **(0,75 point)** using the data below:\n", 176 | "\n", 177 | "| $$ Temperature (^\\circ C) $$ | $$ {k (m^3 \\cdot mol^{-1} \\cdot h^{-1})} $$ |\n", 178 | "| :------- | :------------------------- |\n", 179 | "| 25 | 0,02764 |\n", 180 | "|30|0,03548|\n", 181 | "|35|0,04519|\n", 182 | "|45|0,07165|\n", 183 | "\n", 184 | "*Hint*: $ R = 8.314 J \\cdot mol^{-1}·K^{-1} $\n", 185 | "\n", 186 | "Plot the relation between the rate constant k and the temperature **(0,5 point)**." 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "id": "5611153d-f17b-46d2-a854-d0887476af4c", 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [ 196 | "# Calculate the activation energy\n", 197 | "\n", 198 | "# Your code here" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "id": "11f7015c-e282-47ab-aa86-45975aa8f78e", 205 | "metadata": {}, 206 | "outputs": [], 207 | "source": [ 208 | "# Calculate the Arrhenius constant\n", 209 | "\n", 210 | "# Your code here" 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": null, 216 | "id": "6e5867d2-1045-420f-a2e5-233fc17f161c", 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "# Plot the relation between the rate constant k and the temperature\n", 221 | "\n", 222 | "# Your code here" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "id": "3b102666-5ebd-45a0-9258-3d0c0bd12000", 228 | "metadata": {}, 229 | "source": [ 230 | "6. Write the complete kinetic expression written with the concentration of $C_A$ expressed with help of the initial concentration $C_{A0}$ and X **(1 point)**.\n", 231 | "\n", 232 | "Note: You can also write the complete kinetic expression on paper and upload the file/image here.\n" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "id": "a0fe3a93-da94-42ba-bcbd-ec5566128a8b", 239 | "metadata": {}, 240 | "outputs": [], 241 | "source": [ 242 | "# Write the complete kinetic expression\n", 243 | "\n", 244 | "# Your code here" 245 | ] 246 | } 247 | ], 248 | "metadata": { 249 | "kernelspec": { 250 | "display_name": "Python 3 (ipykernel)", 251 | "language": "python", 252 | "name": "python3" 253 | }, 254 | "language_info": { 255 | "codemirror_mode": { 256 | "name": "ipython", 257 | "version": 3 258 | }, 259 | "file_extension": ".py", 260 | "mimetype": "text/x-python", 261 | "name": "python", 262 | "nbconvert_exporter": "python", 263 | "pygments_lexer": "ipython3", 264 | "version": "3.8.10" 265 | } 266 | }, 267 | "nbformat": 4, 268 | "nbformat_minor": 5 269 | } 270 | -------------------------------------------------------------------------------- /week04/practice/week04_exercise_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "80207388-55b2-4c0f-bfcd-eaf13f5e2dfd", 6 | "metadata": {}, 7 | "source": [ 8 | "## Problem B\n", 9 | "\n", 10 | "The gas phase reaction A + B → C + D is examined in an ideally stirred batch reactor with a constant volume. At time t = 0 the reactor is rapidly filled with a mixture of equal amounts of A and B at a pressure of 100 kPa and a temperature of 25 °C. After one hour the concentration of A is measured as $\\frac{C_{A}}{C_{A0}}=0.15$. The reaction temperature is constant at 25 °C.\n", 11 | "The reaction follows the rate expression:\n", 12 | "\n", 13 | "$R = -r_{A}=-r_{B}=k{C_{A}}{C_{B}}$" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "id": "ef63fc5e-c697-4901-9e19-d06b30a0877e", 19 | "metadata": {}, 20 | "source": [ 21 | "a) What is the relationship between ${C_{A}}$ and ${C_{B}}$?" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "id": "9adb6570-6210-4977-9e58-63c5fb60e20f", 27 | "metadata": {}, 28 | "source": [ 29 | "Since the initial concentrations of A and B are the same and the stoichiometry shows\n", 30 | "that when one mole of A is consumed so is one mole of B it follows that CA = CB.\n", 31 | "The common concentration of A and B will be called C in the following." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "id": "0e1dcdcc-fe55-4cb5-9cfd-ba153e225808", 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "# Calculate initial concentration of A and B\n", 42 | "\n", 43 | "C0 = # your code here\n", 44 | "print(f'The initial concentration of A and B is: {C0} mol/m^3')" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "id": "59d98a85-e7fc-4d22-8117-7aa186a4d198", 50 | "metadata": {}, 51 | "source": [ 52 | "b) Compute the rate constant k.\n", 53 | "The gas can be considered ideal. The gas constant is $R = 8.3144 Pa\\cdot m^3/(mol\\cdot K)$" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "id": "acba5ece-072b-4e56-ae45-0e79fb7cfb69", 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "k = # your code here\n", 64 | "print(f'The constant rate k is: {k} m^3/mol*s')" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "id": "2216d7d4-cd46-4c43-b5d9-b8fc56e28bed", 70 | "metadata": {}, 71 | "source": [ 72 | "The activation energy $E_a$ of the reaction is given by: $E_a/R=10200 K$\n", 73 | "\n", 74 | "c) Calculate the rate constant at 100 °C\n", 75 | "\n", 76 | "The gas constant is $R = 8.3144 J/mol/K $" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "id": "f4d71d6c-8544-4165-9330-c76e677120a5", 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "import math\n", 87 | "\n", 88 | "def rate_constant_100C(k, Ea_R, T1_kelvin, T2_kelvin):\n", 89 | " k_100 = # your code here\n", 90 | " return k_100\n", 91 | "\n", 92 | "Ea_R = 10200 # activation energy in K\n", 93 | "T2 = 100 # temperature in C\n", 94 | "T2_kelvin = round(T2 + 273.15) # temperature in K\n", 95 | "\n", 96 | "print(f'The rate constant at 100 C is: {rate_constant_100C(k, Ea_R, T1_kelvin, T2_kelvin)} m^3/mol*s')" 97 | ] 98 | } 99 | ], 100 | "metadata": { 101 | "kernelspec": { 102 | "display_name": "Python 3 (ipykernel)", 103 | "language": "python", 104 | "name": "python3" 105 | }, 106 | "language_info": { 107 | "codemirror_mode": { 108 | "name": "ipython", 109 | "version": 3 110 | }, 111 | "file_extension": ".py", 112 | "mimetype": "text/x-python", 113 | "name": "python", 114 | "nbconvert_exporter": "python", 115 | "pygments_lexer": "ipython3", 116 | "version": "3.9.7" 117 | } 118 | }, 119 | "nbformat": 4, 120 | "nbformat_minor": 5 121 | } 122 | -------------------------------------------------------------------------------- /week04/practice/week04_exercise_1_solution.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "80207388-55b2-4c0f-bfcd-eaf13f5e2dfd", 6 | "metadata": {}, 7 | "source": [ 8 | "## Problem B\n", 9 | "\n", 10 | "The gas phase reaction A + B → C + D is examined in an ideally stirred batch reactor with a constant volume. At time t = 0 the reactor is rapidly filled with a mixture of equal amounts of A and B at a pressure of 100 kPa and a temperature of 25 °C. After one hour the concentration of A is measured as $\\frac{C_{A}}{C_{A0}}=0.15$. The reaction temperature is constant at 25 °C.\n", 11 | "The reaction follows the rate expression:\n", 12 | "\n", 13 | "$R = -r_{A}=-r_{B}=k{C_{A}}{C_{B}}$" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "id": "ef63fc5e-c697-4901-9e19-d06b30a0877e", 19 | "metadata": {}, 20 | "source": [ 21 | "a) What is the relationship between ${C_{A}}$ and ${C_{B}}$?" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "id": "9adb6570-6210-4977-9e58-63c5fb60e20f", 27 | "metadata": {}, 28 | "source": [ 29 | "Since the initial concentrations of A and B are the same and the stoichiometry shows\n", 30 | "that when one mole of A is consumed so is one mole of B it follows that CA = CB.\n", 31 | "The common concentration of A and B will be called C in the following." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 1, 37 | "id": "0e1dcdcc-fe55-4cb5-9cfd-ba153e225808", 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "name": "stdout", 42 | "output_type": "stream", 43 | "text": [ 44 | "The initial concentration of A and B is: 20.18 mol/m^3\n" 45 | ] 46 | } 47 | ], 48 | "source": [ 49 | "# Calculate initial concentration of A and B\n", 50 | "def calculate_C0(C_ratio, n, P, R, T):\n", 51 | " C0 = (0.5*P)/(R*T)\n", 52 | " return round(C0, 2)\n", 53 | "\n", 54 | "T1 = 25 # temperature in C\n", 55 | "T1_kelvin = round(T1 + 273.15) # temperature in K\n", 56 | "\n", 57 | "CA_CA0 = 0.15 # ratio of CA/CA0\n", 58 | "R = 8.3144 # gas constant in Pa*m^3/(mol*K)\n", 59 | "P = 100000 # pressure\n", 60 | "C0 = calculate_C0(CA_CA0, 0.5, P, R, T1_kelvin)\n", 61 | "print(f'The initial concentration of A and B is: {C0} mol/m^3')" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "id": "59d98a85-e7fc-4d22-8117-7aa186a4d198", 67 | "metadata": {}, 68 | "source": [ 69 | "b) Compute the rate constant k.\n", 70 | "The gas can be considered ideal. The gas constant is $R = 8.3144 Pa\\cdot m^3/(mol\\cdot K)$" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 6, 76 | "id": "acba5ece-072b-4e56-ae45-0e79fb7cfb69", 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "The constant rate k is: 7.800168850713945e-05 m^3/mol*s\n" 84 | ] 85 | } 86 | ], 87 | "source": [ 88 | "def rate_constant(C0, C_ratio, t):\n", 89 | " k_h = (1/(C0*t))* (1/C_ratio -1)\n", 90 | " k_s = k_h/3600\n", 91 | " return k_s\n", 92 | "\n", 93 | "t = 1 # time in h\n", 94 | "k = rate_constant(C0, CA_CA0, t)\n", 95 | "print(f'The constant rate k is: {k} m^3/mol*s')" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "id": "2216d7d4-cd46-4c43-b5d9-b8fc56e28bed", 101 | "metadata": {}, 102 | "source": [ 103 | "The activation energy $E_a$ of the reaction is given by: $E_a/R=10200 K$\n", 104 | "\n", 105 | "c) Calculate the rate constant at 100 °C\n", 106 | "\n", 107 | "The gas constant is $R = 8.3144 J/mol/K $" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 9, 113 | "id": "f4d71d6c-8544-4165-9330-c76e677120a5", 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "name": "stdout", 118 | "output_type": "stream", 119 | "text": [ 120 | "The rate constant at 100 C is: 0.07604449355095103 m^3/mol*s\n" 121 | ] 122 | } 123 | ], 124 | "source": [ 125 | "import math\n", 126 | "\n", 127 | "def rate_constant_100C(k, Ea_R, T1_kelvin, T2_kelvin):\n", 128 | " k_100 = k*math.exp((Ea_R*(1/T1_kelvin-1/T2_kelvin)))\n", 129 | " return k_100\n", 130 | "\n", 131 | "Ea_R = 10200 # activation energy in K\n", 132 | "T2 = 100 # temperature in C\n", 133 | "T2_kelvin = round(T2 + 273.15) # temperature in K\n", 134 | "\n", 135 | "print(f'The rate constant at 100 C is: {rate_constant_100C(k, Ea_R, T1_kelvin, T2_kelvin)} m^3/mol*s')" 136 | ] 137 | } 138 | ], 139 | "metadata": { 140 | "kernelspec": { 141 | "display_name": "Python 3 (ipykernel)", 142 | "language": "python", 143 | "name": "python3" 144 | }, 145 | "language_info": { 146 | "codemirror_mode": { 147 | "name": "ipython", 148 | "version": 3 149 | }, 150 | "file_extension": ".py", 151 | "mimetype": "text/x-python", 152 | "name": "python", 153 | "nbconvert_exporter": "python", 154 | "pygments_lexer": "ipython3", 155 | "version": "3.9.7" 156 | } 157 | }, 158 | "nbformat": 4, 159 | "nbformat_minor": 5 160 | } 161 | -------------------------------------------------------------------------------- /week04/theory/1_reactors_in_python.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "0926ee4f-cbf5-4e73-88c0-42435dcbf370", 6 | "metadata": {}, 7 | "source": [ 8 | "# Reactors in Python\n", 9 | "\n", 10 | "This week we will see how to address problems that you have previously been solving by hand, in Python." 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "7e6c5cc7-b57c-461e-a477-5bd4cca458b2", 16 | "metadata": {}, 17 | "source": [ 18 | "## Ideal batch reactor (week 1)\n", 19 | "### Problem A: \n", 20 | "In an ideal batch reactor, the following reaction takes place\n", 21 | "$A → Products$\n", 22 | "\n", 23 | "with a rate expression of:\n", 24 | "$R = -r_{A}=k{C_{A}}^n $\n", 25 | "\n", 26 | "The reactor is isothermal and the density of the reaction mixture is constant.\n", 27 | "The reaction starts at time t = 0, where the concentration of A is $C_{A0}$.\n", 28 | "\n", 29 | "After a reaction time of 1 hour, the concentration of A is measured to be: $\\frac{C_{A}}{C_{A0}}=0.1$\n", 30 | " \n", 31 | "1) Calculate the rate constant and how much longer the reaction must continue to obtain $\\frac{C_{A}}{C_{A0}}=0.001$\n", 32 | " a. For a first order reaction, n = 1\n", 33 | " b. For a second order reaction, n = 2\n", 34 | " (In this case it is not possible to calculate the rate constant $kC_{A0}$, but can be calculated and used to estimate how much longer the reaction must continue to obtain $\\frac{C_{A}}{C_{A0}}=0.001$)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "id": "a819e5b1-61f8-46eb-8b0c-fa162ccc5a6c", 40 | "metadata": {}, 41 | "source": [ 42 | "### Solving the first order reaction" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 3, 48 | "id": "451daa9a-e1b0-402f-9739-6122687878c0", 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "The rate constant is: 2.3\n", 56 | "Time needed to reach given concentration of A is: 2 hours\n" 57 | ] 58 | } 59 | ], 60 | "source": [ 61 | "# in the code we can make a loop to check whether the V is constant\n", 62 | "# otherwise print something\n", 63 | "# this might help you in the future\n", 64 | "import numpy as np\n", 65 | "\n", 66 | "def first_order_reaction_batch(C_ratio, t, V='constant'):\n", 67 | " '''\n", 68 | " Given the solved equation for an ideal batch reactor and the time, \n", 69 | " this function returns the rate constant for a first order reaction.\n", 70 | " Args:\n", 71 | " C_ratio (float): Concentration of A, given by CA/CA0 ratio.\n", 72 | " t (int): time necessary to reach given concentration of A.\n", 73 | " returns:\n", 74 | " k (float): rate constant.\n", 75 | " '''\n", 76 | " if V == 'constant': \n", 77 | " k = -np.log(C_ratio)/t\n", 78 | " else:\n", 79 | " print('V should be constant in this exercise') \n", 80 | " return k\n", 81 | "\n", 82 | "def first_order_time(C_ratio, k):\n", 83 | " '''\n", 84 | " Given the solved equation for an ideal batch reactor \n", 85 | " and the previously calculated rate constant, \n", 86 | " this function returns the time (how much longer the reaction \n", 87 | " must continue to obtain CA/CA0 = 0.001).\n", 88 | " \n", 89 | " Args:\n", 90 | " C_ratio (float): Concentration of A, given by CA/CA0 ratio.\n", 91 | " k (float): rate constant.\n", 92 | " returns:\n", 93 | " t (int): time necessary to reach given concentration of A.\n", 94 | " '''\n", 95 | " t = -np.log(C_ratio)/k\n", 96 | " return round(t)\n", 97 | " \n", 98 | "t1 = 1\n", 99 | "CA_CA0_1h = 0.1\n", 100 | "CA_CA0_t = 0.001\n", 101 | "k_first_order = first_order_reaction_batch(CA_CA0_1h, t1)\n", 102 | "print(f'The rate constant is: {round(k_first_order, 2)}')\n", 103 | "t2 = first_order_time(CA_CA0_t, k_first_order)\n", 104 | "\n", 105 | "time = t2 - t1\n", 106 | "print(f\"Time needed to reach given concentration of A is: {time} hours\")" 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "id": "8b4dd31c-6c0b-4a7b-a98b-848b5ea925e0", 112 | "metadata": {}, 113 | "source": [ 114 | "### Solving the second order reaction" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 4, 120 | "id": "7e917f38-ecdc-4f2a-9bf1-2c7526ab0036", 121 | "metadata": {}, 122 | "outputs": [ 123 | { 124 | "name": "stdout", 125 | "output_type": "stream", 126 | "text": [ 127 | "The rate constant is: 9.0\n", 128 | "Time needed to reach given concentration of A is: 110.0 hours\n" 129 | ] 130 | } 131 | ], 132 | "source": [ 133 | "def second_order_reaction_batch(C_ratio, t, V='constant'):\n", 134 | " if V == 'constant':\n", 135 | " k_CA0 = 1/t*(1/C_ratio - 1)\n", 136 | " else:\n", 137 | " print('V should be constant in this exercise') \n", 138 | " return k_CA0\n", 139 | "\n", 140 | "def second_order_time(C_ratio, k):\n", 141 | " return 1/k*(1/C_ratio -1)\n", 142 | "\n", 143 | "k_second_order = second_order_reaction_batch(CA_CA0_1h, t1)\n", 144 | "print(f'The rate constant is: {k_second_order}')\n", 145 | "t2 = second_order_time(CA_CA0_t, k_second_order)\n", 146 | "\n", 147 | "time = t2 - t1\n", 148 | "print(f\"Time needed to reach given concentration of A is: {time} hours\")" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "id": "df343271-d055-4543-bea6-66827f7d51da", 154 | "metadata": {}, 155 | "source": [ 156 | "Putting it all together." 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": 7, 162 | "id": "8a74eb3d-3f6c-4e43-89bf-d21be73f26e8", 163 | "metadata": {}, 164 | "outputs": [ 165 | { 166 | "name": "stdout", 167 | "output_type": "stream", 168 | "text": [ 169 | "Rate constant and time for first order batch reaction:\n", 170 | "2.3025850929940455\n", 171 | "2.0\n", 172 | "\n", 173 | "Rate constant and time for second order batch reaction:\n", 174 | "9.0\n", 175 | "110.0\n" 176 | ] 177 | } 178 | ], 179 | "source": [ 180 | "def reaction_batch(C_ratio, t, order):\n", 181 | " \n", 182 | " if order == 'first':\n", 183 | " k = -np.log(C_ratio)/t\n", 184 | " \n", 185 | " elif order == 'second':\n", 186 | " k = 1/t*(1/C_ratio - 1)\n", 187 | " \n", 188 | " else:\n", 189 | " print('Provide the order of the reaction as a string')\n", 190 | " \n", 191 | " return k\n", 192 | "\n", 193 | "def calculate_time(C_ratio, k, order):\n", 194 | " \n", 195 | " if order == 'first':\n", 196 | " t = -np.log(C_ratio)/k\n", 197 | " \n", 198 | " elif order == 'second':\n", 199 | " t = 1/k*(1/C_ratio -1)\n", 200 | " \n", 201 | " else:\n", 202 | " print('Provide the order of the reaction as a string')\n", 203 | " \n", 204 | " return round(t, 2)\n", 205 | "\n", 206 | "print('Rate constant and time for first order batch reaction:')\n", 207 | "k_first_order = reaction_batch(CA_CA0_1h, t1, 'first')\n", 208 | "print(k_first_order)\n", 209 | "print(calculate_time(CA_CA0_t, k_first_order, 'first')-t1)\n", 210 | "print()\n", 211 | "print('Rate constant and time for second order batch reaction:')\n", 212 | "k_second_order = reaction_batch(CA_CA0_1h, t1, 'second')\n", 213 | "print(k_second_order)\n", 214 | "print(calculate_time(CA_CA0_t, k_second_order, 'second')-t1)" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "id": "eeaecb0f-aaae-4f33-9adf-0204b05aa6fe", 220 | "metadata": {}, 221 | "source": [ 222 | "## Residence time in a CSTR" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "id": "ff23cc7c-8768-4aa4-91f4-187b004b5024", 228 | "metadata": {}, 229 | "source": [ 230 | "2) What should be the residence time, $\\tau = V/v_{0}$, in a CSTR to achieve $\\frac{C_{A}}{C_{A0}}=0.001$ for the reaction for each of the two cases: n = 1 and n = 2." 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": 28, 236 | "id": "225f5dcd-7772-4afd-acf9-c88ad0248adc", 237 | "metadata": {}, 238 | "outputs": [ 239 | { 240 | "name": "stdout", 241 | "output_type": "stream", 242 | "text": [ 243 | "The residence time in a CSTR with n=1 is: 434 h\n" 244 | ] 245 | } 246 | ], 247 | "source": [ 248 | "def first_order_reaction_CSTR(C_ratio, k, density='constant'):\n", 249 | " if density == 'constant':\n", 250 | " tau = 1/k*((1-C_ratio)/C_ratio)\n", 251 | " else: \n", 252 | " print('Density should be constant in this exercise')\n", 253 | " return round(tau)\n", 254 | "\n", 255 | "print(f'The residence time in a CSTR with n=1 is: {first_order_reaction_CSTR(CA_CA0_t, k_first_order)} h')" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 29, 261 | "id": "32bb97c1-0c9f-47c2-a56d-14548ee61e3d", 262 | "metadata": {}, 263 | "outputs": [ 264 | { 265 | "name": "stdout", 266 | "output_type": "stream", 267 | "text": [ 268 | "The residence time in a CSTR with n=2 is: 111000 h\n" 269 | ] 270 | } 271 | ], 272 | "source": [ 273 | "def second_order_reaction_CSTR(C_ratio, k, density='constant'):\n", 274 | " if density == 'constant':\n", 275 | " tau = (1/k)*((1-C_ratio)/C_ratio**2)\n", 276 | " else: \n", 277 | " print('Density should be constant in this exercise')\n", 278 | " return round(tau)\n", 279 | "\n", 280 | "print(f'The residence time in a CSTR with n=2 is: {second_order_reaction_CSTR(CA_CA0_t, k_second_order)} h')" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "id": "316d291c-26bc-4102-a697-9840cdd43951", 286 | "metadata": {}, 287 | "source": [ 288 | "**Exercise**: write a function to combine the first and second order reaction for CSTR (as done before for batch reactor).\n", 289 | "\n", 290 | "Level: Medium." 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": null, 296 | "id": "5e58cf23-b64a-4e8f-b57e-9d7704f3001b", 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "# Your code here" 301 | ] 302 | }, 303 | { 304 | "cell_type": "markdown", 305 | "id": "d80e6518-4a27-4424-a2a7-823d0f596b5e", 306 | "metadata": {}, 307 | "source": [ 308 | "3) How would you explain the observed difference between a first order and a second order reaction in words?" 309 | ] 310 | }, 311 | { 312 | "cell_type": "code", 313 | "execution_count": 11, 314 | "id": "8782551f-bd82-4870-9a07-eef81a4496ff", 315 | "metadata": {}, 316 | "outputs": [], 317 | "source": [ 318 | "# Type here" 319 | ] 320 | } 321 | ], 322 | "metadata": { 323 | "kernelspec": { 324 | "display_name": "Python 3 (ipykernel)", 325 | "language": "python", 326 | "name": "python3" 327 | }, 328 | "language_info": { 329 | "codemirror_mode": { 330 | "name": "ipython", 331 | "version": 3 332 | }, 333 | "file_extension": ".py", 334 | "mimetype": "text/x-python", 335 | "name": "python", 336 | "nbconvert_exporter": "python", 337 | "pygments_lexer": "ipython3", 338 | "version": "3.9.7" 339 | } 340 | }, 341 | "nbformat": 4, 342 | "nbformat_minor": 5 343 | } 344 | -------------------------------------------------------------------------------- /week05/theory/week05_exercise_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "3b32892e-b217-4866-a52d-356f88415e55", 6 | "metadata": {}, 7 | "source": [ 8 | "# Instructions\n", 9 | "The task for this week is to solve another exercise previously seen during the course, specifically in week 3.\n", 10 | "You should already be comfortable with the solution, so you can focus on the Python implementation.\n", 11 | "\n", 12 | "Your can find the solution to the exercise in another notebook, but please give it a try to solve it before looking at it. \n", 13 | "If you are not sure about the implementation, try to work in small groups." 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "id": "94ed3e18-5b6f-498c-a357-1b1a07b2aa08", 19 | "metadata": {}, 20 | "source": [ 21 | "### Problem A\n", 22 | "An exothermic reaction A → B is to be carried out adiabatically to achieve a conversion of 90%. \n", 23 | "The rate-conversion data is provided in the figure below.\n", 24 | "1) What size of single CSTR is needed?\n", 25 | "2) What size of single PBR is needed?\n", 26 | "Wishing to minimize the toal mass of catalyst \n", 27 | "needed:\n", 28 | "3) What number, order and size of PBR and \n", 29 | "CSTR in series would you use to obtain a \n", 30 | "conversion of 90 %" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "id": "db3228da-da76-441b-8b02-566278d8d72e", 36 | "metadata": {}, 37 | "source": [ 38 | "First task: Let's first define some data points\n", 39 | "Build the curve illustrated in \"Grupperegningsopgave E3\".\n", 40 | "Then visualize the data in `matplotlib`.\n", 41 | "\n", 42 | "*Hint*: create two lists, one for the x and one for the y values and look into the `interp1d` function from the `scipy.interpolate` package." 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 1, 48 | "id": "b8849608-001a-4f34-a811-5f56721c1b35", 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "import numpy as np\n", 53 | "import matplotlib.pyplot as plt\n", 54 | "from scipy.interpolate import interp1d\n", 55 | "plt.rcParams['text.usetex'] = True\n", 56 | "plt.rcParams.update(plt.rcParamsDefault)\n", 57 | "\n", 58 | "# let's plot our data\n", 59 | "#plt.plot(list_x, list_y, color='green')\n", 60 | "#plt.xlabel('Conversion, X')\n", 61 | "#plt.ylabel(r\"$\\frac{F_{A0}}{-r_{A'}}$\")\n", 62 | "#plt.show()" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "id": "3da77fa8-58fd-4a1f-9039-db2480fa7d7c", 68 | "metadata": {}, 69 | "source": [ 70 | "1) What size of single CSTR is needed?\n", 71 | "\n", 72 | "*Hint*: We can use the `np.where` function to reach 90% conversion" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 5, 78 | "id": "7f71b991-eabc-47ae-8e83-77c51e96564d", 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "F_A0/-r_A' is: _ kg\n" 86 | ] 87 | } 88 | ], 89 | "source": [ 90 | "# Your code here\n", 91 | "print(f\"F_A0/-r_A' is: _ kg\")" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "id": "6390dc3e-e364-487f-8e7f-258b53e898db", 97 | "metadata": {}, 98 | "source": [ 99 | "For a catalytic reactor the size is normally given as weight of catalyst (W).\n", 100 | "\n", 101 | "Print W below:" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 6, 107 | "id": "062842d1-1c76-4b33-81ce-5ac213d12f8f", 108 | "metadata": {}, 109 | "outputs": [ 110 | { 111 | "name": "stdout", 112 | "output_type": "stream", 113 | "text": [ 114 | "The size of the reactor is: _ kg\n" 115 | ] 116 | } 117 | ], 118 | "source": [ 119 | "# Your code here\n", 120 | "print(f'The size of the reactor is: _ kg')" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "id": "b532b9bc-40ef-4b7a-8256-80753e4f7128", 126 | "metadata": {}, 127 | "source": [ 128 | "2) What size of single PBR is needed?\n", 129 | "\n", 130 | "The size of a PBR needed to reach 90% conversion is equivalent to the area under the \n", 131 | "graph (blue area)" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 7, 137 | "id": "56c4d53a-42bd-42af-b333-8bb437a15216", 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "# Your code here" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "id": "af269b92-2904-4529-9f41-2b0e10fe5c3d", 147 | "metadata": {}, 148 | "source": [ 149 | "3) What number, order and size of PBR and \n", 150 | "CSTR in series would you use to obtain a \n", 151 | "conversion of 90 %" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": 8, 157 | "id": "ef6d4008-a28f-467e-8f43-82d5a4a85250", 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "# Your code here" 162 | ] 163 | } 164 | ], 165 | "metadata": { 166 | "kernelspec": { 167 | "display_name": "Python 3 (ipykernel)", 168 | "language": "python", 169 | "name": "python3" 170 | }, 171 | "language_info": { 172 | "codemirror_mode": { 173 | "name": "ipython", 174 | "version": 3 175 | }, 176 | "file_extension": ".py", 177 | "mimetype": "text/x-python", 178 | "name": "python", 179 | "nbconvert_exporter": "python", 180 | "pygments_lexer": "ipython3", 181 | "version": "3.8.10" 182 | } 183 | }, 184 | "nbformat": 4, 185 | "nbformat_minor": 5 186 | } 187 | -------------------------------------------------------------------------------- /week06/practice/1_stoichiometry_solution.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "b43f0281-e5f9-4739-bb51-08b348b5f985", 6 | "metadata": {}, 7 | "source": [ 8 | "# Stoichiometry - Part 1" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "1ec52986-b936-41f9-89a8-1c9b06da306a", 14 | "metadata": {}, 15 | "source": [ 16 | "As seen in the first lecture, stoichiometry is one of the pillars of Chemical Reaction Engineering.\n", 17 | "\n", 18 | "In Python, we will divide the topics into two parts:\n", 19 | "- **Part 1** will cover simple mole-mole calculations, mass-mass reactions and finally provide a solution for balancing coefficients\n", 20 | "- **Part 2** will focus on the application of the stoichiometric table to Batch Reactors and Flow Systems." 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "id": "73eaec1d-a78d-4a12-ac9e-a3949e1ee70e", 26 | "metadata": {}, 27 | "source": [ 28 | "### Mole-mole calculations in Python" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "id": "b46da7b2-a394-4050-a409-e63752539bf5", 34 | "metadata": {}, 35 | "source": [ 36 | "Given a balanced reaction, we want to write a function to where calculate how many moles of a molecule B are needed to react with a given amount of moles A.\n", 37 | "\n", 38 | "Given the following reaction:\n", 39 | "\n", 40 | "$3H_2 + N_2 → 2NH_3$\n", 41 | "\n", 42 | "In Python, we can do the following:" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 3, 48 | "id": "4505f1ac-7163-4d93-af00-fd30cfa1c724", 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "2.5 mols of N2 are needed to react with 7.5 mols of H2, since they have a 1:3 ratio\n" 56 | ] 57 | } 58 | ], 59 | "source": [ 60 | "#we multiply the moles of A by the ratio of what needs to be found and what is given\n", 61 | "# so moles A*coefficient B/coefficient A = moles B\n", 62 | "def mole_mole_calculation(moles_A, coeff_A, coeff_B):\n", 63 | " \"\"\"\n", 64 | " This function calculates how many moles of a compound B are needed to the given moles of A.\n", 65 | " To achieve this, we multiply the given moles of A by the ratio \n", 66 | " of what needs to be found (coeff B) and what is given (coeff A).\n", 67 | " So moles B needed = moles A* coefficient B/coefficient A.\n", 68 | " Input: \n", 69 | " moles A, coeff_A, coeff_B\n", 70 | " Output: \n", 71 | " moles B\n", 72 | " \"\"\"\n", 73 | " return moles_A*(coeff_B/coeff_A)\n", 74 | "\n", 75 | "A_moles = 7.5 # mol\n", 76 | "coeff_A = 3\n", 77 | "coeff_B = 1\n", 78 | "B_moles = mole_mole_calculation(A_moles, coeff_A, coeff_B)\n", 79 | "print(f'{B_moles} mols of N2 are needed to react with 7.5 mols of H2, since they have a 1:3 ratio')" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "id": "b1e141e7-29a3-4b62-bfc8-4f5a075b4192", 85 | "metadata": {}, 86 | "source": [ 87 | "**Exercise**: How many moles of H2 are needed to produce 0.8 moles NH3?\n", 88 | "\n", 89 | "Level: Easy." 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 4, 95 | "id": "c2174435-3a4b-4a28-a164-9f4e7e0bef7f", 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "name": "stdout", 100 | "output_type": "stream", 101 | "text": [ 102 | "1.2 mols of H2 are needed to react with 0.8 mols of NH3\n" 103 | ] 104 | } 105 | ], 106 | "source": [ 107 | "A_moles = 0.8 # mol\n", 108 | "coeff_A = 2\n", 109 | "coeff_B = 3\n", 110 | "B_moles = mole_mole_calculation(A_moles, coeff_A, coeff_B)\n", 111 | "print(f'{round(B_moles, 2)} mols of H2 are needed to react with 0.8 mols of NH3')" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "id": "f9d81f44-b949-4b86-a7c3-e02eeae18c78", 117 | "metadata": {}, 118 | "source": [ 119 | "**Exercise**: Given the methane reaction: $ CH_4 + 2O_2 → CO_2 + 2H_2O $, use the given function to calculate how many moles of O_2 are needed to produce 0.6 moles H_2O.\n", 120 | "\n", 121 | "Level: Easy." 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": 9, 127 | "id": "60841b41-6ca8-4dea-9caf-5a36ee7adfd1", 128 | "metadata": {}, 129 | "outputs": [ 130 | { 131 | "name": "stdout", 132 | "output_type": "stream", 133 | "text": [ 134 | "0.6 mols of O2 are needed to react with 0.6 mols of H2O\n" 135 | ] 136 | } 137 | ], 138 | "source": [ 139 | "A_moles = 0.6 # mol\n", 140 | "coeff_A = 2\n", 141 | "coeff_B = 2\n", 142 | "B_moles = mole_mole_calculation(A_moles, coeff_A, coeff_B)\n", 143 | "print(f'{round(B_moles, 2)} mols of O2 are needed to react with 0.6 mols of H2O')" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "id": "0f206987-3a72-4761-a76c-8456fe97028f", 149 | "metadata": {}, 150 | "source": [ 151 | "### Mass-mass reactions in Python\n", 152 | "\n", 153 | "How many grams of NH_3 is produced if you react 42 g of N_2?" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 6, 159 | "id": "f9b53373-cf3f-4526-b228-12ca7ab58946", 160 | "metadata": {}, 161 | "outputs": [ 162 | { 163 | "name": "stdout", 164 | "output_type": "stream", 165 | "text": [ 166 | "51.0 grams of NH3 produced from reacting 42 g of N2\n" 167 | ] 168 | } 169 | ], 170 | "source": [ 171 | "def mass_mass_calculation(mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B):\n", 172 | " \"\"\"\n", 173 | " This function calculates how many moles of a compound B are needed to the given moles of A.\n", 174 | " To achieve this, we multiply the given mass of A by 1/molar mass of A,\n", 175 | " then multiply the calculated moles of A by the ratio of what needs to be found (coeff B) and what is given (coeff A).\n", 176 | " inally, the mass of B is given by the product of the calculated moles of B by molar mass of B.\n", 177 | " Input: \n", 178 | " mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B\n", 179 | " Output: \n", 180 | " mass B\n", 181 | " \"\"\"\n", 182 | " # convert mass of N2 to moles of N2 using the molar mass of N2\n", 183 | " moles_A = mass_A*(1/molar_mass_A) # 1 mol N2/ g N2\n", 184 | " \n", 185 | " # mole-mole calculation\n", 186 | " moles_B = moles_A*(coeff_B/coeff_A)\n", 187 | " \n", 188 | " # convert moles of ammonia to mass of ammonia using the molar mass of ammonia\n", 189 | " mass_B = moles_B*(molar_mass_B) # g NH3/ 1 mol NH3\n", 190 | " return mass_B\n", 191 | "\n", 192 | "mass_A = 42 # g N2\n", 193 | "molar_mass_A = 28 # g N2 in 1 mol of N2\n", 194 | "molar_mass_B = 17 # g NH3 in 1 mol of NH3\n", 195 | "coeff_A = 1\n", 196 | "coeff_B = 2\n", 197 | "mass_B = mass_mass_calculation(mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B)\n", 198 | "print(f'{mass_B} grams of NH3 produced from reacting 42 g of N2')" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "id": "5f77517b-2a25-4e8e-9e8c-533d125bde73", 204 | "metadata": {}, 205 | "source": [ 206 | "### How to balance coefficients in Python" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "id": "935e892e-521b-43ba-b7cd-b4417cd5df06", 212 | "metadata": {}, 213 | "source": [ 214 | "Take some time to investigate and understand the code below.\n", 215 | "Try to take the code apart and verify what each function is doing.\n", 216 | "Once you understand the code, try to see if you can simplify it.\n", 217 | "\n", 218 | "Suggested readings:\n", 219 | "- https://www.cliffsnotes.com/study-guides/algebra/linear-algebra/real-euclidean-vector-spaces/the-nullspace-of-a-matrix\n", 220 | "- https://en.wikipedia.org/wiki/Kernel_(linear_algebra)" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 7, 226 | "id": "d6041c7d-c729-4d25-b1fb-52970921c12a", 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "# code adapted from https://medium.com/swlh/balancing-chemical-equations-with-python-837518c9075b\n", 231 | "\n", 232 | "import re\n", 233 | "from sympy import Matrix, lcm\n", 234 | "\n", 235 | "element_list = []\n", 236 | "element_matrix = []\n", 237 | "reaction = 'H2 + N2 -> NH3'\n", 238 | "reactants = reaction.split(\"->\")[0].replace(' ', '').split(\"+\")\n", 239 | "products = reaction.split(\"->\")[1].replace(' ', '').split(\"+\")\n", 240 | "\n", 241 | "def add_matrix(element, index, count, side):\n", 242 | " if(index == len(element_matrix)):\n", 243 | " element_matrix.append([])\n", 244 | " for x in element_list:\n", 245 | " element_matrix[index].append(0)\n", 246 | " if(element not in element_list):\n", 247 | " element_list.append(element)\n", 248 | " for i in range(len(element_matrix)):\n", 249 | " element_matrix[i].append(0)\n", 250 | " column = element_list.index(element)\n", 251 | " element_matrix[index][column] += count*side\n", 252 | " \n", 253 | "def find_elements(segment, index, side):\n", 254 | " elements_numbers=re.split('([A-Z][a-z]?)',segment)\n", 255 | " i=0\n", 256 | " while(i < len(elements_numbers)-1):#last element always blank\n", 257 | " i += 1\n", 258 | " if(len(elements_numbers[i]) > 0):\n", 259 | " if(elements_numbers[i+1].isdigit()):\n", 260 | " count = int(elements_numbers[i+1])\n", 261 | " add_matrix(elements_numbers[i], index, count, side)\n", 262 | " i+=1\n", 263 | " else:\n", 264 | " add_matrix(elements_numbers[i], index, 1, side) \n", 265 | " \n", 266 | "for i in range(len(reactants)):\n", 267 | " find_elements(reactants[i], i, 1)\n", 268 | " \n", 269 | "for i in range(len(products)):\n", 270 | " find_elements(products[i], i+len(reactants), -1)\n", 271 | "\n", 272 | "# use Matrix function from sympy to convert list of lists to matrix\n", 273 | "element_matrix = Matrix(element_matrix)\n", 274 | "# transpose matrix vertically\n", 275 | "element_matrix = element_matrix.transpose()\n", 276 | "# nullspace or kernel mapping\n", 277 | "solution = element_matrix.nullspace()[0]\n", 278 | "# find the least common multiple (smallest positive integer that is divisible by the found coefficients)\n", 279 | "multiple = lcm([val.q for val in solution])\n", 280 | "# multiply solution my lcm\n", 281 | "solution = multiple*solution\n", 282 | "coeff = solution.tolist()" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "id": "5ae62bdc-fb2b-4f39-935d-2aa6149362bc", 288 | "metadata": {}, 289 | "source": [ 290 | "Once we balanced the reaction, we can print it in a nice form. \n", 291 | "This is what the following code is doing." 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 8, 297 | "id": "7a7e5452-949b-4368-a4ec-7ba79cafa97a", 298 | "metadata": {}, 299 | "outputs": [ 300 | { 301 | "name": "stdout", 302 | "output_type": "stream", 303 | "text": [ 304 | "3H2 + 1N2 -> 2NH3\n" 305 | ] 306 | } 307 | ], 308 | "source": [ 309 | "# assign the found coefficients to the reactants\n", 310 | "output = \"\"\n", 311 | "for i in range(len(reactants)):\n", 312 | " output += str(coeff[i][0])+reactants[i]\n", 313 | " if i < len(reactants)-1:\n", 314 | " output += \" + \"\n", 315 | "\n", 316 | "# assign the found coefficients to the reactants\n", 317 | "output += \" -> \"\n", 318 | "for i in range(len(products)):\n", 319 | " output += str(coeff[i+len(reactants)][0])+products[i]\n", 320 | " if i < len(products)-1:\n", 321 | " output += \" + \"\n", 322 | " \n", 323 | "# print the final reaction\n", 324 | "print(output)" 325 | ] 326 | } 327 | ], 328 | "metadata": { 329 | "kernelspec": { 330 | "display_name": "Python 3 (ipykernel)", 331 | "language": "python", 332 | "name": "python3" 333 | }, 334 | "language_info": { 335 | "codemirror_mode": { 336 | "name": "ipython", 337 | "version": 3 338 | }, 339 | "file_extension": ".py", 340 | "mimetype": "text/x-python", 341 | "name": "python", 342 | "nbconvert_exporter": "python", 343 | "pygments_lexer": "ipython3", 344 | "version": "3.9.7" 345 | } 346 | }, 347 | "nbformat": 4, 348 | "nbformat_minor": 5 349 | } 350 | -------------------------------------------------------------------------------- /week06/theory/1_stoichiometry.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "b43f0281-e5f9-4739-bb51-08b348b5f985", 6 | "metadata": {}, 7 | "source": [ 8 | "# Stoichiometry - Part 1" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "1ec52986-b936-41f9-89a8-1c9b06da306a", 14 | "metadata": {}, 15 | "source": [ 16 | "As seen in the first lecture, stoichiometry is one of the pillars of Chemical Reaction Engineering.\n", 17 | "\n", 18 | "In Python, we will divide the topics into two parts:\n", 19 | "- **Part 1** will cover simple mole-mole calculations, mass-mass reactions and finally provide a solution for balancing coefficients\n", 20 | "- **Part 2** will focus on the application of the stoichiometric table to Batch Reactors and Flow Systems." 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "id": "73eaec1d-a78d-4a12-ac9e-a3949e1ee70e", 26 | "metadata": {}, 27 | "source": [ 28 | "### Mole-mole calculations in Python" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "id": "b46da7b2-a394-4050-a409-e63752539bf5", 34 | "metadata": {}, 35 | "source": [ 36 | "Given a balanced reaction, we want to write a function to where calculate how many moles of a molecule B are needed to react with a given amount of moles A.\n", 37 | "\n", 38 | "Given the following reaction:\n", 39 | "\n", 40 | "$3H_2 + N_2 → 2NH_3$\n", 41 | "\n", 42 | "In Python, we can do the following:" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 12, 48 | "id": "4505f1ac-7163-4d93-af00-fd30cfa1c724", 49 | "metadata": {}, 50 | "outputs": [ 51 | { 52 | "name": "stdout", 53 | "output_type": "stream", 54 | "text": [ 55 | "2.5 mols of N2 are needed to react with 7.5 mols of H2, since they have a 1:3 ratio\n" 56 | ] 57 | } 58 | ], 59 | "source": [ 60 | "#we multiply the moles of A by the ratio of what needs to be found and what is given\n", 61 | "# so moles A*coefficient B/coefficient A = moles B\n", 62 | "def mole_mole_calculation(moles_A, coeff_A, coeff_B):\n", 63 | " \"\"\"\n", 64 | " This function calculates how many moles of a compound B are needed to the given moles of A.\n", 65 | " To achieve this, we multiply the given moles of A by the ratio \n", 66 | " of what needs to be found (coeff B) and what is given (coeff A).\n", 67 | " So moles B needed = moles A* coefficient B/coefficient A.\n", 68 | " Input: \n", 69 | " moles A, coeff_A, coeff_B\n", 70 | " Output: \n", 71 | " moles B\n", 72 | " \"\"\"\n", 73 | " return moles_A*(coeff_B/coeff_A)\n", 74 | "\n", 75 | "A_moles = 7.5 # mol\n", 76 | "coeff_A = 3\n", 77 | "coeff_B = 1\n", 78 | "B_moles = mole_mole_calculation(A_moles, coeff_A, coeff_B)\n", 79 | "print(f'{B_moles} mols of N2 are needed to react with 7.5 mols of H2, since they have a 1:3 ratio')" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "id": "b1e141e7-29a3-4b62-bfc8-4f5a075b4192", 85 | "metadata": {}, 86 | "source": [ 87 | "**Exercise**: How many moles of H2 are needed to produce 0.8 moles NH3?\n", 88 | "\n", 89 | "Level: Easy." 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 62, 95 | "id": "c2174435-3a4b-4a28-a164-9f4e7e0bef7f", 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "# Your code here" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "id": "f9d81f44-b949-4b86-a7c3-e02eeae18c78", 105 | "metadata": {}, 106 | "source": [ 107 | "**Exercise**: Given the methane reaction: $ CH_4 + 2O_2 → CO_2 + 2H_2O $, use the given function to calculate how many moles of O_2 are needed to produce 0.6 moles H_2O.\n", 108 | "\n", 109 | "Level: Easy." 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": 63, 115 | "id": "60841b41-6ca8-4dea-9caf-5a36ee7adfd1", 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "# Your code here" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "id": "0f206987-3a72-4761-a76c-8456fe97028f", 125 | "metadata": {}, 126 | "source": [ 127 | "### Mass-mass reactions in Python\n", 128 | "\n", 129 | "How many grams of NH_3 is produced if you react 42 g of N_2?" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 20, 135 | "id": "f9b53373-cf3f-4526-b228-12ca7ab58946", 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "name": "stdout", 140 | "output_type": "stream", 141 | "text": [ 142 | "51.0 grams of NH3 produced from reacting 42 g of N2\n" 143 | ] 144 | } 145 | ], 146 | "source": [ 147 | "def mass_mass_calculation(mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B):\n", 148 | " \"\"\"\n", 149 | " This function calculates how many moles of a compound B are needed to the given moles of A.\n", 150 | " To achieve this, we multiply the given mass of A by 1/molar mass of A,\n", 151 | " then multiply the calculated moles of A by the ratio of what needs to be found (coeff B) and what is given (coeff A).\n", 152 | " inally, the mass of B is given by the product of the calculated moles of B by molar mass of B.\n", 153 | " Input: \n", 154 | " mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B\n", 155 | " Output: \n", 156 | " mass B\n", 157 | " \"\"\"\n", 158 | " # convert mass of N2 to moles of N2 using the molar mass of N2\n", 159 | " moles_A = mass_A*(1/molar_mass_A) # 1 mol N2/ g N2\n", 160 | " \n", 161 | " # mole-mole calculation\n", 162 | " moles_B = moles_A*(coeff_B/coeff_A)\n", 163 | " \n", 164 | " # convert moles of ammonia to mass of ammonia using the molar mass of ammonia\n", 165 | " mass_B = moles_B*(molar_mass_B) # g NH3/ 1 mol NH3\n", 166 | " return mass_B\n", 167 | "\n", 168 | "mass_A = 42 # g N2\n", 169 | "molar_mass_A = 28 # g N2 in 1 mol of N2\n", 170 | "molar_mass_B = 17 # g NH3 in 1 mol of NH3\n", 171 | "coeff_A = 1\n", 172 | "coeff_B = 2\n", 173 | "mass_B = mass_mass_calculation(mass_A, molar_mass_A, molar_mass_B, coeff_A, coeff_B)\n", 174 | "print(f'{mass_B} grams of NH3 produced from reacting 42 g of N2')" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "id": "5f77517b-2a25-4e8e-9e8c-533d125bde73", 180 | "metadata": {}, 181 | "source": [ 182 | "### How to balance coefficients in Python" 183 | ] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "id": "935e892e-521b-43ba-b7cd-b4417cd5df06", 188 | "metadata": {}, 189 | "source": [ 190 | "Take some time to investigate and understand the code below.\n", 191 | "Try to take the code apart and verify what each function is doing.\n", 192 | "Once you understand the code, try to see if you can simplify it.\n", 193 | "\n", 194 | "Suggested readings:\n", 195 | "- https://www.cliffsnotes.com/study-guides/algebra/linear-algebra/real-euclidean-vector-spaces/the-nullspace-of-a-matrix\n", 196 | "- https://en.wikipedia.org/wiki/Kernel_(linear_algebra)" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 57, 202 | "id": "d6041c7d-c729-4d25-b1fb-52970921c12a", 203 | "metadata": {}, 204 | "outputs": [], 205 | "source": [ 206 | "# code adapted from https://medium.com/swlh/balancing-chemical-equations-with-python-837518c9075b\n", 207 | "\n", 208 | "import re\n", 209 | "from sympy import Matrix, lcm\n", 210 | "\n", 211 | "element_list = []\n", 212 | "element_matrix = []\n", 213 | "reaction = 'H2 + N2 -> NH3'\n", 214 | "reactants = reaction.split(\"->\")[0].replace(' ', '').split(\"+\")\n", 215 | "products = reaction.split(\"->\")[1].replace(' ', '').split(\"+\")\n", 216 | "\n", 217 | "def add_matrix(element, index, count, side):\n", 218 | " if(index == len(element_matrix)):\n", 219 | " element_matrix.append([])\n", 220 | " for x in element_list:\n", 221 | " element_matrix[index].append(0)\n", 222 | " if(element not in element_list):\n", 223 | " element_list.append(element)\n", 224 | " for i in range(len(element_matrix)):\n", 225 | " element_matrix[i].append(0)\n", 226 | " column = element_list.index(element)\n", 227 | " element_matrix[index][column] += count*side\n", 228 | " \n", 229 | "def find_elements(segment, index, side):\n", 230 | " elements_numbers=re.split('([A-Z][a-z]?)',segment)\n", 231 | " i=0\n", 232 | " while(i < len(elements_numbers)-1):#last element always blank\n", 233 | " i += 1\n", 234 | " if(len(elements_numbers[i]) > 0):\n", 235 | " if(elements_numbers[i+1].isdigit()):\n", 236 | " count = int(elements_numbers[i+1])\n", 237 | " add_matrix(elements_numbers[i], index, count, side)\n", 238 | " i+=1\n", 239 | " else:\n", 240 | " add_matrix(elements_numbers[i], index, 1, side) \n", 241 | " \n", 242 | "for i in range(len(reactants)):\n", 243 | " find_elements(reactants[i], i, 1)\n", 244 | " \n", 245 | "for i in range(len(products)):\n", 246 | " find_elements(products[i], i+len(reactants), -1)\n", 247 | "\n", 248 | "# use Matrix function from sympy to convert list of lists to matrix\n", 249 | "element_matrix = Matrix(element_matrix)\n", 250 | "# transpose matrix vertically\n", 251 | "element_matrix = element_matrix.transpose()\n", 252 | "# nullspace or kernel mapping\n", 253 | "solution = element_matrix.nullspace()[0]\n", 254 | "# find the least common multiple (smallest positive integer that is divisible by the found coefficients)\n", 255 | "multiple = lcm([val.q for val in solution])\n", 256 | "# multiply solution my lcm\n", 257 | "solution = multiple*solution\n", 258 | "coeff = solution.tolist()" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "id": "5ae62bdc-fb2b-4f39-935d-2aa6149362bc", 264 | "metadata": {}, 265 | "source": [ 266 | "Once we balanced the reaction, we can print it in a nice form. \n", 267 | "This is what the following code is doing." 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 40, 273 | "id": "7a7e5452-949b-4368-a4ec-7ba79cafa97a", 274 | "metadata": {}, 275 | "outputs": [ 276 | { 277 | "name": "stdout", 278 | "output_type": "stream", 279 | "text": [ 280 | "3H2 + 1N2 -> 2NH3\n" 281 | ] 282 | } 283 | ], 284 | "source": [ 285 | "# assign the found coefficients to the reactants\n", 286 | "output = \"\"\n", 287 | "for i in range(len(reactants)):\n", 288 | " output += str(coeff[i][0])+reactants[i]\n", 289 | " if i < len(reactants)-1:\n", 290 | " output += \" + \"\n", 291 | "\n", 292 | "# assign the found coefficients to the reactants\n", 293 | "output += \" -> \"\n", 294 | "for i in range(len(products)):\n", 295 | " output += str(coeff[i+len(reactants)][0])+products[i]\n", 296 | " if i < len(products)-1:\n", 297 | " output += \" + \"\n", 298 | " \n", 299 | "# print the final reaction\n", 300 | "print(output)" 301 | ] 302 | } 303 | ], 304 | "metadata": { 305 | "kernelspec": { 306 | "display_name": "Python 3 (ipykernel)", 307 | "language": "python", 308 | "name": "python3" 309 | }, 310 | "language_info": { 311 | "codemirror_mode": { 312 | "name": "ipython", 313 | "version": 3 314 | }, 315 | "file_extension": ".py", 316 | "mimetype": "text/x-python", 317 | "name": "python", 318 | "nbconvert_exporter": "python", 319 | "pygments_lexer": "ipython3", 320 | "version": "3.8.10" 321 | } 322 | }, 323 | "nbformat": 4, 324 | "nbformat_minor": 5 325 | } 326 | -------------------------------------------------------------------------------- /week06/theory/2_stoichiometry_pt2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "8aa72181-e022-4adc-90b2-1a034b7f2a44", 6 | "metadata": {}, 7 | "source": [ 8 | "# Stoichiometry - Part 2" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "b7481870-19c1-4eb6-9565-555fc54fd640", 14 | "metadata": {}, 15 | "source": [ 16 | "## **Goal**: \n", 17 | "The aim of this lesson is to help you design functions to create stoichiometric tables in Python.\n", 18 | "\n", 19 | "Here, an example of how to create a stoichiometric table for an equalmolar reaction is provided.\n", 20 | "Afterwards, a few exercises are provided, so you can try to write your own functions, making them as much generalizable as possible.\n", 21 | "It's a good idea, once you have a working solution, to test the functions of different parameters to see if the results are still correct!\n", 22 | "\n", 23 | "**Remember**, the provided solution is is only **one of the many possible solutions**, so please do try to re-write the function yourself, optimize it and make it more generalizable." 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "id": "6d072e55-6af0-4fc8-b6a0-47e292d15796", 29 | "metadata": {}, 30 | "source": [ 31 | "## **Motivation**: \n", 32 | "Writing these functions in Python might look like a lot of (manual) work, since the tables are populated by strings. \n", 33 | "\n", 34 | "However, if you manage to create the functions for the different types of systems, then you can reuse them and just change the initial parameters provided!\n", 35 | "\n", 36 | "This will also (hopefully) help you thinking carefully about the conditions and the assumptions given (e.g. is the reaction isothermal? Is there a volume change?), since you will have to choose the specific function based on that. In our experience, this is something that students often struggle with, so we hope to provide a tool that helps you taking into account all of this!" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "id": "a485833d-ac9f-4cf6-be78-be283553d792", 42 | "metadata": {}, 43 | "source": [ 44 | "### **Example 1:**\n", 45 | "\n", 46 | "A company is about to start the production of B, this happens by the catalytic reaction:\n", 47 | "$A → B$\n", 48 | "\n", 49 | "The feed stream consists of $1 kmol/m^3$ A and $0.01 kmol/m^3$ B, this is done at a rate of $120 m^3/min$. \n", 50 | "The reaction rate can be written as an elementary reaction and is carried out isothermally in the liquid phase. The reaction rate constant k is $0.18 \\cdot 10^{-3}m^3 \\cdot mol^{-1} \\cdot s^{-1}$\n", 51 | "1) Draw up a stoichiometric table for the equation (here one possible solution is provided below):" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": 11, 57 | "id": "d3b0204c-daa2-4e54-b081-ef1ea8135ae5", 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "data": { 62 | "text/html": [ 63 | "
\n", 64 | "\n", 77 | "\n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | "
speciesF_j0changeF_jC_j
0AF_A0-F_A0*XF_A0*(1-X)C_A0*(1-X)
1B0.01*F_A00.01*F_A0*XF_A0*(0.01+X)C_A0*(0.01+X)
2T1.01*F_A001.01*F_A0None
\n", 115 | "
" 116 | ], 117 | "text/plain": [ 118 | " species F_j0 change F_j C_j\n", 119 | "0 A F_A0 -F_A0*X F_A0*(1-X) C_A0*(1-X)\n", 120 | "1 B 0.01*F_A0 0.01*F_A0*X F_A0*(0.01+X) C_A0*(0.01+X)\n", 121 | "2 T 1.01*F_A0 0 1.01*F_A0 None" 122 | ] 123 | }, 124 | "execution_count": 11, 125 | "metadata": {}, 126 | "output_type": "execute_result" 127 | } 128 | ], 129 | "source": [ 130 | "# Create a stoichiometric table here\n", 131 | "import pandas as pd\n", 132 | "\n", 133 | "def stoichiometry_equalmolar_reaction(A0, B0):\n", 134 | " \"\"\"\n", 135 | " Function to create the stoichiomatric table for an eualmolar reaction with one reactant (A) and one product (B).\n", 136 | " Input:\n", 137 | " A0, B0: initial streams of A and B, respectively, in kmol/m^3.\n", 138 | " Output:\n", 139 | " stoichiometry_table (pd.DataFrame): pandas dataframe of the stoichiometric table of the given reaction.\n", 140 | " It contains 5 columns: the species, \n", 141 | " the number of moles that each species initially presents (feed rate),\n", 142 | " the change in the number of moles brought about by reaction,\n", 143 | " the number of moles after time t (effluent rate),\n", 144 | " the concentration.\n", 145 | " \"\"\"\n", 146 | " # initial cnditions\n", 147 | " Fj0_A = 'F_A0'\n", 148 | " Fj0_B = f'{B0}*F_A0'\n", 149 | " Fj0_T = f'{A0 + B0}*F_A0'\n", 150 | " \n", 151 | " # change\n", 152 | " change_A = '-F_A0*X'\n", 153 | " change_B = f'{B0/A0}*F_A0*X'\n", 154 | " change_T = 0\n", 155 | " \n", 156 | " # after time t\n", 157 | " Fj_A = 'F_A0*(1-X)'\n", 158 | " Fj_B = f'F_A0*({B0}+X)'\n", 159 | " Fj_T = Fj0_T\n", 160 | " \n", 161 | " # concentration\n", 162 | " Cj_A = 'C_A0*(1-X)'\n", 163 | " Cj_B = f'C_A0*({B0}+X)'\n", 164 | " \n", 165 | " stoichiometry_table = pd.DataFrame()\n", 166 | " stoichiometry_table['species'] = ['A', 'B', 'T']\n", 167 | " stoichiometry_table['F_j0'] = [Fj0_A, Fj0_B, Fj0_T]\n", 168 | " stoichiometry_table['change'] = [change_A, change_B, change_T]\n", 169 | " stoichiometry_table['F_j'] = [Fj_A, Fj_B, Fj_T]\n", 170 | " stoichiometry_table['C_j'] = [Cj_A, Cj_B, None]\n", 171 | " \n", 172 | " return stoichiometry_table\n", 173 | " \n", 174 | "stoichiometry_equalmolar_reaction(1, 0.01)" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "id": "146cd313-bd5a-491f-b99e-a5d99ef33926", 180 | "metadata": {}, 181 | "source": [ 182 | "### **Example 2:**\n", 183 | "\n", 184 | "$2A(1)→ B(1)$\n", 185 | "\n", 186 | "takes place in the liquid phase. A kinetic study is carried out in a batch reactor under the following operating conditions. The concentration of A in the reactor at the start is $120 mol/m^3$. There is no B in the reactor at the start of the experiment and the temperature is assumed to be constant at 330 K.\n", 187 | "\n", 188 | "When solving the problem, it can be assumed that there are no volume changes during the reaction.\n", 189 | "\n", 190 | "1.1. Set up a stoichiometric table and find expressions for $C_A$ and $C_B$ as a function of the degree of conversion of A." 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "id": "304ff54a-de03-4eec-8a66-b53d7b247311", 197 | "metadata": {}, 198 | "outputs": [], 199 | "source": [ 200 | "# Your code here" 201 | ] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "id": "e5e557c8-bfcf-41a4-9de0-047ae22ebb29", 206 | "metadata": {}, 207 | "source": [ 208 | "### **Example 3:**\n", 209 | "\n", 210 | "A company is considering implementing a new reaction in their existing process plant. The reaction takes place in the gas phase and is autocatalytic. The reaction is described by the following expression:\n", 211 | "\n", 212 | "$A+0.5B → C+D$\n", 213 | "\n", 214 | "Where the product of the reaction, C, also catalyzes the reaction. \n", 215 | "\n", 216 | "The feed stream consists of equal amounts of A and B. $C_{A0} = C_{B0} = 5 kmol/m^3$. and the flow rate to the reactor is $v_0 = 10 m^3/h$. Laboratory experiments have shown that the reaction rate can be described with the following expression:\n", 217 | "\n", 218 | "$-r_A = k_1C_AC_BC_C \\quad [\\frac{kmol}{hm^3}]$\n", 219 | "\n", 220 | "Under the relevant conditions, the rate constant has been determined to be $k_1 = 0.05 \\frac{m^6}{kmol^2 \\cdot h}$. The reaction is carried out under isothermal conditions.\n", 221 | "\n", 222 | "Question 1.1 \n", 223 | "Set up a stoichiometric table for a flow reactor and derive expressions for the concentration of A, B and C as a function of the degree of conversion, X." 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": null, 229 | "id": "e855201e-5e66-470c-bdd7-a75706424ba8", 230 | "metadata": {}, 231 | "outputs": [], 232 | "source": [ 233 | "# Your code here" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "id": "da060ee0-ad08-4d77-add1-c1c1f2500b03", 239 | "metadata": {}, 240 | "source": [ 241 | "### **Example 4:**\n", 242 | "\n", 243 | "The reaction\n", 244 | "\n", 245 | "$3A+ \\frac{4}{5}B → \\frac{1}{4}C+D$\n", 246 | "\n", 247 | "takes place in liquid fase. A kinetic study is carried out in a batch reactor at the following operating conditions: the initial concentration of A in the reactor is $75 mol/m^3$. There is no C or D in the reactor at the start of the experiment and the temperature is assumed to be constant. A is the limiting reactant and B is present in excess.\n", 248 | "\n", 249 | "When solving the problem, it can be assumed that there are no volume changes during the reaction.\n", 250 | "\n", 251 | "Question 2.1.\n", 252 | "Draw up a stoichiometric table and find expressions for $C_A$ and $C_D$ as a function of the degree of conversion of A. Plot $C_A$, $C_C$ and $C_D$ as a function of time." 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": null, 258 | "id": "ee02378f-f65a-4859-8310-0017166a1446", 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "# Your code here" 263 | ] 264 | } 265 | ], 266 | "metadata": { 267 | "kernelspec": { 268 | "display_name": "Python 3 (ipykernel)", 269 | "language": "python", 270 | "name": "python3" 271 | }, 272 | "language_info": { 273 | "codemirror_mode": { 274 | "name": "ipython", 275 | "version": 3 276 | }, 277 | "file_extension": ".py", 278 | "mimetype": "text/x-python", 279 | "name": "python", 280 | "nbconvert_exporter": "python", 281 | "pygments_lexer": "ipython3", 282 | "version": "3.8.10" 283 | } 284 | }, 285 | "nbformat": 4, 286 | "nbformat_minor": 5 287 | } 288 | -------------------------------------------------------------------------------- /week07/practice/assignment_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "2afb139c-1c01-42ef-8cd3-11f29564533f", 6 | "metadata": {}, 7 | "source": [ 8 | "# 28342 E2022 Chemical Reaction Engineering Assignment 2\n", 9 | "## Energy balance for a laboratory equipment batch reactor for chemical synthesis" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "id": "8d0f3b57-2e1e-4129-9082-0f6f0ee9f1a9", 15 | "metadata": {}, 16 | "source": [ 17 | "## Instructions \n", 18 | "\n", 19 | "Please use Python to solve the exercises below. \n", 20 | "\n", 21 | "Your should hand in a jupyter notebook with your answers.\n", 22 | "When handing in, you are welcome to submit additional material you may have used, such as a scan of the paper to solve parts of the equations, Word and PDF documents and similar." 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "id": "035077e7-89b1-4438-9276-d6b0ee9aefd8", 28 | "metadata": {}, 29 | "source": [ 30 | "## Assignment 2" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "id": "66daf4d9-d025-4e9a-9643-ddbc197a7b54", 36 | "metadata": {}, 37 | "source": [ 38 | "In this programming exercise you will also have from a chemical engineering point of view the task to develop the energy balance for a batch reactor. This is a task, we have not yet investigated in the lectures or group exercises. \n", 39 | "We consider the following Reaction taking place in a laboratory sized reactor using a liquid phase:\n", 40 | "\n", 41 | "$A→B$\n", 42 | "\n", 43 | "The setup is described in the following:\n", 44 | "![alt text](assignment2_system.png)\n", 45 | "\n", 46 | "You can assume that the reaction order follows an elementary reaction and you have found in literature the rate velocity coefficient at 298 K to be 0.005 min-1. \n", 47 | "Please perform with help the following analysis:\n", 48 | "1. Calculate the conversion and the Temperature as a function of time under the assumption that the reactor is operated under adiabatic conditions starting with a temperature of 298 K. \n", 49 | "2. Repeat the calculations for the heated reactor. Here the heating bed will generate a constant temperature of 398 K. Plot the conversion and temperature of the reactor as function of the time\n", 50 | "3. Repeat the calculations for the reactor without reaction, in other words show how the reactor and the reactor mixture would behave as function of time assuming that no reaction takes place.\n" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "id": "d535d219-9667-4662-b310-453734c7efdd", 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "# Your code here" 61 | ] 62 | } 63 | ], 64 | "metadata": { 65 | "kernelspec": { 66 | "display_name": "Python 3 (ipykernel)", 67 | "language": "python", 68 | "name": "python3" 69 | }, 70 | "language_info": { 71 | "codemirror_mode": { 72 | "name": "ipython", 73 | "version": 3 74 | }, 75 | "file_extension": ".py", 76 | "mimetype": "text/x-python", 77 | "name": "python", 78 | "nbconvert_exporter": "python", 79 | "pygments_lexer": "ipython3", 80 | "version": "3.9.7" 81 | } 82 | }, 83 | "nbformat": 4, 84 | "nbformat_minor": 5 85 | } 86 | -------------------------------------------------------------------------------- /week07/practice/assignment_2_system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/f37542b41215bc162a766559f25f32e2a245bbea/week07/practice/assignment_2_system.png -------------------------------------------------------------------------------- /week07/theory/28342 E2022 Chemical Reaction Engineeering Assignment 2 draft.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FiammettaC/Chemical-Reaction-Engineering-in-Python/f37542b41215bc162a766559f25f32e2a245bbea/week07/theory/28342 E2022 Chemical Reaction Engineeering Assignment 2 draft.docx --------------------------------------------------------------------------------