I want to code a FEM programme and here is my code
N1=2; %横向分解成2个元素
N2=2; %纵向分解成2个元素
N=2*N1*N2;
%三角元
top=1;
bottom=0;
left=0;
right=1;
h1=(right-left)/N1;
h2=(top-bottom)/N2;
T=zeros(3,2*N1*N2);%生成初始T矩阵
N10=N1+1;
N20=N2+1;
%先把每个element的行列转化为每个element对应的起始node的坐标,然和把坐标转化为index
for i=1:N2
for j=1:2*N1
if mod(j,2)==1
T(:,2*N1*(i-1)+j)=[(i-1)*N10+ceil(j/2);i*N10+ceil(j/2);(i-1)*N10+ceil(j/2)+1];
else
T(:,2*N1*(i-1)+j)=[(i-1)*N10+j/2+1;i*N10+j/2;i*N10+j/2+1];
end
end
end
P=zeros(2,(N1+1)*(N2+1));
for i=1:N1+1
for j=1:N2+1
P(:,(i-1)*(N1+1)+j)=[left+(i-1)*h1;bottom+(j-1)*h2];
end
end
N1_1= 2*N1;
N2_1= 2*N1;
N_1= 2*N1_1*N2_1;
%三角元
h1_1=(right-left)/N1_1;
h2_1=(top-bottom)/N2_1;
N10_1=N1_1+1;
N20_1=N2_1+1;
P_b=zeros(2,(N1_1+1)*(N2_1+1));
for i=1:N1_1+1
for j=1:N2_1+1
P_b(:,(i-1)*(N1_1+1)+j)=[left+(i-1)*h1_1;bottom+(j-1)*h2_1];
end
end
boundarynodes=zeros(2,N2_1+1+N1_1+N2_1+N1_1-1);
for j=1:2*N2_1+2*N1_1
boundarynodes(1,j)=-1;
end
for i=1:N1_1+1
boundarynodes(2,i)=(i-1)*(N1_1+1)+1;
end
for i=N1_1+2:N1_1+1+N2_1
boundarynodes(2,i)=(N1_1+1-1)*(N1_1+1)+i-(N1_1);
end
for i=N1_1+1+N2_1+N1_1:-1:N1_1+N2_1+2
boundarynodes(2,i)=((-i+2*N1_1+N2_1+2)-1)*(N1_1+1)+N1_1+1;
end
for i=N1_1+N2_1+N2_1+N1_1:-1:N1_1+2+N2_1+N1_1
boundarynodes(2,i)=-i+2*N1_1+2*N2_1+2;
end
%建立坐标到index函数
T_b=zeros(6,2*N1*N2);
c2i=#(i,j) (i-1)*(N1_1+1)+j;
for i=1:N1
for j=1:2*N2
if mod(j,2)==1
i_0=2*i-1;
j_0=2*ceil(j/2)-1;
T_b(:,2*N1*(i-1)+j)=[c2i(i_0,j_0);c2i(i_0+2,j_0);c2i(i_0,j_0+2);c2i(i_0+1,j_0);c2i(i_0+1,j_0+1);c2i(i_0,j_0+1)];
else
i_0=2*i-1;
j_0=2*(j/2+1)-1;
T_b(:,2*N1*(i-1)+j)=[c2i(i_0,j_0);c2i(i_0+2,j_0-2);c2i(i_0+2,j_0);c2i(i_0+1,j_0-1);c2i(i_0+2,j_0-1);c2i(i_0+1,j_0)];
end
end
end
A=sparse((N1_1+1)*(N2_1+1),(N1_1+1)*(N2_1+1));
for n=1:N
y_n2=P_b(2,T_b(2,n));
y_n3=P_b(2,T_b(3,n));
y_n1=P_b(2,T_b(1,n));
y_n4=P_b(2,T_b(4,n));
y_n5=P_b(2,T_b(5,n));
y_n6=P_b(2,T_b(6,n));
x_n3=P_b(1,T_b(3,n));
x_n2=P_b(1,T_b(2,n));
x_n1=P_b(1,T_b(1,n));
x_n4=P_b(1,T_b(4,n));
x_n5=P_b(1,T_b(5,n));
x_n6=P_b(1,T_b(6,n));
Y_n2=P(2,T(2,n));
Y_n3=P(2,T(3,n));
Y_n1=P(2,T(1,n));
X_n3=P(1,T(3,n));
X_n2=P(1,T(2,n));
X_n1=P(1,T(1,n));
xmin=X_n1;
xmax=xmin+h1;
J_n=(X_n2-X_n1)*(Y_n3-Y_n1)-(X_n3-X_n1)*(Y_n2-Y_n1);
x_hat=#(x,y) ((Y_n3-Y_n1)*(x-X_n1)-(X_n3-X_n1)*(y-Y_n1))/J_n;
y_hat=#(x,y) ((X_n2-X_n1)*(y-Y_n1)-(Y_n2-Y_n1)*(x-X_n1))/J_n;
if mod(n,2)==1
ymin= Y_n1;
ymax=#(x) Y_n3+((Y_n3-Y_n2)/(X_n3-X_n2))*(x-X_n3);
else
ymin=#(x) Y_n2+((Y_n2-Y_n1)/(X_n2-X_n1))*(x-x_n2);
ymax= Y_n1;
end
for i=1:6
for j=1:6
fun=#(x,y)...
(p_i_x(x_hat(x,y),y_hat(x,y),i))*((Y_n3-Y_n1)/J_n)+...
(p_i_y(x_hat(x,y),y_hat,i))*((Y_n1-Y_n2)/J_n)*...
(p_i_x(x_hat(x,y),y_hat(x,y),j)*((Y_n3-Y_n1)/J_n)+...
(p_i_y(x_hat(x,y),y_hat(x,y),j))*((Y_n1-Y_n2)/J_n))+...
((p_i_x(x_hat(x,y),y_hat(x,y),i))*((X_n1-X_n3)/J_n)+...
(p_i_y(x_hat(x,y),y_hat(x,y),i))*((X_n2-X_n1)/J_n))*...
((p_i_x(x_hat(x,y),y_hat(x,y),j))*((X_n1-X_n3)/J_n)+...
(p_i_y(x_hat(x,y),y_hat(x,y),j))*(X_n2-X_n1)/J_n);
r=integral2(fun,xmin,xmax,ymin,ymax);
A(T_b(j,n),T_b(i,n))=A(T_b(j,n),T_b(i,n))+r;
end
end
end
please ignore the chinese comment!
the above main programme also use the following two programmes
function r=p_i_x(x,y,i)
i_x=[4*x+4*y-3,4*x-1,0,-8*x-4*y+4,4*y,-4*y];
r=i_x(i);
end
function r=p_i_y(x,y,i)
i_y=[4*x+4*y-3,0,4*y-1,-4*x,4*x,-8*y-4*x+4];
r=i_y(:,i);
end
when I try to execute fun(0,1), "Undefined operator '*' for input arguments of type 'function_handle'." occurs I don't know how to fix this and other answers don't help, how to fix this?
The code is written in 1999 and controls a CNC machine. If the code snippet is not adequate to determine the language i can upload the entire file. This is the code segment:
BEGIN CONDITION +S_P0_PRES AND +N_P0__PNLTST ON EXCEPTION BEGIN
SET N_P0_STB OFF
SET N_P0_KEY(*) TO BITS(0)
SET N_P0_LTS(*) TO BITS(0)
SET ..KEY_PLS(*) TO BITS(0)
SET S_P0_KEY_PLS(*) TO BITS(0)
SET S_NCX0_FLEDS(*) TO BITS(0)
IF
:-S_P0_PRES: BEGIN
SET N_P0_ACT OFF
RETURN
END
END IF
WAIT +N_P0__PNLTST OR -S_P0_PRES
END
IF
:+N_P0_STB: BEGIN
LET ..KEY_INX = 0
REPEAT WHILE [INT(..KEY_PLS(*)) <> 0]
IF
:+..KEY_PLS(..KEY_INX): BEGIN
IF
:[..KEY_NUM(..KEY_INX) < 128]: BEGIN
IF
:-..KEY_ISF(..KEY_INX): SET N_P0_KEY(..KEY_NUM(..KEY_INX)) OFF
:+..KEY_ISF(..KEY_INX): SET .P0_NCX_FUN(..KEY_NUM(..KEY_INX)) OFF
END IF
START N_P0__NCXKEY
END
:[..KEY_NUM(..KEY_INX) < LAST(N_P0_KEY(*)) + 1]: BEGIN
SET N_P0_KEY(..KEY_NUM(..KEY_INX)) OFF
START N_P0__MAIKEY
END
:[..KEY_NUM(..KEY_INX) < LAST(.P0_NCX_FUN(*)) + 1]: BEGIN
SET .P0_NCX_FUN(..KEY_NUM(..KEY_INX) - (LAST(N_P0_KEY(*)) - 127)) OFF
START N_P0__FKEY
END
END IF
I think you're looking at APT.
I have the following simple code:
module past;
logic clk=0;
logic[3:0] adr=0;
// Clock Gen
initial forever #10 clk = ~clk;
initial #100 $finish;
always #(posedge clk) adr <= adr+1;
sequence DUMMY_SEQ;
#(posedge clk) 1'b1;
endsequence
cover property (#(posedge clk) DUMMY_SEQ) begin
$display("ADR %h past(ADR) %h at %0t", adr, $past(adr), $time);
end
endmodule
I would expect the $past(adr) return the value of adr in previous one clock cycle. But I got below simulation result which seemingly the $past(adr) return the value of adr in previous two clock cycle. Please notice it from line number 3.
ADR 1 past(ADR) 0 at 10
ADR 2 past(ADR) 0 at 10
ADR 3 past(ADR) 1 at 10
ADR 4 past(ADR) 2 at 10
ADR 5 past(ADR) 3 at 10
Can anybody explain why it is behaving like that?
Just to be clear, I am using $display just for illustration purpose. The actual problem is I couldn't get correct $past(adr) in cover statement.
Lets forget about the $display and do something else in cover statement. For example, by right, adr - $past(adr) should never exceed 1 as per above code. If I do something like this:
cover property (#(posedge clk) DUMMY_SEQ) begin
if ( (adr > $past(adr))
&& (adr - $past(adr)) > 1) $fatal;
end
then it should never get fatal, because adr increment by 1 at each clock cycle. However, it actually does get fatal error. This is confusing. Any explanation?
$past returns the value of an expression in a previous clock cycle.
Actually, there is difference between $display and $monitor that you have to understand.
$display displays once every time code is executed.
$monitor displays every time one of its parameters changes.
If you replace $display with $monitor then you will get your expected output.
The issue you are seeing is addr is updated before the $display statement and $past. This gives the impression that $past looks two clocks behind. To resolve this, use $sampled. See IEEE Std 1800-2012 16.9.3 Sampled value functions
cover property (#(posedge clk) DUMMY_SEQ) begin
$display("ADR %h past(ADR) %h at %0t", $sampled(adr), $past(adr), $time);
end
Output
ADR 0 past(ADR) 0 at 10
ADR 1 past(ADR) 0 at 30
ADR 2 past(ADR) 1 at 50
ADR 3 past(ADR) 2 at 70
ADR 4 past(ADR) 3 at 90
Another option is to put the display as a sequence_match_item which is best explained in IEEE Std 1800-2012 16.10 Local variables
cover property (#(posedge clk) (DUMMY_SEQ, $display("ADR %h past(ADR) %h at %0t", adr, $past(adr), $time));
For fatal and error reporting, it is better to use assert:
assert property (#(posedge clk) (adr >= $past(adr)) else $fatal;
My code describes a FSM to control a traffic light. There are four states, each with a different
duration.
Whenever the counter equals 1, the counter needs one more clock to change to the next value. For example, at state1, counter is programmed to count from 4 to 1. Every value should only take one clock to
change to the next, when it does, the state is changed to the next state. But when counter equals 1, it takes two clocks to change.
My program is as follows. The counter is implemented at the bottom of the always block:
module HW3(times,A,B,clk,rst,iHand,iChang,s1);
input clk,rst;
output reg [2:0]A,B;
wire oclk;//new freq
reg [2:0] count1,count2,count3,count4;//count times
reg [2:0]times;
reg temp;//control the switch
parameter [2:0]state1=3'd0,state2=3'd1,state3=3'd2,state4=3'd3;
always#(posedge clk or negedge rst )
begin
if(!rst)
begin
s1<=state1;
A<=3'b0;
B<=3'b0;
count1<=3'd4;
count2<=3'd2;
count3<=3'd3;
count4<=3'd2;
temp<=1'b1;
end
else
begin
if(temp==1)
begin
temp<=1'b0;
case(s1)
state1:
begin
times<=count1;
A<=3'b001;
B<=3'b100;
s1<=state2;
end
state2:
begin
times<=count2;
A<=3'b010;
B<=3'b100;
s1<=state3;
end
state3:
begin
times<=count3;
A<=3'b100;
B<=3'b001;
s1<=state4;
end
state4:
begin
times<=count4;
A<=3'b100;
B<=3'b010;
s1<=state1;
end
default:
begin
A<=3'b000;
B<=3'b000;
end
endcase
end
else
begin
if(times>1)
times<=times-1;
else if(times==1)
begin
temp<=1'b1;//can't count averagely
end
end
end
end
endmodule
Modify the code at the bottom of the always clock as:
if(times>2)
times<=times-1;
else if(times==2)
begin
times=times-1;
temp<=1'b1;//can't count averagely
end
Just let the times counts to 2 ,because if let it count to 1, the program will again enter the if
block in the next clock but doesnt change the value of times ,and make the value of times=1 unchanged
for one more clock
My partial program is as followed, it's a FSM to handle the traffic light,and the register "times" (from 4 to 1) is to compute the time that the traffic light should brighten, But whenever "times" counts to "1", the time of "times=1" is longer than other "times" about one clock.
For example:when times = 4~2,every clock will count ,but when times=1,it will take two clocks
to become times=4.
Could anybody tell me how this problem happened?
always#(posedge clk or negedge rst )
if(!rst)
begin
s1<=state1;
A<=3'b0;
B<=3'b0;
count1<=3'd4;
count2<=3'd2;
count3<=3'd3;
count4<=3'd2;
temp<=1'b1;
end
else
begin
if(temp==1)
begin
temp<=1'b0;
case(s1)
state1:
begin
times<=count1;
A<=3'b001;
B<=3'b100;
s1<=state2;
end
state2:
begin
times<=count2;
A<=3'b010;
B<=3'b100;
s1<=state3;
end
state3:
begin
times<=count3;
A<=3'b100;
B<=3'b001;
s1<=state4;
end
state4:
begin
times<=count4;
A<=3'b100;
B<=3'b010;
s1<=state1;
end
default:
begin
A[0]<=3'b000;
B[0]<=3'b000;
end
endcase
end
else
begin
if(times>1)
times<=times-1;
else if(times==1)
begin
temp<=1'b1;//can't count averagely
end
end
end