Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

errors during tdgl testing #69

Open
TJPhysics opened this issue Jan 24, 2024 · 40 comments
Open

errors during tdgl testing #69

TJPhysics opened this issue Jan 24, 2024 · 40 comments
Labels
resolved Issue has been resolved; keeping it open for reference

Comments

@TJPhysics
Copy link

I'm new to python and tdgl. After installing the software I ran the tdgl.testing program and it generated the following errors.

FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-0-5.0] - AssertionError
FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-0-] - AssertionError
FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-1-5.0] - AssertionError
FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-1-] - AssertionError

In scrolling through the code that is printed with the error I found this repeated every time.

      assert cupy is not None

E AssertionError

However, I did install cupy

python -m pip install -U setuptools pip
pip install cupy-cuda12x
pip install cuTENSOR.

but was unable to install the additional libraries like NCCL, etc
However, I'm not sure if that is really the problem. There are instructions to set tdgl.SolverOptions = True, but I'm not sure how to do that. I would assume it would default to the CPU if I didn't set it to TRUE?

Can anyone confirm that not installing those libraries is the problem? Anybody run into this problem and know how to fix it?

@loganbvh
Copy link
Owner

Can you open up Python and just try to import cupy?

import cupy

@loganbvh
Copy link
Owner

loganbvh commented Jan 24, 2024

The default value for tdgl.SolverOptions.gpu is False, so the solver will default to just using the CPU even if cupy is installed. The test failures you are seeing are test cases where SolverOption.gpu is explicitly set to True but for some reason cupy cannot be imported. So it would be good to know if you can import cupy at all, or if there is some issue with the cupy installation.

In any case, you can just work with SolverOptions.gpu = False and everything should work fine.

@TJPhysics
Copy link
Author

I was able to import cupy, but the same errors were generated.

I also set SolverOtion.gpu=False at the prompt and then ran tdgl.testing.run(). Again same errors...

@loganbvh
Copy link
Owner

Could you please run tdgl.version_dict() and paste the output here? Could you also copy and paste more of the text that's printed when the tests fail? I can't reproduce the test failures myself

image image

I also set SolverOtion.gpu=False at the prompt and then ran tdgl.testing.run()

What I meant is that using the default value of SolverOptions.gpu = False should work outside the context of running the tests (e.g. running your own simulation) even though those tests are failing. Setting SolverOptions.gpu at the prompt before running the tests doesn't do anything; the solver options are not global.

@TJPhysics
Copy link
Author

Here is the tdgl.version_dict() output

{'tdgl': '0.8.0;
git revision b779261 [2023-10-30]',
'Numpy': '1.26.3',
'SciPy': '1.10.1',
'matplotlib': '3.8.2',
'cupy': '13.0.0',
'numba': '0.58.1',
'IPython': '8.20.0',
'Python': '3.10.13 (main, Sep 11 2023, 13:44:35) [GCC 11.2.0]',
'OS': 'posix [linux]',
'Number of CPUs': 'Physical: 4, Logical: 8',
'BLAS Info': 'Generic'}

@TJPhysics
Copy link
Author

Here is a section of error output.

______________ test_source_drain_current[1-True-True-True-0-5.0] _______________

transport_device = Device(
'film',
layer=Layer(london_lambda=2, coherence_length=1, thickness=0.1, conductivity=None, u=5.79, ga...ray: shape=(101, 2)>, mesh=False)),
probe_points=array([[-10, 0],
[ 10, 0]]),
length_units='um',
)
current = 5.0
field = CompositeParameter<(constant_field_vector_potential(field_units='uT', length_units='um', Bz=0.0) * linear_ramp(time_dependent=True, initial=0.0, final=1.0, tmin=1, tmax=8))>
terminal_psi = 1, time_dependent = True, gpu = True, vectorized = True

