One condition where this does not work is for Python functions where “None” is a valid argument, but it is not the default. For instance, many Scipy functions working with multi-dimension array input have an “axis” argument that allows “None” as input, but the default is 0. In this case the default value for the Excel function should be set to 0, and the data type set to variant. Before calling the Python function two additional steps are then required:

- If the argument is a number, convert it from “float” to “int”.
- If the argument is the string “None” convert it to the Python None object.

Typical code is shown below:

```
@xl_func
@xl_arg('a', 'numpy_array', ndim = 2)
@xl_arg('axis', 'var')
@xl_arg('dtype', 'str')
@xl_return('numpy_array')
def py_hmean(a, axis = 0, dtype = None):
...
if axis != 'None': axis = int(axis)
kwargs = {'axis': axis, 'dtype': dtype}
kwargs = {k:v for k,v in kwargs.items() if v is not None}
if axis == 'None': kwargs['axis'] = None
res = stats.hmean(a, **kwargs)
```

]]>This raises the question, if an Excel function is being used to call a Python function with default arguments, and both functions require a default value to be specified, how do we ensure that the default values are consistent?

The obvious solution is to specify all the Excel defaults as “None”, so that the Python function applies its specified defaults; however this does not work. “None” is not the same as “nothing”, so the Python function treats the argument value as being “None”, rather than applying the default. An example is the Numpy “linspace” function, where the boolean “endpoint” argument has as default value of True, but setting all defaults to None will result in a default of False, so the resulting series will have one less value, with an increased space between the numbers.

Solutions that do work include:

- Assign all the Python function default values to the Excel function.
- Pass the optional arguments to the Excel function as a single dictionary, using the Python argument names. It is then not necessary to specify default values in the Excel function. Any missing arguments will then not be passed to the Python function, and the Python defaults will be used.
- Assign a default value of “None” to all the optional arguments in the Excel function, then form a dictionary in the Excel code, of any arguments that have a value other than “None”.

Option 1 provides simple coding, but requires extra work in extracting the correct default value from the documentation (which is not always clearly stated).

Option 2 is also simple to code, but does not allow the creation of help for each argument when using the Excel function wizard.

Option 3 requires some extra coding, but allows the Python help for each argument to be copied to the function docstring, from where it can be accessed in Excel using the function wizard.

Typical code for a Scipy Stats function using Option 3 is shown below:

# pyxll decorators, allowing the function to be called from Excel @xl_func @xl_arg('a', 'numpy_array', ndim = 1) @xl_arg('numbins', 'int') @xl_arg('defaultreallimits', 'numpy_array', ndim = 1) @xl_arg('weights', 'numpy_array', ndim = 1) @xl_return('numpy_array') # assign the default None to all optional arguments def py_relfreq(a, numbins = None, defaultreallimits = None, weights = None): # Help that will appear in the Excel function wizard """ Return a relative frequency histogram, using the histogram function. :param a: Input array. :param numbins: The number of bins to use for the histogram. Default is 10. :param defaultreallimits: The lower and upper values for the range of the histogram. If no value is given, a range slightly larger than the range of the values in a is used. Specifically ``(a.min() - s, a.max() + s)``, where ``s = (1/2)(a.max() - a.min()) / (numbins - 1)``. :param weights: The weights for each value in `a`. Default is None, which gives each value a weight of 1.0 """ # create a dictionary of each optional argument name, with the argument value kwargs = {'numbins': numbins, 'defaultreallimits': defaultreallimits, 'weights': weights} # extract the arguments that have a value other than None kwargs = {k:v for k,v in kwargs.items() if v is not None} # call the function, passing the dictionary using **kwargs rf = stats.relfreq(a, **kwargs) # convert the results to a 2D array that can be passed back to Excel ncols = len(rf[0]) binwidth = rf[2] nrf = np.zeros((2,ncols)) nrf[0,:] = rf[0] nrf[1,0] = rf[1]+binwidth for i in range(1, ncols): nrf[1,i] = nrf[1,i-1] + binwidth return nrf

