diff --git a/src/SUMMARY.md b/src/SUMMARY.md index b6a44c7..4fbbb31 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -21,6 +21,7 @@ - [Sampling](tutorial-sampling.md) - [2D Laplace Problem](tutorial-laplace2d.md) - [Release History](release.md) + - [Nutils 9 Jook-Sing](release-9.md) - [Nutils 8 Idiyappam](release-8.md) - [Nutils 7 Hiyamugi](release-7.md) - [Nutils 6 Garak-Guksu](release-6.md) diff --git a/src/examples.md b/src/examples.md index 498a1b9..d6a0e78 100644 --- a/src/examples.md +++ b/src/examples.md @@ -7,7 +7,7 @@ concise examples demonstrating different areas of physics and varying computational techniques. The examples are taken from both the Nutils -[repository](https://github.com/evalf/nutils/tree/master/examples) and user +[repository](https://github.com/evalf/nutils/tree/main/examples) and user contributed repositories, and are tested regularly to confirm validity against different versions of Nutils. @@ -20,7 +20,7 @@ test Nutils against, and, in doing so, they may even help themselves by preventing future Nutils version from accidentally breaking their code. Examples should resemble the [official -examples](https://github.com/evalf/nutils/tree/master/examples) from the Nutils +examples](https://github.com/evalf/nutils/tree/main/examples) from the Nutils repository. In particular, they: - use `cli.run` to call main function; - have reasonable default parameters corresponding to a simulation that is relevant but not overly expensive; diff --git a/src/install-matrix.md b/src/install-matrix.md index 5c3a370..9e8fefa 100644 --- a/src/install-matrix.md +++ b/src/install-matrix.md @@ -23,7 +23,7 @@ The Scipy matrix backend becomes available when [Scipy](https://www.scipy.org/) is installed, either using the platform's package manager or via pip: ```sh -python -m pip install --user scipy +python -m pip install scipy ``` In addition to a sparse direct solver, the Scipy backend provides many @@ -59,3 +59,11 @@ sudo tee /etc/ld.so.conf.d/mkl.conf << EOF > /dev/null EOF sudo ldconfig -v ``` + +If it is impossible to install MKL system wide, for instance because of lacking +administrative powers, then an easy way of installing it with user privileges +is to use pip. Nutils will automatically load the libraries from pip's default +installation path. +```sh +python -m pip install mkl +``` diff --git a/src/install-nutils.md b/src/install-nutils.md index 0af1a75..a552d91 100644 --- a/src/install-nutils.md +++ b/src/install-nutils.md @@ -2,8 +2,10 @@ Nutils is installed via Python's [Pip](https://pip.pypa.io/en/stable/) package installer, which most Python distributions install by default. In the following -instructions we add the flag `--user` for a local installation that does not -require system privileges, which is recommended but not required. +instructions we assume that pip is run with sufficient privileges to install +modules system wide, or (more common) that a [virtual +environment](https://docs.python.org/3/library/venv.html) is active for local +installation. The following command installs the stable version of Nutils from the package archive, along with its dependencies [Numpy](https://numpy.org/), @@ -11,15 +13,14 @@ archive, along with its dependencies [Numpy](https://numpy.org/), [Stringly](https://github.com/evalf/stringly): ```sh -python -m pip install --user nutils +python -m pip install nutils ``` To install the most recent development version we use Github's ability to generate zip balls: ```sh -python -m pip install --user --force-reinstall \ - https://github.com/evalf/nutils/archive/refs/heads/master.zip +python -m pip install https://github.com/evalf/nutils/archive/refs/heads/main.zip ``` Alternatively, if the [Git](https://git-scm.com/) version control system is @@ -27,24 +28,18 @@ installed, we can use pip's ability to interact with it directly to install the same version as follows: ```sh -python -m pip install --user --force-reinstall \ - git+https://github.com/evalf/nutils.git@master +python -m pip install git+https://github.com/evalf/nutils.git@main ``` -This notation has the advantage that even a specific commit (rather than a -branch) can be installed directly by specifying it after the `@`. +This notation has the advantage that even a specific tag or commit (rather than +a branch name) can be installed directly by specifying it after the `@`. -Finally, if we do desire a checkout of Nutils' source code, for instance to +Finally, if we do desire a checkout of the Nutils source code, for instance to make changes to it, then we can instruct pip to install directly from the location on disk: ```sh git clone https://github.com/evalf/nutils.git cd nutils -python -m pip install --user . +python -m pip install . ``` - -In this scenario it is possible to add the `--editable` flag to install Nutils -by reference, rather than by making a copy, which is useful in situations of -active development. Note, however, that pip requires manual intervention to -revert back to a subsequent installation by copy. diff --git a/src/install-quality.md b/src/install-quality.md index f96886f..35281e9 100644 --- a/src/install-quality.md +++ b/src/install-quality.md @@ -5,12 +5,23 @@ used in conjunction with Nutils to make life a little bit better. ## BottomBar -[BottomBar](https://github.com/evalf/bottombar) is a context manager for Python -that prints a status line at the bottom of a terminal window. When it is +[BottomBar](https://pypi.org/project/bottombar/) is a context manager for +Python that prints a status line at the bottom of a terminal window. When it is installed, `cli.run` automatically activates it to display the location of the html log (rather than only logging it at the beginning and end of the -simulation) as well as runtime and memory usage information. +simulation) as well as runtime and (optionally) memory usage information. ```sh python -m pip install bottombar ``` + +## Psutil + +[Psutil](https://pypi.org/project/psutil/) is a cross platform library for +retrieving information on the running process. If it is installed in +conjunction with bottombar, `cli.run` automatically adds an entry that shows +the current memory usage. + +```sh +python -m pip install psutil +``` diff --git a/src/install-remote.md b/src/install-remote.md index 5040713..fdf68af 100644 --- a/src/install-remote.md +++ b/src/install-remote.md @@ -29,9 +29,8 @@ location ~ ^/~(.+?)(/.*)?$ { ``` Finally, the terminal output can be made to show the http address rather than -the local uri by adding the following line to the `~/.nutilsrc` configuration -file: +the local uri by setting the `NUTILS_OUTROOTURI` environment variable, e.g.: ``` -outrooturi = 'https://mydomain.tld/~myusername/' +export NUTILS_OUTROOTURI="http://mydomain.tld/~myname/" ``` diff --git a/src/release-1.md b/src/release-1.md index 3340276..d898727 100644 --- a/src/release-1.md +++ b/src/release-1.md @@ -2,4 +2,4 @@ Nutils 1 was released on August 4th, 2014 and saw no point releases. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v1.0.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v1.0/) +- [API Reference](https://docs.nutils.org/en/v1.0/) diff --git a/src/release-2.md b/src/release-2.md index 5dacbeb..cd8bff3 100644 --- a/src/release-2.md +++ b/src/release-2.md @@ -2,7 +2,7 @@ Nutils 2 was released on February 18th, 2016 and saw no point releases. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v2.0.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v2.0/) +- [API Reference](https://docs.nutils.org/en/v2.0/) ## What's New? diff --git a/src/release-3.md b/src/release-3.md index 70e70be..1d54415 100644 --- a/src/release-3.md +++ b/src/release-3.md @@ -4,7 +4,7 @@ Nutils 3 was released on August 22nd, 2018 and saw one point release for fixes and backports. The most recent and final version in this series is Nutils 3.1, released on February 5th, 2018. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v3.1.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v3.1/) +- [API Reference](https://docs.nutils.org/en/v3.1/) ## What's New? diff --git a/src/release-4.md b/src/release-4.md index a84143b..cb30cff 100644 --- a/src/release-4.md +++ b/src/release-4.md @@ -4,7 +4,7 @@ Nutils 4 was released on June 11th, 2019 and saw one point release for fixes and backports. The most recent and final version in this series is Nutils 4.1 was released on August 28th, 2018. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v4.1.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v4.1/) +- [API Reference](https://docs.nutils.org/en/v4.1/) ## What's New? diff --git a/src/release-5.md b/src/release-5.md index 0c7b93e..9dae91b 100644 --- a/src/release-5.md +++ b/src/release-5.md @@ -4,7 +4,7 @@ Nutils 5 was released on April 3rd, 2020 and saw two point releases for fixes and backports. The most recent and final version in this series is Nutils 5.2, released on June 11th, 2019. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v5.2.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v5.2/) +- [API Reference](https://docs.nutils.org/en/v5.2/) ## What's New? diff --git a/src/release-6.md b/src/release-6.md index 7b947bb..b79fe91 100644 --- a/src/release-6.md +++ b/src/release-6.md @@ -4,7 +4,7 @@ Nutils 6 was released on April 29th, 2020 and saw three point releases for fixes and backports. The most recent and final version in this series is Nutils 6.3, released on November 18th, 2021. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v6.3.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v6.3/) +- [API Reference](https://docs.nutils.org/en/v6.3/) ## What's New? diff --git a/src/release-7.md b/src/release-7.md index 4b9e457..cacc01d 100644 --- a/src/release-7.md +++ b/src/release-7.md @@ -4,7 +4,7 @@ Nutils 7 was released on January 1st, 2022 and saw three point releases for fixes and backports. The most recent and final version in this series is Nutils 7.3, released on June 20th, 2023. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v7.3.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v7.3/) +- [API Reference](https://docs.nutils.org/en/v7.3/) ## What's New? diff --git a/src/release-8.md b/src/release-8.md index 5e5a61b..3b89f1a 100644 --- a/src/release-8.md +++ b/src/release-8.md @@ -4,7 +4,7 @@ Nutils 8 was released on July 28th, 2023 and saw eight point releases for fixes and backports. The most recent and final version in this series is Nutils 8.8, released on July 9th, 2024. - [Download](https://github.com/evalf/nutils/archive/refs/tags/v8.8.zip) (zip) -- [API Reference](http://docs.nutils.org/en/v8.8/) +- [API Reference](https://docs.nutils.org/en/v8.8/) ## What's New? diff --git a/src/release-9.md b/src/release-9.md new file mode 100644 index 0000000..123446b --- /dev/null +++ b/src/release-9.md @@ -0,0 +1,236 @@ +# Nutils 9 Jook-Sing + +Nutils 9 was released on April 9, 2025. + +- [Download](https://github.com/evalf/nutils/archive/refs/tags/v9.0.zip) (zip) +- [API Reference](https://docs.nutils.org/en/v9.0/) + + +## What's new? + +These are the main additions and changes since Nutils 8 Idiyappam. + +### System + +The most prominent new feature of Nutils 9 is arguably the redesign of the +solver module, which now offers the `System` object as the main entry point for +all linear and nonlinear problems. A typical use looks like this: + +```python +>>> sys = solver.System(residual, trial='u', test='v') +>>> args = sys.solve(constrain=cons) +``` + +Nonlinear problems require a `tol` argument, and will switch to a vanilla +newton process by default. Different solution methods, such as line search +newton (solver.LinesearchNewton) or steepest descent minimization +(solver.Minimize) can be specified via the `method` argument. Newly added +solution methods are solver.ReuseNewton and solver.Arnoldi. + +Presently, the main advantage of the new interface is in repeated solves, as +the system object retains information such as the matrix sparsity pattern that +is expensive to recompute. In future, systems will be enhanced to recognize and +exploit features such as one way coupling of matrix blocks. The old functions +such as `solve_linear` and `newton` will be deprecated in the next development +cycle for removal in Nutils 11. All examples are updated to use `System` +directly to encourage new projects to switch over to the new API. + +### Field + +Nutils 8 initiated the transition from operating on basis functions and vector +valued residuals, to fields, i.e. bases contracted with arguments, and scalar +valued residuals. Nutils 9 further promotes this by providing a new `field` +method that makes formation of the basis an entirely internal affair. In the +following example, `u1`, `u2` and `u3` are identical: + +```python +>>> u1 = topo.field('u', btype='spline', degree=2) +>>> basis = topo.basis('spline', degree=2) +>>> u2 = basis @ function.Argument('u', basis.shape) +>>> u3 = function.field('u', basis) +``` + +In the majority of cases that direct acces to the basis is not required, the +first construction is recommended. The second shows what really happens, +discounting some subtle differences in the case of tensorial topologies. The +third form showcases the new function `function.field`, which was renamed from +`function.dotarg` for naming consistency. Like its predecessor, this function +can also be used to create constant fields by not providing a basis argument. + +### Factor + +Another standout new feature is `function.factor`, which offers to speed up +calculations by precomputing assembly loops. Its use is limited to functions +that are already bound to all spaces, e.g. by integration, and that are +polynomial in all their arguments. Building on the previous example, a typical +use would be to factor the system argument: + +```python +>>> sys = solver.System(function.factor(residual), trial='u', test='v') +``` + +Here, residual must by polynomial in 'u' and 'v'. Factor then evaluates the +polynomial coefficients as sparse arrays. Finally, when System evaluates the +resulting function, this amounts to nothing more than sparse tensor +contractions, which can be very fast. Note, however, a high polynomial degree +results in high-dimensional coefficients which, while sparse, may still require +a lot of memory and many operations to perform the required contractions. As +such, the benefits of factor should be assessed on a case by case basis. + +Two examples that benefit greatly from the factor treatment are cylinderflow +and cahnhilliard. In another useful application of factor, these scripts have +greatly sped up post processing by factoring sampled results. The `Sample.bind` +method used for this purpose is also new in Nutils 9. + +### JIT compiler + +Under the hood, a major change in the evaluable module is the way that +functions are evaluated. Where evaluations formerly consisted of a (dynamically +created) sequence of function calls, Nutils 9 generates and compiles a +dedicated Python function. The direct result of this change is a reduction in +function calls, which lowers the total overhead and shifts the balance of total +time spent to the actual numerical operations. + +The compiled function furthermore distinguishes between (intermediate) results +that depend on input arguments, and those that stay constant between +evaluations. The latter are stored as part of the function object and reused +when the function is evaluated for the second time. Noting that part of the +non-changing structures in a function is the entire sparsity pattern, it should +be clear that these are significant savings. This also another reason why the +switch to the new solver API is vital, as the System object holds on to the +compiled function along with its cached data. + +Thirdly, the new approach allows for in-place modifications. Formerly, a sparse +matrix was assembled by concatenating element contributions before +deduplicating and converting it to CSR format. The new approach adds element +data directly into the CSR structure, resulting in substantial memory savings. + +### Other notable changes + +The turek example is added as an implementation of the [Turek Hron +benchmark](https://doi.org/10.1007/3-540-34596-5_15), able to reproduce all of +the 9 distinct benchmark cases as well as freely defined variants thereof. +The new benchmark section in this book contains convergence results of the code, +compared against the reference results of Turek and Hron. + +The `mesh.gmsh` function has been enhanced to accept .geo paths in addition to +the already supported '.msh' files. The new mode requires gmsh to be installed +in the executable path, and uses it to generate the corresponding msh file on +the fly. The new `numbers` parameter provides for parameterized input, in the +form of a dictionary with variables for the geo file. The new turek example +showcases this new ability. + +Support for SI units has been extended to the Numpy operations `real`, `imag`, +`conjugate`, `reshape`, `linalg.norm` and `interp`. The new `Sample.bind` +method is unit aware. Finally, `Topology.locate` now accepts dimensional +quantities provided that the geometry function and points array have matching +dimension, as well as the `tol` argument if provided. + +On the dependencies front, Nutils now requires Python 3.9 or higher, as these +are the only versions still activaly maintained. Likewise, the minimum Numpy +version has been bumped to 1.21. On the other end of the spectrum, support is +added for Numpy series 2. The bottombar and psutil modules are removed as +dependencies, but will still be used by cli.run and cli.choose if they are +detected to be installed. Finally, the MKL matrix will be automatically +recognized with the mkl module is user-installed via pip. + +### Deprecations + +The following constructs have been deprecated and are marked for removal in Nutils 10: +- matrix.assemble (replaced by matrix.assemble_coo and matrix.assemble_csr) +- function.dotarg (replaced by function.field) +- function.outer (replaced by the equivalent numpy operations) +- sample.Sample callable (replaced by Sample.bind) +- function.integral (replaced by Sample.integral) +- function.sample (replaced by Sample.bind) +- function.rootcoords (no replacement) +- sample.Sample.integrate_sparse (replaced by function.eval + function.as_coo + sample.Sample.integral) +- sample.Sample.eval_sparse (replaced by function.eval + function.as_coo + sample.Sample.bind) +- providing arguments as keywords (replaced by the 'arguments' parameter) +- the newly introduced 'legacy' argument in functon.Array.eval and sample.Sample.integrate + + +## Complete overview of changes + +This release cycle was the first where we assigned version numbers to every +commit in the main branch. Since the version is logged at the top (when using +`cli.run`), this should always make it unambiguously clear what version of the +code was used to generate past results, even if this was part of the +development branch. + +In the following overview, the versions indicate when a certain feature was +introduced, changed, fixed or deprecaded, and, if applicable, when it was +backported into the stable branch. + +- *New in v9a1:* support diagonal offset in numpy.trace +- *Changed in v9a1:* minimum Python version 3.8 +- *Changed in v9a2, v8.1:* log version in cli.run, cli.choose +- *Changed in v9a3:* update Docker base image to Debian Bookworm +- *Fixed in v9a3, v8.3:* missing points in trimmed topology with skip_missing=True +- *New in v9a4, v8.3:* support numpy.{real,imag,conjugate} on Quantities +- *New in v9a4, v8.3:* support complex arguments in function.linearize +- *Fixed in v9a6, v8.4:* basis of SimplexTopology +- *Fixed in v9a6, v8.4:* empty boundary of SimplexTopology, triggered when all boundaries are periodic +- *Fixed in v9a7, v8.4:* picklability of sliced function array +- *New in v9a10:* support boolean operators for function arrays +- *Changed in v9a12:* internal: removed remove evaluable.Points,NPoints,Weights +- *Fixed in v9a14, v8.5:* pyproject version constraints +- *New in v9a15, v8.6:* support locate for tensorial topologies +- *New in v9a17:* make svg graphs interactive +- *Changed in v9a19:* more efficient geometry function for equidistant rectilinear mesh +- *Fixed in v9a20, v8.7:* logging of parameters without type annotation +- *Fixed in v9a21:* SI handling of special binary methods +- *Changed in v9a24:* fill nested subgraphs with distinct bg colors +- *Changed in v9a25:* add evaluable.Singular +- *Fixed in v9a25, v8.7:* simplification of Equals involving Range +- *Fixed in v9a28, v8.7:* multipatch interfaces +- *New in v9a30:* add evaluable.compile: a Python code generator +- *Changed in v9a33:* evaluable.Array now derived from types.DataClass +- *Fixed in v9a35:* parsegmsh in presence of multiple periodicity +- *Fixed in v9a35:* parsegmsh's handling of empty physical groups +- *Fixed in v9a36:* getpoints for empty mosaic elements +- *Fixed in v9a36:* 'not watertight' trimming issues +- *Changed in v9a37:* reduce unnecessary evaluations for shape checks during function formation +- *New in v9a37:* matrix.assemble_coo, .assemble_csr, .assemble_block_csr +- *New in v9a37:* evaluable.eval_coo, .unique, .as_csr +- *New in v9a37:* solver.System +- *Fixed in v9a37:* deprecated tol argument in scipy>=1.12 +- *Deprecated in v9a37:* matrix.assemble (replaced by matrix.assemble_coo, matrix.assemble_csr) +- *Changed in v9a39:* disable graphviz node background if ncalls == 0 +- *New in v9a39:* function.factor +- *Fixed in v9a40:* disallow truncation in types.arraydata +- *Fixed in v9a41:* Gramm-Schmidt breakdown in Arnoldi solver +- *New in v9a42:* support Numpy 2 +- *Changed in v9a44:* remove psutil and bottombar dependencies +- *Changed in v9a45:* automatically load mkl from pip user install +- *Changed in v9a46:* add argument checks to mesh.simplex +- *Changed in v9a46:* extend mesh.gmsh with ability to convert geo files +- *New in v9a47:* allow iterator argument in function.vectorize +- *New in v9a47:* topology.field method +- *Changed in v9a47:* rename dotarg to field +- *Deprecated in v9a47:* dotarg (replaced by field) +- *New in v9a49:* Turek benchmark example +- *New in v9a50:* SI support for reshape, linalg.norm, interp +- *New in v9a51:* vorticity plot in drivencavity example +- *Changed in v9a52:* support SI arguments in Topology.locate +- *Changed in v9a52:* support locating points on manifolds +- *New in v9a53:* sample.bind +- *Changed in v9a53:* minimum Python version 3.9 +- *Changed in v9a53:* minimum Numpy version 1.21 +- *Changed in v9a53:* extend numpy.interp to functions with points +- *Fixed in v9a53:* zipping tensorial samples +- *Fixed in v9a53:* graph of evaluables with nested loops +- *Deprecated in v9a53:* function.outer +- *Deprecated in v9a53:* sample callable (replaced by .bind) +- *Deprecated in v9a53:* function.integral, function.sample +- *Changed in v9a54:* simplify TransformLinear, TransformBasis if constant +- *Changed in v9a54:* simplify evaluable.Transform* with masked source +- *Deprecated in v9a54:* function.rootcoords +- *Changed in v9a55*: sparse deduplication during evaluation +- *New in v9a55*: sparse modifiers function.as_coo and function.as_csr +- *New in v9a58*: ability to select spaces in function.grad, Namespace.define_for +- *Deprecated in v9a60*: sample.integrate_sparse, Sample.eval_sparse +- *Deprecated in v9a60*: arguments via keywords (replaced by the 'arguments' parameter) +- *New in v9a60*: legacy parameter in Array.eval, Sample.integrate +- *New in v9a62*: solver methods ReuseNewton and Arnoldi +- *New in v9a63*: support nested integrals over the same space diff --git a/src/release.md b/src/release.md index 3f16e30..f5ff8d8 100644 --- a/src/release.md +++ b/src/release.md @@ -27,5 +27,5 @@ granted that their code may require continuous updating as features develop — keep an eye on the changelog in the project root! The development version is continuously updated here: -- [Download](https://github.com/evalf/nutils/archive/refs/heads/master.zip) (zip) -- [API Reference](http://docs.nutils.org/en/latest/) +- [Download](https://github.com/evalf/nutils/archive/refs/heads/main.zip) (zip) +- [API Reference](https://docs.nutils.org/en/latest/) diff --git a/src/science-publications.md b/src/science-publications.md index f9653c1..50dd333 100644 --- a/src/science-publications.md +++ b/src/science-publications.md @@ -18,6 +18,10 @@ Articles that [cite Nutils](science-citing.md) will be picked up automatically. by A. Cherezov, A. Vasiliev and H, Ferroukhi, October 2024. +- [On the use of elliptic PDEs for the parameterisation of planar multipatch domains](https://doi.org/10.1007/s00366-024-01997-x) + by J. Hinz and A. Buffa, + May 2024. + - [Echocardiogram-based ventricular isogeometric cardiac analysis using multi-patch fitted NURBS](https://doi.org/10.1016/j.cma.2024.116958) by R. Willems, L. Verberne, O. van der Sluis and C.V. Verhoosel, May 2024. @@ -30,6 +34,10 @@ Articles that [cite Nutils](science-citing.md) will be picked up automatically. by J. Hinz, O. Chanon, A. Arrigoni and A. Buffa, February 2024. +- [Using Bayesian optimization for warpage compensation in injection molding](https://doi.org/10.1002/mawe.202300157) + by S. Tillmann, M. Behr and S. Elgeti, + January 2024. + ## 2023 - [Finite element and isogeometric stabilized methods for the advection-diffusion-reaction equation](https://doi.org/10.1016/j.cma.2023.116354) diff --git a/src/tutorial-bases-fig1.svg b/src/tutorial-bases-fig1.svg index e7d8bee..a7610d7 100644 --- a/src/tutorial-bases-fig1.svg +++ b/src/tutorial-bases-fig1.svg @@ -17,8 +17,8 @@ z - - + - - 0.00 - - + - - 0.25 - - + - - 0.50 - - + - - 0.75 - - + - - 1.00 - - - x_0 + + + + + + - + - + - - 0.0 + + 0 - + - + - - 0.2 + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.4 + + 0 - + - + - - 0.6 + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.8 + + 0 - + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + - 1.0 + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 - - + + + + + + + + + 0 + + + + + + + + + + 1 + + - - + + - - + + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + - - + + + + + + + + + + + + + + diff --git a/src/tutorial-bases-fig2.svg b/src/tutorial-bases-fig2.svg index 8bff5e8..a0ea8db 100644 --- a/src/tutorial-bases-fig2.svg +++ b/src/tutorial-bases-fig2.svg @@ -17,8 +17,8 @@ z - - + - - 0.00 - - + - - 0.25 - - + - - 0.50 - - + - - 0.75 - - + - - 1.00 - - - x_0 + + + + + + - + - + - - 0.0 + + 0 - + - + - - 0.2 + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.4 + + 0.0 - + - + - - 0.6 + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.8 + + 0.0 - + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + 0.0 + + + + + + - 1.0 + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 - - + + + + + + + + + 0 + + + + + + + + + + 1 + + - - + + - - + + - - + + - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + - - + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-bases-fig3.svg b/src/tutorial-bases-fig3.svg index b69a9b9..3c40ca1 100644 --- a/src/tutorial-bases-fig3.svg +++ b/src/tutorial-bases-fig3.svg @@ -17,8 +17,8 @@ z - - + - - 0.00 - - + - - 0.25 - - + - - 0.50 - - + - - 0.75 - - + - - 1.00 - - - x_0 + + + + + + - + - + - - 0.0 + + 0 - + - + - - 0.2 + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.4 + + 0.0 - + - + - - 0.6 + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.8 + + 0 - + - + - - 1.0 + + 1 - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-bases-fig4.svg b/src/tutorial-bases-fig4.svg index b69a9b9..3c40ca1 100644 --- a/src/tutorial-bases-fig4.svg +++ b/src/tutorial-bases-fig4.svg @@ -17,8 +17,8 @@ z - - + - - 0.00 - - + - - 0.25 - - + - - 0.50 - - + - - 0.75 - - + - - 1.00 - - - x_0 + + + + + + - + - + - - 0.0 + + 0 - + - + - - 0.2 + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.4 + + 0.0 - + - + - - 0.6 + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.8 + + 0 - + - + - - 1.0 + + 1 - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-bases-fig5.svg b/src/tutorial-bases-fig5.svg index 8a46ad4..28b3235 100644 --- a/src/tutorial-bases-fig5.svg +++ b/src/tutorial-bases-fig5.svg @@ -17,8 +17,8 @@ z - - + - - 0.00 - - + - - 0.25 - - + - - 0.50 - - + - - 0.75 - - + - - 1.00 - - - x_0 + + + + + + - + - + - - 0.0 + + 0 - + - + - - 0.2 + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.4 + + 0.0 - + - + - - 0.6 + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - 0.8 + + 0 - + - + - - 1.0 + + 1 - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 + + + + + + + + + + + + 0 + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-bases.md b/src/tutorial-bases.md index e6ef2f0..1ea7f40 100644 --- a/src/tutorial-bases.md +++ b/src/tutorial-bases.md @@ -20,7 +20,7 @@ basis = topo.basis('spline', degree=1) The five basis functions are ```python -plot_line(basis) +myplot(topo, geom, basis) ``` ![output](tutorial-bases-fig1.svg) @@ -29,7 +29,7 @@ We will use this basis throughout the following sections. Change the `degree` argument to `2` for a quadratic spline basis: ```python -plot_line(topo.basis('spline', degree=2)) +myplot(topo, geom, topo.basis('spline', degree=2)) ``` ![output](tutorial-bases-fig2.svg) @@ -39,14 +39,14 @@ argument `continuity`. For example, a quadratic spline basis with $C^0$ continuity is generated with ```python -plot_line(topo.basis('spline', degree=2, continuity=0)) +myplot(topo, geom, topo.basis('spline', degree=2, continuity=0)) ``` ![output](tutorial-bases-fig3.svg) $C^0$ continuous spline bases can also be generated by the `'std'` basis: ```python -plot_line(topo.basis('std', degree=2)) +myplot(topo, geom, topo.basis('std', degree=2)) ``` ![output](tutorial-bases-fig4.svg) @@ -56,6 +56,6 @@ elements without hanging nodes. Discontinuous basis functions are generated using the `'discont'` type, e.g. ```python -plot_line(topo.basis('discont', degree=2)) +myplot(topo, geom, topo.basis('discont', degree=2)) ``` ![output](tutorial-bases-fig5.svg) diff --git a/src/tutorial-fig1.svg b/src/tutorial-fig1.svg index 18fbbd0..27b53e9 100644 --- a/src/tutorial-fig1.svg +++ b/src/tutorial-fig1.svg @@ -33,60 +33,67 @@ L 0 3.5 " style="stroke: #888888; stroke-width: 0.8"/> - + - 0.00 + 0.0 - + - 0.25 + 0.2 - + - 0.50 + 0.4 - + - 0.75 + 0.6 - + - 1.00 + 0.8 - - x_0 + + + + + + + + 1.0 + - + - 0.0 + 0.75 - + - 0.2 + 0.80 - + - 0.4 + 0.85 - + - 0.6 + 0.90 - + - 0.8 + 0.95 - + - 1.0 + 1.00 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-functions-fig1.svg b/src/tutorial-functions-fig1.svg index 17cd75e..e3b5d1a 100644 --- a/src/tutorial-functions-fig1.svg +++ b/src/tutorial-functions-fig1.svg @@ -17,8 +17,8 @@ z - - + - - 0.00 - - + - - 0.25 - - + - - 0.50 - - + - - 0.75 - - + - - 1.00 - - - x_0 + + + + + + - + - + - - 0.0 + + 0.0 - + - + - - 0.2 + + 0.2 - + - + - - 0.4 + + 0.4 - + - + - - 0.6 + + 0.6 - + - + - - 0.8 + + 0.8 - + - + - - 1.0 + + 1.0 - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + diff --git a/src/tutorial-functions-fig2.svg b/src/tutorial-functions-fig2.svg index b7e8a17..cc28d66 100644 --- a/src/tutorial-functions-fig2.svg +++ b/src/tutorial-functions-fig2.svg @@ -33,60 +33,67 @@ L 0 3.5 " style="stroke: #888888; stroke-width: 0.8"/> - + - 0.00 + 0.0 - + - 0.25 + 0.2 - + - 0.50 + 0.4 - + - 0.75 + 0.6 - + - 1.00 + 0.8 - - x_0 + + + + + + + + 1.0 + - + - 0.00 + 0.00 - + - 0.02 + 0.02 - + - 0.04 + 0.04 - + - 0.06 + 0.06 - + - 0.08 + 0.08 - + - 0.10 + 0.10 - + - 0.12 + 0.12 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +" clip-path="url(#p9ce2eeedc2)" style="fill: none; stroke: #1f77b4; stroke-width: 1.5"/> + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-functions-fig3.svg b/src/tutorial-functions-fig3.svg index 3093228..908265f 100644 --- a/src/tutorial-functions-fig3.svg +++ b/src/tutorial-functions-fig3.svg @@ -33,60 +33,67 @@ L 0 3.5 " style="stroke: #888888; stroke-width: 0.8"/> - + - 0.00 + 0.0 - + - 0.25 + 0.2 - + - 0.50 + 0.4 - + - 0.75 + 0.6 - + - 1.00 + 0.8 - - x_0 + + + + + + + + 1.0 + - + - −1.00 + −1.00 - + - −0.75 + −0.75 - + - −0.50 + −0.50 - + - −0.25 + −0.25 - + - 0.00 + 0.00 - + - 0.25 + 0.25 - + - 0.50 + 0.50 - + - 0.75 + 0.75 - + - 1.00 + 1.00 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +" clip-path="url(#p9ce2eeedc2)" style="fill: none; stroke: #1f77b4; stroke-width: 1.5"/> + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-functions-fig4.svg b/src/tutorial-functions-fig4.svg index 42a1bd6..de1e50d 100644 --- a/src/tutorial-functions-fig4.svg +++ b/src/tutorial-functions-fig4.svg @@ -33,60 +33,67 @@ L 0 3.5 " style="stroke: #888888; stroke-width: 0.8"/> - + - 0.00 + 0.0 - + - 0.25 + 0.2 - + - 0.50 + 0.4 - + - 0.75 + 0.6 - + - 1.00 + 0.8 - - x_0 + + + + + + + + 1.0 + - + - 0 + 0 - + - 1 + 1 - + - 2 + 2 - + - 3 + 3 - + - 4 + 4 - + - 5 + 5 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +" clip-path="url(#p9ce2eeedc2)" style="fill: none; stroke: #1f77b4; stroke-width: 1.5"/> + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-functions.md b/src/tutorial-functions.md index 5d4c803..6abf3cc 100644 --- a/src/tutorial-functions.md +++ b/src/tutorial-functions.md @@ -29,14 +29,14 @@ element of the geometry `geom` you can write `geom[0]` and to select the first two basis functions you can write ```python -plot_line(basis[:2]) +myplot(topo, geom, basis[:2]) ``` ![output](tutorial-functions-fig1.svg) The usual unary and binary operators are available: ```python -plot_line(geom[0]*(1-geom[0])/2) +myplot(topo, geom, geom[0]*(1-geom[0])/2) ``` ![output](tutorial-functions-fig2.svg) @@ -44,15 +44,15 @@ Several trigonometric functions are defined in the `nutils.function` module. An example with a sine function: ```python -plot_line(function.sin(2*geom[0]*numpy.pi)) +myplot(topo, geom, numpy.sin(2*geom[0]*numpy.pi)) ``` ![output](tutorial-functions-fig3.svg) -The dot product is available via `nutils.function.dot`. To contract the basis -with an arbitrary coefficient vector: +The dot product is available via the '@' operator. To contract the basis with an +arbitrary coefficient vector: ```python -plot_line(function.dot(basis, [1,2,0,5,4])) +myplot(topo, geom, basis @ [1,2,0,5,4]) ``` ![output](tutorial-functions-fig4.svg) @@ -63,15 +63,46 @@ coefficients for which this function solves the Laplace problem. ## Arguments -A discrete model is often written in terms of an unknown, or a vector of -unknowns. In Nutils this translates to a function argument, -`nutils.function.Argument`. Usually an argument is used in an inner product -with a basis. For this purpose there exists the `nutils.function.dotarg` -function. For example, the [discrete -solution](tutorial-theory.md#discrete-solution) can be written as +A discrete model is often written in terms of (vectors of) unknowns. In Nutils, +unknowns are represented by functions of type `nutils.function.Argument`, which +have a known shape but undefined contents. Every argument has a name to +identify it, which cannot be reused for different arguments in the same +expression. +The [discrete solution](tutorial-theory.md#discrete-solution) can now be +written as an inner product with a basis, with the vector of unknowns +$\hat{u}_n$ represented by the argument `'u'`: ```python -ns.u = function.dotarg('lhs', ns.basis) +from nutils.function import Argument +u = basis @ Argument('u', basis.shape) ``` -with the argument identified by `'lhs'` the vector of unknowns $\hat{u}_n$. +Since it is slightly tedious to create an argument that has a matching shape to +an existing basis, the function module provides a convenience function that +does the work for you. +```python +from nutils.function import field +u = field('u', basis) +``` + +Moreover, as it is rarely necessary to manipulate a basis directly, the +topology object adds a layer of convenience that creates the basis, contracts +it with an argument, and returns only the result. This is the form that we will +most often encounter: +```python +u = topo.field('u', btype='spline', degree=1) +``` + +If a function depends on one or more arguments, then their values must be +specified at evaluation time. However we cannot demonstrate that yet for the +discrete solution defined here as it still requires a specification of the +relevant topological points. This will be the subject of +[integrals](tutorial-integrals.md). + +What we can do is take derivatives with respect to arguments. The derivative +appends the argument shape to that of the original function. Here we take the +derivative of u, the function, with respect to 'u', the argument, to +effectively extract the basis: +```python +basis = u.derivative('u') +``` diff --git a/src/tutorial-integrals.md b/src/tutorial-integrals.md index 60d26af..924523e 100644 --- a/src/tutorial-integrals.md +++ b/src/tutorial-integrals.md @@ -13,27 +13,26 @@ has been added to the namespace using `ns.define_for(..., jacobians=('dV', ```python I = topo.integral('1 dV' @ ns, degree=0) -I # Array<> ``` The resulting `nutils.function.Array` object is a representation of the -integral, as yet unevaluated. To compute the actual numbers, call the -`Array.eval()` method: +integral, as yet unevaluated. To compute the actual numbers, use the +`function.eval()` function: ```python -I.eval() -# 1.0±1e-15 +function.eval(I) +# 1.0 ``` Be careful with including the Jacobian in your integrands. The following two integrals are different: ```python -topo.integral('(1 + 1) dV' @ ns, degree=0).eval() -# 2.0±1e-15 -topo.integral('1 + 1 dV' @ ns, degree=0).eval() -# 5.0±1e-15 +function.eval(topo.integral('(1 + 1) dV' @ ns, degree=0)) +# 2.0 +function.eval(topo.integral('1 + 1 dV' @ ns, degree=0)) +# 5.0 ``` Like any other `nutils.function.Array`, the integrals can be added or @@ -41,8 +40,8 @@ subtracted: ```python J = topo.integral('x_0 dV' @ ns, degree=1) -(I+J).eval() -# 1.5±1e-15 +function.eval(I+J) +# 1.5 ``` Recall that a topology boundary is also a `nutils.topology.Topology` object, @@ -50,49 +49,75 @@ and hence it supports integration. For example, to integrate the geometry `x` over the entire boundary, write ```python -topo.boundary.integral('x_0 dS' @ ns, degree=1).eval() -# 1.0±1e-15 +function.eval(topo.boundary.integral('x_0 dS' @ ns, degree=1)) +# 1.0 ``` To limit the integral to the right boundary, write ```python -topo.boundary['right'].integral('x_0 dS' @ ns, degree=1).eval() -# 1.0±1e-15 +function.eval(topo.boundary['right'].integral('x_0 dS' @ ns, degree=1)) +# 1.0 ``` - Note that this boundary is simply a point and the integral a point evaluation. -Integrating and evaluating a 1D `nutils.function.Array` results in a 1D -`numpy.ndarray`: +## Back to our discrete solution +We observed earlier that we cannot evaluate our discrete solution because of +lacking a specification of topological points -- or in Nutils jargon: leaving a +*space* unbound. Integrals provide this information by defining the set of +quadrature points that the function will be evaluated in (followed by a +contraction with quadrature weights). This means we could aim to evaluate the +following function: ```python ->>> topo.integral('basis_i dV' @ ns, degree=1).eval() -array([0.125, 0.25 , 0.25 , 0.25 , 0.125])±1e-15 +f = topo.integral('∇_k(u) ∇_k(u) dV' @ ns, degree=1) ``` - -Since the integrals of 2D `nutils.function.Array` functions are usually sparse, -the `Array.eval() ` method does not return a dense -`numpy.ndarray`, but a Nutils sparse matrix object: a subclass of -`nutils.matrix.Matrix`. Nutils interfaces several linear solvers (more on this -in Section [solvers](tutorial-solvers.md) below) but if you want to use a -custom solver you can export the matrix to a dense, compressed sparse row or -coordinate representation via the `Matrix.export()` method. An example: - +However, to do so we do need to provide the weights for argument 'u'. We do +this as follows: ```python -M = topo.integral('∇_i(basis_m) ∇_i(basis_n) dV' @ ns, degree=1).eval() -M.export('dense') +function.eval(f, arguments={'u': [1,2,0,5,4]}) +``` +Since integrals are `nutils.function.Array` objects, integrals involving +arguments support derivatives. Taking the derivative once results in a 1D +function, which evaluates to a `numpy.ndarray`: +```python +function.eval(f.derivative('u'), arguments={'u': [1,2,0,5,4]}) +# array([0.125, 0.25 , 0.25 , 0.25 , 0.125]) +``` +Since our function `f` is quadratic in 'u', the second derivative becomes +constant (i.e. independent of arguments) and can be evaluated without any +argument specification: +```python +M = f.derivative('u').derivative('u') +function.eval(M) # array([[ 4., -4., 0., 0., 0.], # [-4., 8., -4., 0., 0.], # [ 0., -4., 8., -4., 0.], # [ 0., 0., -4., 8., -4.], -# [ 0., 0., 0., -4., 4.]])±1e-15 -M.export('csr') # (data, column indices, row pointers) # doctest: +NORMALIZE_WHITESPACE -# (array([ 4., -4., -4., 8., -4., -4., 8., -4., -4., 8., -4., -4., 4.])±1e-15, -# array([0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4])±1e-15, -# array([ 0, 2, 5, 8, 11, 13])±1e-15) -M.export('coo') # (data, (row indices, column indices)) # doctest: +NORMALIZE_WHITESPACE -# (array([ 4., -4., -4., 8., -4., -4., 8., -4., -4., 8., -4., -4., 4.])±1e-15, -# (array([0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4])±1e-15, -# array([0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4])±1e-15)) +# [ 0., 0., 0., -4., 4.]]) +``` +Observing that this matrix is sparse, it would be more efficient to evaluate +only the nonzero entries and the corresponding indices, so that these can be +used to form an appropriate sparse matric object. For this, the +`nutils.function` module provides the two modifiers `as_coo` and `as_csr`. +The former is valid for objects of any dimension, and return the nonzero values +followed by a number of index vectors equal to the dimension of the array: +```python +function.eval(function.as_coo(M)) +# (array([ 8., -8., -8., 16., -8., -8., 16., -8., -8., 16., -8., -8., 8.]), +# array([0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4]), +# array([0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4])) +``` +The latter of specific to 2D arrays and returns the sparsity structure in +[compressed sparse +row](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_(CSR,_CRS_or_Yale_format)) +format: +```python +function.eval(function.as_csr(M)) +# (array([ 8., -8., -8., 16., -8., -8., 16., -8., -8., 16., -8., -8., 8.]), +# array([ 0, 2, 5, 8, 11, 13]), +# array([0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4])) ``` +Either of these can be used to form a Nutils sparse matrix using the +``nutils.matrix.assemble_coo`` or ``nutils.matrix.assemble_csr`` functions, or +any third party sparse matrix of preference. diff --git a/src/tutorial-laplace2d-fig1.svg b/src/tutorial-laplace2d-fig1.svg index faabc7e..e3c5ecc 100644 --- a/src/tutorial-laplace2d-fig1.svg +++ b/src/tutorial-laplace2d-fig1.svg @@ -17,15 +17,15 @@ z - +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" id="imageb43ad3cdd5" transform="scale(1 -1) translate(0 -265.68)" x="102.96" y="-41.76" width="266.4" height="265.68"/> @@ -35,66 +35,63 @@ L 0 3.5 " style="stroke: #888888; stroke-width: 0.8"/> - + - 0.0 + 0.0 - + - 0.2 + 0.2 - + - 0.4 + 0.4 - + - 0.6 + 0.6 - + - 0.8 + 0.8 - + - 1.0 + 1.0 - - x_0 - @@ -105,196 +102,9691 @@ L -3.5 0 " style="stroke: #888888; stroke-width: 0.8"/> - + - - 0.0 + + 0.0 - + - - 0.2 + + 0.2 - + - - 0.4 + + 0.4 - + - - 0.6 + + 0.6 - + - - 0.8 + + 0.8 - + - - 1.0 + + 1.0 - - x_1 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - 0.0 - - - - - - - - - - 0.2 - - - - - - - - - - 0.4 - - - - - - - - - - 0.6 - - - - - - - - - - 0.8 - - - - - - - - - - 1.0 - - - - - - - - - - 1.2 - - - - - - - - + + diff --git a/src/tutorial-laplace2d.md b/src/tutorial-laplace2d.md index 1f436c4..ee9bb16 100644 --- a/src/tutorial-laplace2d.md +++ b/src/tutorial-laplace2d.md @@ -52,8 +52,8 @@ argument `lhs`. ns = Namespace() ns.x = geom ns.define_for('x', gradient='∇', normal='n', jacobians=('dV', 'dS')) -ns.basis = topo.basis('std', degree=1) -ns.u = function.dotarg('lhs', ns.basis) +ns.u = topo.field('u', btype='std', degree=1) +ns.v = topo.field('v', btype='std', degree=1) ``` Note that the above statements are identical to those of the one-dimensional @@ -62,28 +62,28 @@ example. The residual is implemented as ```python -res = topo.integral('∇_i(basis_n) ∇_i(u) dV' @ ns, degree=2) -res -= topo.boundary['right'].integral('basis_n cos(1) cosh(x_1) dS' @ ns, degree=2) +res = topo.integral('∇_k(v) ∇_k(u) dV' @ ns, degree=2) +res -= topo.boundary['right'].integral('v cos(1) cosh(x_1) dS' @ ns, degree=2) ``` The Dirichlet boundary conditions are rewritten as a least squares problem and -solved for `lhs`, yielding the constraints vector `cons`: +solved for `u`, yielding the constraints vector `cons`: ```python sqr = topo.boundary['left'].integral('u^2 dS' @ ns, degree=2) sqr += topo.boundary['top'].integral('(u - cosh(1) sin(x_0))^2 dS' @ ns, degree=2) -cons = solver.optimize('lhs', sqr, droptol=1e-15) +cons = solver.System(sqr, trial='u').solve_constraints(droptol=1e-15) # optimize > solve > solving 21 dof system to machine precision using arnoldi solver # optimize > solve > solver returned with residual 3e-17±2e-15 # optimize > constrained 21/121 dofs # optimize > optimum value 4.32e-10±1e-9 ``` -To solve the problem `res=0` for `lhs` subject to `lhs=cons` excluding -the `nan` values, we can use `nutils.solver.solve_linear`: +To solve the problem `res=0` for `u` subject to `cons['u']` excluding +the `nan` values, we use the system's `solve` method: ```python -lhs = solver.solve_linear('lhs', res, constrain=cons) +args = solver.System(res, trial='u', test='v').solve(constrain=cons) # solve > solving 100 dof system to machine precision using arnoldi solver # solve > solver returned with residual 2e-15±2e-15 ``` @@ -92,18 +92,7 @@ Finally, we plot the solution. We create a `nutils.sample.Sample` object from `topo` and evaluate the geometry and the solution: ```python -bezier = topo.sample('bezier', 9) -x, u = bezier.eval(['x_i', 'u'] @ ns, lhs=lhs) -``` - -We use `plt.tripcolor` to plot the sampled `x` and `u`: - -```python -plt.tripcolor(x[:,0], x[:,1], bezier.tri, u, shading='gouraud', rasterized=True) -plt.colorbar() -plt.gca().set_aspect('equal') -plt.xlabel('x_0') -plt.ylabel('x_1') +myplot(topo, ns.x, ns.u, args) ``` ![output](tutorial-laplace2d-fig1.svg) diff --git a/src/tutorial-namespace.md b/src/tutorial-namespace.md index 7e914c4..02e310a 100644 --- a/src/tutorial-namespace.md +++ b/src/tutorial-namespace.md @@ -15,39 +15,29 @@ ns = Namespace() ``` New entries are added to a `nutils.expression_v2.Namespace` by assigning an -`nutils.function.Array` to an attribute. For example, to assign the geometry -`geom` to `ns.x`, simply type +`nutils.function.Array` to an attribute. For example, the geometry +`geom` is assigned to `ns.x` via ```python ns.x = geom ``` -You can now use `ns.x` where you would use `geom`. Usually you want to add the -gradient, normal and jacobian of this geometry to the namespace as well. This -can be done using `nutils.expression_v2.Namespace.define_for` naming the -geometry (as present in the namespace) and names for the gradient, normal, and -the jacobian as keyword arguments: - +You can now use `ns.x` where you would use `geom`. Usually you will want to add +the gradient, normal and jacobian of this geometry to the namespace as well. +This can be done by calling `nutils.expression_v2.Namespace.define_for` with +the name of the geometry (as present in the namespace) followed by the names or +symbols you choose to represent the desired features as optional keyword +arguments: ```python ns.define_for('x', gradient='∇', normal='n', jacobians=('dV', 'dS')) ``` -Note that any keyword argument is optional. - -To assign a linear basis to `ns.basis`, type - -```python -ns.basis = topo.basis('spline', degree=1) -``` - -and to assign the discrete solution as the inner product of this basis with -argument `'lhs'`, type - +The discrete solution is again added through a simple assignment: ```python -ns.u = function.dotarg('lhs', ns.basis) +ns.u = topo.field('u', btype='spline', degree=1) ``` -You can also assign numbers and `numpy.ndarray` objects: +It is also possible to assign numbers and `numpy.ndarray` objects: ```python ns.a = 1 @@ -85,7 +75,7 @@ The resulting `ns.e` is an ordinary `nutils.function.Array`. Note that the variables used in the expression should exist in the namespace, not just as a local variable: -```python +```python (skip) localvar = 1 ns.f = '2 localvar' # Traceback (most recent call last): diff --git a/src/tutorial-sampling-fig1.svg b/src/tutorial-sampling-fig1.svg index 6cab856..b99eec1 100644 --- a/src/tutorial-sampling-fig1.svg +++ b/src/tutorial-sampling-fig1.svg @@ -37,7 +37,7 @@ L 0 3.5 - 0.0 + 0.0 @@ -47,7 +47,7 @@ L 0 3.5 - 0.2 + 0.2 @@ -57,7 +57,7 @@ L 0 3.5 - 0.4 + 0.4 @@ -67,7 +67,7 @@ L 0 3.5 - 0.6 + 0.6 @@ -77,7 +77,7 @@ L 0 3.5 - 0.8 + 0.8 @@ -87,7 +87,7 @@ L 0 3.5 - 1.0 + 1.0 @@ -104,7 +104,7 @@ L -3.5 0 - 0.0 + 0.75 @@ -114,7 +114,7 @@ L -3.5 0 - 0.2 + 0.80 @@ -124,7 +124,7 @@ L -3.5 0 - 0.4 + 0.85 @@ -134,7 +134,7 @@ L -3.5 0 - 0.6 + 0.90 @@ -144,7 +144,7 @@ L -3.5 0 - 0.8 + 0.95 @@ -154,20 +154,29 @@ L -3.5 0 - 1.0 + 1.00 - + + + + + + + + + +" clip-path="url(#p9ce2eeedc2)" style="fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square"/> + diff --git a/src/tutorial-sampling.md b/src/tutorial-sampling.md index eb66319..fcccea7 100644 --- a/src/tutorial-sampling.md +++ b/src/tutorial-sampling.md @@ -25,8 +25,7 @@ evaluate the geometry `ns.x` write ```python x = bezier.eval('x_0' @ ns) -x -# array([0. , 0.25, 0.25, 0.5 , 0.5 , 0.75, 0.75, 1. ])±1e-15 +# array([0. , 0.25, 0.25, 0.5 , 0.5 , 0.75, 0.75, 1. ]) ``` The first axis of the returned `numpy.ndarray` represents the collection of @@ -34,11 +33,11 @@ points. To reorder this into a sequence of lines in 1D, a triangulation in 2D or in general a sequence of simplices, use the `Sample.tri` attribute: ```python -x.take(bezier.tri, 0) +x[bezier.tri] # array([[0. , 0.25], # [0.25, 0.5 ], # [0.5 , 0.75], -# [0.75, 1. ]])±1e-15 +# [0.75, 1. ]]) ``` Now, the first axis represents the simplices and the second axis the vertices @@ -50,35 +49,23 @@ specified by keyword arguments to `Sample.eval()`. For example, to evaluate `nutils.solver.solve_linear` above, write ```python -u = bezier.eval('u' @ ns, lhs=lhs) -u -# array([0. , 0.25, 0.25, 0.5 , 0.5 , 0.75, 0.75, 1. ])±1e-15 +u = bezier.eval('u' @ ns, arguments=args) +# array([0. , 0.25, 0.25, 0.5 , 0.5 , 0.75, 0.75, 1. ]) ``` -We can now plot the sampled geometry `x` and solution `u` using `matplotlib`_, +We can now plot the sampled geometry `x` and solution `u` using `matplotlib`, plotting each line in `Sample.tri` with a different color: ```python ->>> plt.plot(x.take(bezier.tri.T, 0), u.take(bezier.tri.T, 0)) +pyplot.plot(x[bezier.tri.T], u[bezier.tri.T]) ``` ![output](tutorial-sampling-fig1.svg) -Recall that we have imported `matplotlib.pyplot` as `plt` above. The -`plt.plot()` function takes an array of x-values and and array of y-values, -both with the first axis representing vertices and the second representing -separate lines, hence the transpose of `bezier.tri`. +The `pyplot.plot()` function takes an array of x-values and and array of +y-values, both with the first axis representing vertices and the second +representing separate lines, hence the transpose of `bezier.tri`. -The `plt.plot()` function also supports plotting lines with discontinuities, -which are represented by `nan` values. We can use this to plot the solution as -a single, but possibly discontinuous line. The function `numpy.insert` can be -used to prepare a suitable array. An example: - -```python -nanjoin = lambda array, tri: numpy.insert(array.take(tri.flat, 0).astype(float), - slice(tri.shape[1], tri.size, tri.shape[1]), numpy.nan, axis=0) -nanjoin(x, bezier.tri) -# array([0. , 0.25, nan, 0.25, 0.5 , nan, 0.5 , 0.75, nan, 0.75, 1. ])±1e-15 -plt.plot(nanjoin(x, bezier.tri), nanjoin(u, bezier.tri)) -``` - -Note the difference in colors between the last two plots. +In our `myplot` utility function we call `nutils.export.triplot` to create a +single line plot out of the many segments, aided by its own `tri` argument for +element connectivity. It further generalizes to 2D (and 3D), as we will see in +the following section. diff --git a/src/tutorial-solvers-fig1.svg b/src/tutorial-solvers-fig1.svg new file mode 100644 index 0000000..00a8184 --- /dev/null +++ b/src/tutorial-solvers-fig1.svg @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 + + + + + + + + + + + + + + + 0.0 + + + + + + + + + + 0.2 + + + + + + + + + + 0.4 + + + + + + + + + + 0.6 + + + + + + + + + + 0.8 + + + + + + + + + + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tutorial-solvers.md b/src/tutorial-solvers.md index 80d5792..66118d6 100644 --- a/src/tutorial-solvers.md +++ b/src/tutorial-solvers.md @@ -6,123 +6,120 @@ perhaps the simplest of its kind, the least squares projection, demonstrating the different implementations now available to us and working our way up from there. -Taking the geometry component $x_0$ as an example, to project it onto the -basis $\{φ_n\}$ means finding the coefficients $\hat{u}_n$ such -that +Taking the function $x_0^2$ as an example, to project it onto the discrete +space means finding the discrete solution $\hat{u}$ such that, for all discrete +test functions $\hat{v}$: -$$ \left(\int_Ω φ_n φ_m \ dV\right) \hat u_m = \int_Ω φ_n x_0 \ dV $$ +$$ \int_Ω \hat v \hat u \ dV = \int_Ω \hat v x_0^2 \ dV $$ -for all $φ_n$, or $A_{nm} \hat{u}_m = f_n$. This is implemented as -follows: +In terms of the discrete coefficients this becomes the linear system $A_{nm} +\hat{u}_m = f_n$. This is implemented as follows: ```python -A = topo.integral('basis_m basis_n dV' @ ns, degree=2).eval() -f = topo.integral('basis_n x_0 dV' @ ns, degree=2).eval() -A.solve(f) -# solve > solving 5 dof system to machine precision using arnoldi solver -# solve > solver returned with residual 3e-17±1e-15 -# array([0. , 0.25, 0.5 , 0.75, 1. ])±1e-15 +ns.u = topo.field('u', btype='spline', degree=1) +ns.v = topo.field('v', btype='spline', degree=1) +A, f = function.eval([ + topo.integral('v u dV' @ ns, degree=2).derivative('v').derivative('u'), + topo.integral('v x_0^2 dV' @ ns, degree=2).derivative('v')]) +u = numpy.linalg.solve(A, f) +# array([-0.01041667, 0.05208333, 0.23958333, 0.55208333, 0.98958333]) ``` +![output](tutorial-solvers-fig1.svg) Alternatively, we can write this in the slightly more general form -$$ R_n := \int_Ω φ_n (u - x_0) \ dV = 0. $$ +$$ R := \int_Ω \hat v (\hat u - x_0^2) \ dV = 0. $$ ```python -res = topo.integral('basis_n (u - x_0) dV' @ ns, degree=2) +res = topo.integral('v (u - x_0^2) dV' @ ns, degree=2) ``` -Taking the derivative of $R_n$ to $\hat{u}_m$ gives the above -matrix $A_{nm}$, and substituting for $\hat{u}$ the zero vector -yields $-f_n$. Nutils can compute those derivatives for you, using the -method `Array.derivative()` to compute the derivative with respect to an +After taking the derivative with respect to the test function 'v', the +derivative to 'u' gives the above matrix $A$, whereas substitution of the zero +vector for 'u' yields `-f`. Nutils can compute those derivatives for you, using +the method `Array.derivative()` to compute the derivative with respect to an `nutils.function.Argument`, returning a new `nutils.function.Array`. ```python -A = res.derivative('lhs').eval() -f = -res.eval(lhs=numpy.zeros(5)) -A.solve(f) -# solve > solving 5 dof system to machine precision using arnoldi solver -# solve > solver returned with residual 3e-17±1e-15 -# array([0. , 0.25, 0.5 , 0.75, 1. ])±1e-15 +A, f = function.eval([ + res.derivative('v').derivative('u'), + -res.derivative('v')], arguments={'u': numpy.zeros(5)}) +u = numpy.linalg.solve(A, f) +# array([-0.01041667, 0.05208333, 0.23958333, 0.55208333, 0.98958333]) ``` -The above three lines are so common that they are combined in the function -`nutils.solver.solve_linear`: +The above three lines are so common that they are combined in the `solve` +method of `nutils.solver.System`: ```python -solver.solve_linear('lhs', res) -# solve > solving 5 dof system to machine precision using arnoldi solver -# solve > solver returned with residual 3e-17±1e-15 -# array([0. , 0.25, 0.5 , 0.75, 1. ])±1e-15 +args = solver.System(res, trial='u', test='v').solve() +# {'u': array([-0.01041667, 0.05208333, 0.23958333, 0.55208333, 0.98958333])} ``` We can take this formulation one step further. Minimizing -$$ S := \int_Ω (u - x_0)^2 \ dV $$ +$$ S := \int_Ω (\hat u - x_0)^2 \ dV $$ -for $\hat{u}$ is equivalent to the above two variants. The derivative of -$S$ to $\hat{u}_n$ gives $2 R_n$: +for $\hat{u}$ is equivalent to the above two variants, as the derivative of $S$ +to $\hat{u}$ equals $2 R$. ```python sqr = topo.integral('(u - x_0)^2 dV' @ ns, degree=2) -solver.solve_linear('lhs', sqr.derivative('lhs')) -# solve > solving 5 dof system to machine precision using arnoldi solver -# solve > solver returned with residual 6e-17±1e-15 -# array([0. , 0.25, 0.5 , 0.75, 1. ])±1e-15 +solver.System([sqr.derivative('u')], trial='u').solve() +# {'u': array([-0.01041667, 0.05208333, 0.23958333, 0.55208333, 0.98958333])} ``` - -The optimization problem can also be solved by the -`nutils.solver.optimize` function, which has the added benefit that -$S$ may be nonlinear in $\hat{u}$ --- a property not used here. +Since `sqr.derivative('u')` is vector valued, `solve` understands that its +assignment is to make the entire vector zero, and no test function needs to be +specified. However, we can go one step shorter by providing `sqr` as is, in +which case `solve` interprets the absence of the test argument as being equal +to the trial. The result is the same as before, with the added benefit of +informing System that the linear system it is solving is symmetric. ```python -solver.optimize('lhs', sqr) -# optimize > solve > solving 5 dof system to machine precision using arnoldi solver -# optimize > solve > solver returned with residual 0e+00±1e-15 -# optimize > optimum value 0.00e+00±1e-15 -# array([0. , 0.25, 0.5 , 0.75, 1. ])±1e-15 +solver.System(sqr, trial='u').solve() +# {'u': array([-0.01041667, 0.05208333, 0.23958333, 0.55208333, 0.98958333])} ``` -Nutils also supports solving a partial optimization problem. In the Laplace -problem stated above, the Dirichlet boundary condition at $Γ_\text{left}$ -minimizes the following functional: +The System object also supports solving a partial optimization problem via its +`solve_constraints` method, so called because this is typically used for +Dirichlet constraints. This method returns an array with `nan` ('not a number') +for every entry for which the optimization problem is invariant, or to be +precise, where the variation is below the mandatory `droptol` argument. + +## Putting it together + +We are now in a position to consider again the Laplace problem stated above. +The Dirichlet boundary condition at $Γ_\text{left}$ minimizes the following +functional: ```python -sqr = topo.boundary['left'].integral('(u - 0)^2 dS' @ ns, degree=2) +sqr = topo.boundary['left'].integral('(u - 1)^2 dS' @ ns, degree=2) ``` -By passing the `droptol` argument, `nutils.solver.optimize` returns an -array with `nan` ('not a number') for every entry for which the optimization -problem is invariant, or to be precise, where the variation is below -`droptol`: +We use the `solve_constraints` method to solve this least squares problem for +the single degree of freedom involved, leaving the others at not a number to +signify that the are yet to be defined: ```python -cons = solver.optimize('lhs', sqr, droptol=1e-15) -# optimize > constrained 1/5 dofs -# optimize > optimum value 0.00e+00 -cons -# array([ 0., nan, nan, nan, nan])±1e-15 +cons = solver.System(sqr, trial='u').solve_constraints(droptol=1e-15) +# {'u': array([ 1., nan, nan, nan, nan])} ``` -Consider again the Laplace problem stated above. The -[residual](tutorial-theory.md#weak-form) is implemented as +The [residual](tutorial-theory.md#weak-form) is implemented as ```python -res = topo.integral('∇_i(basis_n) ∇_i(u) dV' @ ns, degree=0) -res -= topo.boundary['right'].integral('basis_n dS' @ ns, degree=0) +res = topo.integral('(∇_k(v) ∇_k(u) + 2 v) dV' @ ns, degree=2) +res -= topo.boundary['right'].integral('v dS' @ ns, degree=2) ``` -Since this problem is linear in argument `lhs`, we can use the -`nutils.solver.solve_linear` method to solve this problem. The constraints -`cons` are passed via the keyword argument `constrain`: +We can use the system's `solver` method to solve this problem, with the +constraints passed in via the `constrain` keyword argument: ```python -lhs = solver.solve_linear('lhs', res, constrain=cons) -# solve > solving 4 dof system to machine precision using arnoldi solver -# solve > solver returned with residual 9e-16±1e-15 -lhs -# array([0. , 0.25, 0.5 , 0.75, 1. ])±1e-15 +args = solver.System(res, trial='u', test='v').solve(constrain=cons) +# {'u': array([1. , 0.8125, 0.75 , 0.8125, 1. ])} ``` -For nonlinear residuals you can use `nutils.solver.newton`. +Note, finally, that the `solve` method actually does not require the problem to +be linear in 'u' at all; if it is not then it will automatically switch to +Newton iterations unless otherwise specified. diff --git a/src/tutorial-theory.md b/src/tutorial-theory.md index f5a8f7f..c19674b 100644 --- a/src/tutorial-theory.md +++ b/src/tutorial-theory.md @@ -3,12 +3,12 @@ We will introduce fundamental Nutils concepts based on the 1D homogeneous Laplace problem, -$$ u''(x) = 0 $$ +$$ u''(x) = 2 $$ -with boundary conditions $u(0) = 0$ and $u'(1) = 1$. Even though -the solution is trivially found to be $u(x) = x$, the example serves to -introduce many key concepts in the Nutils paradigm, concepts that can then be -applied to solve a wide class of physics problems. +with boundary conditions $u(0) = 1$ and $u'(1) = 1$. Even though the solution +to this problem is easily found to be $u(x) = 1 - x + x^2$, the example serves +to introduce many key concepts in the Nutils paradigm, concepts that can then +be applied to solve a wide class of physics problems. ## Weak Form @@ -22,7 +22,7 @@ space such that any $u ∈ H_0(Ω)$ satisfies $u = 0$ in $ ∈ H_0(Ω)$ for which $R(v, u) = 0$ for all test functions $v ∈ H_0(Ω)$, with $R$ the bilinear functional -$$ R(v, u) := ∫_Ω \frac{∂v}{∂x_i} \frac{∂u}{∂x_i} \ dV - ∫_{Γ_\text{right}} v \ dS. $$ +$$ R(v, u) := ∫_Ω \left( \frac{∂v}{∂x_i} \frac{∂u}{∂x_i} + 2 v \right) dV - ∫_{Γ_\text{right}} v \ dS. $$ ## Discrete Solution diff --git a/src/tutorial.md b/src/tutorial.md index e3aa392..74adbc5 100644 --- a/src/tutorial.md +++ b/src/tutorial.md @@ -17,40 +17,38 @@ ipython. In the sections that follow we will go over these lines ones by one and explain the relevant concepts involved. ```python -from nutils import function, mesh, solver +from nutils import mesh, function, export, solver from nutils.expression_v2 import Namespace +from matplotlib import pyplot import numpy -from matplotlib import pyplot as plt topo, geom = mesh.rectilinear([numpy.linspace(0, 1, 5)]) ns = Namespace() ns.x = geom ns.define_for('x', gradient='∇', normal='n', jacobians=('dV', 'dS')) -ns.basis = topo.basis('spline', degree=1) -ns.u = function.dotarg('lhs', ns.basis) +ns.u = topo.field('u', btype='spline', degree=2) +ns.v = topo.field('v', btype='spline', degree=2) -sqr = topo.boundary['left'].integral('u^2 dS' @ ns, degree=2) -cons = solver.optimize('lhs', sqr, droptol=1e-15) +sqr = topo.boundary['left'].integral('(u - 1)^2 dS' @ ns, degree=2) +cons = solver.System(sqr, trial='u').solve_constraints(droptol=1e-15) # optimize > constrained 1/5 dofs # optimize > optimum value 0.00e+00 -res = topo.integral('∇_i(basis_n) ∇_i(u) dV' @ ns, degree=0) -res -= topo.boundary['right'].integral('basis_n dS' @ ns, degree=0) -lhs = solver.solve_linear('lhs', residual=res, constrain=cons) +res = topo.integral('(∇_k(v) ∇_k(u) + 2 v) dV' @ ns, degree=2) +res -= topo.boundary['right'].integral('v dS' @ ns, degree=2) +args = solver.System(res, trial='u', test='v').solve(constrain=cons) # solve > solving 4 dof system to machine precision using arnoldi solver # solve > solver returned with residual 9e-16±1e-15 -bezier = topo.sample('bezier', 32) -nanjoin = lambda array, tri: numpy.insert(array.take(tri.flat, 0).astype(float), - slice(tri.shape[1], tri.size, tri.shape[1]), numpy.nan, axis=0) -sampled_x = nanjoin(bezier.eval('x_0' @ ns), bezier.tri) -def plot_line(func, **arguments): - plt.plot(sampled_x, nanjoin(bezier.eval(func, **arguments), bezier.tri)) - plt.xlabel('x_0') - plt.xticks(numpy.linspace(0, 1, 5)) +def myplot(topo, geom, func, arguments={}): + bezier = topo.sample('bezier', 9) + x, fs = bezier.eval([geom, list(func) if func.ndim else [func]], arguments=arguments) + fig, axs = pyplot.subplots(nrows=len(fs), sharex=True, squeeze=False) + for (ax,), f in zip(axs, fs): + export.triplot(ax, x, f, tri=bezier.tri, hull=bezier.hull) -plot_line(ns.u, lhs=lhs) +myplot(topo, ns.x, ns.u, args) ``` ![output](tutorial-fig1.svg) diff --git a/util/genimg.py b/util/genimg.py index 6b41e05..5b57ff8 100644 --- a/util/genimg.py +++ b/util/genimg.py @@ -18,24 +18,23 @@ images = [] ns = {} for section in re.findall('[(](tutorial.*)[.]md[)]', open('src/SUMMARY.md').read()): - print('ENTERING', section) index = 0 - for snippet in re.findall('^```python$(.*?)^```$', open(f'src/{section}.md').read(), re.MULTILINE | re.DOTALL): - try: - exec(snippet, ns, ns) - except Exception as e: - print('ERROR:', e) - else: - for fignum in matplotlib.pyplot.get_fignums(): - with io.BytesIO() as f: - matplotlib.pyplot.figure(fignum).savefig(f, metadata=dict(Creator=None, Date=None, Format=None, Type=None)) - data = f.getvalue() - index += 1 - imgpath = f'src/{section}-fig{index}.svg' - images.append(imgpath) - with open(imgpath, 'wb') as f: - f.write(data) - matplotlib.pyplot.close('all') + for snippet in re.findall('^```python\n(.*?)^```$', open(f'src/{section}.md').read(), re.MULTILINE | re.DOTALL): + print(f'In {section}.md:') + for i, line in enumerate(snippet.splitlines(), start=1): + print(f'{i:2d}. {line}') + exec(snippet, ns, ns) + for fignum in matplotlib.pyplot.get_fignums(): + with io.BytesIO() as f: + matplotlib.pyplot.figure(fignum).savefig(f, metadata=dict(Creator=None, Date=None, Format=None, Type=None)) + data = f.getvalue() + index += 1 + imgpath = f'src/{section}-fig{index}.svg' + images.append(imgpath) + print('--> generating', imgpath) + with open(imgpath, 'wb') as f: + f.write(data) + matplotlib.pyplot.close('all') print(f'created {len(images)} images:') print('\n'.join(images))