@pytest.mark.parametrize("current", [5.0, lambda t: 10])
@pytest.mark.parametrize("field", [0, 1])
@pytest.mark.parametrize(
    "terminal_psi, time_dependent, gpu, vectorized",
    [(0, True, False, True), (1, False, False, False), (1, True, True, True)],
)
def test_source_drain_current(
    transport_device,
    current,
    field,
    terminal_psi,
    time_dependent,
    gpu,
    vectorized,
):
    device = transport_device
    total_time = 10
    skip_time = 1

    if gpu and cupy is None:
        options = tdgl.SolverOptions(
            solve_time=total_time,
            skip_time=skip_time,
            field_units="uT",
            current_units="uA",
            save_every=100,
            terminal_psi=terminal_psi,
            gpu=gpu,
        )
        with pytest.raises(SolverOptionsError):
            options.validate()
        return

    options = tdgl.SolverOptions(
        solve_time=total_time,
        skip_time=skip_time,
        field_units="uT",
        current_units="uA",
        save_every=100,
        terminal_psi=terminal_psi,
        gpu=gpu,
    )

    options.sparse_solver = "unknown"
    with pytest.raises(SolverOptionsError):
        options.validate()
    options.sparse_solver = "superlu"
    options.validate()

    if callable(current):

        def terminal_currents(t):
            return dict(source=current(0), drain=-current(0))

    else:
        terminal_currents = dict(source=current, drain=-current)

    with pytest.raises(ValueError):
        solution = tdgl.solve(
            device,
            options,
            disorder_epsilon=2,
            applied_vector_potential=field,
            terminal_currents=terminal_currents,
        )

    if vectorized:

        def disorder_epsilon(r):
            return 1.0 * np.ones(len(r))

    else:

        def disorder_epsilon(r):
            return 1.0

    if time_dependent:
        ramp = tdgl.sources.LinearRamp(tmin=1, tmax=8)
        constant_field = tdgl.sources.ConstantField(
            field,
            field_units=options.field_units,
            length_units=device.length_units,
        )
        field = ramp * constant_field
        field = constant_field * ramp

        _disorder_epsilon = disorder_epsilon

        def disorder_epsilon(r, *, t, vectorized=vectorized):
            return _disorder_epsilon(r)
  solution = tdgl.solve(
        device,
        options,
        disorder_epsilon=disorder_epsilon,
        applied_vector_potential=field,
        terminal_currents=terminal_currents,
    )

tdgl/test/test_solve.py:106:


tdgl/solver/solve.py:44: in solve
solver = TDGLSolver(
tdgl/solver/solver.py:270: in init
operators.build_operators()


self = <tdgl.finite_volume.operators.MeshOperators object at 0x7f53f5ddcb20>

def build_operators(self) -> None:
    """Construct the vector potential-independent operators."""
    mesh = self.mesh
    self.mu_laplacian, _ = build_laplacian(mesh, weights=self.laplacian_weights)
    self.mu_boundary_laplacian = build_neumann_boundary_laplacian(mesh)
    self.mu_gradient = build_gradient(mesh, weights=self.gradient_weights)
    self.divergence = build_divergence(mesh)
    if self.use_cupy:
      assert cupy is not None

E AssertionError

tdgl/finite_volume/operators.py:289: AssertionError
____________ test_source_drain_current[1-True-True-True-0-] ____________

transport_device = Device(
'film',
layer=Layer(london_lambda=2, coherence_length=1, thickness=0.1, conductivity=None, u=5.79, ga...ray: shape=(101, 2)>, mesh=False)),
probe_points=array([[-10, 0],
[ 10, 0]]),
length_units='um',
)
current = <function at 0x7f5411a47e20>
field = CompositeParameter<(constant_field_vector_potential(field_units='uT', length_units='um', Bz=0.0) * linear_ramp(time_dependent=True, initial=0.0, final=1.0, tmin=1, tmax=8))>
terminal_psi = 1, time_dependent = True, gpu = True, vectorized = True

@pytest.mark.parametrize("current", [5.0, lambda t: 10])
@pytest.mark.parametrize("field", [0, 1])
@pytest.mark.parametrize(
    "terminal_psi, time_dependent, gpu, vectorized",
    [(0, True, False, True), (1, False, False, False), (1, True, True, True)],
)
def test_source_drain_current(
    transport_device,
    current,
    field,
    terminal_psi,
    time_dependent,
    gpu,
    vectorized,
):
    device = transport_device
    total_time = 10
    skip_time = 1

    if gpu and cupy is None:
        options = tdgl.SolverOptions(
            solve_time=total_time,
            skip_time=skip_time,
            field_units="uT",
            current_units="uA",
            save_every=100,
            terminal_psi=terminal_psi,
            gpu=gpu,
        )
        with pytest.raises(SolverOptionsError):
            options.validate()
        return

    options = tdgl.SolverOptions(
        solve_time=total_time,
        skip_time=skip_time,
        field_units="uT",
        current_units="uA",
        save_every=100,
        terminal_psi=terminal_psi,
        gpu=gpu,
    )

    options.sparse_solver = "unknown"
    with pytest.raises(SolverOptionsError):
        options.validate()
    options.sparse_solver = "superlu"
    options.validate()

    if callable(current):

        def terminal_currents(t):
            return dict(source=current(0), drain=-current(0))

    else:
        terminal_currents = dict(source=current, drain=-current)

    with pytest.raises(ValueError):
        solution = tdgl.solve(
            device,
            options,
            disorder_epsilon=2,
            applied_vector_potential=field,
            terminal_currents=terminal_currents,
        )

    if vectorized:

        def disorder_epsilon(r):
            return 1.0 * np.ones(len(r))

    else:

        def disorder_epsilon(r):
            return 1.0

    if time_dependent:
        ramp = tdgl.sources.LinearRamp(tmin=1, tmax=8)
        constant_field = tdgl.sources.ConstantField(
            field,
            field_units=options.field_units,
            length_units=device.length_units,
        )
        field = ramp * constant_field
        field = constant_field * ramp

        _disorder_epsilon = disorder_epsilon

        def disorder_epsilon(r, *, t, vectorized=vectorized):
            return _disorder_epsilon(r)
  solution = tdgl.solve(
        device,
        options,
        disorder_epsilon=disorder_epsilon,
        applied_vector_potential=field,
        terminal_currents=terminal_currents,
    )

tdgl/test/test_solve.py:106:

@TJPhysics
Copy link
Author

Here is the warning summary
=============================== warnings summary ===============================
tdgl/test/test_visualization.py: 144 warnings
~/Documents/py-tdgl/tdgl/solution/plot_solution.py:253: DeprecationWarning: Calling nonzero on 0d arrays is deprecated, as it behaves surprisingly. Use atleast_1d(cond).nonzero() if the old behavior was intended. If the context of this warning is of the form arr[nonzero(cond)], just use arr[cond].
ix = np.where(~solution.device.contains_points(xy)[0])

tdgl/test/test_visualize.py::test_interactive[True-False-None]
tdgl/test/test_visualize.py::test_interactive[True-True-None]
tdgl/test/test_visualize.py::test_interactive[False-False-None]
tdgl/test/test_visualize.py::test_interactive[False-True-None]
~/Documents/py-tdgl/tdgl/visualization/interactive.py:144: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown
plt.show()

tdgl/test/test_visualize.py: 40 warnings
~/Documents/py-tdgl/tdgl/visualization/interactive.py:286: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown
plt.show()

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-0-5.0] - AssertionError
FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-0-] - AssertionError
FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-1-5.0] - AssertionError
FAILED tdgl/test/test_solve.py::test_source_drain_current[1-True-True-True-1-] - AssertionError
=========== 4 failed, 780 passed, 188 warnings in 2789.29s (0:46:29) ===========

@loganbvh
Copy link
Owner

It looks like the problem is these lines:

try:
import cupy # type: ignore
from cupyx.scipy.sparse import csc_matrix, csr_matrix # type: ignore
from cupyx.scipy.sparse.linalg import factorized # type: ignore
except ImportError:
cupy = None

I am guessing that import cupy works but one of the other two imports fails. Can you open up a Python session and try the following?

