How can a spectral reaction diffusion solver be written on Shadertoy? - numerical-methods

Even with a 20 point Laplacian operator there are still coordinate system artifacts with a circularly symmetric seed.
That is one reason to try a spectral solver.
The main code for the above mentioned simplest Laplacian with a forward Euler solver is:
#define A(U) texture(iChannel0,(U)/iResolution.xy)
void mainImage( out vec4 Q, in vec2 U )
{
// Lookup Field
Q = A(U);
// Mean Field
// Two way: horizontal, vertical
vec4 sum2 = A(U+vec2(0,1))+A(U+vec2(1,0))+A(U-vec2(0,1))+A(U-vec2(1,0));
vec4 mean2 = 1./4.*(sum2);
// Laplacian
vec4 laplacian2 = (mean2 - Q);
// Diffuse each variable differently :
Q += laplacian2 * vec4(1, .4, 1, 1);
// Compute reactions:
Q.x = Q.x * .99 + 0.01 * Q.y;
Q.y = Q.y + .05 * Q.y * (1. - Q.y) - .03 * Q.x - 1e-3;
// Prevent Negative Values (depends on system):
Q = max(Q, 0.);
}
How can this be rewritten to a spectral solver on Shadertoy?

Related

Gradient descent getting wrong linear regression - Octave

I'm trying to make my own project, learning about linear regression.
For some reasone I got wrong linear regression.
I've tried changing alfa values and iterations but it didnt help.
I was checking also for other advices here but I couldnt make it.
GRADIENT DESCENT
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)
%GRADIENTDESCENT Performs gradient descent to learn theta
% theta = GRADIENTDESCENT(X, y, theta, alpha, num_iters) updates theta by
% taking num_iters gradient steps with learning rate alpha
% Initialize some useful values
m = length(y); % number of training examples
J_history = zeros(num_iters, 1);
for iter = 1:num_iters
x = X(:,2);
h = theta(1) + (theta(2) * x);
theta_zero = theta(1) - alpha * (1/m) * sum(h-y); %a-step*gradient(1)
theta_one = theta(2) - alpha * (1/m) * sum((h - y) .* x); %b-step*gardient(2)
theta = [theta_zero; theta_one];
J_history(iter) = computeCost(X, y, theta);
end
end
MAIN CODE
clear ; close all; clc
%% ======================= Part 2: Plotting =======================
fprintf('Plotting Data ...\n')
data = csvread('Fish.txt');
X = data(:, 1); y = data(:, 2);
m = length(y); % number of training examples
figure;
plot(X, y, 'dp', 'MarkerSize', 5);
title('Wykres')
fprintf('Program paused. Press enter to continue.\n');
pause;
%% =================== Part 3: Gradient descent ===================
fprintf('Running Gradient Descent ...\n')
X = [ones(m, 1), data(:,1)]; % Add a column of ones to x
%disp(X)
theta = zeros(size(X, 2), 1); % initialize fitting parameters
% Some gradient descent settings
iterations = 1500;
alpha = 0.000001;
% compute and display initial cost
computeCost(X, y, theta)
% run gradient descent
theta = gradientDescent(X, y, theta, alpha, iterations);
% print theta to screen
fprintf('Theta found by gradient descent: ');
fprintf('%f %f \n', theta(1), theta(2));
% Plot the linear fit
hold on; % keep previous plot visible
plot(X(:,2), X*theta, '-')
legend('Training data', 'Linear regression')
hold off % don't overlay any more plots on this figure
FILE
Fish.txt
First column is weight, second is length
242,23.2
290,24
340,23.9
363,26.3
430,26.5
450,26.8
500,26.8
390,27.6
450,27.6
500,28.5
475,28.4
500,28.7
500,29.1
340,29.5
600,29.4
600,29.4
700,30.4
700,30.4
610,30.9
650,31
575,31.3
685,31.4
620,31.5
680,31.8
700,31.9
725,31.8
720,32
714,32.7
850,32.8
1000,33.5
920,35
955,35
925,36.2
975,37.4
950,38
40,12.9
69,16.5
78,17.5
87,18.2
120,18.6
0,19
110,19.1
120,19.4
150,20.4
145,20.5
160,20.5
140,21
160,21.1
169,22
161,22
200,22.1
180,23.6
290,24
272,25
390,29.5
270,23.6
270,24.1
306,25.6
540,28.5
800,33.7
1000,37.3
55,13.5
60,14.3
90,16.3
120,17.5
150,18.4
140,19
170,19
145,19.8
200,21.2
273,23
300,24
5.9,7.5
32,12.5
40,13.8
51.5,15
70,15.7
100,16.2
78,16.8
80,17.2
85,17.8
85,18.2
110,19
115,19
125,19
130,19.3
120,20
120,20
130,20
135,20
110,20
130,20.5
150,20.5
145,20.7
150,21
170,21.5
225,22
145,22
188,22.6
180,23
197,23.5
218,25
300,25.2
260,25.4
265,25.4
250,25.4
250,25.9
300,26.9
320,27.8
514,30.5
556,32
840,32.5
685,34
700,34
700,34.5
690,34.6
900,36.5
650,36.5
820,36.6
850,36.9
900,37
1015,37
820,37.1
1100,39
1000,39.8
1100,40.1
1000,40.2
1000,41.1
200,30
300,31.7
300,32.7
300,34.8
430,35.5
345,36
456,40
510,40
540,40.1
500,42
567,43.2
770,44.8
950,48.3
1250,52
1600,56
1550,56
1650,59
6.7,9.3
7.5,10
7,10.1
9.7,10.4
9.8,10.7
8.7,10.8
10,11.3
9.9,11.3
9.8,11.4
12.2,11.5
13.4,11.7
12.2,12.1
19.7,13.2
19.9,13.8
Thank you in advance!
I tried using standard deviation and Ive replaced
theta = zeros(2, 1);
for
theta = zeros(size(X, 2), 1);
I've also changed values of alpha

