{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Jupyter notebook, Python and Applied Thermodynamics\n", "\n", "This notebook intends to present the basics of Jupyter notebook and Python in the context of solution of simple problems in classical thermodynamics.\n", "\n", "> **Here you will meet the following topics:**\n", ">- Thermodynamics: `1st law`, `\"cyclic process\"`,\n", ">- Python: `math`, `print`, `function`, `if`, `for`\n", ">- Jupyter Notebook: `cells`, `kernel`\n", "\n", "\n", "## A Jupyter notebook *Cell*\n", "This unit, from the heading \"Jupyter notebook, Python and Applied Thermo...\" to \"...see some python code.\", at the end of this paragraph, is a Jupyter notebook cell. We can set its type in the toolbar dropdown to *Markdown* or to *Code*. In the first option, we write plain text, and using some special tokens as \\*, \\[, \\(, < ... we can get some nice formatting. In the second option, we write code in Python programming language, we get it to run and display results just below the given cell.\n", "You can see the special tokens as raw text if you click the cell inside a running instance of jupyter notebook (because then you enter cell editing mode), and you can get out of the cell editing mode pressing Ctrl+Enter. Now let's see some python code." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Supose you have to solve the following problem in a thermodynamics course:\n", ">\"Consider a closed system containing `1 mol` of a gas. This system undergoes cyclic trasnformations consisting of four steps. The following table display variations in internal energy as well as total heat and total work input/output in each step. Determine the values of the missing quantities.\"\n", ">\n", "> .......Steps....... | .......$\\Delta U\\mathrm{(}\\mathrm{J}\\mathrm{)}$....... | .......$Q\\mathrm{(}\\mathrm{J}\\mathrm{)}$....... | .......$W\\mathrm{(}\\mathrm{J}\\mathrm{)}$.......\n", "> :--: | --: | --: | --:\n", "> ${A}\\to{B}$ | -200. | $?$ | -6,000.\n", "> ${B}\\to{C}$ | $?$ | -3,800. | $?$\n", "> ${C}\\to{D}$ | $?$ | -800. | 300.\n", "> ${D}\\to{A}$ | 4,700. | $?$ | $?$\n", "> ${A}_{\\to{B}\\to}^{\\leftarrow{D}\\leftarrow}{C}$ | $?$ | $?$ | -1,400.\n", ">> Adapted from `Smith, J. M.; Van Ness, H. C.; Abbot, M. M., Introduction to Chemical Engineering Thermodynamics, 7th Ed.; McGraw Hill Higher Education, 2005.`" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Solution:\n", "## Fundamentals:\n", "According to the first law of thermodynamics, in any process, the variation in energy is equal to the sum of heat and work inputs/outputs\n", "\n", "$$\\Delta U_{A\\to B} = Q_{A\\to B} + W_{A\\to B}$$\n", "\n", "where, by convention,\n", "* $\\Delta U_{A\\to B}$ means difference between internal energy in state $B$ and internal energy in state $A$: $U_B - U_A$\n", "* A positive sign in $Q_{A\\to B}$ means heat entering the system during the process from state $A$ to state $B$\n", "* A positive sign in $W_{A\\to B}$ means work being done on the system during the process from state $A$ to state $B$\n", "\n", "Net Heat and Net Work in a cyclic operation are the sum of heat and work in each step process\n", "\n", "$$Q_{A\\to B} + Q_{B\\to C} + Q_{C\\to D} + Q_{D\\to A} = Q_{net}$$\n", "\n", "$$W_{A\\to B} + W_{B\\to C} + W_{C\\to D} + W_{D\\to A} = W_{net}$$\n", "\n", "Also, as internal energy is a *function of state*, in a cyclic operation its net variation, when a full cycle is complete and the system is found to be in a previously visited state, is zero.\n", "\n", "$$\\Delta U_{A\\to B} + \\Delta U_{B\\to C} + \\Delta U_{C\\to D} + \\Delta U_{D\\to A}= 0$$\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will try three different approaches in python to solve this problem,\n", "each with increasing demand on python features\n", "* Approach 1, using python as a calculator\n", "* Approach 2, defining re-usable functions\n", "* Approach 3, defining general purpose functions with \"if\" and \"for\" constructs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Approach 1:\n", "Our first approach to solve this exercise will be most similar to doing it on your paper notebook with a simple scientific calculator by your side.\n", "\n", "In any process, the first law states that the three quantities presented in the table are related by one function, therefore there are two degrees of freedom to fully determine one line of the table.\n", "\n", "Note that in lines corresponding to processes $A$ $\\to$ $B$ and $C$ $\\to$ $D$, two degreees of freeedom are provided and only one value is missing, therefore we immediately solve any of these processes. Let's start with step $A\\to B$\n", "\n", " > Steps | $\\Delta U$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ | $Q$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ |$W$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$\n", " > :--: | --: | --: | --:\n", " > $A$ $\\to$ $B$ | -200. | \\_ | -6,000.\n", "\n", "\n", ">> $Q_{A\\to B} \\mathrm{(J)} = \\Delta U_{A\\to B} \\mathrm{(J)} - W_{A\\to B} \\mathrm{(J)}$\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dU=\n", "-200.0\n", "W=\n", "-6000.0\n", "Q=\n", "5800.0\n" ] } ], "source": [ "#this is the first Python code cell in the course\n", "#these lines beginning with a hashtag (#) are comments,\n", "#they are merely unformatted descriptive text,\n", "#they do not inlfuence in any way the calculations that we will write\n", "\n", "dU_from_A_to_B=-200. #we can comment just right of any calculation line, this line here is a assignment line,\n", "#it defines a variable dU and assigns it the value of -200.\n", "\n", "print(\"dU=\") #this line call the print command, here we print the string \"dU\", that means literally the characters \"d\" and \"U\"\n", "print(dU_from_A_to_B) #this line call the print command, this means that the value stored in the variable Q\n", "#will be printed in the output section of this cell, just below this space where we wwriting our source code\n", "\n", "W_from_A_to_B=-6000. #this is another definition and assignment\n", "\n", "print(\"W=\")\n", "print(W_from_A_to_B) #this line call the print command, this means that the value stored in the variable Q\n", "#should be printed in the output section of this cell, just below this space where we are writing our source code\n", "\n", "\n", "Q_from_A_to_B=dU_from_A_to_B-W_from_A_to_B #yet another definition and assignment,\n", "#however the assigned value now is the result of the subtraction (-) operation\n", "#between the values stored in the variables dU and W\n", "\n", "print(\"Q=\")\n", "print(Q_from_A_to_B)\n", "\n", "#After modyfing anything here, hit Ctrl+Enter to exit this jupyter notebook cell and run the calculations here\n", "#note the number between square brackets at the left of the cell (e.g. In[1])\n", "#if you hit Ctrl+Enter again it will run again and the counter will become In[2], In[3], and so on...\n", "#Below you can see the result of the calculations" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "du\n", "-20000\n", "dU\n", "-200.0\n" ] } ], "source": [ "#Note: CASING matters. If we assign a variable with uppercase characters\n", "#and then we inquiry on a variable with lowercase characters\n", "#it will not work because these are different variables in the program\n", "\n", "du_from_A_to_B = -20000\n", "\n", "print(\"du\")\n", "print(du_from_A_to_B)\n", "print(\"dU\")\n", "print(dU_from_A_to_B)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###C-D\n", "\n", " > Steps | $\\Delta U$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ | $Q$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ |$W$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$\n", " > :--: | --: | --: | --:\n", " > $C$ $\\to$ $D$ | \\_ | -800. | 300.\n", "\n", ">> $\\Delta U_{C\\to D} \\mathrm{(J)} = Q_{C\\to D} \\mathrm{(J)} + W_{C\\to D} \\mathrm{(J)}$\n", "\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-200.0\n", "-500.0\n", "The variation in the internal energy along the process from state C to state D was equal to [ -500.0 J ].\n" ] } ], "source": [ "#this is another separate python code cell\n", "#this is intended to be run just after the previous one\n", "#note the number between square brackets at the left of the cell and compare with the other cells to see the order in which they were executed before\n", "\n", "\n", "#at the execution of each cell, jupyter remembers whatever was executed since the kernel started\n", "#(i.e. since the jupyter notebook was opened)\n", "#this means we can still see the values of the previous calculations\n", "print(dU_from_A_to_B)\n", "\n", "#if you modify something in such a way that you will need the computer to forget the results of the past calculations\n", "#then you will have to click [Kernel] > [Restart & Clear Output] in jupyter toolbar\n", "\n", "#and now let's perform the calculation for the other process\n", "\n", "Q_from_C_to_D=-800. #we can comment just right of any calculation line, this line here is an assignment line,\n", "#it defines a variable dU and assigns it the value of -200.\n", "\n", "W_from_C_to_D=300.\n", "\n", "dU_from_C_to_D=Q_from_C_to_D+W_from_C_to_D\n", "print(dU_from_C_to_D)\n", "\n", "#we can also format the printing to make it look better:\n", "print(\"The variation in the internal energy along the process from state C to state D was equal to [\",dU_from_C_to_D,\"J ].\")\n", "\n", "#After modyfing anything here, hit Ctrl+Enter to exit this jupyter notebook cell and run the calculations here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, using the last principle exposed, concerning the fact that a cyclic process, on completion of a full cycle returns to the same equilibrium state, we can solve the last line in the table\n", "\n", " > Steps | $\\Delta U$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ | $Q$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ |$W$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$\n", " > :--: | --: | --: | --:\n", " > $A$ $_{\\to B \\to}^{\\leftarrow D \\leftarrow}$ $C$ | \\_ | \\_ | -1,400.\n", "\n", ">> $\\Delta U_{A\\to B\\to C\\to D\\to A}=0$\n", "\n", ">> $Q_{A\\to B\\to C\\to D\\to A}=\\Delta U_{A\\to B\\to C\\to D\\to A}-W_{A\\to B\\to C\\to D\\to A}$\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The net heat input was equal to [ 1400.0 J ].\n" ] } ], "source": [ "dU_net = 0.\n", "\n", "W_net = -1400.\n", "\n", "Q_net = dU_net - W_net\n", "\n", "print(\"The net heat input was equal to [\",Q_net,\"J ].\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now using the last principle again we can solve for the energy variation in step $B$ $\\to$ $C$\n", "\n", "> Steps | $\\Delta U$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$\n", "> :--: | --:\n", "> $A$ $\\to$ $B$ | -200.\n", "> $B$ $\\to$ $C$ | \\_\n", "> $C$ $\\to$ $D$ | -500.\n", "> $D$ $\\to$ $A$ | 4,700.\n", "> $A_{\\to B \\to}^{\\leftarrow D \\leftarrow} C$ | 0.\n", "\n", ">> $\\Delta U_{A\\to B} + \\Delta U_{B\\to C} + \\Delta U_{C\\to D} + \\Delta U_{D\\to A}= 0$" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dU_from_A_to_B = [ -200.0 ] J.\n", "dU_from_C_to_D = [ -500.0 ] J.\n", "dU_net = [ 0.0 ] J.\n", "dU_from_D_to_A = [ 4700.0 ] J.\n", "dU_from_B_to_C = [ -4000.0 ] J.\n" ] } ], "source": [ "#remember the kernel remembers whatever we already told him or whatever was calculated\n", "print(\"dU_from_A_to_B = [\",dU_from_A_to_B,\" ] J.\")\n", "print(\"dU_from_C_to_D = [\",dU_from_C_to_D,\" ] J.\")\n", "print(\"dU_net = [\",dU_net,\" ] J.\")\n", "\n", "dU_from_D_to_A = 4700. #this we hadn't used yet\n", "print(\"dU_from_D_to_A = [\",dU_from_D_to_A,\" ] J.\")\n", "\n", "dU_from_B_to_C = dU_net - (dU_from_A_to_B + dU_from_C_to_D + dU_from_D_to_A) #now calculate the missing\n", "print(\"dU_from_B_to_C = [\",dU_from_B_to_C,\" ] J.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "now the work in B-> C\n", "according to 1st principle\n", "\n", "\n", "> Steps | $\\Delta U$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ | $Q$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ |$W$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$\n", "> :--: | --: | --: | --:\n", "> $B$ $\\to$ $C$ | -4,000. | -3,800. | \\_\n", "\n", ">> $W_{B\\to C} = \\Delta U_{B\\to C} - Q_{B\\to C}$\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "W_from_B_to_C = [ -200.0 ] J.\n" ] } ], "source": [ "Q_from_B_to_C = -3800.\n", "W_from_B_to_C = dU_from_B_to_C - Q_from_B_to_C\n", "print(\"W_from_B_to_C = [\",W_from_B_to_C,\" ] J.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now using the 2nd and 3rd principles we can solve for the heat and for work in step $D$ $\\to$ $A$\n", "\n", "> Steps | $Q$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$ |$W$ $\\mathrm{(}$ $\\mathrm{J}$ $\\mathrm{)}$\n", "> :--: | --: | --:\n", "> $A$ $\\to$ $B$ | 5,800. | -6,000.\n", "> $B$ $\\to$ $C$ | -3,800. | -200.\n", "> $C$ $\\to$ $D$ | -800. | 300.\n", "> $D$ $\\to$ $A$ | \\_ | \\_\n", "> $A$ $_{\\to B \\to}^{\\leftarrow D \\leftarrow}$ $C$ | 1400. | -1,400.\n", "\n", ">> $Q_{D\\to A} = Q_{net} - (Q_{A\\to B} + Q_{B\\to C} + Q_{C\\to D})$\n", "\n", ">> $W_{D\\to A} = W_{net} - (W_{A\\to B} + W_{B\\to C} + W_{C\\to D})$" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Q_from_D_to_A = [ 200.0 ] J.\n", "W_from_D_to_A = [ 4500.0 ] J.\n" ] } ], "source": [ "Q_from_D_to_A = Q_net - ( Q_from_A_to_B + Q_from_B_to_C + Q_from_C_to_D)\n", "W_from_D_to_A = W_net - ( W_from_A_to_B + W_from_B_to_C + W_from_C_to_D)\n", "print(\"Q_from_D_to_A = [\",Q_from_D_to_A,\" ] J.\")\n", "print(\"W_from_D_to_A = [\",W_from_D_to_A,\" ] J.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's just print the whole table now\n", "\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " dU, Q, W\n", " -200.0 5800.0 -6000.0\n", " -4000.0 -3800.0 -200.0\n", " -500.0 -800.0 300.0\n", " 4700.0 200.0 4500.0\n", " 0.0 1400.0 -1400.0\n" ] } ], "source": [ "print(\" dU, Q, W\")\n", "print(\" \",dU_from_A_to_B,\" \",Q_from_A_to_B,\" \",W_from_A_to_B)\n", "print(\"\",dU_from_B_to_C,\" \",Q_from_B_to_C,\" \",W_from_B_to_C)\n", "print(\" \",dU_from_C_to_D,\" \",Q_from_C_to_D,\" \",W_from_C_to_D)\n", "print(\" \",dU_from_D_to_A,\" \",Q_from_D_to_A,\" \",W_from_D_to_A)\n", "print(\" \",dU_net,\" \",Q_net,\" \",W_net)\n", "#note that we are manually adding lots of spaces here, however there are more elegant ways to print values,\n", "#e.g. https://pypi.python.org/pypi/PrettyTable/\n", "#you may want to take a look at these after being done with our beginenr course." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Approach 2\n", "Our second approach involves the use of *functions* in the programming sense.\n", "A function is a named section of a program that performs a specific task, that can be used several times during the execution of the program, and that produces different outputs depending on different inputs provided.\n", "See below how to write a fucntion in Python" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def FirstLaw_dU_from_Q_and_W( Q_input, W_input ): #this is the syntax for definign a function\n", "#def <-- this is the keyword for the definition of a function\n", " #FirstLaw_dU_from_Q_and_W <-- this is the name of the function\n", " #( Q_input, W_input ) <-- these are the name of the dummy arguments that work as input to the function\n", "#This function returns the value of Internal Energy Variation for given values of Heat and Work in a process, according to the first law of thermodynamics\n", "#This is a descriptive comment, so that anybody that reads the code you wrote will understand what you meant\n", "#return is the keyword to assign the output of a given function\n", " return Q_input+W_input " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's look at step $C\\to D$ in the table. There, we know Q and W and we need to calculate U from Q and W, just as is the purpose of the function that we just implemented." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-800.0\n", "300.0\n", "-500.0\n" ] } ], "source": [ "#check that the kernel still know the old values\n", "print(Q_from_C_to_D)\n", "print(W_from_C_to_D)\n", "\n", "#now we call the function in the following manner:\n", "#\"the calculated value for the variable dU_from_C_to_D shall be equal to the result of the function that calculates dU from any Q and W when we use Q_from_C_to_D and W_from_C_to_D as arguments, **respectively**\n", "dU_from_C_to_D = FirstLaw_dU_from_Q_and_W(Q_from_C_to_D,W_from_C_to_D)\n", "\n", "#see the result\n", "print(dU_from_C_to_D)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now for the next step, we can solve the transition from A->B.\n", "There we need to calculate Q from U and W, using the first law" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def FirstLaw_Q_from_dU_and_W( dU_input, W_input ):\n", "#This function returns the value of Heat for given values of Internal Energy Variation and Work in a process, according to the first law of thermodynamics\n", " return dU_input-W_input " ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Q_from_A_to_B = [ 5800.0 ] J\n" ] } ], "source": [ "#now we have a function that matches the interface of the problem posed in step A-B\n", "#and we can use it to solve that problem\n", "Q_from_A_to_B = FirstLaw_Q_from_dU_and_W(dU_from_A_to_B,W_from_A_to_B)\n", "#print the values\n", "print(\"Q_from_A_to_B = [\",Q_from_A_to_B,\"] J\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that order of the arguments matters, if you ever write\n", "\n", "> `dU_from_C_to_D = FirstLaw_dU_from_Q_and_W(W_from_C_to_D,Q_from_C_to_D)`\n", "\n", "you will be asking for the value of dU when the value of Q is equal to the value of W_from_C_to_D and the value of W is equal to the value of Q_from_C_to_D. See below:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "this is what we wanted\n", "if dU is -200.0 and W is -6000.0 then Q is 5800.0\n", "this is not\n", "if dU is -6000.0 and dUW is -6000.0 then Q is -5800.0\n", "this is what we wanted again\n", "if dU is -200.0 and W is -6000.0 then Q is 5800.0\n", "this is what we wanted too\n", "if W is -6000.0 and dU is -200.0 then Q is 5800.0\n" ] } ], "source": [ "#this is what we wanted\n", "print(\"this is what we wanted\")\n", "print(\"if dU is\",dU_from_A_to_B,\"and W is\", W_from_A_to_B,\"then Q is\",FirstLaw_Q_from_dU_and_W(dU_from_A_to_B,W_from_A_to_B))\n", "#this is not\n", "print(\"this is not\")\n", "print(\"if dU is\",W_from_A_to_B,\"and dUW is\", W_from_A_to_B,\"then Q is\",FirstLaw_Q_from_dU_and_W(W_from_A_to_B,dU_from_A_to_B))\n", "#this is what we wanted with explicit dummy-replacement\n", "print(\"this is what we wanted again\")\n", "print(\"if dU is\",dU_from_A_to_B,\"and W is\", W_from_A_to_B,\"then Q is\",FirstLaw_Q_from_dU_and_W(dU_input=dU_from_A_to_B,W_input=W_from_A_to_B))\n", "#this is what we wanted with arguments ordered differently, however with explicit dummy-replacement\n", "print(\"this is what we wanted too\")\n", "print(\"if W is\", W_from_A_to_B,\"and dU is\",dU_from_A_to_B,\"then Q is\",FirstLaw_Q_from_dU_and_W(W_input=W_from_A_to_B,dU_input=dU_from_A_to_B))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To finish approach 2, we can implement all the functions that we already know that we will use, just remembering how we solved the problem using approach 1." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def FirstLaw_W_from_dU_and_Q( dU_input, Q_input ):\n", "#This function returns the value of Work for given values of Internal Energy Variation and Heat in a process, according to the first law of thermodynamics\n", " return dU_input-Q_input\n", "\n", "def net_W_from_4_steps_W(W_a_input,W_b_input,W_c_input,W_d_input):\n", "#This function returns the net Work value for given values of the work in all four steps of the cycle.\n", " return W_a_input + W_b_input + W_c_input + W_d_input\n", "\n", "def net_Q_from_4_steps_Q(Q_a_input,Q_b_input,Q_c_input,Q_d_input):\n", "#This function returns the net Heat value for given values of the heat in all four steps of the cycle.\n", " return Q_a_input+Q_b_input+Q_c_input+Q_d_input\n", "\n", "def some_W_from_3_steps_W_and_net_W(W_a_input,W_b_input,W_c_input,W_net_input):\n", "#This function returns a value of Work in a given step provided that value of work for the other three steps of the cycle and the net Work are determined.\n", " return W_net_input-W_a_input-W_b_input-W_c_input\n", "\n", "def some_Q_from_3_steps_Q_and_net_Q(Q_a_input,Q_b_input,Q_c_input,Q_net_input):\n", "#This function returns a value of Heat in a given step provided that value of heat for the other three steps of the cycle and the net Heat are determined.\n", " return Q_net_input-Q_a_input-Q_b_input-Q_c_input\n", "\n", "def some_dU_from_3_steps_dU(dU_a_input,dU_b_input,dU_c_input):\n", "#This function returns a value of internal energy variation in a given step provided that value of internal energy variation for the other three steps of the cycle are determined.\n", " dU_net_local=0 #this is a local definition of a variable\n", " #it should auxiliate on the calculations that transform the input info to the output info\n", " #however not depending on any other external info neither being acessed form the exteranl scope\n", " #this should behave as if the variable dU_net_local only exists as long as the calculation of the function are being run\n", " #and cease to exist after the function serves its purpose and returns its result.\n", " #for more discussion on this, look up NAMESPACE\n", " return dU_net_local-dU_a_input-dU_b_input-dU_c_input\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can call all those functions to solve the problems in a similar way to the approach 1" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1400.0\n", "-4000.0\n", "200.0\n", "-200.0\n", "4500.0\n" ] } ], "source": [ "\n", "\n", "#we already calculated Q_From_A_to_B and dU_from_C_to_D, and we knwow from dU_net in a cycle is zero\n", "#now the remaining:\n", "Q_net = FirstLaw_Q_from_dU_and_W(dU_net,W_net)\n", "print(Q_net)\n", "dU_from_B_to_C = some_dU_from_3_steps_dU(dU_from_A_to_B,dU_from_C_to_D,dU_from_D_to_A)\n", "print(dU_from_B_to_C)\n", "Q_from_D_to_A = some_Q_from_3_steps_Q_and_net_Q(Q_from_A_to_B,Q_from_B_to_C,Q_from_C_to_D,Q_net)\n", "print(Q_from_D_to_A)\n", "\n", "#and as we implemented a *function*, then we can reutilize it in any problem that has the same interface* i.e. that matches the structure \"we know things A, B, C and want to know things D, E, F\",\n", "#in this case, its a process step in a thermodynamics cycle where we know Q and W and want to know U.\n", "#so let's solve the step 7 and 8 simultaneously at the end\n", "W_from_B_to_C = FirstLaw_W_from_dU_and_Q(dU_from_B_to_C,Q_from_B_to_C)\n", "W_from_D_to_A = FirstLaw_W_from_dU_and_Q(dU_from_D_to_A,Q_from_D_to_A)\n", "print(W_from_B_to_C)\n", "print(W_from_D_to_A)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Approach 3\n", "Instead of manually calling different python fuctions for every type of calculation, we can implement some general purpose functions for each principles exposed, that perform different types of calculation depending on the different information provided and required." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def FirstLaw(dU_in,Q_in,W_in,solve_for_which):\n", " if solve_for_which == 'solve_for_Q': #this is a conditional block, this works in the following manner, after \"if\" we write some conditional statement. If the conditional stamement is met, then the lines below that \"if\" - which are idented (has some space to align in the beggining) - will run. If the conditional statement is not met, they will not run\n", " Q_in = FirstLaw_Q_from_dU_and_W(dU_in,W_in)\n", " elif solve_for_which == \"solve_for_W\": #elif means else if, that is, if the previous if did not run, then this statemente is tried. If it is met the folowing lines - which are also idented - will run.\n", " W_in = FirstLaw_W_from_dU_and_Q(dU_in,Q_in)\n", " elif solve_for_which == \"solve_for_dU\":\n", " dU_in = FirstLaw_dU_from_Q_and_W(Q_in,W_in)\n", " return dU_in, Q_in, W_in #this will return a list of ordered values for dU_in, Q_in, W_in respectively. see in the text below how to use a function like this, that returns a list\n", "\n", "#note that the dummy argument solve_for_which_q should match \"solve_for_W\", \"solve_for_Q\", or \"solve_for_dU\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can call a single function named \"FirstLaw\" and ask it to do three kinds of calculations\n", "See below some test usages:\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "if dU=1 and W = 100, solve FirstLaw\n", "(1.0, -99.0, 100.0)\n", "then Q= -99.0 .\n", "Now, if dU=1 and Q = 10, solve FirstLaw\n", "(1.0, 10.0, -9.0)\n", "then W= -9.0 .\n", "Finally, if Q=10 and W = 100, solve FirstLaw\n", "(110.0, 10.0, 100.0)\n", "then dU= 110.0 .\n" ] } ], "source": [ "#test1 - the input values used here are merely trial values and do not relate to the original problem\n", "print(\"if dU=1 and W = 100, solve FirstLaw\")\n", "print(FirstLaw(dU_in=1.,Q_in=10.,W_in=100.,solve_for_which='solve_for_Q'))\n", "#ignores the guess value for Q and solves for the Q that meets the first law when du is 1 and W is 100.\n", "#In this function, all three variables must be present and assigned, even the one we want to calculate. This is because, in the way the function is written, all variables are expected and the calculations are done only after reading the value of the flag.\n", "print(\"then Q=\",FirstLaw(dU_in=1.,Q_in=10.,W_in=100.,solve_for_which='solve_for_Q')[1],\".\") #if we want to print only Q, which is the second element in the list,\n", "#we use the [1] to extract the element of order 1 from the list (the order counting starts at zero by default). you should remember that the ordering was estabilished in the definition of the First Law function, in the previous jupyter cell containing Python code.\n", "\n", "print(\"Now, if dU=1 and Q = 10, solve FirstLaw\")\n", "print(FirstLaw(dU_in=1.,Q_in=10.,W_in=100.,solve_for_which='solve_for_W'))\n", "print(\"then W=\",FirstLaw(dU_in=1.,Q_in=10.,W_in=100.,solve_for_which='solve_for_W')[2],\".\")\n", "\n", "print(\"Finally, if Q=10 and W = 100, solve FirstLaw\")\n", "print(FirstLaw(dU_in=1.,Q_in=10.,W_in=100.,solve_for_which='solve_for_dU'))\n", "print(\"then dU=\",FirstLaw(dU_in=1.,Q_in=10.,W_in=100.,solve_for_which='solve_for_dU')[0],\".\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we implement the function regarding the fundamentals of net properties in a cycle. This function can be used for all prorperties in this problem." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def Cycle(number_of_steps,step_property_list,solve_for_which):\n", "#This function relates properties in steps of a cycle process and the net property\n", "#the usage of this function considers element zero as being net property\n", "#elements 1 and on are each step properties\n", "#and this function solves for the element of the list indicated in \"solve_for_which\" argument\n", " if solve_for_which == 0:\n", " step_property_list[0] = 0.\n", " for i in range(1,number_of_steps+1,1): #this is a \"for loop\" block, it evaluates a number of times to run the block, and runs the block that many times sucessively, with changing values for the loop counter variable \"i\"\n", " #the function range works as follow: argument 1 is start, argument 2 is stop (exclusive) and argument 3 is step, and generates a range for the loop block for to follow.\n", " step_property_list[0] = step_property_list[0] + step_property_list[i]\n", " elif solve_for_which > 0:\n", " step_property_list[solve_for_which] = step_property_list[0]\n", " for i in range(1,solve_for_which-1+1,1):\n", " step_property_list[solve_for_which] = step_property_list[solve_for_which] - step_property_list[i]\n", " for i in range(solve_for_which+1,number_of_steps+1,1):\n", " step_property_list[solve_for_which] = step_property_list[solve_for_which] - step_property_list[i]\n", " return step_property_list" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can call a single function named \"Cycle\" and ask it to solve for any step or net property, given the remaining are provided correctly.\n", "See below some test usage:\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "if the steps are 10, 200, 3000, 40000\n", "[43210.0, 10, 200, 3000, 40000]\n", "the net is 43210.0\n", "Now, if three of the steps are 200, 3000, 40000, and the net is 0\n", "[0, -43200, 200, 3000, 40000]\n", "the missing step is -43200\n", "And, if three of the steps are 10, 3000, 40000, and the net is 0\n", "[0, 10, -43010, 3000, 40000]\n", "the missing step is -43010\n", "And, if three of the steps are 10, 200, 40000, and the net is 0\n", "[0, 10, 200, -40210, 40000]\n", "the missing step is -40210\n", "Finally, if three of the steps are 10, 200, 3000, and the net is 0\n", "[0, 10, 200, 3000, -3210]\n", "the missing step is -3210\n" ] } ], "source": [ "#test\n", "print(\"if the steps are 10, 200, 3000, 40000\")\n", "print(Cycle(4,[0,10,200,3000,40000],0)) #solve for net\n", "print(\"the net is \",Cycle(4,[0,10,200,3000,40000],0)[0])\n", "\n", "print(\"Now, if three of the steps are 200, 3000, 40000, and the net is 0\")\n", "print(Cycle(4,[0,10,200,3000,40000],1)) #solve for step 1\n", "print(\"the missing step is \",Cycle(4,[0,10,200,3000,40000],1)[1])\n", "\n", "print(\"And, if three of the steps are 10, 3000, 40000, and the net is 0\")\n", "print(Cycle(4,[0,10,200,3000,40000],2)) #solve for step 2\n", "print(\"the missing step is \",Cycle(4,[0,10,200,3000,40000],2)[2])\n", "\n", "print(\"And, if three of the steps are 10, 200, 40000, and the net is 0\")\n", "print(Cycle(4,[0,10,200,3000,40000],3)) #solve for step 3\n", "print(\"the missing step is \",Cycle(4,[0,10,200,3000,40000],3)[3])\n", "\n", "print(\"Finally, if three of the steps are 10, 200, 3000, and the net is 0\")\n", "print(Cycle(4,[0,10,200,3000,40000],4)) #solve for step 4\n", "print(\"the missing step is \",Cycle(4,[0,10,200,3000,40000],4)[4])\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's use this last approach to solve the problem:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dU_from_C_to_D = [ -500.0 ] J\n", "5800.0\n", "1400.0\n", "-4000.0\n", "200.0\n", "-200.0\n", "4500.0\n" ] } ], "source": [ "#Data\n", "dU_from_A_to_B = -200.\n", "# find dU_from_B_to_C\n", "# find dU_from_C_to_D\n", "dU_from_D_to_A = 4700.\n", "# find dU_net\n", "\n", "#find Q_from_A_to_B\n", "Q_from_B_to_C = -3800.\n", "Q_from_C_to_D = -800.\n", "#find Q_from_D_to_A\n", "#find Q_net\n", "\n", "W_from_A_to_B = -6000.\n", "#find W_from_B_to_C\n", "W_from_C_to_D = 300\n", "#find W_from_D_to_A\n", "W_net = -1400\n", "\n", "#1) Principle #3 state property total variation in a cycle is zero\n", "dU_net = 0.\n", "#2)\n", "dU_from_C_to_D = FirstLaw(dU_from_C_to_D,Q_from_C_to_D,W_from_C_to_D,'solve_for_dU')[0]\n", "print(\"dU_from_C_to_D = [\", dU_from_C_to_D, \"] J\" )\n", "#3)\n", "Q_from_A_to_B = FirstLaw(dU_from_A_to_B,Q_from_A_to_B,W_from_A_to_B,'solve_for_Q')[1]\n", "print(Q_from_A_to_B)\n", "#4)\n", "Q_net = Cycle(4,[Q_net,Q_from_A_to_B,Q_from_B_to_C,Q_from_C_to_D,Q_from_D_to_A],0)[0]\n", "print(Q_net)\n", "#5)\n", "dU_from_B_to_C = FirstLaw(dU_from_B_to_C,Q_from_B_to_C,W_from_B_to_C,'solve_for_dU')[0]\n", "print(dU_from_B_to_C)\n", "#6)\n", "Q_from_D_to_A = Cycle(4,[Q_net,Q_from_A_to_B,Q_from_B_to_C,Q_from_C_to_D,Q_from_D_to_A],4)[4]\n", "print(Q_from_D_to_A)\n", "#7)\n", "W_from_B_to_C = FirstLaw(dU_from_B_to_C,Q_from_B_to_C,W_from_B_to_C,'solve_for_dW')[2]\n", "print(W_from_B_to_C)\n", "#8)\n", "W_from_D_to_A = FirstLaw(dU_from_D_to_A,Q_from_D_to_A,W_from_D_to_A,'solve_for_dW')[2]\n", "print(W_from_D_to_A)\n", "#done" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conclusion\n", "In this notebook, you were introduced to some fundamental aspects of programming, using Python language. Along with them, you were also introduced to some of the core principles of Thermodynamics, like the First Law and the operation of cycles. After studying this notebook, you should be able to write code in Python in order to solve simple problems either by using it as calculator or by creating simple functions. The following notebooks will address more complex code structures and thermodynamic issues, thus we recommend that the subjects we addressed here are well understood by you before you continue your journey to master the Applied Thermodynamics knowledge." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## External References\n", "\n", "* operators (`+`, `-`, `*`, `/`, ...), assignments (`=`, ...): [tutorials point / python / basic operators](https://www.tutorialspoint.com/python/python_basic_operators.htm)\n", "* functions (`def`, ...): [tutorials point / functions](https://www.tutorialspoint.com/python/python_functions.htm)\n", "* conditional (`if`, ...): [tutorials point / python / if](https://www.tutorialspoint.com/python/python_if_else.htm)\n", "* loops (`for`, `while`, ...): [tutorials point / python / for](https://www.tutorialspoint.com/python/python_for_loop.htm)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Credits\n", "* Development of this chapter: Iuri Soter Viana Segtovich and Fernando de Azevedo Medeiros\n", "* Acknowledgments:\n", " * To Hermes Ribeiro Sant'Anna for first introducing us to *ipython* and *jupyter notebook*" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [conda root]", "language": "python", "name": "conda-root-py" }, "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.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }