husseinaluie / FlowSieve

FlowSieve coarse-graining code base
https://flowsieve.readthedocs.io/en/latest/
Other
18 stars 10 forks source link

The range to which coarse-grain is performed locally #34

Open Yizhaofeng opened 1 year ago

Yizhaofeng commented 1 year ago

Hello, everyone! I am confused about the searching range of the coarse-grain operation. Supposing filter scale = 100km and Kernel_opt = 4 which is a tanh kernel. I noticed that there is a Kernpad = 2.5, which is scale factor for kernel search radius. Does this mean that I am doing filtering in a range of 250km(100km*2.5) in diameter?Does this go against what I originally wanted to do filtering within 100km? Any reply and answer would be greatly appreciated!

bastorer commented 1 year ago

Hi :-)

The filter scale (ell) sets the kernel function, so ell = 100km with Kernel_opt = 4 gives a tanh kernel with a diameter of ~100km. The KernPad parameter sets how wide of an integration region is used to compute integral( f * G ) [ where f is the function being filtered and G is the kernel ]. Since generally ell << circumference of the Earth, there's a big computational savings by only integrating over a local region.

So, ell = 100km & KernPad = 2.5 means that the kernel has a diameter of 100km and the integration region has a diameter of 250km [outside of which the kernel is close enough to zero to be ignored].

Hope that helps!

Regards, Ben

Yizhaofeng commented 1 year ago

Thanks @bastorer. I want to see the final functional form of the convolution kernel (i.e. the mathematical representation of the kernel that ultimately participates in the convolution operation), which file should I refer to?

bastorer commented 1 year ago

The file Functions/kernel.cpp has the function definitions for the different kernel options.

Yizhaofeng commented 1 year ago

Thanks @bastorer. For scalar fields, the coarse-grained operation can be defined as integral( f * G ). I noticed that the complete coarse-graining formalism of Aluie (2019) is necessary for the general flow(e.g. up/down welling, divergent velocity field). 1.May I ask whether the velocity fields in the basic case and sphrical case are coarse-grained in its complete formalism of Aluie (2019)? 2.If I have the data generated from the ocean model, is it correct for me to coarse-grain according to the sphrical tutorial case or basic tutorial case?

bastorer commented 1 year ago
  1. The "basic case" tutorial works on a Cartesian grid, so the formalism from Aluie (2019) isn't necessary. The spherical tutorial cases, however, do require the Aluie (2019) formalism (in particular, the use of Helmholtz decompositions), and implement that methodology.
  2. Assuming that your ocean data is spherical (i.e. full globe, and not just a Cartesian 2D subset), then you would want to follow the spherical tutorial case.
Yizhaofeng commented 1 year ago

Thanks @bastorer :) I'm trying to change the basic case to one dimension(i.e. Ny = 1). After modifying the code that generates the data, I submit the filtering command. Before that, I concerned that such a change might not make the program work properly, it turns out that the program did report an error:

++ python generate_data.py generate_data.py:57: RuntimeWarning: divide by zero encountered in reciprocal powers[:,:Nx//2] = K[:,:Nx//2]*slope generate_data.py:70: RuntimeWarning: divide by zero encountered in double_scalars u_pert = U_pert / np.max(np.abs(u_pert)) generate_data.py:70: RuntimeWarning: invalid value encountered in multiply u_pert *= U_pert / np.max(np.abs(u_pert)) ++ mpirun -n 1 ./coarse_grain.x --input_file velocity_sample.nc --filter_scales '1e3 15e3 20e3 25e3 30e3 35e3 40e3 45e3 50e3 55e3 95e3 100e3 105e3' terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check

Then, I changed Ny to 2 again, this change will make the program work properly. But I still want to know whether this program can do one-dimensional case? I am sorry for keeping on asking questions.

Best regards Yi

bastorer commented 1 year ago

Hi Yi :-)

To be honest, I've never tried running FlowSieve one a 1D case. The methodology itself still applies, but, as the error that you ran into reveals, there are going to be places in the code where I've implicitly assumed that Nx>1 and Ny>1.

For a 1D case, my personal recommendation would be to just code up a filtering routine in Python. Having the high performance gain of compiled+parallel C++ isn't really necessary for a 1D problem, since the integration areas are so much smaller versus in 2D.

Regards, Ben

Yizhaofeng commented 1 year ago

Thanks again! @bastorer

I noticed in the spherical tutorial that the velocity is generated by the streamfunction and the potential function, and the streamfunction and the potential function need to be saved as variables to the netcdf file. If I only have a two dimension velocity field, I got variabels U and V, should I need to calculate steamfunction and potential function first before coarse-graining?

Having another way to ask this question: If I want to do coarse grain on the spherical data, which variables need to be stored in the input file?