from cupyx.scipy.sparse import csc_matrix, csr_matrix
from cupyx.scipy.sparse.linalg import factorized

@TJPhysics
Copy link
Author

TJPhysics commented Jan 26, 2024

We're reaching the limit of my shallow knowledge of Python. What do you mean by "...try the following?" Do you want me to edit the source code?

@loganbvh
Copy link
Owner

loganbvh commented Jan 26, 2024

I want to check if you can import the necessary modules related to cupy. Just open up a Python interpreter or Jupyter notebook in the same environment that you installed tdgl, run those two lines, and see if you get an error.

python
>>> from cupyx.scipy.sparse import csc_matrix, csr_matrix
>>> from cupyx.scipy.sparse.linalg import factorized

@TJPhysics
Copy link
Author

Ah ok, here you go.

from cupyx.scipy.sparse.linalg import factorized
Traceback (most recent call last):
File "", line 1, in
File "/home/TJPhysics/miniconda3/envs/tdgl/lib/python3.10/site-packages/cupyx/scipy/sparse/linalg/init.py", line 6, in
from cupyx.scipy.sparse.linalg._solve import spsolve # NOQA
File "/home/TJPhysics/miniconda3/envs/tdgl/lib/python3.10/site-packages/cupyx/scipy/sparse/linalg/_solve.py", line 4, in
from cupy import cublas
File "/home/TJPhysics/miniconda3/envs/tdgl/lib/python3.10/site-packages/cupy/cublas.py", line 8, in
from cupy_backends.cuda.libs import cublas
ImportError: libcublas.so.12: cannot open shared object file: No such file or directory

@loganbvh
Copy link
Owner

Thanks! I think the problem may be that the location of the CUDA libraries is not in the LD_LIBRARY_PATH environment variable. If you installed cupy and tdgl in a conda environment, I would suggest running export LD_LIBRARY_PATH=${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH} in your terminal before starting python, then try the imports again. $CONDA_PREFIX is the path to the directory containing the current conda environment.

export LD_LIBRARY_PATH=${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH}
python
>>> from cupyx.scipy.sparse import csc_matrix, csr_matrix
>>> from cupyx.scipy.sparse.linalg import factorized

@loganbvh
Copy link
Owner

If the above works, then you can add the updated LD_LIBRARY_PATH to your shell configuration (e.g. .bashrc file) so that you don't have to do it manually each time you want to use cupy https://www.geeksforgeeks.org/how-to-set-the-environmental-variable-ld_library_path-in-linux/.

For example on my system, I would run

(base) loganbvh ~ % conda activate tdgl
(tdgl) loganbvh ~ % echo $CONDA_PREFIX
/Users/loganbvh/miniforge3/envs/tdgl
(tdgl) loganbvh ~ % export 'LD_LIBRARY_PATH=/Users/loganbvh/miniforge3/envs/tdgl/lib:$LD_LIBRARY_PATH' >> ~/.bashrc

@TJPhysics
Copy link
Author

Hmmm...still same errors.

When i printenv LD_LIBRARY_PATH I get /home/TJPhysics/miniconda3/envs/tdgl/lib

If I try to change the path to anything else I get a "bad substitution" response

@TJPhysics
Copy link
Author

TJPhysics commented Jan 26, 2024

I think the "bad substitution error" was because I wasn't using the CONDA_PREFIX variable. I can assign any path to the CONDA_PREFIX variable and then, export LD_LIBRARY_PATH=${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH}. Got it.

However, I'm still not sure what path to assign it. What do you mean by "the directory containing the current conda environment"? How would I figure that out?

@loganbvh
Copy link
Owner

loganbvh commented Jan 26, 2024

Sorry I wasn't clear. $CONDA_PREFIX will be set automatically when you activate a conda environment. On my system it looks like this

(base) loganbvh@Logans-MacBook-Pro-2 ~ % echo $CONDA_PREFIX
/Users/loganbvh/miniforge3
(base) loganbvh@Logans-MacBook-Pro-2 ~ % conda activate tdgl
(tdgl) loganbvh@Logans-MacBook-Pro-2 ~ % echo $CONDA_PREFIX
/Users/loganbvh/miniforge3/envs/tdgl

