Giter Club home page Giter Club logo

eastereig's Introduction

EasterEig

License: GPL v3 CI-Ubuntu pypi release

Consider a parametric eigenvalue problem depending on a parameter (\nu). This arises for instance in

  • waveguides, where the wavenumber (eigenvalue) depends on the frequency (parameter)
  • waveguides with absorbing materials on the wall, where modal attenuation (eigenvalue imaginary part) depends on the liner properties like impedance, density (parameter)
  • structural dynamics with a randomly varying parameter, where the resonances frequencies (eigenvalue) depend on the parameter
  • ...

Exceptional points (EP) of non-Hermitian systems correspond to particular values of the parameter leading to defective eigenvalue. At EP, both eigenvalues and eigenvectors are merging.

The aim of this package is to locate exceptional points and to reconstruct the eigenvalue loci. The theoretical part of this work is described in [1], as for the location of exceptional points and illustrated in [2] for eigenvalues reconstruction in structural dynamics.

The method requires the computation of successive derivatives of two selected eigenvalues with respect to the parameter so that, after recombination, regular functions can be constructed. This algebraic manipulation enables

  • exceptional points (EP) localization, using standard root-finding algorithms;
  • computation of the associated Puiseux series up to an arbitrary order.

This representation, which is associated with the topological structure of Riemann surfaces, allows to efficiently approximate the selected pair in a certain neighborhood of the EP.

To use this package :

  1. an access to the operator derivative must be possible
  2. the eigenvalue problem must be recast into [ \mathbf{L} (\lambda(\nu), \nu) \mathbf{x} (\nu) =\mathbf{0} ]

The matrices of discrete operators can be either of numpy type for full, scipy type for sparse or petsc mpiaij type for sparse parallel matrices.

If eastereig is useful for your research, please cite the following references. If you have some questions, suggestions or find some bugs, report them as issues here.

References

[1] B. Nennig and E. Perrey-Debain. A high order continuation method to locate exceptional points and to compute Puiseux series with applications to acoustic waveguides. J. Comp. Phys., 109425, (2020). [doi]; [open access]

[2] M. Ghienne and B. Nennig. Beyond the limitations of perturbation methods for real random eigenvalue problems using Exceptional Points and analytic continuation. Journal of Sound and vibration, (2020). [doi]; [open access]

Basic workflow and class hierarchy

eastereig provides several top level classes:

  1. OP class, defines operators of your problem
  2. Eig class, handles eigenvalues, their derivatives and reconstruction
  3. EP class, combines Eig object to locate EP and compute Puiseux series
  4. Loci class, stores numerical value of eigenvalues loci and allows easy Riemann surface plotting

Dependencies

eastereig is based on numpy (full) and scipy (sparse) for most internal computation and can handle large parallel sparse matrices thanks to optional import of petsc4py (and mumps), slepc4py and and mpi4py. As non-hermitian problems involve complex-valued eigenvalues, computations are realized with complex arithmetic and the complex petsc version is expected. Tested for python >= 3.5

Remarks : To run an example with petsc (parallel), you need to run python with mpirun (or mpiexec). For instance, to run a program with 2 proc mpirun -n 2 python myprog.py

Riemann surface can also be plotted using the Loci class either with matplotlib or with pyvista (optional).

Install

You'll need :

  • python (tested for v >= 3.5);
  • python packages: numpy, setuptools, wheel
  • pip (optional).
  • fortran compiler (optional) Note that on ubuntu, you will need to use pip3 instead of pip and python3 instead of python. Please see the steps given in the continous integration script workflows.

By default, the fortan evaluation of multivariate polynomial is desactivated. To enable it, set the environnement variable: EASTEREIG_USE_FPOLY=True. On ubuntu like system, run

export EASTEREIG_USE_FPOLY=True

Using pip (preferred)

Consider using pip over custom script (rationale here).

You can install eastereig either from pypi (main releases only):

pip install eastereig [--user]

or from github:

pip install path/to/EeasterEig-version.tar.gz [--user]

or in editable mode if you want to modify the sources

pip install -e path/to/EeasterEig

The version of the required libraries specified in install_requires field from setup.py are given to ensure the backward compatibility up to python 3.5. A more recent version of these libraries can be safely used for recent python version.

