Summing along an entire array in Fortran 90 [duplicate] - arrays

This question already has an answer here:
sum only on certain dimension
(1 answer)
Closed 3 years ago.
I have an array that is of size [30,3500,7000], and would like to accumulate along the first dimension so I am left with a [3500,7000] array. I have tried the following:
Implicit None
REAL,INTENT(IN) :: datastored(30,3500,7000),emptyarray(3500,7000)
REAL,INTENT(OUT) :: summed(3500,7000)
INTEGER :: i, j, r
DO i = 1,3500
DO j = 1,7000
DO r = 1,30
summed(i,j) = emptyarray(i,j) + datastored(r,i,j)
The problem with this is that, for some reason, it will not sum along the r dimension, and the summed variable will only be the last 'r' value in datastored, basically mirroring datastored(30,i,j).
Any thoughts?

summed = sum(datastored, DIM = 1)
Check this version of the Fortran standard, item 13.7.161, which defines the instrinsic sum. The Example case (iii) is exactly what you are asking for.

Related

Realize an array which the second dimension depends on the first argument [duplicate]

This question already has answers here:
Allocate dynamic array with interdependent dimensions
(2 answers)
Multidimensional array with different lengths
(2 answers)
Closed 1 year ago.
Suppose I have an array A[a,b]. The dimension of a is 2. When a=1, the dimension of b is 3; when a=2, the dimension of b is 6.
For example, one array A looks like
[[1,2,3]
[4,5,6,7,8,9]]
it is combined from 1*3 and 1*6. In total 9 entries, not from input.
Is there any method to define such an array in Fortran? or I need other type of data structure?
You need to provide a better description of what you want to do. With allocatable entities you can trivially achieve what you have described.
program foo
integer a, b
real, allocatable :: x(:,:)
read(*,*) a
if (a == 1 .or. a == 2) then
b = 3 * a
allocate(x(a,b))
else
stop 'Is this right?'
end if
x = 1
print *, shape(x)
end program foo

MATLAB: cannot call or index into a temporary array [duplicate]

This question already has answers here:
How can I index a MATLAB array returned by a function without first assigning it to a local variable?
(9 answers)
Closed 5 years ago.
I am trying to read data files each containing one column and 4097 rows. But my function needs total numbers of rows with even number (means 4096). So I used the MATLAB command x(2:length(x))). But my 'x' value in this command is a(:,k) and the issue is MATLAB cannot call or index into a temporary array. Any solution to this? I thank all for the support.
The code is:
for k = 1:9
with filename = sprintf('F00%d.txt',k);
a(:,k) = load(filename);
x = a(:,k)(2:length(a(:,k)));
w = tqwt(p,1,3,3);
[a1,a2,a3,a4]= deal(w{:});
m(a1,1) = mean(a1);
s(a1,1) = std(a1);
ma(a1,1) = max(a1);
mi(a1,1) = min(a1);
Unfortunately, you have to split x = a(:,k)(2:length(a(:,k))); into two lines as shown below:
temp = a(:,k);
x = temp(2:length(a(:,k)));
Please read:
Indexing of a function's return
How can I use indexing on the output of a function?

MATLAB - Finite Differences [Subscript indices must either be real positive integers or logicals] [duplicate]

