Remap without recursion - autoit

I'm very new in AutoIt, worked before (a lot) with AutoHotkey.
Here is my attempt to slightly rewrite one of the scripts from AutoIt docs. The only part I've changed is the bottom one (Tab key).
What I want to achieve: If current window is Notepad, then send Ctrl-Tab instead of Tab. Otherwise, send normal Tab.
Well, I understand, why this code leads to recursion, but how I can avoid it?
#include <MsgBoxConstants.au3>
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{PAUSE}", "HotKeyPressed")
HotKeySet("{ESC}", "HotKeyPressed")
HotKeySet("{TAB}", "HotKeyPressed")
While 1
Sleep(100)
WEnd
Func HotKeyPressed()
Switch #HotKeyPressed
Case "{PAUSE}"
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
Case "{ESC}"
Exit
Case "{TAB}"
If WinActive("[CLASS:Notepad]") Then
Send("^{TAB}")
Else
Send("{TAB}")
EndIf
EndSwitch
EndFunc

Temporarily disable the hotkey:
Case "{TAB}"
HotKeySet("{TAB}") ;Cancel (or unregister) the hotkey
If WinActive("[CLASS:Notepad]") Then
Send("^{TAB}")
Else
Send("{TAB}")
EndIf
HotKeySet("{TAB}", "HotKeyPressed") ;re-enable hotkey
EndSwitch

Related

Why I get don't care at clk_out?

