There are a few style changes that could be made to make the project more 'pythonic' and to make future development easier. The aim here wouldn't be to change any behaviour, but instead to simplify some code and reduce the potential for bugs to creep in. Let me know your thoughts on any of these suggestions.
while loops
A common pattern throughout the project is to use while loops in places where a for loop might be safer:
# while version
i = 0 # developers might forget to set this when 'i' is reused within a function
while (i < num):
# do something...
i += 1 # developers might also forget this line, leading to infinite loops
# for version
for i in range(num):
# do something...
There are also places where loops are used to build lists, and they could instead be replaced with a list comprehension:
# while version
my_list = []
i = 0
while (i < list_len):
my_list.append(some_function(i))
i += 1
# list comprehension version
my_list = [some_function(i) for i in range(list_len)]
This might perform a little better (although it's never guaranteed), and it leads to much more compact code. I find them quite easy to read, but I understand that some other programmers aren't too keen on them, so it's personal preference if they're used or not. It's easy to fall into the trap of over-engineering list comprehensions until they're near-unreadable, so it's best to keep them simple.
Repeat code
There are some places where a long line of complex arithmetic is repeated on several lines. It'd be better to break these lines down into a few variables, as then there's less risk of developers modifying a line of code but forgetting to make similar changes to later lines (or simply making a mistake when updating later lines). e.g:
https://github.com/AleksandarJ1984/FEDM/blob/720e18015a994defab8c44d01b433bc4ddefaf5d/fedm_modules/functions.py#L220-L228
Could modify to something like:
# Ideally, should break this down further to aid readability
common_part = 2.0*pi*exp(u)*((((1.0+2.0*dt/dt_old)/(1.0+dt/dt_old))*(u - (pow(1.0+dt/dt_old, 2.0)/(1.0+2.0*dt/dt_old))*u_old\
+ (pow(dt/dt_old, 2.0)/(1.0+2.0*dt/dt_old))*u_old1))*v/dt)*r*dx
if (equation_type == 'reaction'):
return common_part - 2.0*pi*f*v*r*dx
elif (equation_type == 'diffusion-reaction'):
return common_part - 2.0*pi*dot(-grad(D*exp(u)), grad(v))*r*dx - 2.0*pi*f*v*r*dx
elif (equation_type == 'drift-diffusion-reaction'):
return common_part - 2.0*pi*dot(Gamma, grad(v))*r*dx - 2.0*pi*f*v*r*dx
else: # handle incorrect 'equation_type'
raise ValueError(f"Equation type {equation_type} not recognised")
Formatting with an autoformatter/linter
I've found some of the longer lines in the project difficult to read, especially if I'm looking at two files side-by-side in my terminal. We could use a tool like Black to automate the formatting of the project, which in my experience tends to do a really good job of producing consistent and readable code (it sometimes does questionable things, but if it makes your code less readable it's usually an indication that you're doing too much on one line anyway).
We could also use flake8 to enforce style further and catch any potential bugs (it's good for catching unused variables). These can both be configured using setup.cfg/pyproject.toml, which would be implemented for Issue #1.
There are a few style changes that could be made to make the project more 'pythonic' and to make future development easier. The aim here wouldn't be to change any behaviour, but instead to simplify some code and reduce the potential for bugs to creep in. Let me know your thoughts on any of these suggestions.
whileloopsA common pattern throughout the project is to use
whileloops in places where aforloop might be safer:There are also places where loops are used to build lists, and they could instead be replaced with a list comprehension:
This might perform a little better (although it's never guaranteed), and it leads to much more compact code. I find them quite easy to read, but I understand that some other programmers aren't too keen on them, so it's personal preference if they're used or not. It's easy to fall into the trap of over-engineering list comprehensions until they're near-unreadable, so it's best to keep them simple.
Repeat code
There are some places where a long line of complex arithmetic is repeated on several lines. It'd be better to break these lines down into a few variables, as then there's less risk of developers modifying a line of code but forgetting to make similar changes to later lines (or simply making a mistake when updating later lines). e.g:
https://github.com/AleksandarJ1984/FEDM/blob/720e18015a994defab8c44d01b433bc4ddefaf5d/fedm_modules/functions.py#L220-L228
Could modify to something like:
Formatting with an autoformatter/linter
I've found some of the longer lines in the project difficult to read, especially if I'm looking at two files side-by-side in my terminal. We could use a tool like Black to automate the formatting of the project, which in my experience tends to do a really good job of producing consistent and readable code (it sometimes does questionable things, but if it makes your code less readable it's usually an indication that you're doing too much on one line anyway).
We could also use flake8 to enforce style further and catch any potential bugs (it's good for catching unused variables). These can both be configured using
setup.cfg/pyproject.toml, which would be implemented for Issue #1.