Which linux distribution are you using? And what is the output of echo $CUDA_PATH?

@loganbvh
Copy link
Owner

Just to reiterate what I said above, you don't need a working installation of cupy to use tdgl. If you just want to get started with tdgl, you can ignore those four failing tests and everything should run fine on the CPU as long as you don't set SolverOptions.gpu = True.

If you end up working with large tdgl models that would benefit from GPU acceleration, then it may be worth further trying to track down this issue with your cupy installation.

@loganbvh
Copy link
Owner

Do you have CUDA Toolkit installed as listed in the requirements for cupy (https://docs.cupy.dev/en/stable/install.html#requirements)? If not, you can install it in your tdgl conda environment using conda (https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#conda-installation)

conda install cuda -c nvidia

@TJPhysics
Copy link
Author

loganbvh, answering your comments from top to bottom.

  1. I am using Ubuntu 22.04.3 LTS
    echo $CUDA_PATH shows nothing!
  2. Ok, thank you for reiterating this. It would be nice to a) use CUDA and b) get rid of errors, so that if more errors pop up they don't get lost in the background of errors.
  3. I was able to partly follow those instructions for installing cupy.
    I did this: python -m pip install -U setuptools pip
    and then this: pip install cupy-cuda12x
    I was also able to install cuTENSOR: pip install cuTENSOR
    but not NCCL or cuDNN or cuSPARSELt

Since that produced problems I tried: conda install -c conda-forge -cupy
The error now is :Error while loading conda entry point: conda-libmamba-solver (libarchive.so.19: cannot open shared object file: No such file or directory)

However, I did set up conda as described at the beginning of the install instructions without any problems. If I repeat those commands, here is what I get:

conda create --name tdgl python="3.10"
Error while loading conda entry point: conda-libmamba-solver (libarchive.so.19: cannot open shared object file: No such file or directory)
WARNING: A conda environment already exists at '/home/tom/miniconda3/envs/tdgl'
Remove existing environment (y/[n])?

If I say no

(tdgl) tom@tom-Nitro-AN515-54:/Documents/py-tdgl$ conda activate tdgl
(tdgl) tom@tom-Nitro-AN515-54:
/Documents/py-tdgl$ conda install -c conda-forge cupy

Error while loading conda entry point: conda-libmamba-solver (libarchive.so.19: cannot open shared object file: No such file or directory)
CondaValueError: You have chosen a non-default solver backend (libmamba) but it was not recognized. Choose one of: classic

@TJPhysics
Copy link
Author

I'm not sure why certain things got crossed out above...

@loganbvh
Copy link
Owner

Thanks, and sorry for the barrage of questions. I am not a CUDA expert and I don't have a GPU in my personal computer (it's a MacBook), so debugging this sort of problem is difficult. To easily access a Linux machine with a GPU I have to use Google Colab.

This is my understanding of the correct steps for installing tdgl with cupy:

  1. Create env: conda create --name tdgl python="3.10"
  2. Activate env: conda activate tdgl
  3. Install CUDA Toolkit: conda install cuda -c nvidia
  4. Install tdgl: pip install tdgl (or install from Git repo)
  5. Install cupy: pip install cupy-cuda12x
  6. Start Python and try import cupy and from cupyx.scipy.sparse import csc_matrix, csr_matrix to verify cupy and CUDA are installed correctly
  7. If (6) doesn't work, you may need to add export LD_LIBRARY_PATH=${CONDA_PREFIX}/lib:${LD_LIBRARY_PATH} to .bashrc, or execute the command in the terminal prior to starting Python

@TJPhysics
Copy link
Author

TJPhysics commented Jan 26, 2024

"Error while loading conda entry point: conda-libmamba-solver (libarchive.so.19: cannot open shared object file: No such file or directory)"

Any thoughts as to what this might mean?

This keeps coming up

