I want to use a Fortran function that simply outputs a real spherical harmonic as a function of the Cartesian coordinates and integers l and m, i.e. Y_lm(r). Does anyone know any code that does this? I may also be interested in the gradient of Y_lm(r) down the road.
Related
Searching for C/C++ implementation of Hermite Interpolation. Please suggest simple/readable/academic program.
Inputs: x and y arrays of doubles with 4 values each. Representing 4 2d points. Please note I do not have tangents with me.
Output: Now given any new value of x (within range of given x values), need to find new y. Please note I do not have parameter 't' with me.
Please suggest formulation and show C/C++ implementation.
I have simple code, which flags nodes with in region enclosed by cylinder. On implementing the code, the result is mild tilt of the cylinder observed case with 90 degrees
The actual issue:
The above algorithm is implemented in Fortran. The code checks for points in Cartesian grid if inside the cylinder. Following being the test case:
The cylinder makes an angle 90 degrees in the yz-plane with respect to y-axis. Therefore, the orientation vector $\vec{o}$ is (0, 1, 0).
Case 1:
Orientation vector is assigned directly with $\vec{o}=(0.0,1.0,0.0)$. This results in perfect cylinder with $\theta=90.$
Case 2:
Orientation vector is specified with intrinsic Fortran functions with double precision accuracy dsin and dcos with $\vec{o}=(0.0, \sin(\pi/2.0), \cos(\pi/2.0))$ with $\pi$ value assigned with more than 20 significant decimal points. The resulting cylinder results in mild tilt.
The highlighted region indicates the extra material due to tilt of cylinder with respect to Cartesian axes. I also tried architecture specific maximum precision "pi" value. This also results in same problem.
This shows like the actual angle made by cylinder is not 90 degrees. Can anyone suggest valid solution for this problem. I need to use the inbuilt trigonometric functions for arbitrary angles and looking for accurate cell flagging method.
Note: All operations are performed with double precision accuracy.
The actual function is below. rk is defined parameter with value 8
pure logical function in_particle(p,px,x)
type(md_particle_type),intent(in) :: p
real(kind=rk),intent(in) :: px(3),x(3)
real(kind=rk) :: r(3),rho(3),rop(2),ro2,rdiff,u
rop = particle_radii(p) ! (/R_orth,R_para/)
ro2 = rop(1)**2
rdiff = rop(2) - rop(1)
r = x-px
! Case 1:
! u = dot_product((/0.0_rk,-1.0_rk,0.0_rk/),r)
! rho = r-u*(/0.0_rk,-1.0_rk,0.0_rk/)
! Case 2:
u = dot_product((/0.0_rk,-dsin(pi/2.0_rk),dcos(pi/2.0_rk)/),r)
rho = r-u*(/0.0_rk,-dsin(pi/2.0_rk),dcos(pi/2.0_rk)/)
if((u.le.rdiff).and.(u.ge.-rdiff)) then
in_particle = dot_product(rho,rho) < ro2
else
in_particle = .false.
end if
end function in_particle
Note: The trigonometric operations are done inside the code to explain the problem better. However the original code reads the orientation in vector form from user. Then converts this information to quaternions for particle-particle collision operations. On converting quaternions back to orientation vector, this error is even more amplified. Even before the start of collision, the orientation of cylinder tends to be disoriented by 2 lattice cells.
cos(pi/2) is not necessarily going to give you exactly 0, no matter how exact you make the cos calculation, and no matter how many digits of pi you have, because:
pi, as an irrational number, will contain up to 1/2 ulp of error when represented as an FP number; and
sin and cos are not guaranteed by the IEEE-754 standard to be correctly rounded (or even implemented).
Now, sin(pi/2) is extremely likely to come out as 1 regardless of precision and FP architecture, simply because sin has such a low derivative around 1; with single-precision floats, it should come out to 1 if you're anywhere within about 3e-4 of the exact value of pi/2. The problematic call is the cos, which has lots of precision to play with around 0 and a derivative of about -1 in the neighborhood.
Still, we're talking about extremely small values here. I think what's really potentiating the problem here is the in/out test you're doing, combined with ordinary FP rounding rules. I would guess, in fact, that if you were to bias your test points by, say, a quarter of the grid quantum, you'd see all straight verticals in your voxelization (though it might not be symmetrical around the minor axes).
Another option would be to actually discard some precision from your sin/cos calculation before doing the dot product, effectively quantizing your axes.
Short answer: Create a table of sin and cos of common angles (0, pi/6, pi/4, pi/3, pi/2, pi and their multiples) and compute only for uncommon angles. The reason being that errors with uncommon angles will be tolerated by most people while errors with common angles will likely not be tolerated.
Explanation:
Because floating point computation is not exact (that is its nature), you sometime need a little bit of compromise between the accuracy and the readability of the code.
One way of doing that is to avoid to compute something that is known exactly. To do that, you can check the value of the angle and do the actual computation only if it is not an obvious angle. For example angle 0, 90, 180 and 270 degrees have obvious values of sin and cos. More generally, the cos and sin of common angles (0, pi/6, pi/4, pi/3, pi/2, pi and their multiples) are known exactly (even if they are irrational numbers).
I am realizing an algorithm using C++ and CUDA. But I got into trouble when I tried to find an inverse of a special matrix.
This matrix has following features:
it is a square matrix (suppose: (m+3)x(m+3),m>0);
its transpose matrix is its self;
its main diagonal must be zeros;
it must have a 3x3 zero matrix on the bottom right corner;
you can consider this matrix in this form:H = [A ,B ;B' ,0];
I have tried some methods but all failed:
pseudo-inverse matrix:
I used matlab at first and got error or warning when I tried to use inv(H'*H): Warning: Matrix is singular to working precision or matrix is close to singular or badly scaled
some approximation methods:
the reference material is here:approximation I found two methods:Gauss-Jordan elimination and Cholesky decomposition.when I tried chol in matlab, i get following error:Matrix must be positive definite
can anybody give me some suggestions?
It would be good to know some more information on your specific problem and, in particular, if you need the inverse per se or if you need to just invert a linear system of equations. I will try to give you directions for both the cases.
Let me start from the consideration that that your matrix is nearly singular and so your system is ill-conditioned.
DETERMINING THE INVERSE OF A NEARLY SINGULAR MATRIX
As it has been clarified in the comments and answers above, seeking the inverse of a nearly singular matrix is meaningless. What makes sense is to construct a regularized inverse of your matrix. You can do that by resorting to the spectral decomposition (Singular Value Decomposition, or SVD) of your matrix. More in detail, you can construct the singular system, remove the least significant singular values which are the source for the nearly singular behavior of the matrix, and then use the singular values and vectors to form an approximate inverse. Of course, in this case A*A_inv will only give an approximation of the identity matrix.
How can this be done on GPU? First, let me say that implementing an SVD algorithm in C++ or CUDA is by no means an easy task. There are several techniques among which you should choose depending on the accuracy you need, for example, to determine the singular values. Anyway, Matlab has a set of linear algebra functions working on GPU. Also, CULA and Magma are two libraries offering SVD calculation routines. Also, you can consider using Arrayfire which also offers linear algebra routines, including the SVD.
INVERTING A NEARLY SINGULAR SYSTEM
In this case, you should consider using some sort of Tikhonov regularization, which consists to formulating the inversion of the linear system as an optimization problem and adding a regularization term, which may depend on the features you already know about your uknowns.
For both the cases above, I recommend reading some theory. The book
M. Bertero, P. Boccacci, Introduction to Inverse Problems in Imaging
would be useful either if you have to find an approximate inverse or if you have the explicitly invert the linear system.
The pseudo-inverse matrix is inv(H'*H)*H', since the condition number of H is very high (try cond(H)), you may need a regularization factor to obtain the pseudo-inverse matrix: inv(H'*H + lambda*eye(size(H)))*H'. The smaller the lambda, the lower bias such estimation will achieve. But too small value of lambda will lead to high variance (ill-conditioned). You may try a best-suit value.
You can of course use pinv(H) directly. The reason why pinv(H)*H ~= eye(size(H)) is because pinv(H) is just an approximation of the inverse of a matrix H with the rank lower than size(H,1). In other words, the columns in H is not completely independent.
I would like to show you a very simple example:
>>a =
0 1 0
0 0 1
0 1 0
pinv(a) * a
>>
ans =
0 0 0
0 1.0000 0
0 0 1.0000
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>>a =
1 0
0 1
1 0
pinv(a) * a
>>
ans =
1.0000 0
0 1.0000
Note a * pinv(a) is not identity matrix, because columns of a are linearly independent, not the row of a. Check this page for more details.
There are analytical expressions that permit the calculation of the curve resulting from the overlapping between three penetrating spheres. There are also approximate methods that using grids or another methodologies, calculate points with more or less accuracy that belong to this interesection. I wonder if for the latter, the calculation can be done somehow using special hardware functions from the GPU, with CUDA or OpenGL. I need it for a very computing intensive number crunching program, so trivial implementations are not valid since they are very slow, and that is why I consider the GPU option
To test if a point (x, y, z) is in a sphere centered on (a, b, c) with radius r, the test is:
(x - a)^2 + (y - b)^2 + (z - c)^2 < r^2
Testing if the point is in multiple spheres is just an and of similar expressions. This only requires subtraction, multiplication, and comparison, no special hardware functions needed. You can write a CUDA kernel that does this with no problem.
The closest "specialized hardware" that might be applicable is the rsqrtf() function in CUDA, which computes 1/sqrt(x) in single precision to good accuracy with a single hardware instruction. You might use this to help calculate z values given x and y values of spheres, this could be useful for more sophisticated point generation algorithms for this problem.
I'm trying to implement some basic linear algebra operations and one of these operations is the inversion of a triangular (upper and/or lower) matrix. Is there an easy and stable algorithm to do that?
Thank you.
Yes, use back substitution. A standard algorithm to invert a matrix is to find its LU decomposition (decomposition into a lower-triangular and an upper-triangular matrix), use back subsitution on the triangular pieces, and then combine the results to obtain the inverse of the original matrix.
Don't invert it if you can. It's one of the basic commandments of numerical linear algebra.
It is much faster and numerically stabler to keep the matrix L itself in memory and compute inv(L)b with back-substitution whenever you need to do something else with inv(L).
Note that the customary algorithm for inverting it requires solving the systems inv(L)[1 0 0 ...],
inv(L)[0 1 0 ....],
inv(L)[0 0 1 ....] and so on, so you see it is much easier not to invert it at all.
Given a lower triangular matrix L, backsubstitution allows you to solve the system
L x = b
quickly for any right-hand side b.
To invert L, you can solve this system for right-hand sides e1=(1,0,...,0), e2=(0,1,...,0), ..., en=(0,0,...,1) and combine the resulting solution vectors into a single (necessarily lower-triangular) matrix.
If you are interested in a closed-form solution, the diagonal elements of the inverse are the inverses of the original diagonal elements, and the formula for the rest of the elements of the inverse gets more and more complicated as you move aways from the diagonal.
If you are talking about single precision reals, have a look at the source code for the LAPACK routines STRTRI and STRTI2.
Being B inverse of A, a triangular matrix, you can use the following MATLAB code:
n = size(A,1);
B = zeros(n);
for i=1:n
B(i,i) = 1/A(i,i);
for j=1:i-1
s = 0;
for k=j:i-1
s = s + A(i,k)*B(k,j);
end
B(i,j) = -s*B(i,i);
end
end
Wow, that's practically half the contents of a numerical analysis course. The standard algorithms will do it, and there is a bunch of canned code here. The ultimate source for this and most other usual numerical analysis problems is Numerical Recipes.