How to fix: "anonymous function bodies must be single expressions" error on Octave

I am trying to make a function in Octave where you give octave a function f(x,y) as a string, a change in X, a change in Y, a starting point, and the size of a matrix, the function will create a matrix populated with the values of f(x,y) at each point in the matrix.
This is for an application that displays a 3d graph, using the matrix to map each value to a block
# funcStr: The function whose Z values are being calculated
# dx: the change in x that each block in the x direction represents
# dy: the change in y that each block in the y direction represents
# startPt: the point (in an array of x, y) that center block represents
# res: the side length (in blocks) of the plane
pkg load symbolic
syms x y
function[zValues] = calculateZValues(funcStr, dx, dy, startPt, res)
zValues = zeros(res);
eqn = #(x, y) inline(funcStr);
startX = startPt{1};
startY = startPt{2};
for yOffset = 1:res
for xOffset = 1:res
xCoord = startX + dx * xOffset;
yCoord = startY + dy * yOffset;
zValues(res * yOffset + xOffset) = double(subs(eqn, #(x, y), {xCoord, yCoord}));
endfor
endfor
endfunction
The error I am getting is:
>> calculateZValues("x*y", 1, 1, {0,0}, 10)
parse error near line 20 of file /home/rahul/Documents/3dGraph/graph/calculateZValues.m
anonymous function bodies must be single expressions
>>> zValues(res * yOffset + xOffset) = double(subs(eqn, #(x, y), {xCoord, yCoord}));
I have no idea what the issue is. I have replaced the #(x,y) part with {x,y} in the line referenced by the error but it says nothing or it raises an error about the function subs not being declared. I have also tried moving the pkg and syms lines above the function header

Chrome not handling multiple floats in WebGL buffer? Fine in Firefox

I am working with a buffer that passes in a few different elements, below is a crude diagram of where each element appears in the buffer:
pos col amb dif spe nor uv t a s
+---+---+---+---+---+---+--+-+-+-+
0 3 6 9 1 1 1 2 2 2 2
2 5 8 0 1 2 3
Where
pos - the vertex (3 floats)
col - the color at that vertex (note, this is a legacy variable that is unused(3 floats)
amb - the ambient RGB reflection of the model (3 floats)
dif - the diffuse RGB reflection of the model (3 floats)
spe - the specular RGB reflection of the model (3 floats)
nor - the normals of the model (3 floats)
uv - the uv coordinates to the mapped texture (2 floats)
t - a pointer to which texture to load (a float)
a - the transparency (alpha) of the model (a float)
s - the specular exponent (a float)
My buffer looks something like this:
// stride = how many floats to skip each round (times 4)
stride = 23 * 4;
// Last parameter = where this attribute starts in the buffer
GL.vertexAttribPointer(_position, 3, GL.FLOAT, false, stride, 0 * 4) ;
GL.vertexAttribPointer(_color, 3, GL.FLOAT, false, stride, 3 * 4) ;
GL.vertexAttribPointer(_ambient, 3, GL.FLOAT, false, stride, 6 * 4) ;
GL.vertexAttribPointer(_diffuse, 3, GL.FLOAT, false, stride, 9 * 4) ;
GL.vertexAttribPointer(_specular, 3, GL.FLOAT, false, stride, 12 * 4) ;
GL.vertexAttribPointer(_normals, 3, GL.FLOAT, false, stride, 15 * 4) ;
GL.vertexAttribPointer(_uvs, 2, GL.FLOAT, false, stride, 18 * 4) ;
GL.vertexAttribPointer(_tex, 1, GL.FLOAT, false, stride, 20 * 4) ;
GL.vertexAttribPointer(_a, 1, GL.FLOAT, false, stride, 21 * 4) ;
GL.vertexAttribPointer(_shine, 1, GL.FLOAT, false, stride, 22 * 4) ;
All three floats are being passed the same way in the vertex shader:
attribute float tex;
attribute float a;
attribute float shine;
...
varying float vTex;
varying float vA;
varying float vShine;
void main(void) {
...
vTex = tex;
vA = a;
vShine = shine;
I'm passing everything fine, literally copy/pasted the _tex code for _a and _shine. No errors are popping up and if I print the array containing all these values, everything is getting stored properly. Likewise, _tex is being used inside the fragment shader without error.
void main(void) {
vec4 texColor;
//Ambient
vec4 Ia = La * Ka;
// Diffuse
vec4 Id = Kd;
vec3 lightDirection = normalize(world_light - vertex);
vec3 L = normalize(lightDirection - world_pos);
vec3 N = normalize(world_norm);
float lambert = max(0.0, dot(N, -L));
Id = Kd*Ld*lambert;
// Specular
vec4 Is = Ks;
vec3 V = normalize(vertex - world_pos);
vec3 H = normalize(L + V);
float NdotH = dot(N, H);
NdotH = max(NdotH, 0.0);
NdotH = pow(NdotH, 10.0);
// NdotH = pow(NdotH, vShine); <-------------------------------- ERRORS
Is = Ks*Ls*NdotH;
if (vTex < 0.1) {
vec4 texColor = texture2D(texture01, vUV);
gl_FragColor = vec4(texColor.rgb, texColor.a);
} else if (vTex < 1.1) {
vec4 texColor = texture2D(texture02, vUV);
gl_FragColor = vec4(texColor.rgb, texColor.a);
} else if (vTex < 2.1) {
vec4 texColor = texture2D(texture03, vUV);
gl_FragColor = vec4(texColor.rgb, texColor.a);
} else {
vec4 texColor = texture2D(texture04, vUV);
gl_FragColor = vec4(texColor.rgb, texColor.a);
}
gl_FragColor = gl_FragColor * (Ia*A) + (Id*D) + (Is*S);
The second I flip to NdotH = pow(NdotH, vShine);, Chrome's WebGL will crash with the following error message:
VM258:1958 WebGL: INVALID_OPERATION: getUniformLocation: program not linked(anonymous function) # VM258:1958
gl.getUniformLocation # VM258:4629
main # texturize.js:569
onload # (index):26
VM258:1958 WebGL: INVALID_OPERATION: getUniformLocation: program not linked(anonymous function) # VM258:1958
gl.getUniformLocation # VM258:4629
main # texturize.js:570
onload # (index):26
This is obviously the confusing part, as the floats are attributes, not uniforms. Again, loading in Firefox is fine, but I am trying to understand what is causing problems on the Chrome front and what the resolution is without having to refactor.
I'm hesitant to post full code, as this is a class assignment.
Thanks!
So I found the issue, it is specifically a limitation to Chrome's cap on Max Varying Vectors, discovered via here: https://www.browserleaks.com/webgl
The issue on why Chrome cannot handle things is I am pushing to many different vectors to a single buffer, while Firefox can handle 30, Chrome can only handle 9. Since I am at this cusp, that is where my error is coming from.

Solving two coupled non-linear second order differentially equations numerically

I have encountered the following system of differential equations in lagrangian mechanics. Can you suggest a numerical method, with relevant links and references on how can I solve it. Also, is there a shorter implementation on Matlab or Mathematica?
mx (y dot)^2 + mgcosy - Mg - (M=m)(x double dot) =0
gsiny + 2(x dot)(y dot + x (y double dot)=0
where (x dot) or (y dot)= dx/dt or dy/dt, and the double dot indicated a double derivative wrt time.
You can create a vector Y = (x y u v)' so that
dx/dt = u
dy/dt = v
du/dt = d²x/dt²
dv/dt = d²y/dt²
It is possible to isolate the second derivatives from the equations, so you get
d²x/dt² = (m*g*cos(y) + m*x*v² - M*g)/(M-m)
d²y/dt² = -(g*sin(y) - 2*u*v)/x
Now, you can try to solve it using standard ODE solvers, such as Runge-Kutta methods. Matlab has a set of solvers, such as ode23. I didn't test he following, but it would be something like it:
function f = F(Y)
x = Y(1); y = Y(2); u = Y(3); v = Y(4);
f = [0,0,0,0];
f(1) = u;
f(2) = v;
f(3) = (m*g*cos(y) + m*x*v*v - M*g)/(M-m);
f(4) = -(g*sin(y) - 2*u*v)/x;
[T,Y] = ode23(F, time_period, Y0);

How can I find the smallest difference between two angles around a point?

Given a 2D circle with 2 angles in the range -PI -> PI around a coordinate, what is the value of the smallest angle between them?
Taking into account that the difference between PI and -PI is not 2 PI but zero.
An Example:
Imagine a circle, with 2 lines coming out from the center, there are 2 angles between those lines, the angle they make on the inside aka the smaller angle, and the angle they make on the outside, aka the bigger angle.
Both angles when added up make a full circle. Given that each angle can fit within a certain range, what is the smaller angles value, taking into account the rollover
This gives a signed angle for any angles:
a = targetA - sourceA
a = (a + 180) % 360 - 180
Beware in many languages the modulo operation returns a value with the same sign as the dividend (like C, C++, C#, JavaScript, full list here). This requires a custom mod function like so:
mod = (a, n) -> a - floor(a/n) * n
Or so:
mod = (a, n) -> (a % n + n) % n
If angles are within [-180, 180] this also works:
a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0
In a more verbose way:
a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180
x is the target angle. y is the source or starting angle:
atan2(sin(x-y), cos(x-y))
It returns the signed delta angle. Note that depending on your API the order of the parameters for the atan2() function might be different.
If your two angles are x and y, then one of the angles between them is abs(x - y). The other angle is (2 * PI) - abs(x - y). So the value of the smallest of the 2 angles is:
min((2 * PI) - abs(x - y), abs(x - y))
This gives you the absolute value of the angle, and it assumes the inputs are normalized (ie: within the range [0, 2π)).
If you want to preserve the sign (ie: direction) of the angle and also accept angles outside the range [0, 2π) you can generalize the above. Here's Python code for the generalized version:
PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
a = (x - y) % TAU
b = (y - x) % TAU
return -a if a < b else b
Note that the % operator does not behave the same in all languages, particularly when negative values are involved, so if porting some sign adjustments may be necessary.
An efficient code in C++ that works for any angle and in both: radians and degrees is:
inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
// c can be PI (for radians) or 180.0 (for degrees);
return c - fabs(fmod(fabs(x - y), 2*c) - c);
}
See it working here:
https://www.desmos.com/calculator/sbgxyfchjr
For signed angle:
return fmod(fabs(x - y) + c, 2*c) - c;
In some other programming languages where mod of negative numbers are positive, the inner abs can be eliminated.
I rise to the challenge of providing the signed answer:
def f(x,y):
import math
return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)
For UnityEngine users, the easy way is just to use Mathf.DeltaAngle.
Arithmetical (as opposed to algorithmic) solution:
angle = Pi - abs(abs(a1 - a2) - Pi);
I absolutely love Peter B's answer above, but if you need a dead simple approach that produces the same results, here it is:
function absAngle(a) {
// this yields correct counter-clock-wise numbers, like 350deg for -370
return (360 + (a % 360)) % 360;
}
function angleDelta(a, b) {
// https://gamedev.stackexchange.com/a/4472
let delta = Math.abs(absAngle(a) - absAngle(b));
let sign = absAngle(a) > absAngle(b) || delta >= 180 ? -1 : 1;
return (180 - Math.abs(delta - 180)) * sign;
}
// sample output
for (let angle = -370; angle <= 370; angle+=20) {
let testAngle = 10;
console.log(testAngle, "->", angle, "=", angleDelta(testAngle, angle));
}
One thing to note is that I deliberately flipped the sign: counter-clockwise deltas are negative, and clockwise ones are positive
There is no need to compute trigonometric functions. The simple code in C language is:
#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;
arg = fmod(y-x, PIV2);
if (arg < 0 ) arg = arg + PIV2;
if (arg > M_PI) arg = arg - PIV2;
return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 ) arg = arg + C360;
if (arg > 180) arg = arg - C360;
return (-arg);
}
let dif = a - b , in radians
dif = difangrad(a,b);
let dif = a - b , in degrees
dif = difangdeg(a,b);
difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000
No sin, no cos, no tan,.... only geometry!!!!
A simple method, which I use in C++ is:
double deltaOrientation = angle1 - angle2;
double delta = remainder(deltaOrientation, 2*M_PI);