\n", "\n", "Now that it is installed, you immediately try it out. There is a particular symmetric $2 \\times 2$ matrix-valued function whose difference of eigenvalues you have been wanting to plot for a long time $\\ldots$ finally, you can." ] }, { "cell_type": "code", "execution_count": null, "id": "44a93aae-e12a-4f23-b3e9-690e7127fa04", "metadata": {}, "outputs": [], "source": [ "from ngsolve import CF, Mesh, unit_square, x, y, Integrate\n", "import ngsolve_addon_template as addon\n", "from ngsolve.webgui import Draw\n", "\n", "mesh = Mesh(unit_square.GenerateMesh(maxh=0.3))\n", "A = CF( (1, y, # Matrix whose eigenvalues you desperately want\n", " y, x+5) ).Reshape((2,2))\n", "ews = addon.EigH(A) # Eigenvalues of A as a vector CF \n", "Draw(ews[0] - ews[1], mesh);" ] }, { "cell_type": "markdown", "id": "653271d3-2045-4023-9afb-492f2d5e580e", "metadata": {}, "source": [ "### You want more" ] }, { "cell_type": "markdown", "id": "0073e141-7a7a-4438-ac9d-2171692dcc12", "metadata": {}, "source": [ "As a typical ngsolve user, you have worked with many other [ngsolve coefficient functions](https://docu.ngsolve.org/latest/i-tutorials/unit-1.2-coefficient/coefficientfunction.html). So you know you can not only `Draw` them, but also evaluate them at a mesh point, see its expression tree, `Integrate` them, `Diff`erentiate them, etc.\n", "\n", "So you are surprised when `Diff` applied to this new eigenvalue coefficient function results in problems:" ] }, { "cell_type": "code", "execution_count": null, "id": "5a9220dd-7e84-4ea4-884b-f1d1b237e995", "metadata": {}, "outputs": [], "source": [ "try: \n", " dews = ews[0].Diff(x)\n", "\n", " if abs(Integrate(dews*dews, mesh)) < 1e-15: \n", " raise ValueError('Derivative is claimed to be 0')\n", "except Exception as e:\n", " print('EXCEPTION RAISED! Message:\\n', e) " ] }, { "cell_type": "markdown", "id": "43c8a318-81d4-417a-8176-2a04752fbf4a", "metadata": {}, "source": [ "

\n", "After you have recovered from this devastating news, you resolve to remedy this state of affairs. " ] }, { "cell_type": "markdown", "id": "de592325-e6cf-4d2c-9ae6-46be73db770c", "metadata": {}, "source": [ "### Identifying the issues\n", "\n", "Printing the expression tree of the eigenvalue coefficient funtion reveals one of the problems: `ews[0]` depends on `ews` as expected, but the dependence of `ews` on the input matrix `A` is not visible:" ] }, { "cell_type": "code", "execution_count": null, "id": "6ebe3af3-89d1-45a2-a447-a9afb1da9d0b", "metadata": {}, "outputs": [], "source": [ "print(ews[0])" ] }, { "cell_type": "markdown", "id": "269f29bc-31cd-4947-9604-73512d6b5901", "metadata": {}, "source": [ "Looking at NGSolve's source code [coefficient.cpp](https://github.com/NGSolve/ngsolve/blob/master/fem/coefficient.cpp#L277), \n", "you find the derivative returned is `ZeroCF` because the new eigenvalue coefficient function has no `InputCoefficientFunctions`. The lack of `InputCoefficientFunctions` is also the reason for the input matrix not showing up when you printed the expression tree.\n", "\n", "A simple fix would be to provide a definition for the virtual function \n", "```c++\n", "virtual Array