Using python setuptools

Go to root folder. and run:

python setup.py install [--user]

To get the lastest updates (dev relases), run:

python setup.py develop [--user]

Running tests

Tests are handled with doctest.

To execute the full test suite, run :

python -m eastereig

Documentation

Generate documentation

Run:

pdoc3 --html --force --config latex_math=True  eastereig

N.B: The doctring are compatible with several Auto-generate API documentation, like pdoc. This notably allows to see latex includes.

Generate class diagram

Run:

pyreverse -s0 eastereig -m yes -f ALL
dot -Tsvg classes.dot -o classes.svg

N.B: Class diagram generation is done using pyreverse (installed with pylint and spyder).

Generate documentation and class diagram

Both aspects are included in the `makedoc.py' script. So, just run :

python ./makedoc.py

Getting started

Several working examples are available in ./examples/ folder

  1. Acoustic waveguide with an impedance boundary condition (with the different supported linear libraries)
  2. 3-dof toy model of a structure with one random parameter (with numpy)

To get started, the first step is to define your problem. Basically it means to link the discrete operators (matrices) and their derivatives to the eastereig OP class. The problem has to be recast in the following form:

( \left[ \underbrace{1}_{f_0(\lambda)=1} \mathbf{K}0(\nu) + \underbrace{\lambda(\nu)}{f_1(\lambda)=\lambda} \mathbf{K}1(\nu) + \underbrace{\lambda(\nu)^2}{f_2(\lambda)} \mathbf{K}_2(\nu) \right] \mathbf{x} = \mathbf{0} ).

Matrices are then stacked in the variable K

K = [K0, K1, K2].

The functions that return the derivatives with respect to (\nu) of each matrices have to be put in dK. The prototype of this function is fixed (the parameter n corresponds to the derivative order) to ensure automatic computation of the operator derivatives.

dK = [dK0, dK1, dK2].

Finally, the functions that returns derivatives with respect to ( \lambda) are stored in 'flda'

flda = [None, ee.lda_func.Lda, ee.lda_func.Lda2].

Basic linear and quadratic dependency are defined in the module lda_func. Others dependencies can be easily implemented; provided that the appropriate eigenvalue solver is also implemented). The None keyword is used when there is no dependency to the eigenvalue, e. g. (\mathbf{K}_0).

This formulation is used to automatically compute (i) the successive derivatives of the operator and (ii) the RHS associated to the bordered matrix.

These variables are defined by creating a subclass that inherits from the eastereig OP class. For example, considering a generalized eigenvalue problem ( \left[\mathbf{K}_0(\nu) + \lambda \mathbf{K}_1(\nu) \right] \mathbf{x} = \mathbf{0} ) :

import eastereig as ee

class MyOP(ee.OP):
    """Create a subclass of the OP class to describe your problem."""

    def __init__(self):
        """Initialize the problem."""
        # Initialize OP interface
        self.setnu0(z)

        # Mandatory -----------------------------------------------------------
        self._lib = 'scipysp'  # 'numpy' or 'petsc'
        # Create the operator matrices
        self.K = self.CreateMyMatrix()
        # Define the list of function to compute the derivatives of each operator matrix (assume 2 here)
        self.dK = [self.dmat0, self.dmat1]
        # Define the list of functions to set the eigenvalue dependency of each operator matrix
        self.flda = [None, ee.lda_func.Lda]
        # ---------------------------------------------------------------------

    def CreateMyMatrices(self, ...):
        """Create my matrices and return a list."""
        ...
        return list_of_Ki

    def dmat0(self, n):
        """Return the matrix derivative with respect to nu.

        N.B. : The prototype of this function is fixed, the n parameter
        stands for the derivative order. If the derivative is null,
        the function returns the value 0.
        """
        ...
        return dM0

    def dmat1(self, n):
        """Return the matrix derivative with respect to nu.

        N.B. : The prototype of this function is fixed, the n parameter
        stands for the derivative order. If the derivative is null,
        the function returns the value 0.
        """
        ...
        return dM1

How to contribute ?

If you want to contribute to eastereig, your are welcomed! Don't hesitate to

  • report bugs, installation problems or ask questions on issues;
  • propose some enhancements in the code or in documentation through pull requests (PR);
  • suggest or report some possible new usages and why not start a scientific collaboration ;-)
  • ...

To ensure code homogeneity among contributors, we use a source-code analyzer (eg. pylint). Before submitting a PR, run the tests suite.

License

This file is part of eastereig, a library to locate exceptional points and to reconstruct eigenvalues loci.

Eastereig is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Eastereig is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Eastereig. If not, see https://www.gnu.org/licenses/.

eastereig's People

Contributors

martinghienne avatar nennigb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

chaogecanfly

eastereig's Issues

Fail to install with python 3.12.

The build of fortran files is based on numpy.distutils and

numpy.distutils has been deprecated in NumPy 1.23.0. It will be removed for Python 3.12; for Python <= 3.11 it will not be removed until 2 years after the Python 3.12 release (Oct 2025).

Until a clean solution will be implemented, to use eastereig with python 3.12 (everything is fine for other version), you will need to edit the setup.py, to remove numpy.distutils calls

# -*- coding: utf-8 -*-
import setuptools
import os

with open("README.md", "r") as fh:
    long_description = fh.read()


def _getversion():
    """ Get version from VERSION."""
    v = None
    with open(os.path.join('./eastereig', 'VERSION')) as f:
        for line in f:
            if line.startswith('version'):
                v = line.replace("'", '').split()[-1].strip()
                break
        return v


this_version = _getversion()
print('version:', this_version)

setuptools.setup(
    name="eastereig",
    version=this_version,
    author="B. Nennig, M. Ghienne",
    author_email="[email protected], [email protected]",
    description="A library to locate exceptional points and to reconstruct eigenvalues loci",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/nennigb/EasterEig",
    include_package_data=True,
    # we can use find_packages() to automatically discover all subpackages
    packages=setuptools.find_packages(),
    install_requires=['numpy',
                      'scipy',
                      'matplotlib'],
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.5',
)

Add semantic versioning

Claimed version (in setup.py) is 1.0.0, whereas the last commit was a bugfix ("Fix problem to load eig object without eigenvector"). This may confuse everyone which use the code. I suggest to use semantic versioning standard, implemented by semver python module and bumping version on 1.0.1 on next PR.

Enable contributing

Although the documentation is quite extensive about how to use EasterEig, there's nothing such as contribution guidelines.

Here's some suggestions:

  • create a CONTRIBUTING.md;
  • use a source-code analyzer (linter, eg. Pylama) to make code homogeneous among contributors;
  • ensure test code coverage provide enough trust so new features don't introduce regressions.

Test coverage
Test coverage is inteded to check if tests are effectively testing code (execute it, and check assertion). This can only be done using mutation testing, eg.MutPy). Here, testing is done using doctest, and there's no reliable mutation-testing libray using doctest. This library is intended as a toy for learning. I've not been able to run xmutant). There's a way, thought, by making unittest run doctest.

Simple coverage (has code been executed during test ?) is a fallback mechanism: only low coverage indicate something bad. 100% coverage, without any assertion, doesn't prevent anything bad from happening, even crashes.

Coverage can handle doctest, and gave a 60% coverage

image

To run:

  • pip3 install coverage
  • coverage run --source=. -m eastereig
  • coverage report -m

The order of operator may not be consistent between eigSolver and flda.

In eigSolver.py, the matrices are passed to eigenvalue solvers depending on their position in the K list. This assume that operators are well ordered in K, dK and in flda. A more robust approach could be to use flda to sort and to pass the matrices to solvers.

The modification will concern all solve methods of EigSolver concrete class. For instance

        # FIXME need to modify matrix order based on flda
        if self.pb_type=='std':
            self.Lda,Vec = sp.linalg.eig(self.K[0],b=None) 
        elif self.pb_type=='gen':            
            self.Lda,Vec = sp.linalg.eig(self.K[0],b=-self.K[1])
        elif self.pb_type=='PEP':
            self.Lda,Vec = self._pep(self.K)
        else:
            raise NotImplementedError('The pb_type {} is not yet implemented'.format(self.pb_type))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.