- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[originally posted on OpenMP Forum with no response]
I'm using OpenMP5 with Intel Fortran (XE 2020.1.216), running under 64-bit Windows 7, and using Visual studio 2019 16.6.1.
When I run my executable, it hangs at the beginning of a parallel region, but only the second time. I cannot understand why this should be.
The main program (Main) is C++. It calls a Fortran subroutine Compute directly (in the main thread), then starts a worker thread to call a second Fortran subroutine, Wide. When Wide has finished, the worker thread terminates.
Both Fortran subroutines contain a single parallel DO
All this works as expected the first time I run it. But the second time, it hangs at the start of the parallel DO in Compute.
The code looks like this:
Main C++ thread:
Compute(...)
Fortran Compute:
!$OMP PARALLEL DEFAULT(NONE) & !$OMP SHARED(...) !$OMP DO & !$OMP PRIVATE(iWavelengthF,... ) DO iWavelengthF=1, nWavelengthsAlloc ... END DO ! wavelength !$OMP END DO !$OMP END PARALLEL
Fortran Wide:
!$OMP PARALLEL DEFAULT(NONE) &
!$OMP SHARED(...)
!$OMP DO &
!$OMP PRIVATE(iWavelengthF, ... )
DO iWavelengthF=1, nWavelengths
...
END DO ! iWavelengthF
!$OMP END DO
!$OMP END PARALLEL
Here are the threads, as shown by the debugger; the initial column is the Windows thread ID. As is evident, OpenMP is not using the set of 7 parallel worker threads it created for the Compute parallel DO, but instead has created a second team of 7. It looks like the second time thru Compute, the first team of worker threads has been activated, but OpenMP is waiting for an event which never happens. This is a 4-core hyper-threaded Intel processor, so there are 8 logical CPUs.
Compute prior to parallel DO
2496 0 Main Thread Main Thread CppMain!Compute(, , , , , , , , , , , , , , , )
Compute after parallel DO
2496 0 Main Thread Main Thread CppMain!Compute(, , , , , , , , , , , , , , , )
9544 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
8052 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
5432 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
8236 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
9712 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
4112 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
6996 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
Wide prior to loop
2496 0 Main Thread Main Thread gdi32.dll!NtGdiGetRandomRgn
9544 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8052 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5432 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8236 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9712 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
4112 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
6996 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
Wide after parallel region
2496 0 Main Thread Main Thread CppMain!AfxInternalPumpMessage
9544 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8052 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5432 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8236 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9712 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
4112 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
6996 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
2328 0 Worker Thread CppMain!thread_start<unsigned int (__cdecl*)(void *),1> CppMain!Wide(, , , )
9836 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
6584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
9220 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
5216 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
1904 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
9656 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
9872 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
Main after Wide thread terminated
2496 0 Main Thread Main Thread CppMain!AfxInternalPumpMessage
9544 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8052 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5432 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8236 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9712 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
4112 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
6996 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9836 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
6584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9220 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5216 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
1904 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9656 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9872 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
Behavior OK to here, although it's a mystery why OpenMP started a second team of threads. I am guessing OpenMP cannot see the first team of threads, because Wide is in a different thread.
Compute before parallel DO:
2496 0 Main Thread Main Thread CppMain!Compute(, , , , , , , , , , , , , , , )
9544 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8052 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5432 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
8236 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9712 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
4112 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
6996 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9836 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
6584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9220 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5216 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
1904 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9656 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9872 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
Compute hanging at start of parallel DO:
2496 0 Main Thread Main Thread libiomp5md.dll!__kmp_suspend_64
9544 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
8052 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
5432 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
8236 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
9712 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
4112 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
6996 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
9836 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
6584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9220 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5216 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
1904 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9656 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9872 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The following may be a reason, and in any event, your code structure is not doing what you intend.
>>It calls a Fortran subroutine Compute directly (in the main thread),
OK
>>then starts a worker thread to call a second Fortran subroutine, Wide.
Not recommended. The spawned thread, when entering its parallel region, will instantiate an independent OpenMP thread pool. Thus generally over-subscribing the system.
>>When Wide has finished, the worker thread terminates.
This leaves the ancillary OpenMP threads of the 2nd thread pool active (each may be in Spin-Wait or suspended).
Then when the main thread enters Compute, this should be OK excepting for CPU competition with Spin-Waiting threads from the 2nd OpenMP thread pool.
Then when the main thread spawns another thread, and it subsequently enters its parallel region, will instantiate an independent (3rd) OpenMP thread pool.
etc...
The proper way to code this (C++ main, Fortran subroutines) is to assure only one OpenMP thread pool is created....
.OR.
Have the ancillary thread be created once, and then use a means of synchronization, perhaps a mutex for it to start/finish each run. Note, with two OpenMP thread pools, you may need to specify a lesser number of threads than all logical processors.
Also, include calls to initialize the Fortran runtime system.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@jimdempseyatthecove:
I understand that OpenMP is creating two thread pools. After I wrote the original post this did occur to me, so I changed the code to eliminate the separate worker thread I created. But the pgm hung in exactly the same way, although with only 7 OpenMP threads.
In fact, a separate worker thread is necessary, because the C++ UI needs to be showing progress of the lengthy Fortran calculations. I am not worried about competition among threads for CPU time, because this will be taken into account by suspending the OpenMP threads.
I see your point about continuing to spawn threads, but I don't see any way to prevent this. I cannot execute the entire app in the same thread. What is needed is either (1) a way to tell OpenMP to terminate a team of threads, which would be executed just before the worker thread terminates, or (2) a way to re-establish connection to the orphaned set of threads left when the thread terminates.
I don't know why you are suggesting I need to initialize the Fortran run-time. Surely this is already being done when execution starts. My pgm has lots of calls to Fortran from the C++ main, and I haven't had any difficulties. So the pgm must already be doing the initialization.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>I changed the code to eliminate the separate worker thread I created. But the pgm hung in exactly the same way, although with only 7 OpenMP threads.
Then one of your threads, within the parallel region, terminated. There is an implicit barrier on !$omp end do, as well as !$omp end parallel.
All threads of a parallel region must enter (and will exit) barriers. One of your threads is somehow exiting/terminating within the parallel region.
>>I don't see any way to prevent this. I cannot execute the entire app in the same thread.
Without knowing about your application's requirements, it will be hard to give you complete advice. I can sketch it for you to use as a starting point.
================== Plan A =======================
int main(int argc, char** argv)
{
for_rtl_init_(&argc, argv); // Fortran pre-PROGRAM initialization (no PROGRAM procedure)
...
omp_set_nested(true);
#pragma omp parallel
{
#pragma omp master
{
for(int interval=0; interval<nTimes; ++interval)
{
...
Compute();
#pragma omp task shared(...) private(...)
{ // runs concurrent with enclosing for(...) loop
// IOW next interval, this task may be running through next Compute()
...
// you are responsible to avoid data usage conflicts between
// Compute and Wide
Wide();
...
}
... // task still running
} // for
} // master
} // parallel
...
for_rtl_finish(&argc, argv); // Fortran pre-PROGRAM initialization (no PROGRAM procedure)
...
} // main
! Compute.f90
... variables
! nested parallel region
!$OMP PARALLEL DEFAULT(NONE) &
!$OMP SHARED(...)
!$OMP DO &
!$OMP PRIVATE(iWavelengthF,... )
DO iWavelengthF=1, nWavelengthsAlloc
...
END DO ! wavelength
!$OMP END DO
!$OMP END PARALLEL
...
! end Compute.f90
----------------------
! Wide.f90
... variables
! code
! nested parallel region
!$OMP PARALLEL DEFAULT(NONE) &
!$OMP SHARED(...)
!$OMP DO &
!$OMP PRIVATE(iWavelengthF, ... )
DO iWavelengthF=1, nWavelengths
...
END DO ! iWavelengthF
!$OMP END DO
!$OMP END PARALLEL
! end Wide.f90
================== Plan B =======================
int main(int argc, char** argv)
{
for_rtl_init_(&argc, argv); // Fortran pre-PROGRAM initialization (no PROGRAM procedure)
...
#pragma omp parallel
{
#pragma omp master
{
int dependVar; // address of this is used for dependency
for(int interval=0; interval<nTimes; ++interval)
{
...
#pragma omp task shared(...) private(...) depend(out: dependVar)
{
...
Compute();
...
}
#pragma omp task shared(...) private(...) depend(in: dependVar)
{ // runs concurrent with enclosing for(...) loop
// IOW next interval, this task may be running through next Compute()
...
// you are responsible to avoid data usage conflicts between
// Compute and Wide
Wide();
...
}
... // task with Wide still running
} // for
} // master
} // parallel
...
for_rtl_finish(&argc, argv); // Fortran pre-PROGRAM initialization (no PROGRAM procedure)
...
} // main
! Compute.f90
...
DO iWavelengthF=1, nWavelengthsAlloc
!$OMP TASK FIRSTPRIVATE(iWavelengthF) PRIVATE(...) SHARED(...)
...
!$OMP END TASK
END DO ! wavelength
...
! end Compute.f90
----------------------
! Wide.f90
...
DO iWavelengthF=1, nWavelengths
!$OMP TASK FIRSTPRIVATE(iWavelengthF) PRIVATE(...) SHARED(...)
...
!$OMP END TASK
END DO ! iWavelengthF
...
! end Wide.f90
>>I don't know why you are suggesting I need to initialize the Fortran run-time. Surely this is already being done when execution starts.
Fortran run-time initialization/finalization is part of the Fortran PROGRAM procedure. Applications with a C/C++/C#/??? main do not have a Fortran PROGRAM procedure, and thus do not have calls to initialization/finalization
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have checked that no thread leaves a parallel region anywhere other than the DO termination. The compiler gives an error if you try to do this, anyways. I had to replace RETURNs and EXITs in the parallel DOs to get the pgm to compile in the first place.
I believe OpenMP is using 7 threads because the main thread already "uses" one of the logical processors. This is not optimal, but doesn't really matter in this case.
I redid the pgm to remove the worker thread, so all Fortran execution is from the same thread. Below are the list of threads at each point. You can see that there is only a single team of threads, and they are the same at everyplace, once we get past the initial parallel region.
Again, the second invocation of Compute hangs at the start of the parallel region. However, I just thought to look at the stack of the hung OpenMP threads, and they all look like
user32.dll!NtUserMessageCall() Unknown
user32.dll!SendMessageWorker() Unknown
user32.dll!SendMessageA() Unknown
CppMain!L_Compute.V_176__par_region0_2.1() Line 185 Fortran
libiomp5md.dll!__kmp_invoke_microtask() Unknown
libiomp5md.dll!__kmp_invoke_task_func(int gtid) Line 7516 C++
libiomp5md.dll!__kmp_launch_thread(kmp_info * this_thr) Line 6109 C++
libiomp5md.dll!__kmp_launch_worker(void * arg) Line 1039 C++
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown
Compute contains, within the parallel region, the line
messageResult = SENDMESSAGE(hWnd, WM_APP_Progress, 2, fractX10000Complete)
This is just supposed to update the C++ UI on the progress of the computation. But since Compute is not in a separate thread, the SendMessage never gets processed, and hence, deadlock. I should have used PostMessage, which returns immediately. I made this change, and now it does not hang, when everything is running in the same thread. Now I need to deal with the multiple teams of threads issue.
Start Compute
6408 0 Main Thread Main Thread CppMain!Compute(, , , , , , , , , , , , , , , )
End Compute
6408 0 Main Thread Main Thread CppMain!Compute(, , , , , , , , , , , , , , , )
7292 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
9576 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
9668 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
4064 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
10036 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
10132 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
5584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
End Wide
6408 0 Main Thread Main Thread CppMain!Wide(, , , )
7292 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
9576 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_hyper_barrier_release
9668 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
4064 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
10036 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
10132 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
5584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_yield
Start Compute
6408 0 Main Thread Main Thread CppMain!Compute(, , , , , , , , , , , , , , , )
7292 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9576 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
9668 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
4064 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
10036 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
10132 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
5584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker libiomp5md.dll!__kmp_suspend_64
Hang in Compute
6408 0 Main Thread Main Thread libiomp5md.dll!__kmp_suspend_64
7292 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
9576 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
9668 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
4064 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
10036 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
10132 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
5584 0 Worker Thread libiomp5md.dll!__kmp_launch_worker CppMain!L_Compute.V_176__par_region0_2.1()
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>This is just supposed to update the C++ UI on the progress of the computation.
Run the UI as a Modal Dialog. Here is a cut/edited version of some Fortran code that I use:
! First time, or in event that Control Pannel terminated for some reason
if(.not. ControlPannelRunning) then
! before creating the dialog box insert values that may be examined/modified
! by the dialog box
vIntegrationStepsize = DLHOST
IntegrationStepsize = DLHOST
! Create seperate thread to run the Modal Dialog control pannel
ControlPanelHandle = CreateThread(&
& NULL, ControlPanelStack, loc(ControlPanel), loc(ControlPanelArg), ControlPanelFlags, loc(ControlPanelThread_ID))
! ** before proceeding, wait for the new thread to complete initialization
do while(.not. ControlPannelRunning)
milliseconds = 500
call sleepqq(milliseconds)
end do
endif
*** The Control Panel Dialog box does not perform significant computations - deffinately no OpenMP parallel regions. It is simply a button/control/dialog display function. Here is my control panel code.
! ControlPanel.f90
#ifndef _AvFRT
#error *-*-*- Must compile with _AvFRT defined
#endif
#define SPIN_INTEGRATION_STEPSIZE_RANGEMIN 1
#define SPIN_INTEGRATION_STEPSIZE_SMALLSTEP 1
#define SPIN_INTEGRATION_STEPSIZE_BIGSTEP 100
#define SPIN_INTEGRATION_STEPSIZE_RANGEMAX 30000
SUBROUTINE ControlPanelCallBack( dlg, id, callbacktype )
!DEC$ ATTRIBUTES DEFAULT :: ControlPanelCallBack
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
TYPE (dialog) dlg
INTEGER id, callbacktype, iStat
CHARACTER(256), automatic :: text
LOGICAL retlog
INTEGER cel, far, retint
real(8), automatic :: xyz(3)
text = 'undefined'
ControlPanelPauseRefresh = .true.
NextDisplayTime = 0 ! update now
SELECT CASE (id)
CASE (IDC_RADIO1)
! Radio button 1 selected by user so
! change display accordingly
vIavDisplayFrame = 0 ! vIavDisplayFrame = 0 Inertial Frame
! vIavDisplayFrame = 1 Orbital Frame
CASE (IDC_RADIO2)
! Radio button 2 selected by user so
! change display accordingly
vIavDisplayFrame = 1 ! vIavDisplayFrame = 1 Orbital Frame
CASE (IDC_SLIDER1)
call ControlPanelSliderDeltaTime ! should pass dlg, slider uses ControlPanelDlg (should be same)
CASE (IDC_SLIDER2)
call ControlPanelSliderAnnealRate
CASE (IDC_SLIDER3)
call ControlPanelStretchX
CASE (IDC_SLIDER4)
call ControlPanelStretchY
CASE (IDC_SLIDER5)
call ControlPanelStretchZ
CASE (IDC_SLIDER6)
call ControlPanelStretchCharts
CASE (IDC_SLIDER7)
call ControlPanelIntegrationStepsizeMultiplierGain
CASE (IDC_BUTTON_TENSION)
call PokeFiveStateButton(IDC_BUTTON_TENSION, vButtonTension)
CASE (IDC_BUTTON_ELASTIC_AREA)
call PokeFiveStateButton(IDC_BUTTON_ELASTIC_AREA, vButtonElasticArea)
if(vButtonElasticArea .eq. 0) then
! Elastic Area, Bead Mass, Ballast Mass, Elastic Area, Bead Mass, Ballast Mass, ...
if(DisplayBeadMassInPlaceOfElasticArea) then
! transition to Ballast Mass
DisplayBeadMassInPlaceOfElasticArea = .false.
DisplayBallastMassInPlaceOfElasticArea = .true.
retlog = DLGSET( ControlPanelDlg, IDC_ElasticAreaOrMass, 'Ballast Mass' )
elseif(DisplayBallastMassInPlaceOfElasticArea) then
! transition to Elastic Area
DisplayBallastMassInPlaceOfElasticArea = .false.
DisplayExternalForceInPlaceOfElasticArea = .true.
retlog = DLGSET( ControlPanelDlg, IDC_ElasticAreaOrMass, 'External Force' )
elseif(DisplayExternalForceInPlaceOfElasticArea) then
! transition to Elastic Area
DisplayExternalForceInPlaceOfElasticArea = .false.
retlog = DLGSET( ControlPanelDlg, IDC_ElasticAreaOrMass, 'Elastic Area' )
else
! Elastic Area transitions to Bead Mass
DisplayBeadMassInPlaceOfElasticArea = .true.
retlog = DLGSET( ControlPanelDlg, IDC_ElasticAreaOrMass, 'Bead Mass' )
endif
endif
CASE (IDC_BUTTON_STRESS)
call PokeFiveStateButton(IDC_BUTTON_STRESS, vButtonStress)
CASE (IDC_BUTTON_STRAIN)
call PokeFiveStateButton(IDC_BUTTON_STRAIN, vButtonStrain)
CASE (IDC_CHECK_ANNEAL)
retlog = DLGGETLOG (dlg, IDC_CHECK_ANNEAL, vCheckAnneal)
CASE (IDC_CHECK_HONE)
retlog = DLGGETLOG (dlg, IDC_CHECK_HONE, vCheckHone)
CASE (IDC_CHECK_DAMPER)
retlog = DLGGETLOG (dlg, IDC_CHECK_DAMPER, vCheckDamper)
CASE (IDC_CHECK_RIGHTEN)
retlog = DLGGETLOG (dlg, IDC_CHECK_RIGHTEN, vCheckRighten)
CASE (IDC_CHECK_GENISIS)
retlog = DLGGETLOG (dlg, IDC_CHECK_GENISIS, vCheckGenisis)
CASE (IDC_CHECK_FLIP_X)
retlog = DLGGETLOG (dlg, IDC_CHECK_FLIP_X, vCheckFlipX)
CASE (IDC_CHECK_FLIP_Y)
retlog = DLGGETLOG (dlg, IDC_CHECK_FLIP_Y, vCheckFlipY)
CASE (IDC_CHECK_FLIP_Z)
retlog = DLGGETLOG (dlg, IDC_CHECK_FLIP_Z, vCheckFlipZ)
CASE (IDC_CHECK_MKS)
retlog = DLGGETLOG (dlg, IDC_CHECK_MKS, vCheckMKS)
CASE (IDC_CHECK_REV)
retlog = DLGGETLOG (dlg, IDC_CHECK_REV, vCheckReverseBeads)
CASE (IDC_CHECK_ALT)
retlog = DLGGETLOG (dlg, IDC_CHECK_ALT, vCheckAltitude)
CASE (IDC_CHECK_TELLTAILS)
retlog = DLGGETLOG (dlg, IDC_CHECK_TELLTAILS, vCheckTelltails)
CASE (IDC_CHECK_EARTH)
retlog = DLGGETLOG (dlg, IDC_CHECK_EARTH, vCheckEarth)
CASE (IDC_CHECK_CROSSHAIRS)
retlog = DLGGETLOG (dlg, IDC_CHECK_CROSSHAIRS, vCheckCrossHairs)
CASE (IDC_ADVANCETETHERSINCRIMENTALLY)
retlog = DLGGETLOG (dlg, IDC_ADVANCETETHERSINCRIMENTALLY, vCheckAdvanceTethersIncrimentally)
CASE (IDC_PAUSE_RESUME)
if(ControlPanelPause .eq. .true.) then
ControlPanelPause = .false.
text = 'Pause'
else
ControlPanelPause = .true.
text = 'Resume'
endif
retlog = DLGSET( dlg, IDC_PAUSE_RESUME, text )
CASE (IDC_PANX)
call ControlPanelPanX
CASE (IDC_PANY)
call ControlPanelPanY
CASE (IDC_PANZ)
call ControlPanelPanZ
CASE(IDC_SPIN_INTEGRATION_STEPSIZE)
call ControlPanelSpinIntegrationStepsize
CASE(IDC_BUTTON_AVRESET)
vButtonArrayVisualizerReset = .true.
CASE(IDC_BUTTON_SNAPSHOT)
vButtonSnapShot = .true.
CASE(IDC_BUTTON_RESET_REGION_HISTORY)
vButtonResetRegionHistory = .true.
CASE(IDC_RADIO_STOP)
vElevatorActionState = ElevatorActionStateStop
CASE(IDC_RADIO_RELEASE)
vElevatorActionState = ElevatorActionStateRelease
CASE(IDC_RADIO_UP)
vElevatorActionState = ElevatorActionStateUp
CASE(IDC_RADIO_DOWN)
vElevatorActionState = ElevatorActionStateDown
CASE(IDC_RADIO_PUMP)
vElevatorActionState = ElevatorActionStatePump
CASE(IDC_BUTTON_VIEW)
vButtonView = .true.
END SELECT
END SUBROUTINE ControlPanelCallBack
integer(4) FUNCTION ControlPanel(arg)
!DEC$ ATTRIBUTES STDCALL, ALIAS:"_controlpanel" :: ControlPanel
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
integer(4),POINTER :: arg
integer(4) returnVal, ns
CHARACTER(256) text
LOGICAL retlog
external ControlPanelCallBack
retlog = DLGINIT( IDD_DIALOG1, ControlPanelDlg )
if(.not. retlog) write(*,*) "Dialog error for IDD_DIALOG1"
call DlgSetTitle( ControlPanelDlg, ControlPanelTitle )
retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO1, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO1"
retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO2, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO2"
retlog = DlgSetSub( ControlPanelDlg, IDC_SLIDER1, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SLIDER1"
retlog = DlgSetSub( ControlPanelDlg, IDC_SLIDER2, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SLIDER2"
retlog = DlgSetSub( ControlPanelDlg, IDC_SLIDER3, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SLIDER3"
retlog = DlgSetSub( ControlPanelDlg, IDC_SLIDER4, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SLIDER4"
retlog = DlgSetSub( ControlPanelDlg, IDC_SLIDER5, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SLIDER5"
retlog = DlgSetSub( ControlPanelDlg, IDC_SLIDER6, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SLIDER6"
retlog = DlgSetSub( ControlPanelDlg, IDC_SLIDER7, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SLIDER7"
retlog = DlgSetSub( ControlPanelDlg, IDC_PANX, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_PANX"
retlog = DlgSetSub( ControlPanelDlg, IDC_PANY, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_PANY"
retlog = DlgSetSub( ControlPanelDlg, IDC_PANZ, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_PANZ"
retlog = DlgSetSub( ControlPanelDlg, IDC_PAUSE_RESUME, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_PAUSE_RESUME"
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_TENSION, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_TENSION"
vButtonTension = vButtonTension - 1
call PokeFiveStateButton(IDC_BUTTON_TENSION, vButtonTension)
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_ELASTIC_AREA, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_ELASTIC_AREA"
vButtonElasticArea = vButtonElasticArea - 1
call PokeFiveStateButton(IDC_BUTTON_ELASTIC_AREA, vButtonElasticArea)
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_STRESS, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_STRESS"
vButtonStress = vButtonStress - 1
call PokeFiveStateButton(IDC_BUTTON_STRESS, vButtonStress)
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_STRAIN, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_STRAIN"
vButtonStrain = vButtonStrain - 1
call PokeFiveStateButton(IDC_BUTTON_STRAIN, vButtonStrain)
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_ANNEAL, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_ANNEAL"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_HONE, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_HONE"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_DAMPER, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_DAMPER"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_RIGHTEN, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_RIGHTEN"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_FLIP_X, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_FLIP_X"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_FLIP_Y, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_FLIP_Y"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_FLIP_Z, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_FLIP_Z"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_MKS, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_MKS"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_REV, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_REV"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_ALT, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_ALT"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_TELLTAILS, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_TELLTAILS"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_EARTH, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_EARTH"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_CROSSHAIRS, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_CROSSHAIRS"
retlog = DlgSetSub( ControlPanelDlg, IDC_ADVANCETETHERSINCRIMENTALLY, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_ADVANCETETHERSINCRIMENTALLY"
call ControlPanelSliderDeltaTime
call ControlPanelSliderAnnealRate
call ControlPanelStretchX
call ControlPanelStretchY
call ControlPanelStretchZ
retlog = DLGSETLOG( ControlPanelDlg, IDC_RADIO1, (vIavDisplayFrame .eq. 0))
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO1"
retlog = DLGSETLOG( ControlPanelDlg, IDC_RADIO2, (vIavDisplayFrame .eq. 1))
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO2"
IavDisplayFrame = vIavDisplayFrame
oIavDisplayFrame = vIavDisplayFrame
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_ANNEAL, vCheckAnneal)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_ANNEAL"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_HONE, vCheckHone)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_HONE"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_DAMPER, vCheckDamper)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_DAMPER"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_RIGHTEN, vCheckRighten)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_RIGHTEN"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_GENISIS, vCheckGenisis)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_GENISIS"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_FLIP_X, vCheckFlipX)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_FLIP_X"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_FLIP_Y, vCheckFlipY)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_FLIP_Y"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_FLIP_Z, vCheckFlipZ)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_FLIP_Z"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_MKS, vCheckMKS)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_MKS"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_REV, vCheckReverseBeads)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_REV"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_ALT, vCheckAltitude)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_ALT"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_TELLTAILS, vCheckTelltails)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_TELLTAILS"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_EARTH, vCheckEarth)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_EARTH"
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_CROSSHAIRS, vCheckCrossHairs)
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_CROSSHAIRS"
retlog = DLGSETLOG (ControlPanelDlg, IDC_ADVANCETETHERSINCRIMENTALLY, vCheckAdvanceTethersIncrimentally)
if(.not. retlog) write(*,*) "Dialog error for IDC_ADVANCETETHERSINCRIMENTALLY"
retlog = DlgSetSub( ControlPanelDlg, IDC_CHECK_GENISIS, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_CHECK_GENISIS"
!
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_AVRESET, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_AVRESET"
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_SNAPSHOT, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_SNAPSHOT"
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_RESET_REGION_HISTORY, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_RESET_REGION_HISTORY"
retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO_STOP, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO_STOP"
retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO_RELEASE, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO_RELEASE"
retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO_UP, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO_UP"
retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO_DOWN, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO_DOWN"
retlog = DlgSetSub( ControlPanelDlg, IDC_RADIO_PUMP, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_RADIO_PUMP"
call ControlPanelSetIntegrationStepsize(IntegrationStepsize)
retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, SPIN_INTEGRATION_STEPSIZE_RANGEMIN, DLG_RANGEMIN)
if(.not. retlog) write(*,*) "Dialog error for IDC_SPIN_INTEGRATION_STEPSIZE_RANGEMIN"
retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, SPIN_INTEGRATION_STEPSIZE_SMALLSTEP, DLG_SMALLSTEP)
if(.not. retlog) write(*,*) "Dialog error for IDC_SPIN_INTEGRATION_STEPSIZE_SMALLSTEP"
retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, SPIN_INTEGRATION_STEPSIZE_BIGSTEP, DLG_BIGSTEP)
if(.not. retlog) write(*,*) "Dialog error for IDC_SPIN_INTEGRATION_STEPSIZE_BIGSTEP"
retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, SPIN_INTEGRATION_STEPSIZE_RANGEMAX, DLG_RANGEMAX)
if(.not. retlog) write(*,*) "Dialog error for IDC_SPIN_INTEGRATION_STEPSIZE_RANGEMAX"
retlog = DlgSetSub( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_SPIN_INTEGRATION_STEPSIZE"
retlog = DLGSET( ControlPanelDlg, IDC_PANX, vPanX, DLG_POSITION)
if(.not. retlog) write(*,*) "Dialog error for IDC_PANX"
retlog = DLGSET( ControlPanelDlg, IDC_PANY, vPanY, DLG_POSITION)
if(.not. retlog) write(*,*) "Dialog error for IDC_PANY"
retlog = DLGSET( ControlPanelDlg, IDC_PANZ, vPanZ, DLG_POSITION)
if(.not. retlog) write(*,*) "Dialog error for IDC_PANZ"
retlog = DlgSetSub( ControlPanelDlg, IDC_BUTTON_VIEW, ControlPanelCallBack )
if(.not. retlog) write(*,*) "Dialog error for IDC_BUTTON_VIEW"
call ControlPanelSetSliderDeltaTime(DeltaTime)
ControlPannelRunning = .true.
returnVal = DlgModal( ControlPanelDlg ) ! Doesn't return unless cancled (or IDC_event not specified)
ControlPanelExit = .TRUE.
ControlPanelPause = .FALSE.
ControlPanel = returnVal
end FUNCTION ControlPanel
recursive subroutine ControlPanelNewDamper(NewDamper)
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
logical :: NewDamper
logical :: retlog
vCheckDamper = NewDamper
CheckDamper = NewDamper
retlog = DLGSETLOG (ControlPanelDlg, IDC_CHECK_DAMPER, vCheckDamper)
end subroutine ControlPanelNewDamper
recursive subroutine ControlPanelPauseSub
use GlobalData
implicit none
do while(ControlPanelPause .eq. .true.)
! wait 100 miliseconds (1/10 second)
call sleepqq(100)
if(ControlPanelPauseRefresh .eq. .true.) then
ControlPanelPauseRefresh = .false.
! Make sure display is refreshed to reflect changes made
call Update_AVFRT(' ')
endif
end do
end subroutine ControlPanelPauseSub
! Display desired stepsize
recursive subroutine ControlPanelDisplay_vIntegrationStepsize
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(256) text
LOGICAL retlog
write(text, '(F16.12)') vIntegrationStepsize
text = ADJUSTL(text)
retlog = DLGSET( ControlPanelDlg, IDC_INTEGRATION_STEPSIZE, text )
end subroutine ControlPanelDisplay_vIntegrationStepsize
! Display current stepsize
recursive subroutine ControlPanelDisplay_IntegrationStepsize
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(256) text
LOGICAL retlog
write(text, '(F16.12)') IntegrationStepsize
text = ADJUSTL(text)
retlog = DLGSET( ControlPanelDlg, IDC_INTEGRATION_STEPSIZE2, text )
end subroutine ControlPanelDisplay_IntegrationStepsize
recursive subroutine ControlPanelDisplayTime(T)
#ifdef _OPENMP
use omp_lib
#endif
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
real :: T
CHARACTER(256) text
LOGICAL retlog
integer :: iTimeHH, iTimeMM, iTimeSS
real :: TimeFraction
#ifdef _OPENMP
real, save :: Tlast = 0.0
real, save :: wTimeLast = 0.0
real :: wTimeNow, virtualTimeInteral, realTimeInterval
wTimeNow = omp_get_wtime()
virtualTimeInteral = T - Tlast
Tlast = T
realTimeInterval = wTimeNow - wTimeLast
wTimeLast = wTimeNow
if(T .eq. 0.0) then
virtualTimeInteral = 1.0 ! avoid first time divide by 0
realTimeInterval = 1.0
endif
#endif
iTimeHH = INT(T / 60 / 60)
iTimeMM = INT((T - (iTimeHH * 60 * 60)) / 60)
iTimeSS = INT(T - (iTimeHH * 60 * 60) - (iTimeMM * 60))
TimeFraction = T - (iTimeHH * 60 * 60) - (iTimeMM * 60) - iTimeSS
#ifdef _OPENMP
write(text, '(I8,A1,I2.2,A1,I2.2,F13.12,A1,F15.12)') iTimeHH, ':', iTimeMM, ':', iTimeSS, TimeFraction, ' ', virtualTimeInteral / realTimeInterval
#else
write(text, '(I8,A1,I2.2,A1,I2.2,F13.12)') iTimeHH, ':', iTimeMM, ':', iTimeSS, TimeFraction
#endif
DisplayTime = text
retlog = DLGSET( ControlPanelDlg, IDC_RUNTIME, text )
! Display desired stepsize
call ControlPanelDisplay_vIntegrationStepsize
! Display current stepsize
call ControlPanelDisplay_IntegrationStepsize
end subroutine ControlPanelDisplayTime
recursive subroutine ControlPanelSliderAnnealRate
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_SLIDER2, &
slide2_position, DLG_POSITION)
CheckAnnealAnnealRate = dble(slide2_position + 1) / 100. ! Never 0, bias by 1
write(text, '(A2,F7.2)') 'ar',CheckAnnealAnnealRate
retlog = DLGSET( ControlPanelDlg, IDC_ar, text )
end subroutine ControlPanelSliderAnnealRate
recursive subroutine ControlPanelSetSliderAnnealRate(Rate)
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
real :: Rate
CHARACTER(25) text
LOGICAL retlog
slide2_position = INT(Rate*100)
slide2_position = MIN(slide2_position, 100)
slide2_position = MAX(slide2_position, 0)
retlog = DLGSET (ControlPanelDlg, IDC_SLIDER2, slide2_position, DLG_POSITION)
CheckAnnealAnnealRate = dble(slide2_position + 1) / 100. ! Never 0, bias by 1
write(text, '(A2,F7.2)') 'ar',CheckAnnealAnnealRate
retlog = DLGSET( ControlPanelDlg, IDC_ar, text )
end subroutine ControlPanelSetSliderAnnealRate
recursive subroutine ControlPanelSliderDeltaTime
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_SLIDER1, &
slide1_position, DLG_POSITION)
if(slide1_position < 10) then
DeltaTime = .0000001 * dble(slide1_position + 1)
elseif(slide1_position < 20) then
DeltaTime = .000001 * dble(slide1_position - 10 + 1)
elseif(slide1_position < 30) then
DeltaTime = .00001 * dble(slide1_position - 20 + 1)
elseif(slide1_position < 40) then
DeltaTime = .0001 * dble(slide1_position - 30 + 1)
elseif(slide1_position < 50) then
DeltaTime = .001 * dble(slide1_position - 40 + 1)
elseif(slide1_position < 60) then
DeltaTime = .01 * dble(slide1_position - 50 + 1)
elseif(slide1_position < 70) then
DeltaTime = .1 * dble(slide1_position - 60 + 1)
elseif(slide1_position < 80) then
DeltaTime = 1. * dble(slide1_position - 70 + 1)
elseif(slide1_position < 90) then
DeltaTime = 100. * dble(slide1_position - 80 + 1)
else
DeltaTime = 50000. * dble(slide1_position - 90 + 1)
endif
write(text, '(A2,F14.6)') 'dt',DeltaTime
retlog = DLGSET( ControlPanelDlg, IDC_dt, text )
end subroutine ControlPanelSliderDeltaTime
recursive subroutine ControlPanelSetSliderDeltaTime(dt)
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
real :: dt
CHARACTER(25) text
LOGICAL retlog
DeltaTime = dt
if(DeltaTime < .000001) then
slide1_position = DeltaTime / .0000001 + 1
elseif(DeltaTime < .00001) then
slide1_position = (DeltaTime / .000001) + 10 + 1
elseif(DeltaTime < .0001) then
slide1_position = (DeltaTime / .00001) + 20 + 1
elseif(DeltaTime < .001) then
slide1_position = (DeltaTime / .0001) + 30 + 1
elseif(DeltaTime < .01) then
slide1_position = (DeltaTime / .001) + 40 + 1
elseif(DeltaTime < .1) then
slide1_position = (DeltaTime / .01) + 50 + 1
elseif(DeltaTime < 1.0) then
slide1_position = (DeltaTime / .1) + 60 + 1
elseif(DeltaTime < 10.0) then
slide1_position = (DeltaTime / 1.0) + 70 + 1
elseif(DeltaTime < 1000.0) then
slide1_position = (DeltaTime / 100.0) + 80 + 1
else
slide1_position = (DeltaTime / 50000.0) + 90 + 1
endif
if(slide1_position .lt. 0) slide1_position = 0
if(slide1_position .gt. 100) slide1_position = 100
retlog = DLGSET (ControlPanelDlg, IDC_SLIDER1, &
slide1_position, DLG_POSITION)
write(text, '(A2,F14.6)') 'dt',DeltaTime
retlog = DLGSET( ControlPanelDlg, IDC_dt, text )
end subroutine ControlPanelSetSliderDeltaTime
recursive subroutine ControlPanelStretchX
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_SLIDER3, &
slide3_position, DLG_POSITION)
vStretchX = MAX(dble(slide3_position)*1., 1.)
end subroutine ControlPanelStretchX
recursive subroutine ControlPanelStretchXtext
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
write(text, '(A4,F14.3)') 'X * ',oStretchX
text = ADJUSTL(text)
text(5:) = ADJUSTL(text(5:))
retlog = DLGSET( ControlPanelDlg, IDC_STRETCHX, text )
end subroutine ControlPanelStretchXtext
recursive subroutine ControlPanelStretchY
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_SLIDER4, &
slide4_position, DLG_POSITION)
vStretchY = MAX(dble(slide4_position)*1., 1.)
end subroutine ControlPanelStretchY
recursive subroutine ControlPanelStretchYtext
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
write(text, '(A4,F14.3)') 'Y * ',oStretchY
text = ADJUSTL(text)
text(5:) = ADJUSTL(text(5:))
retlog = DLGSET( ControlPanelDlg, IDC_STRETCHY, text )
end subroutine ControlPanelStretchYtext
recursive subroutine ControlPanelStretchZ
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_SLIDER5, &
slide5_position, DLG_POSITION)
vStretchZ = MAX(dble(slide5_position)*1., 1.)
end subroutine ControlPanelStretchZ
recursive subroutine ControlPanelStretchZtext
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
write(text, '(A4,F14.3)') 'Z * ',oStretchZ
text = ADJUSTL(text)
text(5:) = ADJUSTL(text(5:))
retlog = DLGSET( ControlPanelDlg, IDC_STRETCHZ, text )
end subroutine ControlPanelStretchZtext
recursive subroutine ControlPanelStretchCharts
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_SLIDER6, &
slide6_position, DLG_POSITION)
! ChartJiggle = ScaleRange / 10.
StretchCharts = (dble(slide6_position) / ((ScaleRange / ChartJiggle)* 3.)) + 1.
end subroutine ControlPanelStretchCharts
recursive subroutine ControlPanelIntegrationStepsizeMultiplierGain
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_SLIDER7, &
vIntegrationStepsizeMultiplierGain, DLG_POSITION)
end subroutine ControlPanelIntegrationStepsizeMultiplierGain
recursive subroutine TweekDisplaySoon
use GlobalData
use MOD_HOST
implicit none
NextDisplayTime = HOST%rT + 1.
end subroutine TweekDisplaySoon
recursive subroutine ControlPanelPanX
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_PANX, &
vPanX, DLG_POSITION)
call TweekDisplaySoon
end subroutine ControlPanelPanX
recursive subroutine ControlPanelPanY
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_PANY, &
vPanY, DLG_POSITION)
call TweekDisplaySoon
end subroutine ControlPanelPanY
recursive subroutine ControlPanelPanZ
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
LOGICAL retlog
retlog = DLGGET (ControlPanelDlg, IDC_PANZ, &
vPanZ, DLG_POSITION)
call TweekDisplaySoon
end subroutine ControlPanelPanZ
recursive subroutine PokeFiveStateButton(id, vButton)
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
INTEGER id, vButton
select case (vButton)
case (0)
vButton = 1
text = 'i/r'
case (1)
vButton = 2
text = 'i/d'
case (2)
vButton = 3
text = 'a/r'
case (3)
vButton = 4
text = 't/r'
case default
vButton = 0
text = '0'
end select
! retlog = DLGSET( dlg, IDC_PAUSE_RESUME, text )
retlog = DLGSET( ControlPanelDlg, id, text )
end subroutine PokeFiveStateButton
recursive subroutine ControlPanelSpinIntegrationStepsize
USE IFLOGM
use GlobalData
use MOD_HOST
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
integer(4) :: us, iValue, usPerTick
real :: TickWeight
retlog = DLGGET (ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, &
iValue , DLG_POSITION)
! Convert iValue to being relative to midpoint
iValue = iValue - (SPIN_INTEGRATION_STEPSIZE_RANGEMAX / 2)
TickWeight = vIntegrationStepsize * 10.0 / dble(SPIN_INTEGRATION_STEPSIZE_RANGEMAX)
vIntegrationStepsize = vIntegrationStepsize + (TickWeight * dble(iValue))
call ControlPanelDisplay_vIntegrationStepsize
end subroutine ControlPanelSpinIntegrationStepsize
recursive subroutine ControlPanelSetGenisisMessage(iPhase, iStep)
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
CHARACTER(25) text
LOGICAL retlog
integer(4) :: iPhase, iStep
write(text, '(I6, A3, I6)') iPhase, ' - ', iStep
retlog = DLGSET( ControlPanelDlg, IDC_STATIC_GENISIS_MESSAGE, text )
end subroutine ControlPanelSetGenisisMessage
recursive subroutine ControlPanelSetIntegrationStepsize(StepSize)
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
real :: StepSize
CHARACTER(25) text
LOGICAL retlog
integer(4) :: iValue, nsPerTick
vIntegrationStepsize = StepSize
iValue = SPIN_INTEGRATION_STEPSIZE_RANGEMAX / 2
retlog = DLGSET( ControlPanelDlg, IDC_SPIN_INTEGRATION_STEPSIZE, iValue, DLG_POSITION)
! Display desired stepsize
call ControlPanelDisplay_vIntegrationStepsize
! Display current stepsize
call ControlPanelDisplay_IntegrationStepsize
end subroutine ControlPanelSetIntegrationStepsize
recursive subroutine LaunchViewDialog
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
INTERFACE
integer(4) FUNCTION ViewPanel(arg)
!DEC$ ATTRIBUTES STDCALL, ALIAS:"_viewpanel" :: ViewPanel
integer(4),POINTER :: arg
END FUNCTION
END INTERFACE
if(oButtonView) return
oButtonView = .true.
if(.not. ViewPannelRunning) then
! Create seperate thread to run the Modal Dialog control pannel
ViewPanelHandle = CreateThread(&
& NULL, ViewPanelStack, loc(ViewPanel), loc(ViewPanelArg), ViewPanelFlags, loc(ViewPanelThread_ID))
ViewPannelRunning = .true.
endif
end subroutine LaunchViewDialog
SUBROUTINE ViewPanelCallBack( dlg, id, callbacktype )
!DEC$ ATTRIBUTES DEFAULT :: ViewPanelCallBack
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
TYPE (dialog) dlg
INTEGER :: id, callbacktype, iStat
LOGICAL :: retlog, retCheck
INTEGER cel, far, retint
ControlPanelPauseRefresh = .true.
NextDisplayTime = 0 ! update now
SELECT CASE (id)
CASE (IDC_RADIO_SBS)
vFocusOn = FocusOnSBS
CASE (IDC_RADIO_SUN)
vFocusOn = FocusOnSun
CASE (IDC_RADIO_MERCURY)
vFocusOn = FocusOnMercury
CASE (IDC_RADIO_VENUS)
vFocusOn = FocusOnVenus
CASE (IDC_RADIO_EARTH)
vFocusOn = FocusOnEarth
CASE (IDC_RADIO_MARS)
vFocusOn = FocusOnMars
CASE (IDC_RADIO_JUPITER)
vFocusOn = FocusOnJupiter
CASE (IDC_RADIO_SATURN)
vFocusOn = FocusOnSaturn
CASE (IDC_RADIO_URANUS)
vFocusOn = FocusOnUranus
CASE (IDC_RADIO_NEPTUNE)
vFocusOn = FocusOnNeptune
CASE (IDC_RADIO_PLUTO)
vFocusOn = FocusOnPluto
CASE (IDC_CHECK_SUN)
call CheckViewSub(dlg, IDC_CHECK_SUN, bitCheckViewSun)
CASE (IDC_CHECK_MERCURY)
call CheckViewSub(dlg, IDC_CHECK_MERCURY, bitCheckViewMercury)
CASE (IDC_CHECK_VENUS)
call CheckViewSub(dlg, IDC_CHECK_VENUS, bitCheckViewVenus)
CASE (IDC_CHECK_EARTH)
call CheckViewSub(dlg, IDC_CHECK_EARTH, bitCheckViewEarth)
CASE (IDC_CHECK_EARTHMOON)
call CheckViewSub(dlg, IDC_CHECK_EARTHMOON, bitCheckViewEarthMoon)
CASE (IDC_CHECK_MARS)
call CheckViewSub(dlg, IDC_CHECK_MARS, bitCheckViewMars)
CASE (IDC_CHECK_JUPITER)
call CheckViewSub(dlg, IDC_CHECK_JUPITER, bitCheckViewJupiter)
CASE (IDC_CHECK_SATURN)
call CheckViewSub(dlg, IDC_CHECK_SATURN, bitCheckViewSaturn)
CASE (IDC_CHECK_URANUS)
call CheckViewSub(dlg, IDC_CHECK_URANUS, bitCheckViewUranus)
CASE (IDC_CHECK_NEPTUNE)
call CheckViewSub(dlg, IDC_CHECK_NEPTUNE, bitCheckViewNeptune)
CASE (IDC_CHECK_PLUTO)
call CheckViewSub(dlg, IDC_CHECK_PLUTO, bitCheckViewPluto)
CASE (IDC_CHECK_ASTEROIDS)
call CheckViewSub(dlg, IDC_CHECK_ASTEROIDS, bitCheckViewAsteroids)
CASE (IDC_CHECK_COMETS)
call CheckViewSub(dlg, IDC_CHECK_COMETS, bitCheckViewComets)
CASE (IDC_CHECK_SPACECRAFT)
call CheckViewSub(dlg, IDC_CHECK_SPACECRAFT, bitCheckViewSpacecraft)
END SELECT
END SUBROUTINE ViewPanelCallBack
recursive subroutine CheckViewSub(dlg, id, bitCheckViewBit)
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
TYPE (dialog) dlg
INTEGER :: id, bitCheckViewBit
LOGICAL :: retlog, retCheck
retlog = DLGGETLOG (dlg, id, retCheck)
if(retCheck) then
vCheckViewMask = IOR(vCheckViewMask, bitCheckViewBit)
else
vCheckViewMask = IAND(vCheckViewMask, NOT(bitCheckViewBit))
endif
end subroutine CheckViewSub
integer(4) FUNCTION ViewPanel(arg)
!DEC$ ATTRIBUTES STDCALL, ALIAS:"_viewpanel" :: ViewPanel
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
integer(4),POINTER :: arg
integer(4) returnVal, us
CHARACTER(256) text
LOGICAL retlog
external ViewPanelCallBack
retlog = DLGINIT( IDD_DIALOG2, ViewPanelDlg )
! call DlgSetTitle( ViewPanelDlg, ViewPanelTitle )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_SBS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_SUN, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_MERCURY, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_VENUS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_EARTH, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_MARS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_JUPITER, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_SATURN, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_URANUS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_NEPTUNE, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_RADIO_PLUTO, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_SUN, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_MERCURY, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_VENUS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_EARTH, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_EARTHMOON, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_MARS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_JUPITER, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_SATURN, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_URANUS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_NEPTUNE, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_PLUTO, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_ASTEROIDS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_COMETS, ViewPanelCallBack )
retlog = DlgSetSub( ViewPanelDlg, IDC_CHECK_SPACECRAFT, ViewPanelCallBack )
call ViewPanelSetFocus
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_SUN, (IAND(vCheckViewMask, bitCheckViewSun) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_MERCURY, (IAND(vCheckViewMask, bitCheckViewMercury) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_VENUS, (IAND(vCheckViewMask, bitCheckViewVenus) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_EARTH, (IAND(vCheckViewMask, bitCheckViewEarth) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_EARTHMOON, (IAND(vCheckViewMask, bitCheckViewEarthMoon) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_MARS, (IAND(vCheckViewMask, bitCheckViewMars) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_JUPITER, (IAND(vCheckViewMask, bitCheckViewJupiter) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_SATURN, (IAND(vCheckViewMask, bitCheckViewSaturn) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_URANUS, (IAND(vCheckViewMask, bitCheckViewUranus) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_NEPTUNE, (IAND(vCheckViewMask, bitCheckViewNeptune) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_PLUTO, (IAND(vCheckViewMask, bitCheckViewPluto) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_ASTEROIDS, (IAND(vCheckViewMask, bitCheckViewAsteroids) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_COMETS, (IAND(vCheckViewMask, bitCheckViewComets) .ne. 0))
retlog = DLGSETLOG (ViewPanelDlg, IDC_CHECK_SPACECRAFT, (IAND(vCheckViewMask, bitCheckViewSpacecraft) .ne. 0))
returnVal = DlgModal( ViewPanelDlg ) ! Doesn't return unless cancled (or IDC_event not specified)
ViewPanel = returnVal
ViewPannelRunning = .FALSE.
oButtonView = .FALSE.
vButtonView = .FALSE.
ViewPanelHandle = 0
end FUNCTION ViewPanel
recursive subroutine ViewPanelSetFocus
USE IFLOGM
use GlobalData
implicit none
INCLUDE 'RESOURCE.FD'
integer(4),POINTER :: arg
integer(4) returnVal, us
CHARACTER(256) text
LOGICAL retlog
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_SBS, (vFocusOn .eq. FocusOnSBS))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_SUN, (vFocusOn .eq. FocusOnSun))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_MERCURY, (vFocusOn .eq. FocusOnMercury))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_VENUS, (vFocusOn .eq. FocusOnVenus))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_EARTH, (vFocusOn .eq. FocusOnEarth))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_MARS, (vFocusOn .eq. FocusOnMars))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_JUPITER, (vFocusOn .eq. FocusOnJupiter))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_SATURN, (vFocusOn .eq. FocusOnSaturn))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_URANUS, (vFocusOn .eq. FocusOnUranus))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_NEPTUNE, (vFocusOn .eq. FocusOnNeptune))
retlog = DLGSETLOG( ViewPanelDlg, IDC_RADIO_PLUTO, (vFocusOn .eq. FocusOnPluto))
end subroutine ViewPanelSetFocus
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@jimdempseyatthecove: I am using a modal dialog for the UI, but, unlike yours, it's written in C++. My project does all the UI in C++, and almost all of the computations in Fortran.
After replacing the SendMessage with PostMessage, my app does not hang, so OpenMP is blameless. As far as the second team of threads, this still happens, but repeat computations use the same two teams, even though Wide is called from a different thread each time. I have no explanation for this, but it does what I need.
I'm impressed with your control panel code. It must have been a lot of work. Are you by any chance using a planetary ephemeris?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>but repeat computations use the same two teams, even though Wide is called from a different thread each time.
Then the behavior has changed since I first observed this about 3 years ago with a C# main, spawning/terminating a thread that eventually called a Fortran DLL that used OpenMP. It is likely that Intel has inserted code into the (Windows) TerminateThread function that disbands its OpenMP thread pool. Note, this being the case, your application is encountering excessive overhead in creating and disbanding thread pools on each iteration. It would be much better to create this ancillary thread once, then synchronize its start on each iteration.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@jimdempseyatthecove
>>but repeat computations use the same two teams, even though Wide is called from a different thread each time.
>It is likely that Intel has inserted code into the (Windows) TerminateThread function that disbands its OpenMP thread pool. Note, this being the case, your application is encountering excessive overhead in creating and disbanding thread pools on each iteration. It would be much better to create this ancillary thread once, then synchronize its start on each iteration.
I checked this, and the Windows thread IDs (handles) are unchanged, so threads aren't being created and destroyed. I also verified that after thread termination of the worker thread on the final return of the thread in C++, the second team of OpenMP threads were still there.
Even if threads were being destroyed and created, though, the overhead is negligible in comparison to the Fortran computation's time. Somehow, it seems that OpenMP has managed to keep their thread team intact over worker thread boundaries.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page