1d heat equation in maple - for-loop

I am solving 1d heat equation with neumman boundary conditions by finite difference method on maple but my code is not working please can anyone of you suggest me some better code for this equation on maple..
restart;
with(LinearAlgebra);
FX := 1;
FT := 0.5e-1;
M := 5;
N := 5;
M1 := M-1;
H := FX/M;
K := FT/N; c := 1;
r := c^2*K/H^2;
loop for initial condition;
for i to M1 do V[i, 0] := cos(Pi*i*H) end do;
loop for boundary condition;
for j to N do V[-1, j] := V[1, j] end do;
for j to N do V[M+1, j] := V[M-1, j] end do;
loop for discretized equation;
for j from 0 to N-1 do for i to M-1 do V[i, j+1] := (1-2*r)*V[i, j]+r*V[i-1, j]+r*V[i+1, j] end do end do;
please friends let me know why my last loop is not executing.

Very much a subtlety of Maple. The loop is executing - it just isn't printing the results. Every level of statement nesting adds one to the "printlevel" of the statement. Entering a procedure adds 5 to the printlevel of the containing procedure. The interactive session is level 0. The results of statements are only printed if their printlevel is less than or equal to the global variable printlevel which defaults to one. To see your loop execute, try
printlevel := 4;
Which prints up to 4 levels of nesting but not into any procedure calls. See ?printlevel for the full details.
On a side note, you may want to evalf the cos calls to ensure you get floating point values.

Related

how to check if the sum of digits is divisible by this sum?

I want to calculate the sum of the digits of a user-specified number first. Then I want to check if this number is divisible by the sum of its digits. Unfortunately, for example, for 21 it shows that it is not divisible, and for 200 that it is divisible. Maybe someone helps me. I'm just learning the language pl SQL.
DECLARE
n number(5):=&give_number;
temp_sum INTEGER;
r INTEGER;
a varchar(20);
BEGIN
temp_sum := 0;
WHILE n <> 0 LOOP
r := MOD(n, 10);
temp_sum := temp_sum + r;
n := Trunc(n / 10);
END LOOP;
a:=mod(r,temp_sum);
if a = 0 then
dbms_output.put_line('Divisible');
else
dbms_output.put_line('No divisible');
end if;
END;
You are checking if r is divisible by temp_sum and, if you consider what values they are holding then r is the most-significant digit and temp_sum is the digit sum. Which for an input of 21 checks whether 2 (the most-significant digit) is exactly divisible by 3, which it correctly reports that it is not divisible.
To fix it, you want to keep the input number in a variable that you do not modify and use that in the final comparison and not r:
If we remove some of the unnecessary variables and give the others more meaningful names:
DECLARE
input_value NUMBER(5) := &give_number;
remainder_value NUMBER(5) := input_value;
digit_sum INTEGER;
BEGIN
digit_sum := 0;
WHILE remainder_value <> 0 LOOP
digit_sum := digit_sum + MOD(remainder_value, 10);
remainder_value := TRUNC(remainder_value / 10);
END LOOP;
dbms_output.Put_line(remainder_value);
dbms_output.Put_line('sum of digits = ' || digit_sum);
IF MOD(input_value,digit_sum) = 0 then
dbms_output.put_line('Divisible');
ELSE
dbms_output.put_line('Not divisible');
END IF;
END;
/
Then when you put in 21 the output is:
0
sum of digits = 3
Divisible
And for 202, the output is:
0
sum of digits = 4
Not Divisible
db<>fiddle here
Here is a more compact way to write your PL/SQL block, using some of the features specific to the language. Perhaps the most interesting one is the nesting of program units (subroutines) - something that, in C for example, is not permitted. I am referring to the declaration and full code of a "helper function" (the sum of digits function) right in the DECLARE section of the outer block.
The function also demonstrates a compact way to write the function recursively. In this case recursion isn't too deep (only as many recursive calls as there are digits in the input number); in general, if you can write the same function using a loop, as you did, instead of using recursion, is preferred - far less overhead. On the other hand, with the proper settings (an advanced topic), the interpreter will inline the recursive calls - essentially converting the recursive function to a simple loop. That way you can have the best of both worlds: clean, compact code, yet efficient interpreted code and execution.
I also show the more compact way to display your output to the screen. You only need one call to put_line; let the "if" (or "case expression") take care of what is to be displayed within the put_line call. Moreover, the common part, 'Divisible', can be factored out; the case expression simply adds 'Not ' when it's needed.
declare
n number := &input_number;
function sum_of_digits(n integer) return integer is
begin
return mod(n, 10) + case when n < 10 then 0
else sum_of_digits(trunc(n/10)) end;
end;
begin
dbms_output.put_line(
case when mod(n, sum_of_digits(n)) != 0 then 'Not' end || 'Divisible');
end;
/
Notice one more thing: the outer block has a variable called n, but the function (in the declare section) also has a variable n. For the duration of the nested block (the function definition), n means the local variable. You need to always pay attention to such "masking" of an outer variable by a local variable by the same name.