conda install cuda -c nvidia
Error while loading conda entry point: conda-libmamba-solver (libarchive.so.19: cannot open shared object file: No such file or directory)

CondaValueError: You have chosen a non-default solver backend (libmamba) but it was not recognized. Choose one of: classic

@loganbvh
Copy link
Owner

I have not seen this error before, but it looks like it is a known issue with conda (conda/conda-libmamba-solver#283) and it may be fixed by re-installing a library called libarchive (source):

conda install -n base libarchive -c main --force-reinstall

@TJPhysics
Copy link
Author

Same error as above with: conda install -n base libarchive -c main --force-reinstall
whether i'm in or out of my tdgl environment.

@loganbvh
Copy link
Owner

It seems like your conda installer is just not working at all for some reason. Can you check whether you have CUDA installed at all by running "nvcc --version" in a terminal?

If that command succeeds, it means CUDA is installed. In that case, verify that the CUDA version is compatible with the version of cupy you installed

If the command produces an error, it means CUDA is not installed. In that case, I you can just download CUDA Toolkit directly from the Nvidia website: https://developer.nvidia.com/cuda-toolkit. This will do a global install on your system (I think), whereas installing CUDA with conda is required if you want to have different CUDA versions for different conda environments.

@TJPhysics
Copy link
Author

Wow, nothing is working!
nvcc --version

Command 'nvcc' not found, but can be installed with:
sudo apt install nvidia-cuda-toolkit

I tried installing directly from the NVIDIA website 1st. Everything went smoothly. But no change when I type the nvcc --version command. So I tried sudo apt install nvidia-cuda-toolkit

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
libcuinj64-11.5 : Depends: libnvidia-compute-495 (>= 495) but it is not going to be installed or
libnvidia-compute-495-server (>= 495) but it is not installable or
libcuda.so.1 (>= 495) or
libcuda-11.5-1
libnvidia-ml-dev : Depends: libnvidia-compute-495 (>= 495) but it is not going to be installed or
libnvidia-compute-495-server (>= 495) but it is not installable or
libnvidia-ml.so.1 (>= 495)
nvidia-cuda-dev : Depends: libnvidia-compute-495 (>= 495) but it is not going to be installed or
libnvidia-compute-495-server (>= 495) but it is not installable or
libcuda.so.1 (>= 495) or
libcuda-11.5-1
Recommends: libnvcuvid1 but it is not installable
E: Unable to correct problems, you have held broken packages.

I appreciate you trying to figure this out. As you said, its not really an issue for you since you don't have an NVIDIA graphics card. Has anybody made CUDA work for the tdgl program?

@loganbvh
Copy link
Owner

loganbvh commented Jan 26, 2024

I tried installing directly from the NVIDIA website 1st. Everything went smoothly. But no change when I type the nvcc --version command.

If you installed CUDA directly from the NVIDIA website and the nvcc command is not found, I think there is just an issue with the environment variables pointing to the CUDA installation. All you should need to do is figure out where CUDA was installed (e.g. I think the default is /usr/local/cuda/) and update $PATH and $LD_LIBRARY_PATH accordingly. For example (https://askubuntu.com/questions/885610/nvcc-version-command-says-nvcc-is-not-installed):

export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}$ 
export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

If that works, you will want to add those lines to .bashrc so they are run automatically when you start a terminal.

Has anybody made CUDA work for the tdgl program?

This is not a problem with cupy or tdgl. I have successfully run tdgl with NVIDIA GPUs many times (just not on my personal/development laptop). The issue is just that you are missing a critical dependency of cupy (the CUDA Toolkit), which cannot be installed automatically by either cupy or tdgl. The way I would normally recommend installing the CUDA Toolkit is using conda (#69 (comment)), but for some reason conda is not working properly on your system so installing CUDA from the NVIDIA website is the other option.

@TJPhysics
Copy link
Author

Updating the path was the trick to getting rid of those errors. Thanks for the help on that. Now I'm just getting warnings. I know I can run with the warnings, but I thought I'd check to see if there were any easy fixes.

tdgl/test/test_visualization.py: 144 warnings
/home/TJPhysics/Documents/py-tdgl/tdgl/solution/plot_solution.py:253: DeprecationWarning: Calling nonzero on 0d arrays is deprecated, as it behaves surprisingly. Use atleast_1d(cond).nonzero() if the old behavior was intended. If the context of this warning is of the form arr[nonzero(cond)], just use arr[cond].
ix = np.where(~solution.device.contains_points(xy)[0])

tdgl/test/test_visualize.py::test_interactive[True-False-None]
tdgl/test/test_visualize.py::test_interactive[True-True-None]
tdgl/test/test_visualize.py::test_interactive[False-False-None]
tdgl/test/test_visualize.py::test_interactive[False-True-None]
/home/TJPhysics/Documents/py-tdgl/tdgl/visualization/interactive.py:144: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown
plt.show()

tdgl/test/test_visualize.py: 40 warnings
/home/TJPhysics/Documents/py-tdgl/tdgl/visualization/interactive.py:286: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown
plt.show()

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================== 784 passed, 188 warnings in 2777.98s (0:46:17) ===================

@loganbvh
Copy link
Owner

Great, thanks for letting me know. I will update the documentation with more detailed instructions on installing cupy and CUDA. I will also update the code to prevent those warnings and let you know when the new version is available (should be no more than a day or two).

@TJPhysics
Copy link
Author

TJPhysics commented Jan 30, 2024

Would you be willing to field some basic questions about the Quickstart examples? I'm not sure if this is the venue. I think they are Python related more than physics.

@loganbvh
Copy link
Owner

Sure, no problem

@TJPhysics
Copy link
Author

I'm following your Quickstart guide, and I'm working at the command line in a linux shell (not Colab). I'm entering your commands as given, and that seems to be working until I arrive at the command numer [8]: fig, ax = device.draw() which I think is supposed to generate the picture immediately below it on the webpage, correct? If so I don't generate anything. What is going on here?

@loganbvh
Copy link
Owner

loganbvh commented Jan 30, 2024

The most widely used Python graphing library is matplotlib and most of the functions needed for plotting exist under the matplotlib.pyplot module. The command import matplotlib.pyplot as plt imports this module and assigns it the name plt. When using Python from the command line, matplotlib figures are not shown automatically. You can turn on the matplotlib "interactive mode" by calling plt.ion() (ref.). In interactive mode, figures should be shown and updated automatically. You can turn off interactive mode by calling plt.ioff(). You can also call plt.show() to show all figures.

One popular interface for Python, aside from the command line, is Jupyter. The Quickstart example in the documentation is one of these Jupyter notebooks: https://github.com/loganbvh/py-tdgl/blob/main/docs/notebooks/quickstart.ipynb. Jupyter is a dependency of tdgl, so it will already be installed in your tdgl environment. You can start a Jupyter server locally by calling jupyter notebook from the command line. This will open up a tab/window in your web browser with a user interface to navigate the file system or create a new notebook.

If you have cloned the py-tdgl repository from GitHub, you can run jupyter notebook in the command line from the py-tdgl directory, then navigate in the browser to py-tdgl/tdgl/docs/notebooks/. There you can directly open and run the quickstart.ipynb notebook yourself. All of the tutorials in the documentation were designed to be run from a Jupyter notebook.

@TJPhysics
Copy link
Author

Great! That all worked. I will probably start using Jupyter. In the mean time if I want to see the Mesh Stats [11]: device.mesh_stats() is there a way to do that from the command line or do I need to be in Jupyter. It looks like it is trying to generate some html.

@loganbvh
Copy link
Owner

You can call device.mesh_stats_dict()

@TJPhysics
Copy link
Author

TJPhysics commented Jan 31, 2024

I am running into an error at section 18 of the quickstart guide:

When I enter this code

if MAKE_ANIMATIONS:
zero_field_video = make_video_from_solution(
zero_field_solution,
quantities=["order_parameter", "phase", "scalar_potential"],
figsize=(6.5, 4),
)
display(zero_field_video)

I get this error


RuntimeError Traceback (most recent call last)
Cell In[19], line 2
1 if MAKE_ANIMATIONS:
----> 2 zero_field_video = make_video_from_solution(
3 zero_field_solution,
4 quantities=["order_parameter", "phase", "scalar_potential"],
5 figsize=(6.5, 4),
6 )
7 display(zero_field_video)

Cell In[4], line 16, in make_video_from_solution(solution, quantities, fps, figsize)
9 with h5py.File(solution.path, "r") as h5file:
10 anim = create_animation(
11 h5file,
12 quantities=quantities,
13 fps=fps,
14 figure_kwargs=dict(figsize=figsize),
15 )
---> 16 video = anim.to_html5_video()
17 return HTML(video)

File ~/.local/lib/python3.10/site-packages/matplotlib/animation.py:1285, in Animation.to_html5_video(self, embed_limit)
1282 path = Path(tmpdir, "temp.m4v")
1283 # We create a writer manually so that we can get the
1284 # appropriate size for the tag
-> 1285 Writer = writers[mpl.rcParams['animation.writer']]
1286 writer = Writer(codec='h264',
1287 bitrate=mpl.rcParams['animation.bitrate'],
1288 fps=1000. / self._interval)
1289 self.save(str(path), writer=writer)

File ~/.local/lib/python3.10/site-packages/matplotlib/animation.py:148, in MovieWriterRegistry.getitem(self, name)
146 if self.is_available(name):
147 return self._registered[name]
--> 148 raise RuntimeError(f"Requested MovieWriter ({name}) not available")

RuntimeError: Requested MovieWriter (ffmpeg) not available

I installed ffmpeg using pip. The error change slightly. It says, "UserWarning: Animation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. anim, that exists until you output the Animation using plt.show() or anim.save().
warnings.warn("

It still highlights the same sections of code, and says that ffmpeg is not available.

@TJPhysics
Copy link
Author

I cut and paste out of the Jupyter notebook so I lost the indentation. Also there are sections of the code highlighted but I'm not sure how to communicate that

@loganbvh
Copy link
Owner

Installing the ffmpeg Python package from pip doesn't actually install the ffmpeg library (ref.). You need to install ffmpeg using your system package manager, e.g. sudo apt install ffmpeg.

The function make_video_from_solution() generates an HTML5 video that will only be displayed in a Jupyter notebook. You can update the function as follows to instead save a video in MP4 format. The variable anim refers to a matplotlib.animation.FuncAnimation object https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.FuncAnimation.html.

def make_mp4_video_from_solution(
    solution,
    output_file="output.mp4",
    quantities=("order_parameter", "phase"),
    fps=20,
    figsize=(5, 4),
):
    """Saves an MP4 video from a tdgl.Solution."""
    with tdgl.non_gui_backend():
        with h5py.File(solution.path, "r") as h5file:
            anim = create_animation(
                h5file,
                quantities=quantities,
                fps=fps,
                figure_kwargs=dict(figsize=figsize),
            )
            anim.save(output_file)

Then you can call the following and view the resulting MP4 file in whatever video application you'd like.

if MAKE_ANIMATIONS:
    make_mp4_video_from_solution(
        zero_field_solution,
        output_file="cell18.mp4",
        quantities=["order_parameter", "phase", "scalar_potential"],
        figsize=(6.5, 4),
    )

@loganbvh
Copy link
Owner

I started a PR with more detailed instructions in the documentation for installing CUDA: https://py-tdgl--70.org.readthedocs.build/en/70/installation.html#gpu-acceleration

Want to take a look and let me know if you think there's anything that needs further clarification?

@TJPhysics
Copy link
Author

All of that worked! Got through the Quickstart. Thanks for all your help in getting me started.

@loganbvh loganbvh added the resolved Issue has been resolved; keeping it open for reference label Jan 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolved Issue has been resolved; keeping it open for reference
Projects
None yet
Development

No branches or pull requests

2 participants