<jupyter_start><jupyter_text>Plot a Function, Save the plot to a fileThis notebook shows how to plot an elabortae function, then send to output to a file.  The example is adapted from a server-side implementation of the same problem:    In the server-side implementation the following steps are used    1) Input interface is an html web page, with input cells (built into html)    2) Action button, uses POST method to send request to the python script housed in cgi-bin directory linked to the webroot.    3) Parse the form , structure the inputs -- in the code below, the interactive inputs `` variable = float(input{"message")``replace the parser script.    4) Run the calculations - prepare the plot    5) Send the plot to a file    6) Create output html, use the plot as an image source.    7) Done!      Here we will only do step 3 (modified) and step 4; there is substantial added work to do the web interface -- that's shown at the end of this notebook.For our notebook, we will need ``math`` and ``matplotlib``. There are someother imports from the cgi-bin script, that are commented out.<jupyter_code># This is script is a test for SERVER-SIDE computation
# Values to enter via a web interface and leave in a graphic
# <NAME> 2016-0216
#
# Import mathlibrary to get special functions
#
from math import sqrt,erf,erfc,exp  # get special math functions
#
# Import graphics routines for picture making
#
from matplotlib import pyplot as plt
#
# Import system calls to nicely exit the program -- may need to change for server-side processing
#
#import sys ## used in the html/cgi-bin, not needed here<jupyter_output><empty_output><jupyter_text>Forward Define the FunctionsThis step is important, the functions must be defined before they are called -- in an interpreter, this is usually done at the top of the script.  Other scripting languages store the scripts at the end (JavaScript usually keeps scripts at end of the file -- it internally promotes then to the top before it runs its JIT bytecode compiler.In a compiled language, this is not as necessary (predefinition is, location not so much). These prototype functions are usually written so that they are organic with respect to their variables, so there is no leakage -- in these two functions, the input list is just names, and the output is just a value that must be assigned in the calling script.Our first function evaluates:\begin{equation}C(x,t) = \frac{a}{b}\end{equation}<jupyter_code># contaminant function
def concentration(c_initial,c_source,space,time,t_pulse,dispersion,velocity,retardation,mu,lamda):
# PARAMETERS (ARGUMENTS)
# c_initial == concentration everywhere at time = 0, excpet at source
# c_source == concentration at source (x=0), for any time
# space == distance from source at x=0
# time  == elapsed time from t=0
# t_pulse == duration of finite source pulse
# dispersion == dispersion (diffusion) coefficient (length^2/time)
# velocity == species velocity (mean section velocity/porosity) (length/time)  Calculate before call function
# retardation == retardation coefficient (adjusted time) Calculate before call function
# mu == 1st order decay rate coefficient (time^-1)
# lamda == 0th order rate constant (concentration/time)
#################################################
## COMPUTE A                                   ##
#################################################
    termA1 = (1.0-0.5*erfc(((retardation*space)-(velocity*time))/(2.0*sqrt(dispersion*retardation*time))))
    termA2 = (-0.5*exp(velocity*space/dispersion)*erfc(((retardation*space)+(velocity*time))/(2.0*sqrt(dispersion*retardation*time))))
    termA3 = (exp(-mu*time/retardation))
    termA = termA1*(termA2+termA3)
#################################################
# error handler for negative (undefined) time ###
#################################################
    if(time < 0):
        print("negative time -- no solution")
        concentration = (-999.9)
        return (concentration)
################################################
# During the finite pulse                    ###
################################################
    if(time <= t_pulse):
        concentration = (lamda/mu)+(c_initial - lamda/mu)*termA + (c_source - lamda/mu)*termB(space,time,velocity,dispersion,retardation,mu)
        return(concentration)
    else:
        concentration = (lamda/mu)+(c_initial - lamda/mu)*termA + (c_source - lamda/mu)*termB(space,time,velocity,dispersion,retardation,mu) -c_source*termB(space,time-t_pulse,velocity,disersion,retardation,mu)
        return(concentration)
#################################################
# error handler for impossible
    print("no path to this message")
    concentration = -999.0
    return(concentration)
#################################################<jupyter_output><empty_output><jupyter_text>Here is the other function, this uses a concept of adjusted time to account for a linear equilibrium isotherm for the underlying mass transport process.  Code wise nothing special, just another funcion<jupyter_code># term B function to handle time shift
def termB(space,time,velocity,dispersion,retardation,mu):
## COMPUTE B ##
## Compute adjusted velocity
    u = velocity* sqrt(1.0+(4.0*mu*dispersion)/(velocity**2)) # cm/day
#
    termB1 =(0.5)*exp(0.5*((velocity-u)*space)/(dispersion))
    termB2 = erfc(((retardation*space)-(u*time))/(2.0*sqrt(dispersion*retardation*time)))
    termB3 = termB1*termB2
#
    termB4 =(0.5)*exp(0.5*((velocity+u)*space)/(dispersion))
    termB5 = erfc(((retardation*space)+(u*time))/(2.0*sqrt(dispersion*retardation*time)))
    termB6 = termB4*termB5
#
    termB = termB3+termB6
    return(termB)

#################################################
# lets test
c_initial = float(input("Initial Concentration 0"))
c_source = float(input("Source Concentration 1000"))
space = float(input("Space 1"))
time  = float(input("Time 10"))
t_pulse = float(input("Pulse Duration 100"))
dispersion = float(input("Dispersion Coefficient 1"))
velocity = float(input("Velocity .5"))
retardation = float(input("Retardation Factor 1.0"))
mu = 0.0000001
lamda = 0.0

#c_initial = 0.0
#c_source = 1000.0
#space = 1.
#time  = 10.
#t_pulse = 100.0
#dispersion = 1.0
#velocity = 0.5
#retardation = 1.0
#mu = 0.0000001
#lamda = 0.0

#
# forward define and initialize vectors for a profile plot
#
how_many_points = 50
x = range(0,how_many_points,1) # null list
c = [0.0 for i in range(how_many_points)] # null list
#
# initialize the vectors so can use ordinary arithmetic
#dist = [0.1,1.0,2.0,3.0,4.0,5.0]
#dist = range(0,50,1)
for i in range(0,how_many_points,1):
    c[i] = concentration(c_initial,c_source,x[i],time,t_pulse,dispersion,velocity,retardation,mu,lamda)
#    print (x[i],c[i])  # cool, now can build plot
#
# Building the Plot
#
plt.plot(x,c, color='red', marker='o', linestyle = 'solid')  # make the plot object
plt.title(" Concentration Profile ") # caption the plot object
plt.xlabel(" Distance from Source ") # label x-axis
plt.ylabel(" Concentration        ") # label y-axis
plt.savefig("1D-ADR.png")
plt.show() # plot to stdio -- has to be last call as it kills prior objects
plt.close('all') # needed when plt.show call not invoked
print("end of script")
#sys.exit() # used to elegant exit for CGI-BIN use<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16445114430587912, 'fraction_numerical': 0.021789776620528986, 'mean_word_length': 4.852445870088212, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '249519', 'license': 'CC0-1.0', 'n_tokens_mistral': 2257, 'n_tokens_neox': 2094, 'n_words': 738, 'path': '9-MyJupyterNotebooks/99-1D-ADR-Decay-Model/1D-ADR-Decay.ipynb', 'repo_name': 'dustykat/engr-1330-psuedo-course', 'size': '7302'}