breaking out of a loop in Julia

I have a Vector of Vectors of different length W. These last vectors contain integers between 0 and 150,000 in steps of 5 but can also be empty. I am trying to compute the empirical cdf for each of those vectors. I could compute these cdf iterating over every vector and every integer like this
cdfdict = Dict{Tuple{Int,Int},Float64}()
for i in 1:length(W)
v = W[i]
len = length(v)
if len == 0
pcdf = 1.0
else
for j in 0:5:150_000
pcdf = length(v[v .<= j])/len
cdfdict[i, j] = pcdf
end
end
end
However, this approach is inefficient because the cdf will be equal to 1 for j >= maximum(v) and sometimes this maximum(v) will be much lower than 150,000.
My question is: how can I include a condition that breaks out of the j loop for j > maximum(v) but still assigns pcdf = 1.0 for the rest of js?
I tried including a break when j > maximum(v) but this, of course, stops the loop from continuing for the rest of js. Also, I can break the loop and then use get! to access/include 1.0 for keys not found in cdfdict later on, but that is not what I'm looking for.
To elaborate on my comment, this answer details an implementation which fills an Array instead of a Dict.
First to create a random test case:
W = [rand(0:mv,rand(0:10)) for mv in floor(Int,exp(log(150_000)*rand(10)))]
Next create an array of the right size filled with 1.0s:
cdfmat = ones(Float64,length(W),length(0:5:150_000));
Now to fill the beginning of the CDFs:
for i=1:length(W)
v = sort(W[i])
k = 1
thresh = 0
for j=1:length(v)
if (j>1 && v[j]==v[j-1])
continue
end
pcdf = (j-1)/length(v)
while thresh<v[j]
cdfmat[i,k]=pcdf
k += 1
thresh += 5
end
end
end
This implementation uses a sort which can be slow sometimes, but the other implementations basically compare the vector with various values which is even slower in most cases.
break only does one level. You can do what you want by wrapping the for loop function and using return (instead of where you would've put break), or using #goto.
Or where you would break, you could switch a boolean breakd=true and then break, and at the bottom of the larger loop do if breakd break end.
You can use another for loop to set all remaining elements to 1.0. The inner loop becomes
m = maximum(v)
for j in 0:5:150_000
if j > m
for k in j:5:150_000
cdfdict[i, k] = 1.0
end
break
end
pcdf = count(x -> x <= j, v)/len
cdfdict[i, j] = pcdf
end
However, this is rather hard to understand. It would be easier to use a branch. In fact, this should be just as fast because the branch is very predictable.
m = maximum(v)
for j in 0:5:150_000
if j > m
cdfdict[i, j] = 1.0
else
pcdf = count(x -> x <= j, v)/len
cdfdict[i, j] = pcdf
end
end
Another answer gave an implementation using an Array which calculated the CDF by sorting the samples and filling up the CDF bins with quantile values. Since the whole Array is thus filled, doing another pass on the array should not be overly costly (we tolerate a single pass already). The sorting bit and the allocation accompanying it can be avoided by calculating a histogram in the array and using cumsum to produce a CDF. Perhaps the code will explain this better:
Initialize sizes, lengths and widths:
n = 10; w = 5; rmax = 150_000; hl = length(0:w:rmax)
Produce a sample example:
W = [rand(0:mv,rand(0:10)) for mv in floor(Int,exp(log(rmax)*rand(n)))];
Calculate the CDFs:
cdfmat = zeros(Float64,n,hl); # empty histograms
for i=1:n # drop samples into histogram bins
for j=1:length(W[i])
cdfmat[i,1+(W[i][j]+w-1)÷5]+=one(Float64)
end
end
cumsum!(cdfmat,cdfmat,2) # calculate pre-CDF by cumsum
for i=1:n # normalize each CDF by total
if cdfmat[i,hl]==zero(Float64) # check if histogram empty?
for j=1:hl # CDF of 1.0 as default (might be changed)
cdfmat[i,j] = one(Float64)
end
else # the normalization factor calc-ed once
f = one(Float64)/cdfmat[i,hl]
for j=1:hl
cdfmat[i,j] *= f
end
end
end
(a) Note the use of one,zero to prepare for change of Real type - this is good practice. (b) Also adding various #inbounds and #simd should optimize further. (c) Putting this code in a function is recommended (this is not done in this answer). (d) If having a zero CDF for empty samples is OK (which means no samples means huge samples semantically), then the second for can be simplified.
See other answers for more options, and reminder: Premature optimization is the root of all evil (Knuth??)

'For' loop pre and post empty statements

What does it mean in Go that the pre and post statements of a for loop are empty, like in the following example?
sum := 1
for ; sum < 10; {
sum += sum
}
fmt.Println(sum)
Remember that a for loop is the same as a while loop.
Your code can be rewritten in other languages as
sum := 1
while(sum < 10) {
sum += sum
}
fmt.Println(sum)
In a for loop, there are 3 parts.
for(initial statement ; condition ; end statement usually iterate)
This is equivalent to
initial statement
while(condition) {
Stuff here
End iteration statement
}
The reason your loop can be written withiut the pre and post statements is because you've specified them in other parts of the code.
It behaves like a while in other languages. You don't need the two semicolons:
sum := 1
for sum < 10 {
sum += sum
}
fmt.Println(sum)
A for loop has three elements: initialization statement, condition check, and variable change.
for <initialization statement>; <condition check>; <variable change>{
<actual body>
}
The initialization statement is executed only once when the loop starts. Based on the name, it initializes something (in a lot of cases a variable you iterate through). If it is omitted, then it does nothing
The condition check verifies whether the condition evaluates to true. If it is not, the loop stops. If it is omitted, then it is always true.
The variable change is modifying variables during each iteration of the loop. Most of the time, the iterated variable is increased/decreased, but you can do whatever you want. If it is omitted, it does nothing
After this explanation, you can see that this loop does nothing during your initialization and post condition phase.
You also do not need to use semicolons here. This will be enough.
sum := 1
for sum < 10 {
sum += sum
}
You can even write a loop like this: for {} which will never stop executing, or do something like a while loop:
t := 10
for t > 0{
t--
}
Note that inside your initialization, condition, and change phase you can use many expressions (not just one). So with a simple while loop you can do something like:
for f1, f2, n := 1, 1, 10; n > 0; f1, f2, n = f2, f1 + f2, n - 1{
fmt.Println(f1)
}
which creates Fibonacci numbers—see Go Playground. Showing this not because this is the best way to write it, but rather because it is possible.

How to check if a real number is a natural number in pascal?

I'm a beginner and I'm trying to write a simple program that will calculate all the dividers of a number. After doing a division I want to write only the dividers that give me a natural number. I can't think of a way to do it.
Loop with dividing the number
For i := 1 to x do
Begin
D := x div i;
WriteLn ('Divider', lp, '. ', x, ' : ', i, ' = ', D);
lp := lp +1;
End;
Here's a hint - rather than checking whether the result of x div i is natural, why not check whether x is divided exactly by i? Meaning that x mod i should be 0.

Mathematica, define multiple functions using for loop

I am using usual for-loop for computation in Mathematica:
For[i=1,i<n+1,i++, ...calculation... ]
For each i I need to define a function F_i[x_,y_]:=.... Here "i" is suuposed to be a label of the function. This is however not the corrcet Mathematica expression.
The question is, how to define multiple functions distinguished by the label i? I mean, what is the correct syntax?
Thanks a lot.
I'm not exactly sure what you are trying to do, but I have some confidence that the for loop is not the way to go in Mathematica. Mathematica already has pattern matching that likely eliminates the need for the loop.
What about something like this
f[i_][x_,y_]:= i(x+y)
or something like this
f[s_String][x_,y_]:=StringLength[s](x+y)
or even
f[s_,x_,y_]:=StringLength[s](x+y)
Here are some steps which may help. There are two versions below, the second one includes the value of i on the RHS of the function definition.
n = 2;
For[i = 1, i < n + 1, i++,
f[i][x_, y_] := (x + y)*i]
?f
Global`f
f[1][x_,y_] := (x+y) i
f[2][x_,y_] := (x+y) i
Clear[i]
f[2][2, 3]
5 i
Quit[]
n = 2;
For[i = 1, i < n + 1, i++,
With[{j = i},
f[i][x_, y_] := (x + y)*j]]
?f
Global`f
f[1][x$,y$] := (x$+y$) 1
f[2][x$,y$] := (x$+y$) 2
Clear[i]
f[2][2, 3]
10

Resources