I am getting X as clk_out.Example of the frequency divider.
module freq_by2(input clk,rst,output reg clk_out);
always #(posedge clk)
begin
if (rst==1'b1)
begin
clk_out<=0;
end
else
begin
clk_out<=~clk_out;
end
end
endmodule
module freq_by4(input clk,rst,output reg [1:0] clk_out);
freq_by2 f0(.clk(clk),.rst(rst),.clk_out(clk_out[0]));
freq_by2 f1(.clk(clk_out[0]),.rst(rst),.clk_out(clk_out[1]));
endmodule
Are you sure, you are generating a correct, synchronous rst pulse? That is, synchronous to both clk and clk/2, because your f1 instantiation is synchronous to the clk_out output of f0? Otherwise, you are negating the last value of clk_out inside of freq_by2, which is X initially, unless a correct reset was generated.

How do I generalize the transfer of data between processors to a number of processors greater than 2?

I need to transfer the left most rij columns of an array (slast) from my_rank to my_rank-1 (paddedSright) and the rightmost rij columns of an array (slast) to my_rank+1 (paddedSleft). On my_rank equal zero just the rightmost RIJ columns are transferred to my_rank equal one, while if my_rank equals the number of processors minus one only the left most RIJ columns are transferred to my_rank-1. The following source works for 2 processors but mpi_scatter (I assume there is an optimized wrapper around mpi_send/recv?) targets all processors. I tried mpi_send+mpi_recv and mpi_sendrecv for nprocs>2 and it hangs up. The domain is broken up only in the X direction so the inner domains need to send data to the adjacent domains. The dimensions of the domains are indexed as slast(is:ie,js:je) while the padded arrays are (paddedSright/left(js:je,0:(RIJ-1)). This is for travel between domains in a pandemic model, right now the Berlin wall is holding up. My domains are typically 10000x5000 XY points and RIJ is 25 (25km average commuting distance). The attached code is general so any size array slast can be passed to it. I can build a quick wrpapper if that is needed, all the variables are in a massive module (virus_initialization) so I won't attach that. As is my usual practice, anyone who helps me solve this will be included on subsequent publications.
Thanks for your time,
Joe
#ifdef USEMPI
USE mpi
USE VIRUS_INITIALIZATION, only:slast,ilast,rlast,paddedSleft,paddedSright,paddedIleft,paddedIright,&
paddedRleft,paddedRright,is,ie,js,je,my_rank,nprocs,i,rij,debug,ierr
use mystuff
implicit none
real(8), allocatable::tmpcolumn(:)
integer(4) ids,idr
if(my_rank<1)then
! first send right Rij column of my_rank to left pad array of my_rank+1
allocate(tmpcolumn(js:je))
do i=0,rij-1
ids=my_rank
idr=my_rank+1
!send my_rank=0 S(susceptible) column to my_rank=0 padded array left
tmpcolumn(js:je)=slast(ie-i,js:je)
if(debug>=30)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedSleft(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=ilast(ie-i,js:je)
if(debug>=30)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedIleft(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=rlast(ie-i,js:je)
if(debug>=30)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedRleft(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
enddo
if(debug>=30)write(6,*)'Sent SIR to Lpad ',my_rank,i,nprocs,maxval(tmpcolumn)
deallocate(tmpcolumn)
endif
call mpi_barrier(mpi_comm_world,ierr)
if(my_rank>=nprocs-1)then
! send left Rij column of my_rank to left pad array of my_rank-1
allocate(tmpcolumn(js:je))
do i=0,rij-1
ids=my_rank
idr=my_rank-1
tmpcolumn(js:je)=slast(is+i,js:je)
if(debug>=30)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedSright(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=ilast(is+i,js:je)
if(debug>=30)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedIright(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=rlast(is+i,js:je)
if(debug>=30)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedRright(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
enddo
if(debug>=30)write(6,*)'Sent SIR to Rpad ',my_rank,i,nprocs,maxval(tmpcolumn)
deallocate(tmpcolumn)
endif
if(debug>=30)write(6,*)'Finished padding',my_rank
call mpi_barrier(mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
#endif
end subroutine virus_BCpad
Following Victor's comment I went back to MPI_SENDRECV and now the S/R hangs
#ifdef USEMPI
USE mpi
USE VIRUS_INITIALIZATION, only:slast,ilast,rlast,paddedSleft,paddedSright,paddedIleft,paddedIright,&
paddedRleft,paddedRright,is,ie,js,je,my_rank,nprocs,i,rij,debug,ierr
use mystuff
implicit none
real(8), allocatable::tmpcolumn(:)
integer(4) ids,idrL,idrR,rtag,ltag,stag
write(6,*)'Transferring BC data'
allocate(tmpcolumn(js:je))
! source rank
ids=my_rank
! desination rank left
idrL=my_rank-1
! desination rank right
idrR=my_rank+1
rtag=idrR
ltag=idrL
stag=ids
do i=1,rij-1
! if bad rank skip
if(idrL<0)goto 1
tmpcolumn(js:je)=slast(is+i,js:je)
if(debug>=0)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_SendRecv(tmpcolumn(:),je,mpi_double,idrL,stag,paddedSleft(:,i),je,mpi_double,ids,rtag,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
1 continue
! if bad rank skip
if(ids>=(nprocs-1))goto 2
tmpcolumn(js:je)=slast(ie-i,js:je)
if(debug>=0)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_SendRecv(tmpcolumn(:),je,mpi_double,idrR,stag,paddedSright(:,i),je,mpi_double,ids,ltag,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
2 continue
enddo
if(debug>=30)write(6,*)'Finished padding',my_rank
deallocate(tmpcolumn)
call mpi_barrier(mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
#endif
end subroutine virus_BCpad```
Transferring BC data
Transferring BC data
Sending S to Lpad 1 1 BLOCK 1L
2662.64005184174
Sending S to Rpad 0 1 BLOCK 1R
3232.02006292343

AutoIt pause/continue script function

I'm trying to make a function with hotkeys that pauses the script, so it doesn't send anything. But also a function that enables the script again. Here is what I have so far:
Func TogglePause()
$Paused = NOT $Paused
If $Paused Then ToolTip('Script "Paused"',500,500)
While $Paused
Sleep(1)
WEnd
ToolTip("")
EndFunc
Let's say you're typing H, the script pauses so it doesn't do anything. Once you press J the script is enabled again.
Directly from the helpfile (HotKeyset)
#include <MsgBoxConstants.au3>
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{PAUSE}", "TogglePause")
HotKeySet("{ESC}", "Terminate")
HotKeySet("+!d", "ShowMessage") ; Shift-Alt-d
While 1
Sleep(100)
WEnd
Func TogglePause()
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
EndFunc ;==>TogglePause
Func Terminate()
Exit
EndFunc ;==>Terminate
Func ShowMessage()
MsgBox($MB_SYSTEMMODAL, "", "This is a message.")
EndFunc ;==>ShowMessage
Does this fix your problem?
#include <MsgBoxConstants.au3>
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{PAUSE}", "HotKeyPressed")
HotKeySet("1", "HotKeyPressed")
HotKeySet("2", "HotKeyPressed")
HotKeySet("+!d", "HotKeyPressed") ; Shift-Alt-d
While 1
Sleep(100)
WEnd
Func HotKeyPressed()
Switch #HotKeyPressed ; The last hotkey pressed.
Case "{PAUSE}" ; String is the {PAUSE} hotkey.
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
Case "1"
While 1
Send('F')
Sleep(500)
WEnd
Case "2"
While 1
Send('D')
Sleep(500)
WEnd
Case "+!d" ; String is the Shift-Alt-d hotkey.
MsgBox($MB_SYSTEMMODAL, "", "This is a message.")
EndSwitch
EndFunc ;==>HotKeyPressed
I am revising the answer again to show my new example. This example will send "Q{ENTER}" at the start of the script every time the user hits the enter key. Now, when typing the letter 'b' on the keyboard, it automatically pauses the script and sends the key like normal. Whenever the user types the spacebar, the script is automatically activated again to start sending "Q{ENTER}" again. It can be manually paused/unpaused by using the pause/break key on the keyboard, and the process can be terminated by pressing the escape key.
Code.au3
; 1 - If the pause/break button is pressed, activate the togglePause function.
; 2 - If the esc (escape) key is pressed, stop the program.
; 3 - If the Enter key is pressed, run your function.
HotKeySet("{PAUSE}", "togglePause")
HotKeySet("{ESC}", "quitScript")
HotKeySet("{ENTER}","Enter")
; ADDED TWO HOTKEYS FOR B AND SPACE
HotKeySet("b", "keyPressB")
HotKeySet("{SPACE}", "keyPressSpace")
; This variable is set to leave the program unpaused at start.
global $isPaused = False
; This empty while loops keeps the program active until manually exiting.
While 1
WEnd
; This is a variation of the function you created.
Func Enter()
; If the program is unpaused (which it is at start), the program will send the Q then Enter button.
if $isPaused == false then
HotKeySet("{ENTER}");
Send("Q{ENTER}");
HotKeySet("{ENTER}","Enter")
; If the program is paused, it will send JUST the enter button like you are typing normally.
elseif $isPaused == true then
HotKeySet("{ENTER}");
Send("{ENTER}");
HotKeySet("{ENTER}","Enter")
EndIf
EndFunc
; ADDED THE TWO FUNCTIONS BELOW TO PROCESS THE B AND SPACE HOTKEYS
Func keyPressB ()
; Pauses the program
$isPaused = true
; Sends the b key like you are normally typing
HotKeySet("b")
Send("b")
HotKeySet("b", "keyPressB")
EndFunc
Func keyPressSpace ()
; Unpauses the program
$isPaused = false
HotKeySet("{space}")
Send("{SPACE}")
HotKeySet("{SPACE}", "keyPressSpace")
EndFunc
; Function to pause script
Func togglePause ()
; When this function is initiated, the code on the next line 'toggles' the variable to True/False. If the script is unpaused (the $isPaused variable is set to 'False') then the next line will change it to 'True' and vice versa.
$isPaused = NOT $isPaused
; Create a while loop to stall the program
; The line below is the same thing as "While $isPaused == True"
While $isPaused
; This code will run constantly until the $isPaused variable is set to 'True'. To make the script do nothing, simply add a sleep command.
Sleep(250)
WEnd
EndFunc
Func quitScript ()
Exit
EndFunc
Start - nothing happens.
Press f ==> script sends f until
a) you press d or ESC
a1) pressed d ==> script sends d until you press f or ESC
a2) pressed ESC ==> script pauses until you press
b1) d ==> sends D
b2) f ==> sends F
b3) ESC ==> sends the last letter sent before.
#include
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{ESC}", "HotKeyPressed")
HotKeySet("f", "HotKeyPressed")
HotKeySet("d", "HotKeyPressed")
HotKeySet("+!d", "HotKeyPressed") ; Shift-Alt-d
While 1
Sleep(100)
WEnd
Func HotKeyPressed()
Switch #HotKeyPressed ; The last hotkey pressed.
Case "{ESC}" ; String is the {PAUSE} hotkey.
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
Case "f"
$g_bPaused = False
While 1
Send('F')
Sleep(500)
WEnd
Case "d"
$g_bPaused = False
While 1
Send('D')
Sleep(500)
WEnd
Case "+!d" ; String is the Shift-Alt-d hotkey.
MsgBox($MB_SYSTEMMODAL, "", "This is a message.")
EndSwitch
EndFunc ;==>HotKeyPressed

Refresh and execute a program in Autoit

I want to make a program in autoit with a GUI - 2 buttons: the first button must refresh a web page (Ex: Google page) every 3 seconds, the second button must stop the refresh and do some operations on the web page. I'm ok with the first button, but I cannot exit from the loop with the second button and execute the operation I want. Can someone help me? Thanks a lot! This is the code:
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
$Form1 = GUICreate("Example", 190, 133, 192, 124)
GUISetBkColor(0xFFFF00)
$Button1 = GUICtrlCreateButton("UPDATE", 3, 31 ,179, 37, 0)
$Button2 = GUICtrlCreateButton("EXECUTE", 3, 80 ,179, 37, 0)
GUICtrlSetColor(-1, 0x0000FF)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlSetCursor (-1, 0)
GUICtrlSetColor(-1, 0x000000)
GUISetState(#SW_SHOW)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $button1
HotKeySet("{x}", "_Exit") ; Sets a shortcut to kill the script quickly. ESC
Opt("WinTitleMatchMode", 3) ; This is to tell the script to only refresh the EXACT window, incase there are similar windows. Such as: Window 1, Window 2.
While 1 ; This begins a While LOOP
Sleep(3000) ; Tell the script to pause for 3 seconds
$title = WinGetTitle("Google - Mozilla Firefox", "") ; Grabs the exactly title and saves it to a variable to do an If statement against.
If WinExists($title) Then ; Check to see if the desired window is running.
WinActivate($title) ; If it is running, first activate the window.
WinWaitActive($title) ; This tells the script to not send the refresh key (F5) until the window has appeared.
Send("{F5}") ; This sends the F5 key to refresh the window.
Else ; This is an else statement to tell the script to do a different operation if the window is not running.
Sleep(10) ; Just a filler item to wait until the desired window is running.
EndIf ; End the If statement to continue the script.
WEnd ; Close the While LOOP
Func _Exit() ; This is the function that is linked to the kill switch, ESC. It tells the script to perform the following actions.
ExitLoop ; Block pressing "x"
EndFunc ; Close the function up.
Case $button2
ExitLoop ; stop the loop and make operations below
Send("{TAB}")
Send("^v")
EndSwitch
WEnd
Something like this?
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
Global $Go2 = True
$Form1 = GUICreate("Example", 190, 133, 192, 124)
GUISetBkColor(0xFFFF00)
$Button1 = GUICtrlCreateButton("UPDATE", 3, 31, 179, 37, 0)
$Button2 = GUICtrlCreateButton("EXECUTE", 3, 80, 179, 37, 0)
GUICtrlSetColor(-1, 0x0000FF)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlSetCursor(-1, 0)
GUICtrlSetColor(-1, 0x000000)
GUISetState(#SW_SHOW)
Local $hTimer = TimerInit()
While True
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $Button1
$Go2 = True
HotKeySet("!{e}", "_Exit") ; Sets a shortcut to kill the script quickly. ESC
HotKeySet("{s}", "_ExitLoop") ; Sets a shortcut to kill the script quickly. ESC
Opt("WinTitleMatchMode", 3) ; This is to tell the script to only refresh the EXACT window, incase there are similar windows. Such as: Window 1, Window 2.
While $Go2 ; Avoid getting stuck in the while loop forever
If TimerDiff($hTimer) > 3000 Then
ConsoleWrite("Refreshing Mozilla" & #LF)
$title = WinGetTitle("Google - Mozilla Firefox", "") ; Grabs the exactly title and saves it to a variable to do an If statement against.
If WinExists($title) Then ; Check to see if the desired window is running.
WinActivate($title) ; If it is running, first activate the window.
WinWaitActive($title) ; This tells the script to not send the refresh key (F5) until the window has appeared.
Send("{F5}") ; This sends the F5 key to refresh the window.
$hTimer = TimerInit()
HotKeySet("{x}")
Else ; This is an else statement to tell the script to do a different operation if the window is not running.
;~ Sleep(10) ; Just a filler item to wait until the desired window is running.
EndIf ; End the If statement to continue the script.
EndIf
WEnd
$hTimer = TimerInit()
HotKeySet("{x}") ; Release hotkey
HotKeySet("!{e}") ; Release hotkeys
ConsoleWrite("Exited loop" & #LF)
Case $Button2
;you can't exit the loop from the $button1 here but there is a hotkey set to exit it, ALT + E
Send("{TAB}")
Send("^v")
EndSwitch
WEnd
Exit
Func _Exit()
Exit
EndFunc ;==>_Exit
Func _ExitLoop()
$Go2 = Not $Go2
EndFunc
P.S. I avoid using sleep because it pauses the script.
This is how I would do it.
Local $Refresh = 0 ; Set refresh OFF
Local $Timer = TimerInit()
Local $RefreshEvery = 3 ; seconds
Do
$msg = GUIGetMsg()
Select
Case $msg = $BtnRefresh
$Refresh = 1 ; Set refresh ON
Case $msg = $btnStop
$Refresh = 0 ; Set refresh OFF
EndSelect
If $Refresh And (TimerDiff($Timer) > $RefreshEvery*1000) Then
RefreshBrowser()
$Timer = TimerInit()
EndIf
Until $msg = $GUI_EVENT_CLOSE

How does the MPI_SENDRECV work?

I have a question about MPI_SENDRECV.
here is an example:
PROGRAM sendrecv
IMPLICIT NONE
INCLUDE "mpif.h"
INTEGER a,b,myrank,nprocs,ierr
integer istat(MPI_STATUS_SIZE)
CALL MPI_INIT(ierr)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr)
if (myrank.eq.0) then
a=1;b=3
else
a=2;b=4
endif
if (myrank == 0) then
call MPI_SENDRECV(b,1,MPI_REAL,1,0,
. a,1,MPI_REAL,1,0,
. MPI_COMM_WORLD,istat,ierr)
elseif (myrank == 1) then
call MPI_SENDRECV(b,1,MPI_REAL,0,0,
. a,1,MPI_REAL,0,0,
. MPI_COMM_WORLD,istat,ierr)
end if
if (myrank.eq.0) then
write(*,*) b,a
else
write(*,*) a,b
endif
CALL MPI_FINALIZE(ierr)
END
After this we get 3 4 and 3 4.
My question is that is we replace the MPI_SENDRECV(if we assume that MPI_SENDRECV is send first and then receive)
if (myrank == 0) then
call MPI_SEND(b,1,MPI_REAL,1,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,0,0,MPI_COMM_WORLD,istat,ierr)
elseif (myrank == 1) then
call MPI_SEND(b,1,MPI_REAL,0,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,1,0,MPI_COMM_WORLD,istat,ierr)
end if
Then this will be deadlock
So this means that MPI_SENDRECV it not first sends and then receives, but sends ans receives simultaneously,right?
You are right, MPI_Sendrecv is not the same a send followed by a receive. Think of it as an MPI_Isend, MPI_Irecv, and a pair of MPI_Waits. So in effect, the send and receive proceed in parallel.
Incidentally, this is how it is commonly implemented in the MPI libraries.
If you wanted to fix the deadlock in your second example, the processes would have to issue the sends and receives in a different order. So rank 0 would issue a send followed by receive, and rank 1 - a receive followed by a send.
Even though the message is routed to receive process B , process B still has to acknowledge that it wants to receive A's data. Once it does this, the data has been transmitted. Process A is acknowledged that the data has been transmitted and may go back to work.
So your second code can't satisfy the condition, which seems like that you don't answer the call by others. It should be like the follows:
if (myrank == 0) then
call MPI_SEND(b,1,MPI_REAL,1,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,1,0,MPI_COMM_WORLD,istat,ierr)
elseif (myrank == 1) then
call MPI_SEND(b,1,MPI_REAL,0,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,0,0,MPI_COMM_WORLD,istat,ierr)
end if

Resources