Published November 25, 2025
| Version v2.0.0
Software
Open
aatmdelissen/pyMOTO: v2.0.0
Authors/Creators
- 1. TNO
- 2. Delft University of Technology
- 3. University of Luxembourg
Description
What's Changed
Main improvements with syntax change:
- More clear intent of code
- Much less boilerplate code. Adding modules to a Network does not require
appendanymore, but modules are automatically added to Network, user can select which Network(s) to use with context manager (with:) - Modules now accept optional positional arguments (not keyword arguments)
- Standard functions
__init__and__call__are used, for much better IDE integration and code hints - Normal variables can now be used instead of or in combination with signals as module inputs
- The module response is run once upon creation, which is more convenient for debugging
An examples gallery is added on the documentation page, which contains all examples in the new syntax style. Also, several new examples were added.
Renamed (old names will raise deprecation warning):
MathGeneral->MathExpressionDomainDefinition->VoxelDomainDyadCarrier->DyadicMatrixVecSet->SetValueConcatSignal->Concatenate
Module improvements:
AutoDiffmodule improvements, supporting backend based on HIPSautogradas alternative tojaxWriteToVTInow supports writing complex vectorsScalingnow supports double-sided constraints, where both a minimum and maximum value is requestedAssembleGeneralnow supports non-square matrices. Also, multiple element matrices can be passed with each their own individual scaling values to support multi-material topology optimization. The matrix assembly is also sped up by storing the sparsity pattern.OverhangFilternow supports freely choosing overhang angle for additive manufacturing, instead of only 45 degrees (for details see linked paper).
New modules:
SplitComplex- Splits complex value into its real and imaginary partsPrint- Print values in a signal to consoleSetValue- Set values in anumpyarray for specified indicesAddMatrix- Linear combination of sparse matricesConjugate- Complex conjugationTransientSolve- Calculation of transient response with numerical time-stepping (implemented for first order system)SeriesToVTI- Export of time-series data to VTI format (Paraview)
Other improvements:
- New methods in
VoxelDomain(formerlyDomainDefinition) (element_size,domain_size,size,get_dofnumber,get_element_indices) VoxelDomainnow also can voxelize mesh objects (e.g. from STL) using the methodscreate_for_mesh, which generates a suitable domain, andvoxelizewhich then converts a triangle mesh into voxel elements.- Switch from using
pypardisoto directly usingmklfor usage of Pardiso solver. Also enable solving matrices with complex and/or single precision. - MMA now supports unconstrained optimization (only an objective), see issue #7
- MMA optimizer can now also switch to the globally convergent version (GCMMA) with option
mmaversion='GCMMA') - MMA speedups
- SLP optimization algorithm
Software implementation:
- Improve publishing scripts
- Refactoring and formatting (
ruff) - Switch to
hatchlingas build backend to better support VSCode integration
How to port your code to version 2.0
Module definition
Old style (pymoto < 2)
class MyModule(pym.Module):
def _prepare(self, val1, val2=0.5)
... # Preparations here
def _response(self, x, *args):
if len(args) == 1:
y = args[0]
... # Response calculation here
return z
def _sensitivity(self, dz):
.... # Do sensitivity calculations here
return dx, ...
In the new style (pymoto >= 2) this becomes
class MyModule(pym.Module):
# __init__ function is used instead of _prepare
def __init__(self, val1, val2=0.5):
... # Preparations here
# __call__ function is used instead of _response
def __call__(self, x, y=None): # Optional positional arguments are now supported
... # Response calculation here
return z
# No changes to sensitivity
def _sensitivity(self, dz):
.... # Do sensitivity calculations here
return dx, ...
Module creation and usage
Old style (pymoto < 2)
fn = pym.Network()
sz1 = fn.append(MyModule(sx, val1=1.0, val2=3.0)) # Module with one input
sz2 = fn.append(MyModule([pym.Signal('constant', 1.0), sz1], val1=2.0)) # Module with two inputs
fn.response() # Only after calling `response()`, the response functions in the network will be run for the first time
pym.minimize_mma(fn, sx, sz2) # Optimize something
New style (pymoto >= 2)
with pym.Network() as fn: # Network as context manager
sz1 = MyModule(1.0, val2=3.0)(sx) # First options for the module (for __init__), after that the signal values (for __call__)
sz2 = MyModule(2.0)(1.0, sz1) # Constant values can be used directly as module input
# At this point all the response function in the network have been run once.
... # Change inputs signals
fn.response() # Usage of network remains the same. For updated values, response() can be called to re-calculate responses
pym.minimize_mma(sx, sz2, function=fn) # Passing function to the optimizer is now optional. If not passed, a global network will be used instead of the network called `fn`.
Full Changelog: https://github.com/aatmdelissen/pyMOTO/compare/v1.5.1...v2.0.0
Files
aatmdelissen/pyMOTO-v2.0.0.zip
Files
(24.1 MB)
| Name | Size | Download all |
|---|---|---|
|
md5:9648b9b164e319773611ada54f135942
|
24.1 MB | Preview Download |
Additional details
Related works
- Is supplement to
- Software: https://github.com/aatmdelissen/pyMOTO/tree/v2.0.0 (URL)
Software
- Repository URL
- https://github.com/aatmdelissen/pyMOTO