Skip to content

Releases: aatmdelissen/pyMOTO

v2.0.0

25 Nov 15:02

Choose a tag to compare

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 append anymore, 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 -> MathExpression
  • DomainDefinition -> VoxelDomain
  • DyadCarrier -> DyadicMatrix
  • VecSet -> SetValue
  • ConcatSignal -> Concatenate

Module improvements:

  • AutoDiff module improvements, supporting backend based on HIPS autograd as alternative to jax
  • WriteToVTI now supports writing complex vectors
  • Scaling now supports double-sided constraints, where both a minimum and maximum value is requested
  • AssembleGeneral now 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.
  • OverhangFilter now 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 parts
  • Print - Print values in a signal to console
  • SetValue - Set values in a numpy array for specified indices
  • AddMatrix - Linear combination of sparse matrices
  • Conjugate - Complex conjugation
  • TransientSolve - 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 (formerly DomainDefinition) (element_size, domain_size, size, get_dofnumber, get_element_indices)
  • VoxelDomain now also can voxelize mesh objects (e.g. from STL) using the methods create_for_mesh, which generates a suitable domain, and voxelize which then converts a triangle mesh into voxel elements.
  • Switch from using pypardiso to directly using mkl for 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 hatchling as 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: v1.5.1...v2.0.0

v2.0.0-rc2

13 Nov 09:45

Choose a tag to compare

v2.0.0-rc2 Pre-release
Pre-release

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 append anymore, 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:

  • MathGeneral -> MathExpression
  • DomainDefinition -> VoxelDomain
  • DyadCarrier -> DyadicMatrix

Module improvements:

  • AutoDiff module improvements, supporting backend based on HIPS autograd as alternative to jax
  • WriteToVTI now supports writing complex vectors
  • Scaling now supports double-sided constraints, where both a minimum and maximum value is requested
  • AssembleGeneral now 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.

New modules:

  • SplitComplex - Splits complex value into its real and imaginary parts
  • Print - Print values in a signal to console
  • SetValue - Set values in a numpy array for specified indices
  • AddMatrix - Linear combination of sparse matrices
  • Conjugate - Complex conjugation

Other improvements:

  • New methods in VoxelDomain (formerly DomainDefinition) (element_size, domain_size, size, get_dofnumber)
  • VoxelDomain now also can voxelize mesh objects (e.g. from STL) using the methods create_for_mesh, which generates a suitable domain, and voxelize which then converts a triangle mesh into voxel elements.
  • Switch from using pypardiso to directly using mkl for 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 hatchling as 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: v1.5.1...v2.0.0-rc2

v2.0.0-rc1

19 Sep 07:55
193a0fb

Choose a tag to compare

v2.0.0-rc1 Pre-release
Pre-release

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 append anymore, 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

Other improvements:

  • Add examples gallery on documentation page
  • All examples now in same style with new syntax
  • Several new examples
  • AutoDiff module improvements, supporting backend based on autograd as alternative to jax
  • New methods in DomainDefinition (element_size, domain_size, size, get_dofnumber)
  • Improve publishing scripts
  • Refactoring and formatting (Ruff)
  • MMA now supports unconstraints optimization (only an objective), see issue #7
  • Switch from using pypardiso to directly using mkl for usage of Pardiso solver. Also enable solving matrices with complex and/or single precision.
  • WriteToVTI now supports writing complex vectors
  • SLP optimization algorithm

New modules:

  • SplitComplex
  • Print
  • VecSet
  • AddMatrix
  • Conjugate

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: v1.5.1...v2.0.0-rc1

v1.5.1

28 Jan 18:12
c18e126

Choose a tag to compare

What's Changed

  • Pass a and c parameters to MMA by @bva99 in #24
  • Extra origin attribute of DomainDefinition
  • Add support for complex eigenvalue and eigenvector sensitivities
  • Add support for complex matrix sensitivities (using AssembleGeneral)
  • Split up pure diagonal entries in LDAS solver for increased performance
  • Allow plotting in log scale in PlotIter