Use of this function from the Excel function wizard is shown in the screen-shot below (click the image for full-size view):

This code will generate the correct function defaults, but creates a problem in the case where “None” is a valid option, but not the default, since entering None as the argument value will result in the default value being used. The next post will look at how to handle that situation.

]]>The revised spreadsheet, including full open-source code, can be downloaded from:

]]>The UMom function in ULS Design Functions can be used to analyse any reinforced concrete section that can be divided into a series of stacked trapezoids. For the purpose of comparing the results of a rectangular or parabolic stress block when analysing a circular section the circle was divided into 24 layers:

The parabolic-linear stress block option uses the form specified in Eurocode 2 for both the Eurocode and AS 3600 codes, and a modified version for the ACI code, as specified in the PCA document: PCA Notes on ACI 318-11 Building Code (EB712). The main differences in the ACI stress block are:

- The maximum concrete stress reduction factor is 0.85 (1.0 for the default Eurocode and 0.9 for AS 3600)
- The strain at the compression face is 0.003 (0.0035 in Eurocode)
- The strain at the end of the parabolic portion is based on a parabolic curve with an initial slope equal to 1/Ec -see below (tabulated values based on concrete strength in Eurocode)
- The exponent of the parabolic curve is 2 for all concrete strengths (reduced values for high strength concrete in Eurocode.

The graphs below compare moment vs axial load results using the rectangular and parabolic-linear stress blocks for circular sections with low and high concrete strengths to the three codes.

The ACI results below used customary US units with concrete strengths of 5 and 10 ksi (approximately 34.5 and 69.0 MPa)

For the lower strength concrete the rectangular stress block moment capacities are significantly higher than the parabolic stress block for all axial load greater than the balance load, and for higher strength concrete the difference increases to almost a 50% increase at loads close to the maximum axial load.

For the AS 3600 code (below) the parabolic stress block gives a greater moment capacity with the lower strength concrete, but with the high strength concrete the rectangular stress block is less conservative for mid-range axial loads, but the parabolic stress block has higher capacity with very high axial loads.

The Eurocode results show a similar relationship between the two stress blocks as AS 3600 for the lower strength concrete, but the parabolic stress block also has higher moment results with the high strength concrete, for all axial loads above the balance load. Note that the Eurocode results for the rectangular stress block have an additional reduction factor of 0.9, in accordance with Eurocode requirements for sections where the concrete width reduces towards the compression face:

The graphs below compare the parabolic stress block results from the 3 codes:

For the lower strength concrete the AS 3600 and ACI 318 are very close for high axial loads and zero axial load to maximum tension, but for intermediate axial loads the ACI results are significantly higher. This is because of the different procedures for calculating the transition of the capacity reduction factor from 0.85 to 0.65. For the high strength concrete the ACI results are significantly higher than AS 3600 over the full range of compressive axial loads up to the ACI maximum.

The Eurocode results are higher than both ACI 318 and AS 3600 for loads above the balance load for both the low and high strength concrete. The reasons for this difference, when the Eurocode and AS 3600 calculations use the same stress block, are examined below:

If the global reduction factors are set to 1.0, and the AS 3600 steel yield strength and concrete compressive strength are factored down by 1.15 and 1.5 repectiveley, the AS 3600 results exactly match the Eurocode results:

However if in AS 3600 the global reduction factor is set to 1/1.5, with the steel yield strength factored by 1.5/1.15, and the concrete strength factored by 1/0.9, so the nett material properties after factoring are the same as in the Eurocode analysis, the results are different:

The reason is that in the Eurocode analysis forces in the reinforcing bars within the elastic range are not factored down, whereas in the AS 3600 analysis all the forces in the reinforcement are factored down by 1.5. In effect, the elastic modulus of the steel is reduced by a factor of 1.5 in the AS 3600 analysis, but remains unchanged in the Eurocode analysis. If the previous analysis is repeated with the steel elastic modulus factored up to 30,000 MPa in the AS 3600 run, the results from the two analyses are identical:

Update 27 Jan 2021:

Following the comment dated 25th Jan. below, I have modified the MomA function so that if any of the tabulated input axial loads exceed the section capacity, the function moves on to the next value, rather than exiting. The new file is now in the ULS Design Functions zip file near the top of the post.

]]>The pyFEM sites associated with the book are:

jjcremmers/PyFEM: A Python finite element code (github.com)

and an associated pypi site:

PyFEM is a python-based finite element code accompanies the book: ‘Non-Linear Finite Element Analysis of Solids and Structures’ by R. de Borst, M.A. Crisfield, J.J.C. Remmers and C.V. Verhoosel. The code is open source and intended for educational and scientific purposes only. If you use PyFEM in your research, the developers would be grateful if you could cite the book in your work.

Another github site of the same name, but apparently entirely independent is:

rvcristiand/pyFEM: Finite Elements Analysis with python (github.com)

A third package of the same name, but with the specific purpose of finite element mesh conversion is:

The PyFEM Mesh Conversion Software Library

]]>The PyFEM library is an open -software project for the conversion of 2D and 3D mesh formats. • Primarily designed for conversion of Finite Element meshes as used in numerical simulations in the geosciences.

Lost Sydney is a Facebook site with 100’s of photographs of Sydney, some dating back well over 100 years.

]]>This is Sydney’s story. Lost Sydney is not just about demolished buildings, it’s also about photos of Sydney’s past.

Lost Sydney

On Wikipedia the table looks like this:

and when copied and pasted as Unicode text into Excel, like this:

To convert the text in the final column to values the following changes are required:

- Skip the leading non-numeric characters,
- Remove spaces between numbers.
- Remove the final numbers enclosed in brackets, indicating the uncertainty in the final digits.
- Convert the exponent (e.g. x10-27) to Excel format (E-27). Note that a positive exponent displays as a 4 digit number, e.g. x1027.
- Convert the resulting text string to a number with double data type.
- Extract the units
- Skip references to notes.

The following code does the job:

```
Function ExtractVal(Txt As String, Optional ExtractUnits As Boolean = True)
' Extract number and optionally units from Wikipedia unit conversion factor table
' Remove preceding text and trailing notes, and variance value enclosed in ()
' Convert x10nn to Enn or x10-nn to E-nn
Dim n As Long, m As Long, char As String, ValStr As String, RtnA() As Variant, i As Long, strcode As Long
' Skip over any non-numeric text before the first number
If ExtractUnits Then
ReDim RtnA(1 To 2)
Else
ReDim RtnA(1 To 1)
End If
n = Len(Txt)
For i = 1 To n
char = Mid(Txt, i, 1)
If IsNumeric(char) Then Exit For
Next i
ValStr = char
m = i + 1
' Extract all numbers until the first non-numeric text
' Skip over single spaces followed by a number
For i = m To n
char = Mid(Txt, i, 1)
If IsNumeric(char) = False And char <> "." Then
If IsNumeric(Mid(Txt, i + 1, 1)) = False Or char <> " " Then Exit For
Else
ValStr = ValStr & char
End If
Next i
m = i + 1
' Skip over numbers enclosed in ()
char = Mid(Txt, i, 1)
If char = "(" Then
For i = m To n
char = Mid(Txt, i, 1)
If char = ")" Then
i = i + 1
Exit For
End If
Next i
End If
' Extract numbers following 'x10' and add to value string as Enn
' The 'x' in the Wikipedia table is Ascii code 215
char = Mid(Txt, i, 1)
strcode = Asc(char)
If strcode = 215 Then
m = i + 3
ValStr = ValStr & "E"
For i = m To n
char = Mid(Txt, i, 1)
strcode = Asc(char)
If strcode = 45 Then char = "-"
If IsNumeric(char) = False And char <> "-" Then Exit For
ValStr = ValStr & char
Next i
End If
' Convert value string to double and copy to RtnA
RtnA(1) = CDbl(ValStr)
' Extract unit text, skip over final note reference
If ExtractUnits Then
m = i + 1
ValStr = ""
For i = m To n
char = Mid(Txt, i, 1)
If char = "[" Then Exit For
ValStr = ValStr & char
Next i
' Copy unit to RtnA
RtnA(2) = ValStr
End If
ExtractVal = RtnA
End Function
```

