From eed1889b8d6bc8d6dfe0a62abed435166c877fa7 Mon Sep 17 00:00:00 2001 From: Andrew Logsdail Date: Thu, 23 Oct 2025 18:33:59 +0100 Subject: [PATCH 1/4] Add files via upload Updated the notebook after teaching experience - broke down final task with clearer description, and also resolved clashing variable definitions. --- CH5210_Programming_1_Functions.ipynb | 1239 ++++++++++++++++++++++++++ 1 file changed, 1239 insertions(+) create mode 100644 CH5210_Programming_1_Functions.ipynb diff --git a/CH5210_Programming_1_Functions.ipynb b/CH5210_Programming_1_Functions.ipynb new file mode 100644 index 0000000..3077e18 --- /dev/null +++ b/CH5210_Programming_1_Functions.ipynb @@ -0,0 +1,1239 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "df9906a4-08f7-4c0d-b03a-a896fa30e882", + "metadata": { + "id": "df9906a4-08f7-4c0d-b03a-a896fa30e882" + }, + "source": [ + "# Programming 1 – Calculations in Python\n", + "\n", + "Authors:\n", + "- Dr Tom Slater\n", + "\n", + "Email: slatert2@cardiff.ac.uk\n", + "\n", + "## Learning Objectives\n", + "-\tUse Jupyter notebooks to execute Python code.\n", + "-\tDefine and call functions, including single-line functions using lambda.\n", + "-\tUse Python functions to calculate basic thermodynamic quantities.\n", + "\n", + "## Table of Contents\n", + "\n", + "1. [Variables and Types](#variables) \n", + "2. [Mathematical Operations](#maths)\n", + "3. [NumPy](#numpy)\n", + "4. [Functions](#functions)\n", + "5. [Lambda Functions](#lambda)\n", + "6. [End of Session Task](#final-task)\n", + "\n", + "### Further reading for this topic\n", + "\n", + "- [Software carpentry lessons](http://swcarpentry.github.io/python-novice-gapminder/index.html)\n", + "\n", + "**Jupyter Cheat Sheet**\n", + "- To run the currently highlighted cell and move focus to the next cell, hold ⇧ Shift and press ⏎ Enter;\n", + "- To run the currently highlighted cell and keep focus in the same cell, hold Ctrl and press ⏎ Enter;\n", + "- To get help for a specific function, place the cursor within the function's brackets, hold ⇧ Shift, and press ⇥ Tab;" + ] + }, + { + "cell_type": "markdown", + "id": "ce563f6f-d25f-4a3b-a536-e0fd0cd7df78", + "metadata": { + "id": "ce563f6f-d25f-4a3b-a536-e0fd0cd7df78" + }, + "source": [ + "## 1. Variables and Types\n", + "\n", + "\n", + "Python variables store data. Variables can have almost any name but it's best to use an understandable name. For example:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "172b1bfe-8f9e-4561-ad46-7f0fe0275745", + "metadata": { + "id": "172b1bfe-8f9e-4561-ad46-7f0fe0275745" + }, + "outputs": [], + "source": [ + "mass_of_electron = 9.1093837e-31" + ] + }, + { + "cell_type": "markdown", + "id": "968ed4b1-b055-4ea1-8536-ad6996a37c5a", + "metadata": { + "id": "968ed4b1-b055-4ea1-8536-ad6996a37c5a" + }, + "source": [ + "The most used style guide for programming in Python is [PEP8](https://peps.python.org/pep-0008/). This style guide notes that variables should include only lowercase letters and words should be separated by underscores. Hence the name used above!" + ] + }, + { + "cell_type": "markdown", + "id": "e0496e67-3dc1-411e-87e3-80f5d0851e53", + "metadata": { + "id": "e0496e67-3dc1-411e-87e3-80f5d0851e53" + }, + "source": [ + "Variables can have a variety of different types. To determine the type of a variable, we can apply the type() function to the variable." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8c14913-57ee-418b-a138-6ec4b4a8f438", + "metadata": { + "id": "e8c14913-57ee-418b-a138-6ec4b4a8f438" + }, + "outputs": [], + "source": [ + "type(mass_of_electron)" + ] + }, + { + "cell_type": "markdown", + "id": "e91fbddc-565b-4091-a174-89c23ba10ce9", + "metadata": { + "id": "e91fbddc-565b-4091-a174-89c23ba10ce9" + }, + "source": [ + "The most common types (most of which we saw in first year programming) include:\n", + "\n", + "- Integers (int): Whole numbers.\n", + "- Floating point numbers (float): Any real number including a decimal point.\n", + "- Strings (str): Groups of characters, e.g., a word or sentence.\n", + "- Booleans (bool): True or false.\n", + "- Lists (list): Collection of multiple items.\n", + "\n", + "As examples, lets print the type of some variables:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12ce4b1d-5b80-4811-a104-8c5687ccd7d1", + "metadata": { + "id": "12ce4b1d-5b80-4811-a104-8c5687ccd7d1" + }, + "outputs": [], + "source": [ + "quantum_number = 2\n", + "print(type(quantum_number))\n", + "\n", + "mass_of_electron = 9.1093837e-31\n", + "print(type(mass_of_electron))\n", + "\n", + "scientist_name = \"Erwin Schrödinger\"\n", + "print(type(scientist_name))\n", + "\n", + "cat_alive = True\n", + "print(type(cat_alive))\n", + "\n", + "first_five_numbers = [1, 2, 3, 4, 5]\n", + "print(type(first_five_numbers))" + ] + }, + { + "cell_type": "markdown", + "id": "a8520fe7-832c-483c-bcc2-bcde281c6213", + "metadata": { + "id": "a8520fe7-832c-483c-bcc2-bcde281c6213" + }, + "source": [ + "One of the big benefits of Python is that you don't have to declare the type of a variable, Python interprets the type for you. You can also change the type of a variable, which can be useful but can also present risks!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6f45ae95-47a5-4b1d-89c4-9b8e9340ffda", + "metadata": { + "id": "6f45ae95-47a5-4b1d-89c4-9b8e9340ffda" + }, + "outputs": [], + "source": [ + "mass_of_electron = 1\n", + "print(type(mass_of_electron))" + ] + }, + { + "cell_type": "markdown", + "id": "bac7e654-dba4-415a-b1dd-fad47e39384a", + "metadata": { + "id": "bac7e654-dba4-415a-b1dd-fad47e39384a" + }, + "source": [ + "
\n", + "Task 1.1: Define and assign variables with suitable names for:
\n", + "- The ideal gas constant.
\n", + "- The atomic number of an element (pick your favourite).
\n", + "- The name of an element (pick your favourite).\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "95099844-568d-4145-9e94-9cd456b96177", + "metadata": { + "id": "95099844-568d-4145-9e94-9cd456b96177" + }, + "outputs": [], + "source": [ + "#Enter code for Task 1.1 here\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "08aaf655-df6b-4152-8ffc-b03c78e21763", + "metadata": { + "id": "08aaf655-df6b-4152-8ffc-b03c78e21763" + }, + "source": [ + "
\n", + "Task 1.2: Create a list that contains all of the variables created in Task 1.1.
\n", + "\n", + "Note here: Lists can contain items of different types!\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9bc0091a-b1ab-4346-baae-2a7aa99e4fc2", + "metadata": { + "id": "9bc0091a-b1ab-4346-baae-2a7aa99e4fc2" + }, + "outputs": [], + "source": [ + "#Enter code for Task 1.2 here\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "2a9b1829-2bb9-49a5-8700-bd493f7f2c25", + "metadata": { + "id": "2a9b1829-2bb9-49a5-8700-bd493f7f2c25" + }, + "source": [ + "## 2. Simple mathematical operations\n", + "\n", + "\n", + "In this session, we will be using Python to perform mathematical operations. Python has a number of native mathematical operators, which include:\n", + "\n", + "- (+) : addition\n", + "- (-) : subtraction\n", + "- (/) : division\n", + "- (//): floor division\n", + "- (*) : multiplication\n", + "- (**): raise to the power\n", + "\n", + "These are mostly straightforward, as shown in the examples below:" + ] + }, + { + "cell_type": "markdown", + "id": "d7172e5d-777b-4f05-a4d8-036d13a1ee99", + "metadata": { + "id": "d7172e5d-777b-4f05-a4d8-036d13a1ee99" + }, + "source": [ + "Addition:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a30b54a5-4729-444e-9aa6-6c7376c6cbf2", + "metadata": { + "id": "a30b54a5-4729-444e-9aa6-6c7376c6cbf2" + }, + "outputs": [], + "source": [ + "3+2" + ] + }, + { + "cell_type": "markdown", + "id": "6e6d2283-65e3-43aa-8728-3ae8204bc9a4", + "metadata": { + "id": "6e6d2283-65e3-43aa-8728-3ae8204bc9a4" + }, + "source": [ + "Multiplication:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "123b3bf9-d74b-41f4-9bd3-883194e21934", + "metadata": { + "id": "123b3bf9-d74b-41f4-9bd3-883194e21934" + }, + "outputs": [], + "source": [ + "3*2" + ] + }, + { + "cell_type": "markdown", + "id": "b397aa60-7e7a-41a5-90bb-061211e3ccc6", + "metadata": { + "id": "b397aa60-7e7a-41a5-90bb-061211e3ccc6" + }, + "source": [ + "Exponentials:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0fef4c77-a559-4f25-9355-e52c209dc305", + "metadata": { + "id": "0fef4c77-a559-4f25-9355-e52c209dc305" + }, + "outputs": [], + "source": [ + "3**2" + ] + }, + { + "cell_type": "markdown", + "id": "b921b248-d683-47dd-acf9-7264a1a660e8", + "metadata": { + "id": "b921b248-d683-47dd-acf9-7264a1a660e8" + }, + "source": [ + "The two division operators require a little more explanation. The (/) operator does division in a standard way, i.e., it will output a non-integer if the numerator is not divisble by the denominator." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b3e5e65-a0b9-472d-8c97-db9165fe0532", + "metadata": { + "id": "0b3e5e65-a0b9-472d-8c97-db9165fe0532" + }, + "outputs": [], + "source": [ + "3/2" + ] + }, + { + "cell_type": "markdown", + "id": "33d97710-6433-4851-a9a0-e8f295dfe2b6", + "metadata": { + "id": "33d97710-6433-4851-a9a0-e8f295dfe2b6" + }, + "source": [ + "However, the (//) operator will do the division and round down to the nearest integer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58dc4d4a-81b1-4d07-bb1e-87fa9cb38186", + "metadata": { + "id": "58dc4d4a-81b1-4d07-bb1e-87fa9cb38186" + }, + "outputs": [], + "source": [ + "3//2" + ] + }, + { + "cell_type": "markdown", + "id": "d733df28-c4ff-44fe-990a-477dc6d75ee8", + "metadata": { + "id": "d733df28-c4ff-44fe-990a-477dc6d75ee8" + }, + "source": [ + "This is true even if using floating point numbers!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88ba2637-429f-4dd2-b1a1-a92b1fb77226", + "metadata": { + "id": "88ba2637-429f-4dd2-b1a1-a92b1fb77226" + }, + "outputs": [], + "source": [ + "3.0//2.0" + ] + }, + { + "cell_type": "markdown", + "id": "46b1893b-306b-4292-bf11-d1fcf033b7b9", + "metadata": { + "id": "46b1893b-306b-4292-bf11-d1fcf033b7b9" + }, + "source": [ + "### 2.1 Mathematical operations on lists\n", + "\n", + "Some of the operators above also work on lists, but in a manner that is very different to their operations on integers or floating point numbers.\n", + "\n", + "For instance, the + operator concatenates (joins together) the two lists here, rather than adding the values together." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b2424b2-206d-4405-9c71-5895b150a612", + "metadata": { + "id": "2b2424b2-206d-4405-9c71-5895b150a612" + }, + "outputs": [], + "source": [ + "[1, 2] + [3, 4]" + ] + }, + { + "cell_type": "markdown", + "id": "90c9c2fd-7883-441a-aa0d-c85731da252e", + "metadata": { + "id": "90c9c2fd-7883-441a-aa0d-c85731da252e" + }, + "source": [ + "It's possible to multiply a list by an integer, but this simply adds copies of the list elements to the list." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6f513c37-c15b-4081-b9af-9b141c2a4238", + "metadata": { + "id": "6f513c37-c15b-4081-b9af-9b141c2a4238" + }, + "outputs": [], + "source": [ + "[1, 2] * 2" + ] + }, + { + "cell_type": "markdown", + "id": "df5e9872-6e44-45c1-920b-deaf54e4d32b", + "metadata": { + "id": "df5e9872-6e44-45c1-920b-deaf54e4d32b" + }, + "source": [ + "For many calculations, we will have a one-dimensional set of data that we would like to perform a mathematical operation on. We've seen that this is difficult to achieve with lists, but next we'll move onto the NumPy package which makes this much easier." + ] + }, + { + "cell_type": "markdown", + "id": "39a62387-2e2d-4114-b95f-720396f272f1", + "metadata": { + "id": "39a62387-2e2d-4114-b95f-720396f272f1" + }, + "source": [ + "
\n", + "Task 2.1: Perform the following calculations:
\n", + "- Add 3.14 to 2.72.
\n", + "- Set the variable `a` to be 3. Multiply `a` by 4.
\n", + "- Set the variable `b` to be 1. Add 3 to `b` and then raise it to the power 3.\n", + "\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6bed00df-2d62-45c8-9702-53effecb56e9", + "metadata": { + "id": "6bed00df-2d62-45c8-9702-53effecb56e9" + }, + "outputs": [], + "source": [ + "#Enter code for Task 2.1 here\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "8b500b65-e3e9-42c3-ae64-18dfbc9d90a8", + "metadata": { + "id": "8b500b65-e3e9-42c3-ae64-18dfbc9d90a8" + }, + "source": [ + "## 3. NumPy\n", + "\n", + "\n", + "NumPy is the standard package for working with numerical arrays in Python. We can import NumPy using the `import` statement. Here, we are importing NumPy to use with the name `np`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93a4d7e7-1349-495c-957b-e2082c03cd9e", + "metadata": { + "id": "93a4d7e7-1349-495c-957b-e2082c03cd9e" + }, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "id": "5bcff21f-d0bc-4d88-a299-9e9a67518786", + "metadata": { + "id": "5bcff21f-d0bc-4d88-a299-9e9a67518786" + }, + "source": [ + "An array is similar to a matrix, but can have any number of dimensions. We'll stick to one dimension in this session.\n", + "\n", + "To create an array, you can use the `array` function within NumPy with a list of numbers as input." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3d7e420d-ff24-48f5-880d-8dbbd5eada0a", + "metadata": { + "id": "3d7e420d-ff24-48f5-880d-8dbbd5eada0a" + }, + "outputs": [], + "source": [ + "arr = np.array([1, 2, 3, 4, 5])\n", + "print(arr)" + ] + }, + { + "cell_type": "markdown", + "id": "b6db5657-a3cc-4fa8-ba77-d90851dc942b", + "metadata": { + "id": "b6db5657-a3cc-4fa8-ba77-d90851dc942b" + }, + "source": [ + "To create larger arrays, there are other in-built functions. For example, to create a linearly-spaced array (i.e., the same interval between all elements), the `linspace` function can be used. Using `linspace` requires arguments of the form `linspace(start,stop,number of values)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7aca0f5-79f0-465c-94ab-df39b72a426a", + "metadata": { + "id": "e7aca0f5-79f0-465c-94ab-df39b72a426a" + }, + "outputs": [], + "source": [ + "arr2 = np.linspace(1,5,5)\n", + "print(arr2)" + ] + }, + { + "cell_type": "markdown", + "id": "8e6045e0-a370-410f-b46a-7c8d18b9058c", + "metadata": { + "id": "8e6045e0-a370-410f-b46a-7c8d18b9058c" + }, + "source": [ + "
\n", + "Task 3.1: Use the linspace function to create a numpy array `data` with the values [10, 20, 30, 40, 50].
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3fa2153-6868-4338-b581-3391d80ec84b", + "metadata": { + "id": "d3fa2153-6868-4338-b581-3391d80ec84b" + }, + "outputs": [], + "source": [ + "#Enter code for Task 3.1 here\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "829aefc0-e623-49e0-9bc2-1c9cdc32e766", + "metadata": { + "id": "829aefc0-e623-49e0-9bc2-1c9cdc32e766" + }, + "source": [ + "### 3.1 Mathematical operations on NumPy arrays" + ] + }, + { + "cell_type": "markdown", + "id": "9eb0af3b-81a6-417f-bf26-2bea7b2cc410", + "metadata": { + "id": "9eb0af3b-81a6-417f-bf26-2bea7b2cc410" + }, + "source": [ + "A major advantage of NumPy arrays over lists is that it's straightforward to use mathematical operations.\n", + "\n", + "The mathematical operators used in Section 2 work on NumPy arrays in an element-wise fashion. That is, they operate individually on each element. Here are some examples using the array created above." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79f4d10c-328b-4b20-b8e3-08d0877b4015", + "metadata": { + "id": "79f4d10c-328b-4b20-b8e3-08d0877b4015" + }, + "outputs": [], + "source": [ + "# Basic operations\n", + "arr_times_two = arr * 2\n", + "arr_squared = arr ** 2\n", + "\n", + "print(arr_times_two, arr_squared)" + ] + }, + { + "cell_type": "markdown", + "id": "1dbc4af1-e85e-450c-bd6e-ab3ee9d6ce46", + "metadata": { + "id": "1dbc4af1-e85e-450c-bd6e-ab3ee9d6ce46" + }, + "source": [ + "It's also possible to perform maths using two NumPy arrays, but only if they are the same size. For instance, adding one array to another." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b0d6ae0-ea67-4115-b4c6-fa889a7f5b25", + "metadata": { + "id": "0b0d6ae0-ea67-4115-b4c6-fa889a7f5b25" + }, + "outputs": [], + "source": [ + "arr_summed = arr_times_two + arr_squared\n", + "print(arr_summed)" + ] + }, + { + "cell_type": "markdown", + "id": "b354d534-3d04-42be-affa-954e2c08168b", + "metadata": { + "id": "b354d534-3d04-42be-affa-954e2c08168b" + }, + "source": [ + "NumPy also includes useful mathematical functions. For example, taking the logarithm or exponential of elements of an array." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a16939eb-148c-4f4e-89e6-33cf9c79c5d1", + "metadata": { + "id": "a16939eb-148c-4f4e-89e6-33cf9c79c5d1" + }, + "outputs": [], + "source": [ + "# Useful functions\n", + "log_arr = np.log(arr)\n", + "exp_arr = np.exp(arr)\n", + "print(log_arr,exp_arr)" + ] + }, + { + "cell_type": "markdown", + "id": "497a9d7e-bf47-42bc-bdf4-d302ad03a5f2", + "metadata": { + "id": "497a9d7e-bf47-42bc-bdf4-d302ad03a5f2" + }, + "source": [ + "As a note that will be particularly useful for the End of Session Task, if you try to take the log of 0 using `np.log` you will get a warning and the resultant element will be infinite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "155af08b-126c-4680-a3d8-92c6768a221a", + "metadata": { + "id": "155af08b-126c-4680-a3d8-92c6768a221a" + }, + "outputs": [], + "source": [ + "np.log(log_arr)" + ] + }, + { + "cell_type": "markdown", + "id": "58435cff-8e5d-427b-9060-506872e4c7ef", + "metadata": { + "id": "58435cff-8e5d-427b-9060-506872e4c7ef" + }, + "source": [ + "One way to avoid having zeros in any array is to use the `np.clip()` function. This function will clip any values which are not within the bounds set in the function call. For example, the following code will clip the zero value to 0.01." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17d77ac1-0d65-4ed9-9dd2-30ab1b9e8cf9", + "metadata": { + "id": "17d77ac1-0d65-4ed9-9dd2-30ab1b9e8cf9" + }, + "outputs": [], + "source": [ + "np.clip(log_arr, 0.01, 2.)" + ] + }, + { + "cell_type": "markdown", + "id": "62843c23-8fe7-4b5f-8b4e-172515330db2", + "metadata": { + "id": "62843c23-8fe7-4b5f-8b4e-172515330db2" + }, + "source": [ + "
\n", + "Task 3.2: Subtract 10 from your `data` array, clip the array so that no elements are zero and take its logarithm.
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ba2ab4d-697b-458e-82b4-aba20c7035c5", + "metadata": { + "id": "3ba2ab4d-697b-458e-82b4-aba20c7035c5" + }, + "outputs": [], + "source": [ + "#Enter code for Task 3.2 here\n" + ] + }, + { + "cell_type": "markdown", + "id": "f26fa3bb-fc83-461a-a738-d50629134d1e", + "metadata": { + "id": "f26fa3bb-fc83-461a-a738-d50629134d1e" + }, + "source": [ + "### 3.2 Indexing and slicing" + ] + }, + { + "cell_type": "markdown", + "id": "6ef0bd66-5f15-4307-87cd-8ddc61c5ed4a", + "metadata": { + "id": "6ef0bd66-5f15-4307-87cd-8ddc61c5ed4a" + }, + "source": [ + "It's often necessary to check the value of one or more elements inside an array, and if the array is particularly long this can be difficult from just visually inspecting the array. Thankfully, NumPy has an easy way to access individual elements of an array, indexing.\n", + "\n", + "A single element of a NumPy array can be indexed using square brackets." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67a7f1e2-6937-4fc7-badc-959c4c244a81", + "metadata": { + "id": "67a7f1e2-6937-4fc7-badc-959c4c244a81" + }, + "outputs": [], + "source": [ + "print(\"First element:\", arr[0])" + ] + }, + { + "cell_type": "markdown", + "id": "312f41df-3ae5-4217-b4d9-ca44c87533f6", + "metadata": { + "id": "312f41df-3ae5-4217-b4d9-ca44c87533f6" + }, + "source": [ + "Remember, in Python indexing starts from 0 (NOT 1!). It's also possible to index from the end of an array by using a minus sign." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a75abb0-87aa-41b8-85da-a71e20c1e790", + "metadata": { + "id": "1a75abb0-87aa-41b8-85da-a71e20c1e790" + }, + "outputs": [], + "source": [ + "print(\"Last element:\", arr[-1])\n", + "\n", + "print(\"Third last element:\", arr[-3])" + ] + }, + { + "cell_type": "markdown", + "id": "89e9176f-0dfd-48f1-bbcd-dd422625e0d6", + "metadata": { + "id": "89e9176f-0dfd-48f1-bbcd-dd422625e0d6" + }, + "source": [ + "Use of square brackets can also be used to access more than one element of an array. This is called slicing. To slice an array, a colon (:) is used. The colon is placed between the elements to slice between, e.g.," + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cba6d7c-3092-4a34-adad-a61686dc66a0", + "metadata": { + "id": "1cba6d7c-3092-4a34-adad-a61686dc66a0" + }, + "outputs": [], + "source": [ + "print(\"First three elements:\", arr[0:3])\n", + "\n", + "#Slicing from the first element or to the last element doesn't need the 0 to be included\n", + "print(\"First three elements:\", arr[:3])\n", + "print(\"Last three elements:\", arr[-3:])" + ] + }, + { + "cell_type": "markdown", + "id": "ccb62091-0deb-467f-a1e7-8e73a3b29caa", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "id": "ccb62091-0deb-467f-a1e7-8e73a3b29caa" + }, + "source": [ + "
\n", + "Task 3.3: Print the first two elements and last element of the logarithm of `data`.
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "817c3dce-ab09-4a49-83f4-4af4a7dbbf52", + "metadata": { + "id": "817c3dce-ab09-4a49-83f4-4af4a7dbbf52" + }, + "outputs": [], + "source": [ + "#Enter code for Task 3.3 here\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "4220b5e0-5ff1-4cef-aab9-366f1752a183", + "metadata": { + "id": "4220b5e0-5ff1-4cef-aab9-366f1752a183" + }, + "source": [ + "## 4. Functions\n", + "\n", + "\n", + "You were previously introduced to functions in first year programming, and we've seen a number of them used in this notebook already! In essence, functions let you reuse code, which can be incredibly useful for carrying out the same actions again and again." + ] + }, + { + "cell_type": "markdown", + "id": "6b214fbb-94df-4573-bdf8-93103d3f0cf7", + "metadata": { + "id": "6b214fbb-94df-4573-bdf8-93103d3f0cf7" + }, + "source": [ + "We've already used one function extensively in this notebook, the `print()` function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a54bf0e7-0ac6-48bb-8d1c-6d3426c43daf", + "metadata": { + "id": "a54bf0e7-0ac6-48bb-8d1c-6d3426c43daf" + }, + "outputs": [], + "source": [ + "print('Hello')" + ] + }, + { + "cell_type": "markdown", + "id": "228d9053-0436-493f-801b-77b922c89987", + "metadata": { + "id": "228d9053-0436-493f-801b-77b922c89987" + }, + "source": [ + "Using a function is known as \"calling\" a function, the above statement calls the `print` function with an argument of 'Hello'. Functions arguments are the inputs to a function and go inside the brackets of a function call." + ] + }, + { + "cell_type": "markdown", + "id": "f97c61a9-2922-47ec-9655-857d37128559", + "metadata": { + "id": "f97c61a9-2922-47ec-9655-857d37128559" + }, + "source": [ + "Now you know how functions are used, but how do you define your own functions? In Python you define them with `def`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f43793e-973f-4f71-b1c3-cd828fc4993a", + "metadata": { + "id": "7f43793e-973f-4f71-b1c3-cd828fc4993a" + }, + "outputs": [], + "source": [ + "def square(x):\n", + " return(x ** 2)" + ] + }, + { + "cell_type": "markdown", + "id": "a3c5707c-6abb-4afd-b43d-b7a2b31e6192", + "metadata": { + "id": "a3c5707c-6abb-4afd-b43d-b7a2b31e6192" + }, + "source": [ + "The above code is known as a function definition, i.e., where a function is defined. Let's go through this in detail:\n", + "\n", + "- The function definition starts with `def`.\n", + "- After `def` comes the name of the function.\n", + "- Then, the input to the function (the arguments) are included in brackets immediately after the function name. The arguments can have any name, but this variable name should only be used within the function, it shouldn't be a variable name used outside of the function.\n", + "- A colon follows the brackets.\n", + "- The contents of the functions (what it does) is included on the lines immediately following the first line. The Python interpreter only includes lines that have been indented after the colon. The next line which is not indented is read as being outside the function.\n", + "- Most functions include a return statement. This tells the Python interpreter what the output of the function is. In the case above, the output is the square of the input." + ] + }, + { + "cell_type": "markdown", + "id": "56886d1c-fdc6-47c0-994f-8e6f78c9fb8c", + "metadata": { + "id": "56886d1c-fdc6-47c0-994f-8e6f78c9fb8c" + }, + "source": [ + "The code above only defines the function `square()`, it doesn't call the function (i.e., use it). Let's try calling the function with a few different arguments." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52c78a96-2270-433b-bfe1-181c3ad56a90", + "metadata": { + "id": "52c78a96-2270-433b-bfe1-181c3ad56a90" + }, + "outputs": [], + "source": [ + "square(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a3de092-1e24-4ddb-b105-3ff76eb210aa", + "metadata": { + "id": "6a3de092-1e24-4ddb-b105-3ff76eb210aa" + }, + "outputs": [], + "source": [ + "square(3.4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b502c498-a0cd-407a-92d4-ed5c48c3d241", + "metadata": { + "id": "b502c498-a0cd-407a-92d4-ed5c48c3d241" + }, + "outputs": [], + "source": [ + "square([3,4,5]) #Should get an error" + ] + }, + { + "cell_type": "markdown", + "id": "c44dcd41-e361-4200-9bab-33ac87b67df5", + "metadata": { + "id": "c44dcd41-e361-4200-9bab-33ac87b67df5" + }, + "source": [ + "The code cell above should throw an error, as it's not possible to square a list!\n", + "\n", + "However, it is possible to square a NumPy array:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d503bff-1edd-41ea-bcd0-ccf5b9ae0af7", + "metadata": { + "id": "8d503bff-1edd-41ea-bcd0-ccf5b9ae0af7" + }, + "outputs": [], + "source": [ + "square(arr)" + ] + }, + { + "cell_type": "markdown", + "id": "d5d75c37-8a4a-4929-a0f4-5574ba4106e9", + "metadata": { + "id": "d5d75c37-8a4a-4929-a0f4-5574ba4106e9" + }, + "source": [ + "### 4.1 Multiple arguments" + ] + }, + { + "cell_type": "markdown", + "id": "ef977a3b-9fda-4489-b893-5494da2d811e", + "metadata": { + "id": "ef977a3b-9fda-4489-b893-5494da2d811e" + }, + "source": [ + "Functions can take multiple arguments and can return multiple objects. If using multiple arguments, these should be separated by a comma." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f21f5254-a0ae-43c8-b970-61bdf3ee41e2", + "metadata": { + "id": "f21f5254-a0ae-43c8-b970-61bdf3ee41e2" + }, + "outputs": [], + "source": [ + "def add(a, b):\n", + " return(a + b)\n", + "\n", + "print(\"Sum of 4 and 5:\", add(4, 5))" + ] + }, + { + "cell_type": "markdown", + "id": "d519186e-f280-4766-bfe4-e732c7e54421", + "metadata": { + "id": "d519186e-f280-4766-bfe4-e732c7e54421" + }, + "source": [ + "
\n", + "Task 4.1: Write a function to calculate the total number of moles, $n$, of reactant and product in the reaction $A \\rightarrow 2B$, where the arguments should be initial moles of A and the extent of reaction $\\xi$. Use the function to calculate the total number of moles at $\\xi = 0.4$ when the reaction started with 3 mol of A.
\n", + "
\n", + "Hint: The number of moles of reactant equals 1 - $\\xi$. What are the number of moles of product with respect to $\\xi$?\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d948eab9-1d6e-4b1c-996b-14d0a06868ab", + "metadata": { + "id": "d948eab9-1d6e-4b1c-996b-14d0a06868ab" + }, + "outputs": [], + "source": [ + "#Enter code for Task 4.1 here\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "d609b02a-a3c3-47f5-adce-679117add890", + "metadata": { + "id": "d609b02a-a3c3-47f5-adce-679117add890" + }, + "source": [ + "## 5. Lambda functions\n", + "\n", + "\n", + "Python also allows you to define small functions of a single output using `lambda`.\n", + "\n", + "They are useful for short, throwaway mathematical functions. An example is shown below, where the variable `cube` is assigned a lambda function. The arguments immediately follow the `lambda`, with the output following a colon. Lambda functions should always be single lines of code." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "469e76ba-dd86-4609-9523-aea0cb2babe2", + "metadata": { + "id": "469e76ba-dd86-4609-9523-aea0cb2babe2" + }, + "outputs": [], + "source": [ + "# A lambda function to compute x^3\n", + "cube = lambda x: x**3\n", + "\n", + "cube(2)" + ] + }, + { + "cell_type": "markdown", + "id": "6c2bcd02-7348-4f3f-8d93-2d6d4499ea0b", + "metadata": { + "id": "6c2bcd02-7348-4f3f-8d93-2d6d4499ea0b" + }, + "source": [ + "Lambda functions can take multiple arguments." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8df72e66-d87d-4036-a203-56f5892cd6b3", + "metadata": { + "id": "8df72e66-d87d-4036-a203-56f5892cd6b3" + }, + "outputs": [], + "source": [ + "# A lambda function to multiply two variables\n", + "multiply = lambda x, y: x * y\n", + "\n", + "multiply(2,3)" + ] + }, + { + "cell_type": "markdown", + "id": "12df3734-9c6d-4e8f-8fa9-e806771cebb6", + "metadata": { + "id": "12df3734-9c6d-4e8f-8fa9-e806771cebb6" + }, + "source": [ + "
\n", + "Task 5.1: Write a lambda function to compute the mole fraction of product in the reaction $A \\rightarrow 2B$, where the only required argument is the extent of reaction. Use the function to calculate the mole fraction of B at $\\xi = 0.5$.
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77f22e8c-ceee-4d1b-8322-05f4c7caf54f", + "metadata": { + "id": "77f22e8c-ceee-4d1b-8322-05f4c7caf54f" + }, + "outputs": [], + "source": [ + "#Enter code for Task 5.1 here\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "c77f07f2-2efc-45b6-94e7-450bed8aa41f", + "metadata": { + "id": "c77f07f2-2efc-45b6-94e7-450bed8aa41f" + }, + "source": [ + "## End of Session Task\n", + "\n", + "\n", + "Write a function called `gibbs_energy` that calculates the change in Gibbs energy at different extents of reaction ($\\xi$) for a reaction of the form:\n", + "\n", + "
$A(g) \\rightarrow 2B(g)$
\n", + "\n", + "Assume 1 mol of A at $\\xi = 0$.\n", + "\n", + "The change in Gibbs energy change is defined as the sum of contributions from the change in Gibbs energy between reactant and product ($\\Delta G_{\\mathrm{core}}$) and the Gibbs energy change due to mixing ($\\Delta G_{\\mathrm{mix}}$):\n", + "\n", + "
$\\Delta G_{\\mathrm{total}}(\\xi) = \\Delta G_{\\mathrm{core}}(\\xi) + \\Delta G_{\\mathrm{mix}}(\\xi)$
\n", + "\n", + "The Gibbs energy change due to mixing is given by the equation:\n", + "\n", + "
$\\Delta G_{\\text{mix}}(\\xi) = RT \\Big[ n_A\\ln(\\chi_A) + n_B\\ln(\\chi_B) \\Big]$
\n", + "\n", + "where $\\chi$ is the mole fraction of a respective species.\n", + "\n", + "\n", + "The function `gibbs_energy` must take the following arguments:\n", + "- The change in Gibbs energy between the reactant and product.\n", + "- The temperature at which the reaction takes place.\n", + "\n", + "and return:\n", + "- A 1D NumPy array representing the extent of reaction.\n", + "- A 1D NumPy array representing the Gibbs energy change for each extent of reaction." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a11be95-8273-415c-8ca6-1597f2426772", + "metadata": { + "id": "3a11be95-8273-415c-8ca6-1597f2426772" + }, + "outputs": [], + "source": [ + "#Enter code for End of Session Task here\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "9b301f4f-2862-473c-b06e-9f24d5c0fccd", + "metadata": { + "id": "9b301f4f-2862-473c-b06e-9f24d5c0fccd" + }, + "source": [ + "Once you have completed the End of Session Task, run the code cell below to use your code to create an interactive plot of the Gibbs energy of a reaction based on the difference in Gibbs energy of reactant and product!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8dbea88e-dfa4-440d-b304-0ab99c557b74", + "metadata": { + "id": "8dbea88e-dfa4-440d-b304-0ab99c557b74" + }, + "outputs": [], + "source": [ + "from ipywidgets import interact, FloatSlider\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def plot_gibbs(delta_G, T=298):\n", + " xi, dG = gibbs_energy(delta_G, T)\n", + "\n", + " plt.figure(figsize=(6,4))\n", + " plt.plot(xi, dG, lw=2)\n", + " plt.axhline(0, color='k', ls='--')\n", + " plt.xlabel(\"Extent of reaction, ξ\")\n", + " plt.ylabel(\"ΔG (J/mol)\")\n", + " plt.title(f\"Gibbs Energy Profile (ΔG° = {delta_G:.0f} J/mol)\")\n", + " plt.grid(True, alpha=0.3)\n", + " plt.show()\n", + "\n", + "\n", + "# Interactive widget\n", + "interact(\n", + " plot_gibbs,\n", + " delta_G=FloatSlider(value=0, min=-2e4, max=2e4, step=10, description=\"ΔG° (J/mol)\")\n", + ");" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "particlespy_270423", + "language": "python", + "name": "particlespy_270423" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file From 05624431c258f158b081a8532a0b5c1bce0a088c Mon Sep 17 00:00:00 2001 From: Andrew Logsdail Date: Thu, 23 Oct 2025 18:34:41 +0100 Subject: [PATCH 2/4] Delete CH5210 Programming 1 - Functions.ipynb Moving files around. --- CH5210 Programming 1 - Functions.ipynb | 1228 ------------------------ 1 file changed, 1228 deletions(-) delete mode 100644 CH5210 Programming 1 - Functions.ipynb diff --git a/CH5210 Programming 1 - Functions.ipynb b/CH5210 Programming 1 - Functions.ipynb deleted file mode 100644 index e01fdbd..0000000 --- a/CH5210 Programming 1 - Functions.ipynb +++ /dev/null @@ -1,1228 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "df9906a4-08f7-4c0d-b03a-a896fa30e882", - "metadata": { - "id": "df9906a4-08f7-4c0d-b03a-a896fa30e882" - }, - "source": [ - "# Programming 1 – Calculations in Python\n", - "\n", - "Authors:\n", - "- Dr Tom Slater\n", - "\n", - "Email: slatert2@cardiff.ac.uk\n", - "\n", - "## Learning Objectives\n", - "-\tUse Jupyter notebooks to execute Python code.\n", - "-\tDefine and call functions, including single-line functions using lambda.\n", - "-\tUse Python functions to calculate basic thermodynamic quantities.\n", - "\n", - "## Table of Contents\n", - "\n", - "1. [Variables and Types](#variables) \n", - "2. [Mathematical Operations](#maths)\n", - "3. [NumPy](#numpy)\n", - "4. [Functions](#functions)\n", - "5. [Lambda Functions](#lambda)\n", - "6. [End of Session Task](#final-task)\n", - "\n", - "### Further reading for this topic\n", - "\n", - "- [Software carpentry lessons](http://swcarpentry.github.io/python-novice-gapminder/index.html)\n", - "\n", - "**Jupyter Cheat Sheet**\n", - "- To run the currently highlighted cell and move focus to the next cell, hold ⇧ Shift and press ⏎ Enter;\n", - "- To run the currently highlighted cell and keep focus in the same cell, hold Ctrl and press ⏎ Enter;\n", - "- To get help for a specific function, place the cursor within the function's brackets, hold ⇧ Shift, and press ⇥ Tab;" - ] - }, - { - "cell_type": "markdown", - "id": "ce563f6f-d25f-4a3b-a536-e0fd0cd7df78", - "metadata": { - "id": "ce563f6f-d25f-4a3b-a536-e0fd0cd7df78" - }, - "source": [ - "## 1. Variables and Types\n", - "\n", - "\n", - "Python variables store data. Variables can have almost any name but it's best to use an understandable name. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "172b1bfe-8f9e-4561-ad46-7f0fe0275745", - "metadata": { - "id": "172b1bfe-8f9e-4561-ad46-7f0fe0275745" - }, - "outputs": [], - "source": [ - "mass_of_electron = 9.1093837e-31" - ] - }, - { - "cell_type": "markdown", - "id": "968ed4b1-b055-4ea1-8536-ad6996a37c5a", - "metadata": { - "id": "968ed4b1-b055-4ea1-8536-ad6996a37c5a" - }, - "source": [ - "The most used style guide for programming in Python is [PEP8](https://peps.python.org/pep-0008/). This style guide notes that variables should include only lowercase letters and words should be separated by underscores. Hence the name used above!" - ] - }, - { - "cell_type": "markdown", - "id": "e0496e67-3dc1-411e-87e3-80f5d0851e53", - "metadata": { - "id": "e0496e67-3dc1-411e-87e3-80f5d0851e53" - }, - "source": [ - "Variables can have a variety of different types. To determine the type of a variable, we can apply the type() function to the variable." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e8c14913-57ee-418b-a138-6ec4b4a8f438", - "metadata": { - "id": "e8c14913-57ee-418b-a138-6ec4b4a8f438" - }, - "outputs": [], - "source": [ - "type(mass_of_electron)" - ] - }, - { - "cell_type": "markdown", - "id": "e91fbddc-565b-4091-a174-89c23ba10ce9", - "metadata": { - "id": "e91fbddc-565b-4091-a174-89c23ba10ce9" - }, - "source": [ - "The most common types (most of which we saw in first year programming) include:\n", - "\n", - "- Integers (int): Whole numbers.\n", - "- Floating point numbers (float): Any real number including a decimal point.\n", - "- Strings (str): Groups of characters, e.g., a word or sentence.\n", - "- Booleans (bool): True or false.\n", - "- Lists (list): Collection of multiple items.\n", - "\n", - "As examples, lets print the type of some variables:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "12ce4b1d-5b80-4811-a104-8c5687ccd7d1", - "metadata": { - "id": "12ce4b1d-5b80-4811-a104-8c5687ccd7d1" - }, - "outputs": [], - "source": [ - "quantum_number = 2\n", - "print(type(quantum_number))\n", - "\n", - "mass_of_electron = 9.1093837e-31\n", - "print(type(mass_of_electron))\n", - "\n", - "scientist_name = \"Erwin Schrödinger\"\n", - "print(type(scientist_name))\n", - "\n", - "cat_alive = True\n", - "print(type(cat_alive))\n", - "\n", - "first_five_numbers = [1, 2, 3, 4, 5]\n", - "print(type(first_five_numbers))" - ] - }, - { - "cell_type": "markdown", - "id": "a8520fe7-832c-483c-bcc2-bcde281c6213", - "metadata": { - "id": "a8520fe7-832c-483c-bcc2-bcde281c6213" - }, - "source": [ - "One of the big benefits of Python is that you don't have to declare the type of a variable, Python interprets the type for you. You can also change the type of a variable, which can be useful but can also present risks!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6f45ae95-47a5-4b1d-89c4-9b8e9340ffda", - "metadata": { - "id": "6f45ae95-47a5-4b1d-89c4-9b8e9340ffda" - }, - "outputs": [], - "source": [ - "mass_of_electron = 1\n", - "print(type(mass_of_electron))" - ] - }, - { - "cell_type": "markdown", - "id": "bac7e654-dba4-415a-b1dd-fad47e39384a", - "metadata": { - "id": "bac7e654-dba4-415a-b1dd-fad47e39384a" - }, - "source": [ - "
\n", - "Task 1.1: Define and assign variables with suitable names for:
\n", - "- The ideal gas constant.
\n", - "- The atomic number of an element (pick your favourite).
\n", - "- The name of an element (pick your favourite).\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "95099844-568d-4145-9e94-9cd456b96177", - "metadata": { - "id": "95099844-568d-4145-9e94-9cd456b96177" - }, - "outputs": [], - "source": [ - "#Enter code for Task 1.1 here\n" - ] - }, - { - "cell_type": "markdown", - "id": "08aaf655-df6b-4152-8ffc-b03c78e21763", - "metadata": { - "id": "08aaf655-df6b-4152-8ffc-b03c78e21763" - }, - "source": [ - "
\n", - "Task 1.2: Create a list that contains all of the variables created in Task 1.1.
\n", - "\n", - "Note here: Lists can contain items of different types!\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9bc0091a-b1ab-4346-baae-2a7aa99e4fc2", - "metadata": { - "id": "9bc0091a-b1ab-4346-baae-2a7aa99e4fc2" - }, - "outputs": [], - "source": [ - "#Enter code for Task 1.2 here\n" - ] - }, - { - "cell_type": "markdown", - "id": "2a9b1829-2bb9-49a5-8700-bd493f7f2c25", - "metadata": { - "id": "2a9b1829-2bb9-49a5-8700-bd493f7f2c25" - }, - "source": [ - "## 2. Simple mathematical operations\n", - "\n", - "\n", - "In this session, we will be using Python to perform mathematical operations. Python has a number of native mathematical operators, which include:\n", - "\n", - "- (+) : addition\n", - "- (-) : subtraction\n", - "- (/) : division\n", - "- (//): floor division\n", - "- (*) : multiplication\n", - "- (**): raise to the power\n", - "\n", - "These are mostly straightforward, as shown in the examples below:" - ] - }, - { - "cell_type": "markdown", - "id": "d7172e5d-777b-4f05-a4d8-036d13a1ee99", - "metadata": { - "id": "d7172e5d-777b-4f05-a4d8-036d13a1ee99" - }, - "source": [ - "Addition:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a30b54a5-4729-444e-9aa6-6c7376c6cbf2", - "metadata": { - "id": "a30b54a5-4729-444e-9aa6-6c7376c6cbf2" - }, - "outputs": [], - "source": [ - "3+2" - ] - }, - { - "cell_type": "markdown", - "id": "6e6d2283-65e3-43aa-8728-3ae8204bc9a4", - "metadata": { - "id": "6e6d2283-65e3-43aa-8728-3ae8204bc9a4" - }, - "source": [ - "Multiplication:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "123b3bf9-d74b-41f4-9bd3-883194e21934", - "metadata": { - "id": "123b3bf9-d74b-41f4-9bd3-883194e21934" - }, - "outputs": [], - "source": [ - "3*2" - ] - }, - { - "cell_type": "markdown", - "id": "b397aa60-7e7a-41a5-90bb-061211e3ccc6", - "metadata": { - "id": "b397aa60-7e7a-41a5-90bb-061211e3ccc6" - }, - "source": [ - "Exponentials:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0fef4c77-a559-4f25-9355-e52c209dc305", - "metadata": { - "id": "0fef4c77-a559-4f25-9355-e52c209dc305" - }, - "outputs": [], - "source": [ - "3**2" - ] - }, - { - "cell_type": "markdown", - "id": "b921b248-d683-47dd-acf9-7264a1a660e8", - "metadata": { - "id": "b921b248-d683-47dd-acf9-7264a1a660e8" - }, - "source": [ - "The two division operators require a little more explanation. The (/) operator does division in a standard way, i.e., it will output a non-integer if the numerator is not divisble by the denominator." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0b3e5e65-a0b9-472d-8c97-db9165fe0532", - "metadata": { - "id": "0b3e5e65-a0b9-472d-8c97-db9165fe0532" - }, - "outputs": [], - "source": [ - "3/2" - ] - }, - { - "cell_type": "markdown", - "id": "33d97710-6433-4851-a9a0-e8f295dfe2b6", - "metadata": { - "id": "33d97710-6433-4851-a9a0-e8f295dfe2b6" - }, - "source": [ - "However, the (//) operator will do the division and round down to the nearest integer." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "58dc4d4a-81b1-4d07-bb1e-87fa9cb38186", - "metadata": { - "id": "58dc4d4a-81b1-4d07-bb1e-87fa9cb38186" - }, - "outputs": [], - "source": [ - "3//2" - ] - }, - { - "cell_type": "markdown", - "id": "d733df28-c4ff-44fe-990a-477dc6d75ee8", - "metadata": { - "id": "d733df28-c4ff-44fe-990a-477dc6d75ee8" - }, - "source": [ - "This is true even if using floating point numbers!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "88ba2637-429f-4dd2-b1a1-a92b1fb77226", - "metadata": { - "id": "88ba2637-429f-4dd2-b1a1-a92b1fb77226" - }, - "outputs": [], - "source": [ - "3.0//2.0" - ] - }, - { - "cell_type": "markdown", - "id": "46b1893b-306b-4292-bf11-d1fcf033b7b9", - "metadata": { - "id": "46b1893b-306b-4292-bf11-d1fcf033b7b9" - }, - "source": [ - "### 2.1 Mathematical operations on lists\n", - "\n", - "Some of the operators above also work on lists, but in a manner that is very different to their operations on integers or floating point numbers.\n", - "\n", - "For instance, the + operator concatenates (joins together) the two lists here, rather than adding the values together." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2b2424b2-206d-4405-9c71-5895b150a612", - "metadata": { - "id": "2b2424b2-206d-4405-9c71-5895b150a612" - }, - "outputs": [], - "source": [ - "[1, 2] + [3, 4]" - ] - }, - { - "cell_type": "markdown", - "id": "90c9c2fd-7883-441a-aa0d-c85731da252e", - "metadata": { - "id": "90c9c2fd-7883-441a-aa0d-c85731da252e" - }, - "source": [ - "It's possible to multiply a list by an integer, but this simply adds copies of the list elements to the list." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6f513c37-c15b-4081-b9af-9b141c2a4238", - "metadata": { - "id": "6f513c37-c15b-4081-b9af-9b141c2a4238" - }, - "outputs": [], - "source": [ - "[1, 2] * 2" - ] - }, - { - "cell_type": "markdown", - "id": "df5e9872-6e44-45c1-920b-deaf54e4d32b", - "metadata": { - "id": "df5e9872-6e44-45c1-920b-deaf54e4d32b" - }, - "source": [ - "For many calculations, we will have a one-dimensional set of data that we would like to perform a mathematical operation on. We've seen that this is difficult to achieve with lists, but next we'll move onto the NumPy package which makes this much easier." - ] - }, - { - "cell_type": "markdown", - "id": "39a62387-2e2d-4114-b95f-720396f272f1", - "metadata": { - "id": "39a62387-2e2d-4114-b95f-720396f272f1" - }, - "source": [ - "
\n", - "Task 2.1: Perform the following calculations:
\n", - "- Add 3.14 to 2.72.
\n", - "- Set the variable `a` to be 3. Multiply `a` by 4.
\n", - "- Set the variable `b` to be 1. Add 3 to `b` and then raise it to the power 3.\n", - "\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6bed00df-2d62-45c8-9702-53effecb56e9", - "metadata": { - "id": "6bed00df-2d62-45c8-9702-53effecb56e9" - }, - "outputs": [], - "source": [ - "#Enter code for Task 2.1 here\n" - ] - }, - { - "cell_type": "markdown", - "id": "8b500b65-e3e9-42c3-ae64-18dfbc9d90a8", - "metadata": { - "id": "8b500b65-e3e9-42c3-ae64-18dfbc9d90a8" - }, - "source": [ - "## 3. NumPy\n", - "\n", - "\n", - "NumPy is the standard package for working with numerical arrays in Python. We can import NumPy using the `import` statement. Here, we are importing NumPy to use with the name `np`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "93a4d7e7-1349-495c-957b-e2082c03cd9e", - "metadata": { - "id": "93a4d7e7-1349-495c-957b-e2082c03cd9e" - }, - "outputs": [], - "source": [ - "import numpy as np" - ] - }, - { - "cell_type": "markdown", - "id": "5bcff21f-d0bc-4d88-a299-9e9a67518786", - "metadata": { - "id": "5bcff21f-d0bc-4d88-a299-9e9a67518786" - }, - "source": [ - "An array is similar to a matrix, but can have any number of dimensions. We'll stick to one dimension in this session.\n", - "\n", - "To create an array, you can use the `array` function within NumPy with a list of numbers as input." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3d7e420d-ff24-48f5-880d-8dbbd5eada0a", - "metadata": { - "id": "3d7e420d-ff24-48f5-880d-8dbbd5eada0a" - }, - "outputs": [], - "source": [ - "arr = np.array([1, 2, 3, 4, 5])\n", - "print(arr)" - ] - }, - { - "cell_type": "markdown", - "id": "b6db5657-a3cc-4fa8-ba77-d90851dc942b", - "metadata": { - "id": "b6db5657-a3cc-4fa8-ba77-d90851dc942b" - }, - "source": [ - "To create larger arrays, there are other in-built functions. For example, to create a linearly-spaced array (i.e., the same interval between all elements), the `linspace` function can be used. Using `linspace` requires arguments of the form `linspace(start,stop,number of values)`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e7aca0f5-79f0-465c-94ab-df39b72a426a", - "metadata": { - "id": "e7aca0f5-79f0-465c-94ab-df39b72a426a" - }, - "outputs": [], - "source": [ - "arr2 = np.linspace(1,5,5)\n", - "print(arr2)" - ] - }, - { - "cell_type": "markdown", - "id": "8e6045e0-a370-410f-b46a-7c8d18b9058c", - "metadata": { - "id": "8e6045e0-a370-410f-b46a-7c8d18b9058c" - }, - "source": [ - "
\n", - "Task 3.1: Use the linspace function to create a numpy array `data` with the values [10, 20, 30, 40, 50].
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d3fa2153-6868-4338-b581-3391d80ec84b", - "metadata": { - "id": "d3fa2153-6868-4338-b581-3391d80ec84b" - }, - "outputs": [], - "source": [ - "#Enter code for Task 3.1 here\n" - ] - }, - { - "cell_type": "markdown", - "id": "829aefc0-e623-49e0-9bc2-1c9cdc32e766", - "metadata": { - "id": "829aefc0-e623-49e0-9bc2-1c9cdc32e766" - }, - "source": [ - "### 3.1 Mathematical operations on NumPy arrays" - ] - }, - { - "cell_type": "markdown", - "id": "9eb0af3b-81a6-417f-bf26-2bea7b2cc410", - "metadata": { - "id": "9eb0af3b-81a6-417f-bf26-2bea7b2cc410" - }, - "source": [ - "A major advantage of NumPy arrays over lists is that it's straightforward to use mathematical operations.\n", - "\n", - "The mathematical operators used in Section 2 work on NumPy arrays in an element-wise fashion. That is, they operate individually on each element. Here are some examples using the array created above." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "79f4d10c-328b-4b20-b8e3-08d0877b4015", - "metadata": { - "id": "79f4d10c-328b-4b20-b8e3-08d0877b4015" - }, - "outputs": [], - "source": [ - "# Basic operations\n", - "arr_times_two = arr * 2\n", - "arr_squared = arr ** 2\n", - "\n", - "print(arr_times_two, arr_squared)" - ] - }, - { - "cell_type": "markdown", - "id": "1dbc4af1-e85e-450c-bd6e-ab3ee9d6ce46", - "metadata": { - "id": "1dbc4af1-e85e-450c-bd6e-ab3ee9d6ce46" - }, - "source": [ - "It's also possible to perform maths using two NumPy arrays, but only if they are the same size. For instance, adding one array to another." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0b0d6ae0-ea67-4115-b4c6-fa889a7f5b25", - "metadata": { - "id": "0b0d6ae0-ea67-4115-b4c6-fa889a7f5b25" - }, - "outputs": [], - "source": [ - "arr_summed = arr_times_two + arr_squared\n", - "print(arr_summed)" - ] - }, - { - "cell_type": "markdown", - "id": "b354d534-3d04-42be-affa-954e2c08168b", - "metadata": { - "id": "b354d534-3d04-42be-affa-954e2c08168b" - }, - "source": [ - "NumPy also includes useful mathematical functions. For example, taking the logarithm or exponential of elements of an array." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a16939eb-148c-4f4e-89e6-33cf9c79c5d1", - "metadata": { - "id": "a16939eb-148c-4f4e-89e6-33cf9c79c5d1" - }, - "outputs": [], - "source": [ - "# Useful functions\n", - "log_arr = np.log(arr)\n", - "exp_arr = np.exp(arr)\n", - "print(log_arr,exp_arr)" - ] - }, - { - "cell_type": "markdown", - "id": "497a9d7e-bf47-42bc-bdf4-d302ad03a5f2", - "metadata": { - "id": "497a9d7e-bf47-42bc-bdf4-d302ad03a5f2" - }, - "source": [ - "As a note that will be particularly useful for the End of Session Task, if you try to take the log of 0 using `np.log` you will get a warning and the resultant element will be infinite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "155af08b-126c-4680-a3d8-92c6768a221a", - "metadata": { - "id": "155af08b-126c-4680-a3d8-92c6768a221a" - }, - "outputs": [], - "source": [ - "np.log(log_arr)" - ] - }, - { - "cell_type": "markdown", - "id": "58435cff-8e5d-427b-9060-506872e4c7ef", - "metadata": { - "id": "58435cff-8e5d-427b-9060-506872e4c7ef" - }, - "source": [ - "One way to avoid having zeros in any array is to use the `np.clip()` function. This function will clip any values which are not within the bounds set in the function call. For example, the following code will clip the zero value to 0.01." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "17d77ac1-0d65-4ed9-9dd2-30ab1b9e8cf9", - "metadata": { - "id": "17d77ac1-0d65-4ed9-9dd2-30ab1b9e8cf9" - }, - "outputs": [], - "source": [ - "np.clip(log_arr, 0.01, 2.)" - ] - }, - { - "cell_type": "markdown", - "id": "62843c23-8fe7-4b5f-8b4e-172515330db2", - "metadata": { - "id": "62843c23-8fe7-4b5f-8b4e-172515330db2" - }, - "source": [ - "
\n", - "Task 3.2: Subtract 10 from your `data` array, clip the array so that no elements are zero and take its logarithm.
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ba2ab4d-697b-458e-82b4-aba20c7035c5", - "metadata": { - "id": "3ba2ab4d-697b-458e-82b4-aba20c7035c5" - }, - "outputs": [], - "source": [ - "#Enter code for Task 3.2 here\n" - ] - }, - { - "cell_type": "markdown", - "id": "f26fa3bb-fc83-461a-a738-d50629134d1e", - "metadata": { - "id": "f26fa3bb-fc83-461a-a738-d50629134d1e" - }, - "source": [ - "### 3.2 Indexing and slicing" - ] - }, - { - "cell_type": "markdown", - "id": "6ef0bd66-5f15-4307-87cd-8ddc61c5ed4a", - "metadata": { - "id": "6ef0bd66-5f15-4307-87cd-8ddc61c5ed4a" - }, - "source": [ - "It's often necessary to check the value of one or more elements inside an array, and if the array is particularly long this can be difficult from just visually inspecting the array. Thankfully, NumPy has an easy way to access individual elements of an array, indexing.\n", - "\n", - "A single element of a NumPy array can be indexed using square brackets." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "67a7f1e2-6937-4fc7-badc-959c4c244a81", - "metadata": { - "id": "67a7f1e2-6937-4fc7-badc-959c4c244a81" - }, - "outputs": [], - "source": [ - "print(\"First element:\", arr[0])" - ] - }, - { - "cell_type": "markdown", - "id": "312f41df-3ae5-4217-b4d9-ca44c87533f6", - "metadata": { - "id": "312f41df-3ae5-4217-b4d9-ca44c87533f6" - }, - "source": [ - "Remember, in Python indexing starts from 0 (NOT 1!). It's also possible to index from the end of an array by using a minus sign." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1a75abb0-87aa-41b8-85da-a71e20c1e790", - "metadata": { - "id": "1a75abb0-87aa-41b8-85da-a71e20c1e790" - }, - "outputs": [], - "source": [ - "print(\"Last element:\", arr[-1])\n", - "\n", - "print(\"Third last element:\", arr[-3])" - ] - }, - { - "cell_type": "markdown", - "id": "89e9176f-0dfd-48f1-bbcd-dd422625e0d6", - "metadata": { - "id": "89e9176f-0dfd-48f1-bbcd-dd422625e0d6" - }, - "source": [ - "Use of square brackets can also be used to access more than one element of an array. This is called slicing. To slice an array, a colon (:) is used. The colon is placed between the elements to slice between, e.g.," - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1cba6d7c-3092-4a34-adad-a61686dc66a0", - "metadata": { - "id": "1cba6d7c-3092-4a34-adad-a61686dc66a0" - }, - "outputs": [], - "source": [ - "print(\"First three elements:\", arr[0:3])\n", - "\n", - "#Slicing from the first element or to the last element doesn't need the 0 to be included\n", - "print(\"First three elements:\", arr[:3])\n", - "print(\"Last three elements:\", arr[-3:])" - ] - }, - { - "cell_type": "markdown", - "id": "ccb62091-0deb-467f-a1e7-8e73a3b29caa", - "metadata": { - "jp-MarkdownHeadingCollapsed": true, - "id": "ccb62091-0deb-467f-a1e7-8e73a3b29caa" - }, - "source": [ - "
\n", - "Task 3.3: Print the first two elements and last element of the logarithm of `data`.
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "817c3dce-ab09-4a49-83f4-4af4a7dbbf52", - "metadata": { - "id": "817c3dce-ab09-4a49-83f4-4af4a7dbbf52" - }, - "outputs": [], - "source": [ - "#Enter code for Task 3.3 here\n", - "\n", - "log_data = np.log(data)\n", - "print(log_data)\n", - "\n", - "print(\"First two elements, \", log_data[0:2])\n", - "print(\"Last element: \", log_data[-1])\n" - ] - }, - { - "cell_type": "markdown", - "id": "4220b5e0-5ff1-4cef-aab9-366f1752a183", - "metadata": { - "id": "4220b5e0-5ff1-4cef-aab9-366f1752a183" - }, - "source": [ - "## 4. Functions\n", - "\n", - "\n", - "You were previously introduced to functions in first year programming, and we've seen a number of them used in this notebook already! In essence, functions let you reuse code, which can be incredibly useful for carrying out the same actions again and again." - ] - }, - { - "cell_type": "markdown", - "id": "6b214fbb-94df-4573-bdf8-93103d3f0cf7", - "metadata": { - "id": "6b214fbb-94df-4573-bdf8-93103d3f0cf7" - }, - "source": [ - "We've already used one function extensively in this notebook, the `print()` function." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a54bf0e7-0ac6-48bb-8d1c-6d3426c43daf", - "metadata": { - "id": "a54bf0e7-0ac6-48bb-8d1c-6d3426c43daf" - }, - "outputs": [], - "source": [ - "print('Hello')" - ] - }, - { - "cell_type": "markdown", - "id": "228d9053-0436-493f-801b-77b922c89987", - "metadata": { - "id": "228d9053-0436-493f-801b-77b922c89987" - }, - "source": [ - "Using a function is known as \"calling\" a function, the above statement calls the `print` function with an argument of 'Hello'. Functions arguments are the inputs to a function and go inside the brackets of a function call." - ] - }, - { - "cell_type": "markdown", - "id": "f97c61a9-2922-47ec-9655-857d37128559", - "metadata": { - "id": "f97c61a9-2922-47ec-9655-857d37128559" - }, - "source": [ - "Now you know how functions are used, but how do you define your own functions? In Python you define them with `def`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7f43793e-973f-4f71-b1c3-cd828fc4993a", - "metadata": { - "id": "7f43793e-973f-4f71-b1c3-cd828fc4993a" - }, - "outputs": [], - "source": [ - "def square(x):\n", - " return(x ** 2)" - ] - }, - { - "cell_type": "markdown", - "id": "a3c5707c-6abb-4afd-b43d-b7a2b31e6192", - "metadata": { - "id": "a3c5707c-6abb-4afd-b43d-b7a2b31e6192" - }, - "source": [ - "The above code is known as a function definition, i.e., where a function is defined. Let's go through this in detail:\n", - "\n", - "- The function definition starts with `def`.\n", - "- After `def` comes the name of the function.\n", - "- Then, the input to the function (the arguments) are included in brackets immediately after the function name. The arguments can have any name, but this variable name should only be used within the function, it shouldn't be a variable name used outside of the function.\n", - "- A colon follows the brackets.\n", - "- The contents of the functions (what it does) is included on the lines immediately following the first line. The Python interpreter only includes lines that have been indented after the colon. The next line which is not indented is read as being outside the function.\n", - "- Most functions include a return statement. This tells the Python interpreter what the output of the function is. In the case above, the output is the square of the input." - ] - }, - { - "cell_type": "markdown", - "id": "56886d1c-fdc6-47c0-994f-8e6f78c9fb8c", - "metadata": { - "id": "56886d1c-fdc6-47c0-994f-8e6f78c9fb8c" - }, - "source": [ - "The code above only defines the function `square()`, it doesn't call the function (i.e., use it). Let's try calling the function with a few different arguments." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "52c78a96-2270-433b-bfe1-181c3ad56a90", - "metadata": { - "id": "52c78a96-2270-433b-bfe1-181c3ad56a90" - }, - "outputs": [], - "source": [ - "square(3)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6a3de092-1e24-4ddb-b105-3ff76eb210aa", - "metadata": { - "id": "6a3de092-1e24-4ddb-b105-3ff76eb210aa" - }, - "outputs": [], - "source": [ - "square(3.4)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b502c498-a0cd-407a-92d4-ed5c48c3d241", - "metadata": { - "id": "b502c498-a0cd-407a-92d4-ed5c48c3d241" - }, - "outputs": [], - "source": [ - "square([3,4,5]) #Should get an error" - ] - }, - { - "cell_type": "markdown", - "id": "c44dcd41-e361-4200-9bab-33ac87b67df5", - "metadata": { - "id": "c44dcd41-e361-4200-9bab-33ac87b67df5" - }, - "source": [ - "The code cell above should throw an error, as it's not possible to square a list!\n", - "\n", - "However, it is possible to square a NumPy array:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8d503bff-1edd-41ea-bcd0-ccf5b9ae0af7", - "metadata": { - "id": "8d503bff-1edd-41ea-bcd0-ccf5b9ae0af7" - }, - "outputs": [], - "source": [ - "square(arr)" - ] - }, - { - "cell_type": "markdown", - "id": "d5d75c37-8a4a-4929-a0f4-5574ba4106e9", - "metadata": { - "id": "d5d75c37-8a4a-4929-a0f4-5574ba4106e9" - }, - "source": [ - "### 4.1 Multiple arguments" - ] - }, - { - "cell_type": "markdown", - "id": "ef977a3b-9fda-4489-b893-5494da2d811e", - "metadata": { - "id": "ef977a3b-9fda-4489-b893-5494da2d811e" - }, - "source": [ - "Functions can take multiple arguments and can return multiple objects. If using multiple arguments, these should be separated by a comma." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f21f5254-a0ae-43c8-b970-61bdf3ee41e2", - "metadata": { - "id": "f21f5254-a0ae-43c8-b970-61bdf3ee41e2" - }, - "outputs": [], - "source": [ - "def add(a, b):\n", - " return(a + b)\n", - "\n", - "print(\"Sum of 4 and 5:\", add(4, 5))" - ] - }, - { - "cell_type": "markdown", - "id": "d519186e-f280-4766-bfe4-e732c7e54421", - "metadata": { - "id": "d519186e-f280-4766-bfe4-e732c7e54421" - }, - "source": [ - "
\n", - "Task 4.1: Write a function to calculate the total number of moles of reactant and product in the reaction $A \\rightarrow 2B$, where the arguments should be initial moles of A and the extent of reaction $\\chi$. Use the function to calculate the total number of moles at $\\chi = 0.4$ when the reaction started with 3 mol of A.
\n", - "
\n", - "Hint: The number of moles of reactant equals 1 - $\\chi$. What are the number of moles of product with respect to $\\chi$?\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d948eab9-1d6e-4b1c-996b-14d0a06868ab", - "metadata": { - "id": "d948eab9-1d6e-4b1c-996b-14d0a06868ab" - }, - "outputs": [], - "source": [ - "#Enter code for Task 4.1 here\n" - ] - }, - { - "cell_type": "markdown", - "id": "d609b02a-a3c3-47f5-adce-679117add890", - "metadata": { - "id": "d609b02a-a3c3-47f5-adce-679117add890" - }, - "source": [ - "## 5. Lambda functions\n", - "\n", - "\n", - "Python also allows you to define small functions of a single output using `lambda`.\n", - "\n", - "They are useful for short, throwaway mathematical functions. An example is shown below, where the variable `cube` is assigned a lambda function. The arguments immediately follow the `lambda`, with the output following a colon. Lambda functions should always be single lines of code." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "469e76ba-dd86-4609-9523-aea0cb2babe2", - "metadata": { - "id": "469e76ba-dd86-4609-9523-aea0cb2babe2" - }, - "outputs": [], - "source": [ - "# A lambda function to compute x^3\n", - "cube = lambda x: x**3\n", - "\n", - "cube(2)" - ] - }, - { - "cell_type": "markdown", - "id": "6c2bcd02-7348-4f3f-8d93-2d6d4499ea0b", - "metadata": { - "id": "6c2bcd02-7348-4f3f-8d93-2d6d4499ea0b" - }, - "source": [ - "Lambda functions can take multiple arguments." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8df72e66-d87d-4036-a203-56f5892cd6b3", - "metadata": { - "id": "8df72e66-d87d-4036-a203-56f5892cd6b3" - }, - "outputs": [], - "source": [ - "# A lambda function to multiply two variables\n", - "multiply = lambda x, y: x * y\n", - "\n", - "multiply(2,3)" - ] - }, - { - "cell_type": "markdown", - "id": "12df3734-9c6d-4e8f-8fa9-e806771cebb6", - "metadata": { - "id": "12df3734-9c6d-4e8f-8fa9-e806771cebb6" - }, - "source": [ - "
\n", - "Task 5.1: Write a lambda function to compute the mole fraction of product in the reaction $A \\rightarrow 2B$, where the only required argument is the extent of reaction. Use the function to calculate the mole fraction of B at $\\chi = 0.5$.
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "77f22e8c-ceee-4d1b-8322-05f4c7caf54f", - "metadata": { - "id": "77f22e8c-ceee-4d1b-8322-05f4c7caf54f" - }, - "outputs": [], - "source": [ - "#Enter code for Task 5.1 here\n" - ] - }, - { - "cell_type": "markdown", - "id": "c77f07f2-2efc-45b6-94e7-450bed8aa41f", - "metadata": { - "id": "c77f07f2-2efc-45b6-94e7-450bed8aa41f" - }, - "source": [ - "## End of Session Task\n", - "\n", - "\n", - "Write a function called `gibbs_energy` that calculates the Gibbs energy change at different extents of reaction ($\\chi$) for a reaction of the form:\n", - "\n", - "
$A(g) \\rightarrow 2B(g)$

\n", - "\n", - "Assume 1 mol of A at $\\chi = 0$.\n", - "\n", - "The Gibbs energy change is the sum of contributions from the change in Gibbs energy between reactant and product and the Gibbs energy change due to mixing. The Gibbs energy change due to mixing is given by the equation:\n", - "\n", - "
$\\Delta G_{\\text{mix}}(\\xi) = RT \\Big[ n_A\\ln(\\chi_A) + n_B\\ln(\\chi_B) \\Big]$
\n", - "\n", - "The function should take as arguments:\n", - "- The change in Gibbs energy between the reactant and product.\n", - "- The temperature at which the reaction takes place.\n", - "\n", - "The function should return:\n", - "- A 1D NumPy array representing the extent of reaction.\n", - "- A 1D NumPy array representing the Gibbs energy change for each extent of reaction." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3a11be95-8273-415c-8ca6-1597f2426772", - "metadata": { - "id": "3a11be95-8273-415c-8ca6-1597f2426772" - }, - "outputs": [], - "source": [ - "#Enter code for End of Session Task here\n" - ] - }, - { - "cell_type": "markdown", - "id": "9b301f4f-2862-473c-b06e-9f24d5c0fccd", - "metadata": { - "id": "9b301f4f-2862-473c-b06e-9f24d5c0fccd" - }, - "source": [ - "Once you have completed the End of Session Task, run the code cell below to use your code to create an interactive plot of the Gibbs energy of a reaction based on the difference in Gibbs energy of reactant and product!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8dbea88e-dfa4-440d-b304-0ab99c557b74", - "metadata": { - "id": "8dbea88e-dfa4-440d-b304-0ab99c557b74" - }, - "outputs": [], - "source": [ - "from ipywidgets import interact, FloatSlider\n", - "import matplotlib.pyplot as plt\n", - "\n", - "def plot_gibbs(delta_G, T=298):\n", - " xi, dG = gibbs_energy(delta_G, T)\n", - "\n", - " plt.figure(figsize=(6,4))\n", - " plt.plot(xi, dG, lw=2)\n", - " plt.axhline(0, color='k', ls='--')\n", - " plt.xlabel(\"Extent of reaction, ξ\")\n", - " plt.ylabel(\"ΔG (J/mol)\")\n", - " plt.title(f\"Gibbs Energy Profile (ΔG° = {delta_G:.0f} J/mol)\")\n", - " plt.grid(True, alpha=0.3)\n", - " plt.show()\n", - "\n", - "\n", - "# Interactive widget\n", - "interact(\n", - " plot_gibbs,\n", - " delta_G=FloatSlider(value=0, min=-2e4, max=2e4, step=1000, description=\"ΔG° (J/mol)\")\n", - ");" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "particlespy_270423", - "language": "python", - "name": "particlespy_270423" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - }, - "colab": { - "provenance": [] - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 06e29357c3c8c305512e81d0cd8f766194c3a25c Mon Sep 17 00:00:00 2001 From: Andrew Logsdail Date: Thu, 23 Oct 2025 18:35:39 +0100 Subject: [PATCH 3/4] Rename CH5210_Programming_1_Functions.ipynb to CH5210 Programming 1 Functions.ipynb --- ...ng_1_Functions.ipynb => CH5210 Programming 1 Functions.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename CH5210_Programming_1_Functions.ipynb => CH5210 Programming 1 Functions.ipynb (99%) diff --git a/CH5210_Programming_1_Functions.ipynb b/CH5210 Programming 1 Functions.ipynb similarity index 99% rename from CH5210_Programming_1_Functions.ipynb rename to CH5210 Programming 1 Functions.ipynb index 3077e18..c30f281 100644 --- a/CH5210_Programming_1_Functions.ipynb +++ b/CH5210 Programming 1 Functions.ipynb @@ -1236,4 +1236,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} From 3408a08932deec503af4cfaf7d0909e938b00973 Mon Sep 17 00:00:00 2001 From: Andrew Logsdail Date: Thu, 23 Oct 2025 18:37:26 +0100 Subject: [PATCH 4/4] Update CH5210 Programming 1 Functions.ipynb Minor rewording of G_core to G_total --- CH5210 Programming 1 Functions.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CH5210 Programming 1 Functions.ipynb b/CH5210 Programming 1 Functions.ipynb index c30f281..5fbdaa0 100644 --- a/CH5210 Programming 1 Functions.ipynb +++ b/CH5210 Programming 1 Functions.ipynb @@ -1135,9 +1135,9 @@ "\n", "Assume 1 mol of A at $\\xi = 0$.\n", "\n", - "The change in Gibbs energy change is defined as the sum of contributions from the change in Gibbs energy between reactant and product ($\\Delta G_{\\mathrm{core}}$) and the Gibbs energy change due to mixing ($\\Delta G_{\\mathrm{mix}}$):\n", + "The total change in Gibbs energy is defined as the sum of contributions from the Gibbs energy change between reactant and product ($\\Delta G_{\\mathrm{reaction}}$) and the Gibbs energy change due to mixing ($\\Delta G_{\\mathrm{mix}}$):\n", "\n", - "
$\\Delta G_{\\mathrm{total}}(\\xi) = \\Delta G_{\\mathrm{core}}(\\xi) + \\Delta G_{\\mathrm{mix}}(\\xi)$
\n", + "
$\\Delta G_{\\mathrm{total}}(\\xi) = \\Delta G_{\\mathrm{reaction}}(\\xi) + \\Delta G_{\\mathrm{mix}}(\\xi)$
\n", "\n", "The Gibbs energy change due to mixing is given by the equation:\n", "\n", @@ -1152,7 +1152,7 @@ "\n", "and return:\n", "- A 1D NumPy array representing the extent of reaction.\n", - "- A 1D NumPy array representing the Gibbs energy change for each extent of reaction." + "- A 1D NumPy array representing the total Gibbs energy change for each extent of reaction." ] }, {