Bugfixes:

  • Correct convergence tolerances for multiple RHS in CG solver
  • Fix complex value contractions in DyadCarrier
  • Type conversion in SolverSparsePardiso in case int vectors are passed
  • Fix memory leak in SolverSparsePardiso in case it was constructed many times

New Contributors

  • @bva99 made their first contribution in #24

Full Changelog: v1.5.0...v1.5.1

v1.5.0

22 Nov 14:00
43e2988

Choose a tag to compare

What's Changed

  • Thermo mechanical by @JoranZwet in #21 containing new modules ElementAverage, NodalOperation and ThermoMechanical
  • ScalarToFile to output scalar values to txt or csv files by @JoranZwet in #22
  • Sparse eigenvector sensitivities
  • Additional functionality in DyadCarrier: min(), max(), n_dyads, shape
  • Add Svanberg 2007 version in MMA for better conversion

Bugfixes:

  • Fix problem in MMA with identifiying scalar variable in numpy2 by @schnellerhase in #20
  • Bugfixes in copying empty DyadCarrier
  • Bugfix when calling 'H' or 'T' before calling 'N'-type solve in Pardiso solver

New Contributors

Full Changelog: v1.4.0...v1.5.0

v1.4.0

05 Sep 19:55
8ba68f8

Choose a tag to compare

Changes:

What's Changed

Full Changelog: v1.3.0...v1.4.0

v1.3.0

31 Jan 15:14
9aa5264

Choose a tag to compare

New features:

  • Assembly of generic Poisson type matrices (AssemblePoisson), which can be used for e.g. thermal conduction, electric permittivity
  • Mass matrix assembly AssembleMass now supports other type of physics; e.g. mass, damping, thermal capacity
  • Node coordinates and cartesian indices can now be obtained from DomainDefinition, respectively, by using methods get_node_position() and get_node_indices()

Examples:

  • 3D thermal optimization now works! (ex_compliance.py)

What's Changed

Full Changelog: v1.2.1...v1.3.0

v1.2.1

14 Dec 13:20
b53f14c

Choose a tag to compare

Bugfixes:

  • Corrected shape functions for finite element assembly

What's Changed

New Contributors

Full Changelog: v1.2.0...v1.2.1

v1.2.0

06 Nov 20:47
f055dd6

Choose a tag to compare

Contributions to modules:

  • Allow for additional values on DOFs in assembly (add_constant argument)
  • Modules for stress calculation, vonmises stress and constraint aggregation (in ex_volume_stress.py)
  • Module for enforcing symmetry (in ex_flexure.py)
  • StaticCondensation module for use in kinetostatic formulation (ex_compliant_mechanism_kinetostatic.py)

New examples:

  • Compliant mechanism design using springs (Sigmund formulation)
  • Compliant mechanism design using kinetostatic approach (Koppen formulation)
  • Volume minimization under stress constraints
  • Thermo-mechanical example ex_thermo_mech.py

Bug fixes:

  • Fixed sensitivity analysis of SoQ as to allow for Nonetype sensitivity input

Tests:

  • More tests for SoQ (test for Nonetype input sensitivity)
  • Test StaticCondensation module

Documentation:

  • Added documentation to multiple existing examples

What's Changed

Full Changelog: v1.1.0...v1.2.0

v1.1.0

20 Oct 15:53
ce9a88d

Choose a tag to compare

Features:

  • New module SystemOfEquations for solving a linear system of equations with constraints
  • New module Scaling for proper scaling of objective functions and constraints
  • New topology optimization examples for dynamic compliance, compliant mechanisms, and compliance optimization based on prescribed displacements

Bugfixes:

  • Support for multiple right-hand-sides in LinSolve
  • Mixed real and complex signals for EinSum

What's Changed

New Contributors

Full Changelog: v1.0.3...v1.1.0