Code Monkey home page Code Monkey logo

rootsandpoles.jl's Introduction

RootsAndPoles.jl: Global complex Roots and Poles Finding in Julia

Build Status Build status DOI

A Julia implementation of GRPF by Piotr Kowalczyk.

Description

RootsAndPoles.jl attempts to find all the zeros and poles of a complex valued function with complex arguments in a fixed region. These types of problems are frequently encountered in electromagnetics, but the algorithm can also be used for similar problems in e.g. optics, acoustics, etc.

The GRPF algorithm first samples the function on a triangular mesh through Delaunay triangulation. Candidate regions to search for roots and poles are determined and the discretized Cauchy's argument principle is applied without needing the derivative of the function or integration over the contour. To improve the accuracy of the results, a self-adaptive mesh refinement occurs inside the identified candidate regions.

simplefcn

Usage

Installation

]add RootsAndPoles

Example Problem

Consider a simple rational (complex) argument function simplefcn(z) for which we seek roots and poles.

function simplefcn(z)
    w = (z - 1)*(z - im)^2*(z + 1)^3/(z + im)
end

Next, we define parameters for the initial complex domain over which we would like to search.

xb = -2  # real part begin
xe = 2  # real part end
yb = -2  # imag part begin
ye = 2  # imag part end
r = 0.1  # initial mesh step
tolerance = 1e-9

This package includes convenience functions for rectangular and disk shaped domains, but any "shape" can be used. origcoords below is simply a vector of complex numbers containing the original mesh coordinates which will be Delaunay triangulated. For maximum efficiency, the original mesh nodes should form equilateral triangles.

using RootsAndPoles

origcoords = rectangulardomain(complex(xb, yb), complex(xe, ye), r)

Roots and poles can be obtained with the grpf function. We only need to pass the handle to our simplefcn and the origcoords.

zroots, zpoles = grpf(simplefcn, origcoords)

Additional parameters

Additional parameters can be provided to the tessellation and GRPF algorithms by explicitly passing a GRPFParams struct.

The two most useful parameters are tess_sizehint for the final total number of nodes in the internal DelaunayTessellation2D object and the root finder tolerance at which the mesh refinement stops. Just like sizehint! for other collections, setting tess_sizehint to a value approximately equal to the final number of nodes in the tessellation can improve performance. tolerance is the largest triangle edge length of the candidate edges defined in the origcoords domain. In practice, the root and pole accuracy is a larger value than tolerance, so tolerance needs to be set smaller than the desired tolerance on the roots and poles.

By default, the value of tess_sizehint is 5000 and the tolerance is 1e-9, but they can be specified by providing the GRPFParams argument

zroots, zpoles = grpf(simplefcn, origcoords, GRPFParams(5000, 1e-9))

Beginning version v1.1.0, calls to the provided function, e.g. simplefcn, can be multithreaded using Julia's @threads capability. The function is called at every node of the triangulation and the results should be independent of one another. For fast-running functions like simplefcn, the overall runtime of grpf is dominated by the Delaunay Triangulation itself, but for more complicated functions, threading can provide a significant advantage. To enable multithreading of the function calls, specify so as a GRPFParams argument

zroots, zpoles = grpf(simplefcn, origcoords, GRPFParams(5000, 1e-9, true))

By default, multithreading = false.

Additional parameters which can be controlled are maxiterations, maxnodes, and skinnytriangle. maxiterations sets the maximum number of mesh refinement iterations and maxnodes sets the maximum number of nodes allowed in the DelaunayTessellation2D before returning. skinnytriangle is the maximum allowed ratio of the longest to shortest side length in a tessellation triangle before the triangle is automatically subdivided in the mesh refinement step. Default values are

  • maxiterations: 100
  • maxnodes: 500000
  • skinnytriangle: 3

These can be specified along with the tess_sizehint, tolerance and multithreading as, e.g.

zroots, zpoles = grpf(simplefcn, origcoords, GRPFParams(100, 500000, 3, 5000, 1e-9, true))

Plot data

If mesh node quadrants and phasediffs are wanted for plotting, simply pass a PlotData() instance.

zroots, zpoles, quadrants, phasediffs, tess, g2f = grpf(simplefcn, origcoords, PlotData())

A GRPFParams can also be passed.

zroots, zpoles, quadrants, phasediffs, tess, g2f = grpf(simplefcn, origcoords, PlotData(), GRPFParams(5000, 1e-9))