This function can be applied to the text at the top of the final column, and copied down, resulting in:

Columns AB and AC are the function output. Column AD uses the built in IsNumber function to confirm that the values in Column AB are indeed valid numbers.

]]>The new file is located (as before) at:

Any problems, please leave a comment below, with details of error messages and Excel version, including 32 bit or 64 bit.

]]>In her speech to the GI Movement of the Vietnam War Era (whose text can be found in the booklet that’s included in Paredon Records’ *FTA! Songs of the GI Resistance* vinyl album of 1970), Barbara Dane said, “I was too stubborn to hire one of the greed-head managers, probably because I’m a woman who likes to speak for herself. I always made my own deals and contracts, and after figuring out the economics of it, I was free to choose when and where I worked, able to spend lots more time with my three children and doing political work, and even brought home more money in the end, by not going for the ‘bigtime.’ I did make some really nice records, because I was able to choose and work with wonderfully gifted musicians.”^{[7]}

**Tia Blake** was the stage name of **Christiana Elizabeth Wallman** (1952-2015), an American writer and singer…

Wallman was born in Columbus, Georgia, in 1952, and grew up in North Carolina.^{[1]} In 1970 she worked for Farrar, Straus and Giroux in New York for six months, before moving to Paris.^{[1]} In Paris she recorded an album of folk songs at Ossian Studio in 1971. This was released in February 1972 by Société Française de Productions Phonographiques (SFPP) under the title *Folk Songs and Ballads: Tia Blake and Her Folk-group*.^{[1]}

**Bridget St John** (born **Bridget Anne Hobbs**; 4 October 1946 in Surrey, England)^{[1]} is an English singer-songwriter and guitarist, best known for the three albums she recorded between 1969 and 1972 for John Peel‘s Dandelion record label. Peel produced her debut album *Ask Me No Questions*. She also recorded a large number of BBC Radio and Peel sessions and toured regularly on the British college and festival circuit. St John appeared at leading folk venues in the UK, along with other folk and pop luminaries of the time such as Nick Drake, Paul Simon, and David Bowie, among others.^{[2]} In 1974 she was voted fifth most popular female singer in that year’s *Melody Maker* readers poll.^{[3]} Blessed with a “rich cello-like”^{[4]} vocal style, she is also an accomplished guitar player who credits John Martyn and Michael Chapman as her “musical brothers”.^{[5]}

**Vashti Bunyan** (born **Jennifer Vashti Bunyan**^{[2]} in 1945^{[3]}) is an English singer-songwriter.

Bunyan released her debut album, *Just Another Diamond Day*, in 1970. The album sold very few copies and Bunyan, discouraged, abandoned her musical career. By 2000, her album had acquired a cult following; it was re-released and Bunyan recorded more songs, initiating the second phase of her musical career after a gap of thirty years.^{[4]} She subsequently released two albums: *Lookaftering* in 2005, and *Heartleap* in 2014.

The Newton Raphson method explained, details, pictures, python code Highly instructive examples for the Newton Raphson method |

I have added an example from these papers to my ItSolve spreadsheet, illustrating some advantages of Brent’s Method for problems that may be difficult to solve using the Newton-Raphson method. The updated spreadsheet (including full open-source code) may be downloaded from:

The example finds solutions to the function shown below:

Using the Newton-Raphson Method a solution may not be found:

The screen-shots below show all four solutions between -7 and 7 using Brent’s method:

Note that:

- The values specified for the search range must return a positive and negative function result. If both are positive, or both negative an error message is returned.
- The Quadbrent function works with functions entered as text on the spreadsheet as shown, or (by default) will call a named VBA function. The QuadbrentT function is a front-end for Quadbrent with defaults set to use text on the spreadsheet, as shown above.
- The text function must be entered in a format recognisable by Excel, for instance the value Pi is entered as Pi().