This question already has answers here:
Subscript indices must either be real positive integers or logicals, generic solution
(3 answers)
Closed 6 years ago.
Not sure if I should have posted this here or on the Maths stackexchange, so sorry if it's the wrong place. I'm very new to MATLAB and programming in general, and am having some troubles trying to solve an ODE problem using finite difference methods for an assignment.
My finite difference equation is:
z(t+dt) = (dt^2*(γ^2*h*sin(γ*t)-β*z(t)) - z(t-dt)*(1-dt*α)+2*z(t))/(1 + dt*α)
Where t is a 51x1 array for the time increments. Basically I want to calculate z(t) for t values from 0 to 1 in increments of 0.02. I have the initial conditions z(0) = 0 and z(Δt) = 0.
My current code (not everything, but the bit that's giving me trouble:
dt = 0.02
t = [0:dt:T]';
z(0) = 0
z(dt)= 0
for i = t
z(i+dt) = (dt^2*(gamma^2.*h.*sin(gamma*t)-beta*z(i)) - z(i-dt)*(1-dt*alpha)+2*z(i))/(1 + dt*alpha)
end
Alpha, beta and gamma are all constants in this case, they're defined earlier in the code.
I keep getting the error "Subscript indices must either be real positive integers or logicals." I understand that MATLAB arrays begin with element 1 and not 0, so trying to access element 0 will give an error.
I'm not sure if the error is with how I've entered my finite difference function, or the initial conditions. By setting i = t, am I running the for loop for those values of t, or for those elements in the matrix? E.g. when i = 0, is it trying to access the 0 element of the matrix, or is it setting the i variable in the equation to 0 like I want it to?
Any help would be greatly appreciated.
Thankyou!
problem is with dt and I think dt is not integer value and cannot be used for indexing array. index of arrays are always integer values in Matlab. Please try below code and check if solves the problem
t = [0:dt:T]';
z(1) = 0
z(2)= 0
for i = 2 : length(t)
z(i) = (dt^2*(gamma^2.*h.*sin(gamma*t(i))-beta*z(i)) - z(i-1)*(1-dt*alpha)+2*z(i))/(1 + dt*alpha)
end

Subtract a vector from a matrix (row-wise) [duplicate]

This question already has answers here:
Broadcast array multiplication in Fortran 90/95
(3 answers)
Closed 6 years ago.
Suppose I have a matrix A in fortran which is (n,m), and a vector B which is (1,m). I want to subtract the vector B from all rows of A without using a loop.
As of now I have only been able to do it with a loop:
PROGRAM Subtract
IMPLICIT NONE
REAL, DIMENSION(250,5) :: A
INTEGER, DIMENSION(1,5) :: B
INTEGER :: i
B(1,1) = 1
B(1,2) = 2
B(1,3) = 3
B(1,4) = 4
B(1,5) = 5
CALL RANDOM_NUMBER(A)
do i=1,250
A(i,:) = A(i,:) - B(1,:)
end do
end program
But this is very inefficient. E.g. in matlab one can do it in one line using the function reptmat.
Any suggestion on better way to do this?
You can use spread for this:
A = A - spread( B(1,:), 1, 250 )
Please note that Fortran is column-major, so B(1,:) is in general not contiguous in memory, and a temporary array is created.
[ It is in your case since you have only one column - but still worth mentioning. ]
In the same way, looping over the first index of A is inefficient.
It would probably speed things up a lot if you transposed your matrices.
Then, a loop solution might even be faster than the one using spread. (But this depends on the compiler. )

Storing multiple powers of matrices in matlab [duplicate]

This question already has answers here:
How to generate the first twenty powers of x?
(4 answers)
Closed 7 years ago.
I have 1000 matrices with dimensions 2x2.
What I now need to do is to get 30 consecutive powers of those matrices (A^2, A^3... ...A^30) and store them all.
I found a topic that suggested using bsxfun:
Vectorizing the creation of a matrix of successive powers
However, bsxfun does not work with cell arrays ("Error using bsxfun
Operands must be numeric arrays").
What can I do?
PS. A secondary question: once I have them, I want to plot 4 graphs (each corresponding to 1 of the elements of the 2x2 matrices) with 30 positions (x-axis) which will show confidence bands (16th and 84th percentile).
EDIT: Someone linked to a question that was similar to the one that I linked. From what I can understand, the question there is about a vector, not array of matrices.
Assuming your array A is 2-by-2-by-1000, here are two loops to make things work:
A = rand(2,2,1000);
K = 30;
%%
N = size(A,3);
APower = zeros(2,2,N,K);
APower(:,:,:,1) = A;
for i = 1:N
for k = 2:K
APower(:,:,i,k) = A(:,:,i)*APower(:,:,i,k-1);
%// Alternatively you could use:
%APower(:,:,i,k) = A(:,:,i)^k;
end
end
You need to replicate the matrix 30 times to do this using cellfun. For example,
a = repmat(A{1},1,30);% Select one of your A matrices
b = num2cell(1:30);
x = cellfun(#(a,b) a^b,a,b,'UniformOutput',false)
Since you need to run cellfun for each element of A another way is to use arrayfun as below.
a = A{1};
b = 1:30;
x = arrayfun(#(b) a^b,b,'UniformOutput',false)

Resources