In v1.4.0, a function getplotdata makes plotting the tessellation results more convenient. The code below was used to create the figure shown at the top of the page.

zroots, zpoles, quadrants, phasediffs, tess, g2f = grpf(simplefcn, origcoords, PlotData());
z, edgecolors = getplotdata(tess, quadrants, phasediffs, g2f);

using Plots

pal = ["yellow", "purple", "green", "orange", "black", "cyan"]
plot(real(z), imag(z), group=edgecolors, palette=pal,
     xlabel="Re(z)", ylabel="Im(z)",
     xlims=(-2, 2), ylims=(-2, 2),
     legend=:outerright, legendtitle="f(z)", title="Simple rational function",
     label=["Re > 0, Im ≥ 0" "Re ≤ 0, Im > 0" "Re < 0, Im ≤ 0" "Re ≥ 0, Im < 0" "" ""])

Additional examples

See test/ for additional examples.

Limitations

This package uses VoronoiDelaunay.jl to perform the Delaunay tessellation. VoronoiDelaunay is numerically limited to the range of 1.0+eps(Float64) to 2.0-2eps(Float64) for its point coordinates. RootsAndPoles.jl will accept functions and origcoords that aren't limited to Complex{Float64}, for example Complex{BigFloat}, but the internal tolerance of the root finding is limited to Float64 precision.

Citing

Please consider citing Piotr's publications if this code is used in scientific work:

  1. P. Kowalczyk, “Complex Root Finding Algorithm Based on Delaunay Triangulation”, ACM Transactions on Mathematical Software, vol. 41, no. 3, art. 19, pp. 1-13, June 2015. https://dl.acm.org/citation.cfm?id=2699457

  2. P. Kowalczyk, "Global Complex Roots and Poles Finding Algorithm Based on Phase Analysis for Propagation and Radiation Problems," IEEE Transactions on Antennas and Propagation, vol. 66, no. 12, pp. 7198-7205, Dec. 2018. https://ieeexplore.ieee.org/document/8457320

We also encourage you to cite this package if used in scientific work. Refer to the Zenodo DOI at the top of the page or CITATION.bib.

rootsandpoles.jl's People

Contributors

fgasdia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

githubbjs

rootsandpoles.jl's Issues

Release v1.3.0

  • Remove parameterization of tolerance field in GRPFParams. It is now always Float64 type so GRPFParams no longer has any parametric types.
  • Relax compat requirements on SpecialFunctions (only affects tests)

@JuliaRegistrator register

rectangulardomain boundary issues

The upper boundary of the rectangular domain is not correctly handled.

Picture attached shows the problem with the error along the top circled in red. The underlying plot is generated with:

using RootsAndPoles

z1 = complex(-2, -2)
z2 = complex(2, 2)
r = 0.1

grid = rectangulardomain(z1, z2, r);

using Plots

plot(real(grid), imag(grid), seriestype=:scatter, legend=false)

brokenrectangulardomain

Release v1.3.1

@JuliaRegistrator register

Release notes:

  • Bug fix parameterization of ScaledFunction.
  • Simplify conversion to/from user function domain to VoronoiDelaunay domain.

Release 1.0.0

"GRPF" is shorter than the recommended 5 character long package name, but directly refers to the GRPF algorithm it implements. There is also a GRPF.m Matlab package with MIT license. The full name of the algorithm is the Global complex Roots and Poles Finding algorithm, which would be fairly long for a package name.

@JuliaRegistrator register

Make GRPFParams immutable again

There is little reason for GRPFParams to be mutable. It originally seemed convenient to update (mutate) GRPFParams entries in a project in which I was using RootsAndPoles, but it is inexpensive to create an entirely new GRPFParams struct and changes to fields can be easily made if we use Parameters.jl. Immutable structs are also a little "safer", e.g. when it comes to threading.

Poles of simple Log(z)

Recently, I tried this Julia package with the simple function f(z)=log(z) using standard parameters as described in the readme and obtain for a moderate domain around the origin the result

number of roots: 1
number of poles: 1

poles_roots_logarithm

The root at z=1 is clear but the Log has no pole at z=-1 - is there a bug?

Move NEWS to its own file

Move NEWS out of the README, or at least move it from the top to the bottom. Alternately move it to its own file or use built-in Github functionality for tracking changes.

Add a plot function

Have a function that produces a plot like those shown in the GRPF papers. It may also be possible to always return tess and get rid of the PlotData() flag, or at least have a flag that only returns tess and doesn't need to do anything else to simplify the current PlotData() functionality.

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

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.