# Development of the Object-Oriented Dynamic Simulation Models Using Visual C++ Freeware

Authors: Alexander I. Kozynchenko; Sergey A. Kozynchenko
Journal: Modelling and Simulation in Engineering
 (2016)

---

## Abstract

The paper mostly focuses on the methodological and programming aspects of developing a versatile desktop framework to provide the available basis for the high-performance simulation of dynamical models of different kinds and for diverse applications. So the paper gives some basic structure for creating a dynamical simulation model in C++ which is built on the Win32 platform with an interactive multiwindow interface and uses the lightweight Visual C++ Express as a free integrated development environment. The resultant simulation framework could be a more acceptable alternative to other solutions developed on the basis of commercial tools like Borland C++ or Visual C++ Professional, not to mention the domain specific languages and more specialized ready-made software such as Matlab, Simulink, and Modelica. This approach seems to be justified in the case of complex research object-oriented dynamical models having nonstandard structure, relationships, algorithms, and solvers, as it allows developing solutions of high flexibility. The essence of the model framework is shown using a case study of simulation of moving charged particles in the electrostatic field. The simulation model possesses the necessary visualization and control features such as an interactive input, real time graphical and text output, start, stop, and rate control.


---

## Body

## 1. Introduction

This paper is primarily intended for the researchers who focus on the development of scientific continuous and hybrid simulation models of dynamical systems and have programming skills in C++ and Windows. The dynamical systems evolving with the flow of time are described by sets of differential equations, ordinary or partial ones. Such systems are the main part of diverse modelling applications belonging to different scientific and engineering domains as high-energy and accelerator physics (see, e.g., Hajari et al. [1]), ship navigation (Sandaruwan et al. [2]), electric power systems (Yusop et al. [3]), mechatronics and robotics (Ferretti et al. [4]), aerospace (Kozynchenko [5]), process control (Sivakumaran and Radhakrishnan [6]), and so forth. These applications, being characterized by advanced theoretical level of underlying mathematical models, can be multidomain and have rather complex structures including frequent decision-making and intelligent control units.The problem of choice of programming language and simulation environment which could be most suitable for developing such complex and unconventional models from the viewpoint of their universality, flexibility, effectiveness, and interactive features comes to the fore. There exists specialized ready-made software, such as Maple, Mathematica, MathCAD, and above-mentioned Matlab and Simulink, which provides a range of opportunities sufficient for a number of applications of average complexity, especially for the models consisting of standard subcomponents. On the other hand, a number of domain-specific languages have been developed for the simulation purposes, such as the one described by Ewald and Uhrmacher [7]. However, it seems rather difficult to find the adequate tools for more complicated models. Even the use of thedeclarative languages like Modelica [8] is also questionable in this case, because the solution based onimperative (and compiled) languages, the C++ first of all, usually provides better effectiveness and flexibility. An example of applying the imperative language Object Pascal (Delphi) to the problem of simulation and optimization of the particle beam emitter has been shown by Kozynchenko and Svistunov [9]. However, the rapid development environments like Delphi or its counterpart C++ Builder are proprietary software, whereas the use of open or free tools would be more suitable in case of lack of funding.It should be noted that the problem of numerical simulation and visualization using Microsoft Visual C++.NET (which is a proprietary software) has been considered by Salleh et al. [10, 11]. The main feature of the approach discussed in the book is the support of MFC (Microsoft Foundation Classes) library in developing the graphical user interface applications. However, the essential issue of simulation of dynamical systems with the real time graphical output and simulation rate control is not addressed in the book.To sum up, we can say that the problem of developing an appropriate flexible interactive graphical interface and framework for complex object-oriented dynamical simulation models still remains actual. This interface and framework should provide the following desirable features and properties for the dynamical simulation models focused on complex scientific and engineering problems:(1)
Usage of efficient (presumably compiled), flexible, and widespread programming language, as well as a mainstream integrated development environment (IDE).(2)
Ability to draw graphs in progress, tracing out the change of state variables and other parameters with respect to the simulation time.(3)
Ability to interrupt the program execution, to resume and continue it, and to change the simulation rate over the time.(4)
Ability to make required inputs in the course of simulation, using several windows if necessary.(5)
Ability to display the selected numerical output in progress and simultaneously with displaying the graphical output.(6)
Usage of open-source and/or nonproprietary software.In the paper, we try to show an example of a simulation framework that possesses the above features. The modelling application is taken from electrodynamics domain and describes the motion of charged particles in the field of an electrostatic lens. The model is developed in the standard unmanaged C++ using the Visual C++ Express 2010 Edition as a development environment. When creating a new project, the “Empty Project” template has been selected for simplicity, because it only fixes the file structure and, for the rest, allows the developer to create the project of own type. One can choose the “Win32 Project” template as well, and on the “Application settings” page the option “Empty project” should be selected. We focus on a Win32-based application, that is, an application that handles Windows messages directly using message loops. The pure Win32 C++ code is used to create the project from scratch. Such an alternative as writing a code with the help of the MFC library is not available, because the MFC is not supported in the Express Edition. The designed program relates to so-called dialog-based applications which use a dialog box as a main window. The project consists of the set of header files,field.h,particle.h,rk4_4eq.h, andresource.h, two resource files,script.rc andscript2.rc, and a source file,main.cpp.


## 2. Structure of the Simulation Model

First of all, the general outline of the simulation model to be studied is provided below. The diagram shown in Figure1 displays the class and function relationships and is helpful in introducing the subject. The model has an ordinary structure of the desktop dialog-based Win32 two-threaded programs and includes the following global functions and classes:(i)
The functionWinMain as an entry point at the main thread.(ii)
The application-defined callback functionsModalDlgProc andModelessDlgProc that process the messages in the modal and modeless dialog boxes.(iii)
The application-defined callback functionThreadProc that is executed by the second thread and performs the application-specific algorithms.(iv)
The application classesField andParticle describing the motion of a charged particle in the field of the electrostatic immersion lens.(v)
The function templateRK4_4eq which defines a Runge-Kutta solver carrying out one integration step for a set of ordinary differential equations (ODEs).(vi)
The helper functionDrawEquipotentialLines used for the field visualization.(vii)
The STL vector containervpp to keep theParticle’s objects.Again, the model includes also global variables ::pause and ::sleep to control the simulation process and two global variables ::particleListBox and ::particleModelessBox which denote the particles whose data is to be shown at the list box and the modeless dialog box correspondingly. For the sake of completeness, the other four Windows functions are shown in the diagram:DialogBox,CreateDialog,CreateThread, andInvalidateRect. The Windows functions marked at the diagram with the sign “Win32” are placed in the Windows-specific header file <windows.h> that adds the Win32 API to the project. This diagram does not follow the UML (Unified Modelling Language) standards completely because we tried to show the chains of function calls in one diagram too, not only the class relationships. The description of the model presented below is illustrated by a number of listings shown in Algorithms 2–9 and in Appendix. For simplicity, the code fragments do not contain some features being important but not affecting the program logic, like exception handling,private class sections, andset andget functions.Figure 1
The block diagram showing relationships between classes, objects, functions, and global variables being included in the simulation model.


## 3. Description of the Modeling Application

Below we consider in more detail a physical model to be simulated. This is a two-dimensional model that includes a number of hydrogen nuclei (protons) moving in the axial-symmetric electrostatic field of the immersion lens (see, e.g., Humphries Jr. [12], §6.6). The model consists of two classes,Field andParticle, whose objects are created in the program.


### 3.1. ClassField

The electrostatic field is formed by two coaxial cylindrical electrodes having the potentials 0 and −1000 V. The inner diameter and the length of each electrode are 0.06 m and 0.1144 m correspondingly, and they are separated by the gap of 0.0112 m long. On the axis of the left electrode, the needle-like particle emitter of 0.063 m long is situated. The middle part of the immersion lens is shown in the screenshot in Figure2(a). The field of the lens is described in a classField which is defined in the header filefield.h. The class includes a two-dimensional array u of the field potentials at the nodes of the square grid with the spacingh = 0.003 m plotted at the planeyz, the cross section, through the diameter, of the immersion lens. These potentials are calculated by solving the Laplace equation with the use of the finite difference method and Liebmann’s iteration process (see, e.g., Veerarajan and Ramachandran [13], Chapter 11). The classField contains also arrays of pairs (yi, zi) of the coordinates of the ith point belonging to one of the equipotential lines to be plotted for potentials -10,-25,…,-990 V. A data memberzMax being equal to the length of the immersion lens sets the maximal distance of particle motion along z-axis. This variable is used in the second thread in the functionThreadProc as a termination condition of simulation for the given particle (see Algorithm 9, line 21.9).Figure 2
Screenshot of the graphic user interface (a) and a magnified view of the part of modal dialog box with control items (b).
(a)
(b)


### 3.2. ClassParticle

Another application-related class is the classParticle defined in the header fileparticle.h (Algorithm 2). The class contains all variables and constants being necessary for calculating the motion of a proton in the electrostatic field. These are time t, coordinates y, z, velocity v and its components vy and vz, kinetic energy W, proton mass m and charge q presented asstatic constants, components of electrostatic force fy, fz, the dimensions of the lens (lengthOfElectrode andlengthOfGap), a set of variables (such asuLeft andyCellTop) used in calculating the forces in the helper functionFzFy, a field grid spacing dy=dz, and a control variablekVy which is used in theParticle’s constructor to set the initial values of velocity components vy and vz under the given energy W0 by the formulas:(1)v=2W0·1.6022·10-19m,vz=v1+kvy2,vy=kvyvz.The Boolean flag variablestop initialized asfalse shows whether the particle moves inside the lens; it becomestrue when it reaches the rightmost edge of the lens at zi≥Max and so it falls out of the further simulation. Additionally, the class includes a nested structureData, objects of which keep the information about the current particle’s state and are placed in the STLvector containerhistory for holding the particle’s state during the simulation. The data members are initialized in the combined (i.e., both default and parameterized) constructor. Other member functions are four right-hand sides of the ODE’s set:DzDt,DyDt,DvzDt, andDvyDt. The class also contains a helper functionFzFy computing the values of electrostatic forces fz and fy used in the member functionsDvzDt andDvyDt.


## 3.1. ClassField

The electrostatic field is formed by two coaxial cylindrical electrodes having the potentials 0 and −1000 V. The inner diameter and the length of each electrode are 0.06 m and 0.1144 m correspondingly, and they are separated by the gap of 0.0112 m long. On the axis of the left electrode, the needle-like particle emitter of 0.063 m long is situated. The middle part of the immersion lens is shown in the screenshot in Figure2(a). The field of the lens is described in a classField which is defined in the header filefield.h. The class includes a two-dimensional array u of the field potentials at the nodes of the square grid with the spacingh = 0.003 m plotted at the planeyz, the cross section, through the diameter, of the immersion lens. These potentials are calculated by solving the Laplace equation with the use of the finite difference method and Liebmann’s iteration process (see, e.g., Veerarajan and Ramachandran [13], Chapter 11). The classField contains also arrays of pairs (yi, zi) of the coordinates of the ith point belonging to one of the equipotential lines to be plotted for potentials -10,-25,…,-990 V. A data memberzMax being equal to the length of the immersion lens sets the maximal distance of particle motion along z-axis. This variable is used in the second thread in the functionThreadProc as a termination condition of simulation for the given particle (see Algorithm 9, line 21.9).Figure 2
Screenshot of the graphic user interface (a) and a magnified view of the part of modal dialog box with control items (b).
(a)
(b)


## 3.2. ClassParticle

Another application-related class is the classParticle defined in the header fileparticle.h (Algorithm 2). The class contains all variables and constants being necessary for calculating the motion of a proton in the electrostatic field. These are time t, coordinates y, z, velocity v and its components vy and vz, kinetic energy W, proton mass m and charge q presented asstatic constants, components of electrostatic force fy, fz, the dimensions of the lens (lengthOfElectrode andlengthOfGap), a set of variables (such asuLeft andyCellTop) used in calculating the forces in the helper functionFzFy, a field grid spacing dy=dz, and a control variablekVy which is used in theParticle’s constructor to set the initial values of velocity components vy and vz under the given energy W0 by the formulas:(1)v=2W0·1.6022·10-19m,vz=v1+kvy2,vy=kvyvz.The Boolean flag variablestop initialized asfalse shows whether the particle moves inside the lens; it becomestrue when it reaches the rightmost edge of the lens at zi≥Max and so it falls out of the further simulation. Additionally, the class includes a nested structureData, objects of which keep the information about the current particle’s state and are placed in the STLvector containerhistory for holding the particle’s state during the simulation. The data members are initialized in the combined (i.e., both default and parameterized) constructor. Other member functions are four right-hand sides of the ODE’s set:DzDt,DyDt,DvzDt, andDvyDt. The class also contains a helper functionFzFy computing the values of electrostatic forces fz and fy used in the member functionsDvzDt andDvyDt.


## 4. Description of the Two-Threaded Simulation Engine

Algorithm3 lists the source filemain.cpp that contains the functionWinMain, as well as a set of global variables, constants, and function declarations (lines 10.3–27.3). Among them there are handles (descriptors) to dialog boxeshModalDlg andhModelessDlg, a handlehThread to a thread which carries out the model computations, control variablespause andsleep responsible for interrupting, resuming, and changing the rate of the simulation, constantsheight andwidth that determine the size of a plot rectangle where the particle trajectories, electrodes, and the field of the lens will be drawn, and scale factorsmy,mz, andkzy used in displaying the field. Also noteworthy is an STLvector containervpp which is used for keeping a set ofParticle’s objects taking part in the simulation. A global variableparticleModelessBox is introduced to provide the particle’s data numerical output at the modeless dialog window, along with a global variableparticleListBox that indicates the selected particle whose numerical data is expected to be displayed in the list box placed at the modal dialog window.The functionWinMain first creates a dynamically allocated object of the classField, initializing the static pointerParticle::pF (line 31.3). Simultaneously, the electrostatic field is computed in the invoked constructor of the classField. Furthermore,WinMain creates a modal dialog box from the dialog box template resource, using the functionDialogBox. The corresponding resource-definition script (filescript.rc) is listed in Algorithm 4. It contains most of resources relating to the modal dialog box and forming the graphical user interface (GUI), such as Windows controls (child windows): buttons, edit controls, text controls, a list box, and a trackbar. In Figures 2(a) and 2(b), a screenshot of the dialog boxes in the process of simulation is shown (a) together with a part of the modal dialog box with the most important GUI controls and associated resources’ IDs (b). The functionWinMain includes also a message loop that retrieves the Windows messages from the message queue (lines 33.3–38.3). If the messages are intended for themodeless dialog box, they should not be processed at the program’s message loop. In this case, the functionIsDialogMessage sends the messages directly to the modeless dialog box avoiding the program’s message loop, as is done using theif statement in line 34.3.


### 4.1. Description of the Modal Dialog Procedure

Next we describe the modal dialog box window procedureModalDlgProc; the definition of that is listed in Algorithms 5–8. The function has the following heading:int CALLBACK ModalDlgProc(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam).The function’s body begins with definitions of the variables used in designing the graphical interface. These are a handlehDC to the device context, a structure defining a set of graphic objects, with some of them also defined here (pens, brushes, and fonts), a variablepsPaint of type PAINTSTRUCT keeping the information necessary for drawing in a client area of the modal dialog box, a variablerect of type RECT used to keep coordinates of the client area, and temporary text buffers. It should be noted that most of the variables above must be declared asstatic ones; otherwise the graphical information will not be displayed properly. The basic part of the dialog box procedure is aswitch statement with the controlling expression. The function is intended to be processing the Windows messages sent to the dialog box and passed through the second formal parametermessage. The first message is WM_INITDIALOG which is sent by the system immediately before displaying the dialog box and carries out the required initializations. In the case of sending this message, the following actions are made:(i)
Creation of the second thread with the handlehThread in the suspended state (lines 27.5–32.5).(ii)
Initialization of the global handle to the modal dialog boxhModalDlg (line 33.5) in order to be used further in the thread procedure as a control variable.(iii)
Creation of the modeless dialog box with the global handlehModelessDlg, which can display more detailed console-like output for the particles selected during the simulation (lines 34.5-35.5).(iv)
Completion of creating an edit box (IDC_EDIT_ParticleModelessBox) with an up-down (spin) control (IDC_UpDown) which is sometimes referred to as a “spinner” control; this is done by calling the functionsSendMessage to set the edit box as a buddy one and to set the range and the initial zero value (lines 36.5–40.5).(v)
An analogous procedure accomplished concerning the trackbar control which provides changing the rate of simulation: the functionsSendMessage in the lines 48.5–51.5 define the range and set the slider to the initial position between two tick marks; anotherSendMessage function gets the slider’s logical position that is assigned to the global variablesleep (lines 52.5-53.5).(vi)
Statements in lines 42.5–47.5 and in lines 54.5-55.5 setting the initial values for all edit windows.


#### 4.1.1. Processing the Control Related MessagesWM_COMMAND

Another important case we need to focus on is processing the messageWM_COMMAND which is sent when the user clicks a button at the modal dialog box. If the user chooses a button “Create a new particle,” the functionGetDlgItemText retrieves strings from the corresponding edit windows with control identifiers IDC_EDIT_W0 and IDC_EDIT_kVy to the text buffer (Algorithm 6, lines 8.6 and 10.6). Then the strings are converted into numerical values of the variablesW0 andkVy (lines 9.6 and 11.6) and are passed to theParticle’s constructor. The latter creates aParticle’s object that will be kept in the global STLvector containervpp:12.6   vpp.push_back(Particle(W0, kVy));The size of this container, that is, the total number N of particles involved in the simulation, is then passed to the edit window with an identifier IDS_EDIT_PartNum to be displayed (lines 13.6-14.6).The considered simulation model allows displaying not only graphs but also numerical data in the console-like fashion. Therefore, after at least one particle is created, the user may choose a particle whose state data could be displayed both at the above-mentioned modeless dialog box with the handlehModelessDlg and in the list box placed at the modal dialog box. It is accomplished in the edit box with the up-down control, where the required particle is chosen by the spin button. When the user clicks the button “Confirm,” the numeric input, that is, the particle’s number, is retrieved by the functionGetDlgItemInt and is assigned to the variableparticleModelessBox (lines 18.6-19.6). The particle chosen for the first time, that is, under the first click of the button “Confirm,” is selected to be displayed in the list box. The number of this particle kept in the variableparticleModelessBox is assigned to the variableparticleListBox in line 23.6 (and made visible in line 24.6) which is then used in both threads, remaining unchanged during the simulation. It should be noted that the user can change the particle, whose data are displayed at the modeless dialog box, at any time, using the above procedure.The modal dialog box contains also two buttons “Run” and “Pause” placing an important part in controlling the simulation process. When the user clicks the button “Run” the program checks if the global variablepause equalstrue. If so, the functionResumeThread is called and the value ofpause is reversed tofalse (lines 27.6–31.6). As a result, the hitherto suspended thread with the handlehThread is resumed and executes the functionThreadProc carrying out the model calculations. In the case of a need to stop the simulation temporarily, the user may choose the button “Pause.” Since the variablepause has thefalse value until this moment, the functionSuspendThread is invoked, thepause reverts totrue (lines 33.6–37.6), and all calculations in the functionThreadProc will stop. And, at last, if the user clicks a “Cancel” button, the dialog box procedure closes the dialog box by calling theEndDialog function (line 40.6) as it does in case of processing the WM_CLOSE message (line 2.6). Next up is the case of processing another windows message WM_HSCROLL that is sent if the user wants to change the simulation rate and moves the slider of the trackbar control to the left to increase the rate or to the right to slow it down. The simulation rate is controlled by the global variablesleep used further in the functionThreadProc. As mentioned above,sleep is assigned the value returned by the functionSendMessage in lines 45.6-46.6. For information, this value is also shown at the edit box with an identifier IDC_EDIT_Sleep (lines 48.6-49.6).


#### 4.1.2. Painting at the Modal Dialog Box: Processing the MessageWM_PAINT

Drawing graphical objects at the modal dialog box is carried out when the system generates a messageWM_PAINT. It is done either implicitly when the window must be updated after sizing, moving, and so forth, or the application explicitly requests an update, invoking, for example, the functionInvalidateRect. In our case, these key control actions are accomplished in the functionThreadProc (Algorithm 9, lines 36.9–38.9).The typical processing of theWM_PAINT starts with calling the functionBeginPaint (Algorithm 6, line 51.6) which passes the painting information to the variablepsPaint and returns the handlehDC to the device context. Then a number of functions are called to prepare the client area at the modal box to draw the interface elements and data (lines 52.6–55.6). When calling the functionGetClientRect, a rectangle of the client area gets its coordinates; calling the functionSetMapMode sets the mapping mode between page space and device space. In case of a parameter MM_ISOTROPIC logical units are mapped to device (e.g., display) units with equally scaled axes. The functionSetWindowExtEx sets the maximum values for the horizontal and vertical axes of the window in logical units, whereas the functionSetViewportExtEx does the same in device units for the view port, that is, thedevice coordinate system. So, using both functions determines the scaling factor between the window and the view port.Shown below (Algorithm7, lines 2.7–5.7) is the fragment that draws the caption of the simulation application “A simulation model of the motion….” Next, in lines 6.7–50.7, the graphic functions are invoked such asRectangle, MoveToEx, andLineTo. These functions provide drawing a plot rectangle, axes, gridlines, and tick marks (see the screenshot in Figure 2(a)) necessary for displaying electrodes, field lines, particle’s trajectories, and so on. The equipotential lines are drawn by calling the helper functionDrawEquipotentialLines (lines 53.7-54.7). The principal painting, that is, drawing the particles’ trajectories in real time, is carried out in the fragments placed between lines 2.8 and 14.8 in Algorithm 8. Both the global vectorvpp and theParticle’s data members, vectorshistory keeping the particles’ states, are involved in the drawing of the trajectories y(z) in the nestedfor loop. The processing of the message WM_PAINT is completed with the fragment written in lines 17.8–21.8 which displays thevpp’s index of a particle whose data is to be output at the list box. The final statement of the processing is the call ofEndPaint.When the modal dialog box is being destroyed and is removed from the screen, the messageWM_DESTROY is sent to the functionModalDlgProc. The processing of this message includes the set of function calls ofDeleteObject to delete the logical pens and the brush.


### 4.2. Description of the Modeless Dialog Box with the Console-Like Output

The modeless dialog box can be shown even while the modal dialog box exists. Its purpose in this application is to display the numerical data describing the history of the state of a particle having been selected at the edit box with an identifierIDC_EDIT_ParticleModelessBox during the simulation (see Figure 2(b)). The output is carried out by the window functionModelessDlgProc in the console-like fashion and requires the vertical and horizontal scrolling to get more display space the modeless box can provide. That is, vertical and horizontal scroll bars are used in the modeless box.The window function has the similar structure as in case of the modal dialog. It processes the messages in theswitch selection statement that has eight branches,case labels for processing the messages WM_INITDIALOG, WM_VSCROLL, WM_HSCROLL, WM_PAINT, and so on. As the most of the procedure code contains the common, near standard fragments (see, e.g., Petzold [14], Chapter 4, section “Scroll Bars”), the listing of the procedure is placed to Appendix. However, a short description of the procedure is still given below. The resource script placed in the filescript2.rc and associated with the modeless dialog contains styles WS_VSCROLL and WS_HSCROLL among other ones:STYLE DS_SETFONT ∣ WS_VISIBLE ∣ WS_CAPTION ∣WS_SYSMENU ∣ WS_VSCROLL ∣ WS_HSCROLL ∣WS_MINIMIZEBOX ∣ WS_OVERLAPPEDWINDOWA number of variables and constants are defined in the window procedure. The constantNUMLINES is the maximal number of lines of text involved into the vertical scrolling. The variabletm of type TEXTMETRIC defines the font and rows parameters such as width and height of characters and space between characters. The static variablesyPos andxPos are current positions of the scroll bar thumbs for vertical and horizontal scroll bars correspondingly, andyInc contains an incremental value for updatingyPos. The messages WM_VSCROLL and WM_HSCROLL are sent to the window procedure if the scroll events occur either in the window’s vertical scroll bar or in the horizontal scroll bar. Processing these messages made within nestedswitch statements (see Appendix, Algorithm 11, lines 46.11–63.11 and 73.11–89.11) with the parameter notification code SB_TOP, SB_BOTTOM, and so forth results in updatingyPos andxPos.When calling the functionScrollWindow in lines 68.11 and 96.11, the system invalidates the client area and generates the WM_PAINT message. One more origin of a WM_PAINT message is the thread procedure, where the functionInvalidateRect is called (see Algorithm 9, line 38.9) after completing the nestedfor loop of one step integration of charged particles’ motion. The code written in the WM_PAINT selection brunch provides drawing the full set of text lines from the beginning of simulation to the current instant. Each text line outputs the time, position, velocity, and kinetic energy of a particle (i.e., the set of t, y, z, vy, vz, v, W).


### 4.3. Thread Procedure as the Physics Engine

The physics engine of the considered simulation model is placed in the functionThreadProc. The function includes thewhile loop (Algorithm 9, lines 4.9–40.9) providing the simulation until the last particle reaches the rightmost edge of the lens. The nestedfor loop (lines 5.9–25.9) carries out one step of integration for all particles which did not reach the right lens edge (i.e., zi<zMax). When a particle gets moved beyond this boundary, its data memberstop is set totrue; that is, the particle is excluded from simulation, and the variablecounter keeping the number of excluded particles is incremented. The integration is carried out by the global function templateRK4_4eq (lines 7.9–10.9). This function is a solver that processes one step of integration of the system of four ODEs by the Runge-Kutta method of the 4th order. The function template is defined in the header filerk4_eq.h and has the prototype as shown in Algorithm 1.Algorithm 1
t
emplate
<
class
T>
inline void
RK4_4eq(T* p, //pointer to an object of the class
T
doubleh, //time step of integration (htin the class Particle)
doubleT::*pX0, // pointer to the independent variable-timet
doubleT::*pX1, // pointer to the state variable-velocityvz
doubleT::*pX2, // pointer to the state variable-velocityvy
doubleT::*pX3, // pointer to the state variable-coordinatez
doubleT::*pX4, // pointer to the state variable-coordinatey
void(T::*pPrecompute)(),//pointer to the helper functionFzFy
double(T::*pF1)(), //pointer to the equation of motionDvzDt
double(T::*pF2)(), //pointer to the equation of motionDvyDt
double(T::*pF3)(), //pointer to the equation of motionDzDt
double(T::*pF4)() //pointer to the equation of motionDyDt
);Algorithm 2:The header file particle.h defining the class Particle.
1.2#pragma once
2.2#include"field.h"
3.2#include"rk4_4eq.h"
4.2#include<vector>
5.2
6.2classParticle
7.2 public:
8.2  static const doublem, q; //mass and charge of a particle
9.2  doubleW0, W, v;
10
.2  doublet, z, y, vz, vy;
11
.2  structData
12
.2   doublet, z, y, vz, vy, v, W;
13
.2  currentData;
14
.2  doublefz, fy; //components of an electric force
15
.2  doubledz, dy; //spacing of the field grid along z and y axes
16
.2  staticField* pF;
17
.2  doubleuLeft, uRight, uTop, uBottom;
18
.2  doubleyCellTop, yCellBottom, zCellLeft, zCellRight;
19
.2  intiTopLeft, jTopLeft;
20
.2  vector<Data> history;
21
.2  doublekVy;
22
.2  boolstop;
23
.2  Particle(doubleW0 = 25., doublekVy = 0.): W0(W0), W(W0),
24
.2     t(0.), z(0.), y(0.), kVy(kVy), fz(0.), fy(0.),
25
.2     v(sqrt(2./m*W0*1.6022e-19)),
26
.2     vz(v/sqrt(1.+kVy*kVy)), vy(kVy*vz), stop(false)
27
.2   dy = dz = pF->h;
28
.2   zCellLeft = zCellRight = 0.;
29
.2   if(y == 0)
30
.2    yCellTop = yCellBottom = 0.;
31
.2
32
.2  voidFzFy(); //computing the force components fy and fz
33
.2  doubleDzDt()  return  vz;
34
.2  doubleDyDt()  return  vy;
35
.2  doubleDvzDt()  return  1./m*fz;
36
.2  doubleDvyDt()  return  1./m*fy;
37
.2;
38
.2const doubleParticle::m = 1.6726e-27;  //kg
39
.2const doubleParticle::q = 1.6022e-19;  //C (Coulomb)
40
.2Field* Particle::pF = NULL;Algorithm 3:The source file main.cpp containing the entry point to the program: function WinMain.
1.3#include<windows.h>
2.3#include<iostream>
3.3#include"resource.h"
4.3#include"particle.h"
5.3#include"field.h"
6.3#include<CommCtrl.h>
7.3#pragma comment(lib, "comctl32.lib")
8.3using namespace  std;
9.3
10
.3HWND hModalDlg, hModelessDlg = 0;
11
.3INT_PTR nResult;
12
.3HANDLE hThread;
13
.3bool  pause  =  true; // a control to make the pause in execution
14
.3int  sleep = 0;  //a control affecting the rate of running
15
.3const double  my = 200./0.06, mz = my, kzy = 0.004;
16
.3const int  height = 200, height2 = (int)(height*0.5),
17
.3                 width=(int)(height*28./15.);
18
.3const int  zLeft = 80, yTop = 70; //coordinates of the drawing area
19
.3vector<Particle> vpp; //container keeping the set of particles
20
.3int  particleModelessBox = -1;
21
.3int  particleListBox = -1;
22
.3char  bufListBox[180];
23
.3
24
.3int  CALLBACK ModalDlgProc(HWND, UINT, WPARAM, LPARAM);
25
.3int  CALLBACK ModelessDlgProc(HWND, UINT, WPARAM, LPARAM);
26
.3DWORD CALLBACK ThreadProc(LPVOID);
27
.3void  DrawEquipotentialLines(HDC, HFONT, LOGFONT, HPEN, Field*);
28
.3
29
.3int  WINAPI WinMain(HINSTANCE hI, HINSTANCE hI2, LPSTR p,  int  n)
30
.3  MSG msg;
31
.3  Particle::pF = new Field();
32
.3  nResult = DialogBox(NULL, "MYDIALOG", 0, (DLGPROC)ModalDlgProc);
33
.3  while(GetMessage(&msg, NULL, 0, 0) > 0)
34
.3   if(hModelessDlg == 0 || !IsDialogMessage(hModelessDialog, &msg))
35
.3   TranslateMessage(&msg);
36
.3   DispatchMessage(&msg);
37
.3
38
.3
39
.3  delete Particle::pF;
40
.3  returnmsg.wParam;
41
.3Algorithm 4:The resource script file script.rc for the modal dialog.
1.4#include<windows.h>
2.4#include"resource.h"
3.4
4.4MYDIALOG DIALOGEX 0, 0, zW, yW
5.4STYLE DS_MODALFRAME|WS_CAPTION|WS_SYSMENU| WS_MINIMIZEBOX
6.4CAPTION "MyDialogWindow"
7.4FONT 8, "MS Shell Dlg"
8.4
9.4 PUSHBUTTON "Create a new particle", IDB_NewParticle,
10
.4                        210, 363, 70, 14
11
.4 PUSHBUTTON "Confirm",   IDB_Confirm,    310, 400, 50, 14
12
.4 PUSHBUTTON "Run",     IDB_Run,      50, 430, 50, 14
13
.4 PUSHBUTTON "Pause",    IDB_Pause,  135, 430, 50, 14
14
.4 PUSHBUTTON "Cancel",      IDB_Cancel  220, 430, 50, 14
15
.4 EDITTEXT IDC_EDIT_W0      150, 353, 40, 15, ES_CENTER
16
.4 EDITTEXT IDC_EDIT_kVy     150, 375, 40, 15, ES_CENTER
17
.4 EDITTEXT IDC_EDIT_PartNum 390,363,25,15, ES_CENTER|ES_READONLY
18
.4 EDITTEXT IDC_EDIT_ParticleToModelessBox  270,400,30,15,ES_CENTER
19
.4 EDITTEXT IDC_EDIT_Sleep 570,400,40,15, ES_CENTER|ES_READONLY
20
.4 LISTBOX  IDC_ListBox   550, 70, 200, 250, WS_VSCROLL
21
.4 CONTROL "" IDC_UpDown, "msctls_updown32",
22
.4         UDS_SETBUDDYINT|UDS_ALIGNRIGHT,   0, 0, 0, 0
23
.4 CONTROL "" IDC_Trackbar, "msctls_trackbar32", WS_VISIBLE|
24
.4              WS_TABSTOP|TBS_HORZ, 400, 400, 150, 30
25
.4 LTEXT "Set initial data∖nfor a new particle:", 99, 50,360,65,20
26
.4 LTEXT "W0 = ",  100,  118, 356, 30, 10
27
.4 LTEXT "Vy/Vz = ", 101,  118, 378, 30, 10
28
.4 LTEXT "Total number N∖nof created particles:", 102,
29
.4                        315, 360,  70, 20
30
.4 LTEXT "Indicate the particle ( from 0 to N-1 )∖
31
.4   whose data you want to display: ", 103,   50, 400, 220, 10
32
.4 LTEXT "Displaying data of the first selected particle:", 104,
33
.4                       550,  55, 160,  10
34
.4 LTEXT "0 V",105,          150,58,  25,10
35
.4 LTEXT "-1000 V", 106,           360,58,25,10
36
.4 LTEXT "Simulation speed", 107,       445, 385, 70,10
37
.4 LTEXT "Increase”, 108,            410, 420,35,10
38
.4 LTEXT“Slowdown", 109,            508, 420,35,10
39
.4 LTEXT "Delay, ms", 110,           570, 385,40,10
40
.4 LTEXT "z, m", 111,               463, 169,15,10
41
.4 LTEXT "y, m", 112,             60,52,15,10
42
.4 LTEXT "0",    113,              70, 162,5,10
43
.4 //Two sets of LTEXT controls for displaying the numerical
44
.4 //values for both y-gridlines and z-tick marks of the plot.
45
.4 //Relating to the y-gridline:
46
.4 LTEXT "0.01", 114,    62, 129, 15, 10
47
.4 ...
48
.4 LTEXT "-0.03", 119,    60, 255, 16, 10
49
.4 //Relating to the z-tick marks:
50
.4 LTEXT "0.00", 120,   73, 288, 15, 10
51
.4 ...
52
.4 LTEXT "0.11", 131,   438, 288, 15, 10
53
.4Algorithm 5:Modal dialog box: function ModalDlgProc (part 1).
1.5int  CALLBACK ModalDlgProc(HWND hwnd, UINT message,
2.5             WPARAM wParam, LPARAM lParam)
3.5 static  HDC hDC;
4.5 PAINTSTRUCT psPaint;
5.5 RECT rect;
6.5 static  HBRUSH hBlackBrush=(HBRUSH)GetStockObject(BLACK_BRUSH),
7.5 g_hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
8.5 static  HPEN hBlackPen = (HPEN)GetStockObject(BLACK_PEN),
9.5 hBlackThickPen = CreatePen(PS_SOLID, 5, RGB(0,0,0)),
10
.5 hWhitePen = CreatePen(PS_SOLID,(int)0.5, RGB(255, 255, 255)),
11
.5 hGreyPen = CreatePen(PS_SOLID,  (int)0.5, RGB(200, 200, 200)),
12
.5 hPinkPen = CreatePen(PS_SOLID,  (int)0.5, RGB(255, 150, 150)),
13
.5 hBluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
14
.5 static  HFONT fontPotential, fontCaption;
15
.5 static  LOGFONT lf, lf2;
16
.5 strcpy_s(lf.lfFaceName, "MS Sans Serif");
17
.5 lf.lfHeight = 8;
18
.5 strcpy_s(lf2.lfFaceName, "Century");
19
.5 lf2.lfHeight = 18;
20
.5 lf2.lfWeight = FW_MEDIUM;
21
.5 char  caption[]= "A simulation model of the motion of charged∖
22
.5  particles in the electrostatic field of an immersion lens";
23
.5 char  bufferLB[3], buffer[500];
24
.5 Particle temp;
25
.5 switch(message)
26
.5  case  WM_INITDIALOG:
27
.5  hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)
28
.5            &ThreadProc, NULL, CREATE_SUSPENDED, 0);
29
.5  if(hThread == NULL)
30
.5   MessageBox(0,"Error Creating Thread","Message",MB_OK);
31
.5  return  1;
32
.5
33
.5  hModalDlg = hwnd;
34
.5  hModelessDlg = CreateDialog(0, "MODELESS_DIALOG", 0,
35
.5                   (DLGPROC)ModelessDlgProc);
36
.5  SendMessage(GetDlgItem(hwnd, IDC_UpDown), UDM_SETBUDDY,
37
.5  (WPARAM)GetDlgItem(hwnd,IDC_EDIT_ParticleModelessBox),0);
38
.5  SendMessage(GetDlgItem(hwnd,IDC_UpDown),
39
.5                      UDM_SETRANGE, 0, 100);
40
.5  SendMessage(GetDlgItem(hwnd, IDC_UpDown),UDM_SETPOS,0, 0);
41
.5  int  pLB;
42
.5  sprintf_s(buffer, "%.2f", temp.W0);
43
.5  SetDlgItemText(hwnd, IDC_EDIT_W0, buffer);
44
.5  sprintf_s(buffer, "%.2f", temp.kVy);
45
.5  SetDlgItemText(hwnd, IDC_EDIT_kVy, buffer);
46
.5  sprintf_s(buffer, "%d", 0);
47
.5  SetDlgItemText(hwnd, IDC_EDIT_PartNum, buffer);
48
.5  SendMessage(GetDlgItem(hwnd, IDC_Trackbar), TBM_SETRANGE,
49
.5                    TRUE, MAKELONG(0, 1000));
50
.5  SendMessage(GetDlgItem(hwnd, IDC_Trackbar), TBM_SETPOS,
51
.5                           TRUE, 200);
52
.5  sleep = SendMessage(GetDlgItem(hwnd, IDC_Trackbar),
53
.5                        TBM_GETPOS, 0, 0);
54
.5  sprintf_s(buffer, "%d", sleep);
55
.5  SetDlgItemText(hwnd, IDC_EDIT_Sleep, buffer);
56
.5  break;Algorithm 6:Modal dialog box: function ModalDlgProc (part 2).
1.6 case  WM_CLOSE:
2.6  EndDialog(hwnd, nResult);
3.6  break;
4.6 case  WM_COMMAND:
5.6  double  kVy, W0;
6.6  switch(LOWORD(wParam))
7.6  case  IDB_NewParticle:
8.6   GetDlgItemText(hwnd,IDC_EDIT_W0,buffer,sizeof(buffer));
9.6   W0 = atof(buffer);
10
.6   GetDlgItemText(hwnd, IDC_EDIT_kVy, buffer,sizeof(buffer));
11
.6   kVy = atof(buffer);
12
.6   vpp.push_back(Particle(W0, kVy));
13
.6   sprintf_s(buffer, "%d", vpp.size());
14
.6   SetDlgItemText(hwnd, IDC_EDIT_PartNum, buffer);
15
.6   break;
16
.6  case  IDB_Confirm:  //the button  “Confirm”  is pressed
17
.6   if(vpp.empty())  break;
18
.6   particleModelessBox = GetDlgItemInt(hwnd,
19
.6      IDC_EDIT_ParticleModelessBox, NULL, FALSE);
20
.6   if(particleModelessBox >= (signed)vpp.size())
21
.6    particleModelessBox = vpp.size() - 1;
22
.6   if(particleListBox == -1 )
23
.6    particleListBox = particleModelessBox;
24
.6    InvalidateRect(hwnd, NULL, FALSE);
25
.6
26
.6   break;
27
.6  case  IDB_Run:  //the button  “Run”  is pressed
28
.6   if(pause  ==  true)
29
.6    ResumeThread(hThread);
30
.6    pause  =  false;
31
.6
32
.6   break;
33
.6  case  IDB_Pause: //the button  “Pause”  is pressed
34
.6   if(pause  ==  false)
35
.6    SuspendThread(hThread);
36
.6    pause  =  true;
37
.6
38
.6   break;
39
.6  case  IDB_Cancel: //the button  “Cancel”  is pressed
40
.6   EndDialog(hwnd, nResult);
41
.6   break;
42
.6
43
.6  break;
44
.6 case  WM_HSCROLL:
45
.6  sleep = SendMessage(GetDlgItem(hwnd, IDC_Trackbar),
46
.6                        TBM_GETPOS, 0, 0);
47
.6  sprintf_s(buffer, "%3d", sleep);
48
.6  SetDlgItemText(hwnd, IDC_EDIT_Sleep, buffer);
49
.6  break;
50
.6 case  WM_PAINT:
51
.6  hDC = BeginPaint(hwnd, &psPaint);
52
.6  GetClientRect(hwnd, &rect);
53
.6  SetMapMode(hDC, MM_ISOTROPIC);
54
.6   SetWindowExtEx(hDC, zW, yW, NULL);
55
.6  SetViewportExtEx(hDC, rect.right, rect.bottom, NULL);Algorithm 7:Modal dialog box: function ModalDlgProc (part 3).
1
.7 // drawing the caption:
2
.7  SetBkMode(hDC, TRANSPARENT);
3
.7  fontCaption = CreateFontIndirect(&lf2);
4
.7  SelectObject(hDC, fontCaption);
5
.7  TextOut(hDC, 130, 20, caption, strlen(caption));
6
.7 // drawing the plot rectangle:
7
.7  SelectObject(hDC, hWhitePen);
8
.7  Rectangle(hDC, zLeft, yTop-4, zLeft+width, yTop+height+4);
9
.7 // drawing the Z-axis with an arrow head:
10
.7  SelectObject(hDC, hBlackPen);
11
.7  MoveToEx(hDC, zLeft, yTop + height2, NULL);
12
.7  LineTo(hDC, zLeft + width + 15, yTop + height2);
13
.7  LineTo(hDC,   zLeft + width + 10, yTop + height2 -2);
14
.7  MoveToEx(hDC, zLeft + width + 15, yTop + height2, NULL);
15
.7  LineTo(hDC,   zLeft + width + 10, yTop + height2 +2);
16
.7 // drawing the horizontal grey gridlines:
17
.7  SelectObject(hDC, hGreyPen);
18
.7  MoveToEx(hDC, zLeft, yTop + height2*2/3, NULL);
19
.7  LineTo(hDC, zLeft + width, yTop + height2*2/3);
20
.7  MoveToEx(hDC, zLeft, yTop + height2/3, NULL);
21
.7  LineTo(hDC,   zLeft + width, yTop + height2/3);
22
.7  MoveToEx(hDC, zLeft, yTop + height2*4/3, NULL);
23
.7  LineTo(hDC,   zLeft + width, yTop + height2*4/3);
24
.7  MoveToEx(hDC, zLeft, yTop + height2*5/3, NULL);
25
.7  LineTo(hDC,   zLeft + width, yTop + height2*5/3);
26
.7 // drawing the horizontal black axis with tick marks:
27
.7  SelectObject(hDC, hBlackPen);
28
.7  MoveToEx(hDC, zLeft, yTop + height + 25, NULL);
29
.7  LineTo(hDC,   zLeft + width, yTop + height + 25);
30
.7 // drawing the y-axis with an arrow head:
31
.7  MoveToEx(hDC, zLeft, yTop + height + 25, NULL);
32
.7  LineTo(hDC,   zLeft, yTop - 15);
33
.7  LineTo(hDC,   zLeft - 2, yTop - 10);
34
.7  MoveToEx(hDC, zLeft, yTop - 15, NULL);
35
.7  LineTo(hDC,   zLeft + 2, yTop - 10);
36
.7 // drawing the vertical grey gridlines:
37
.7  SelectObject(hDC, hGreyPen);
38
.7  for(inti = 1; i <= 11; ++i)
39
.7   MoveToEx(hDC, zLeft+(int)(0.01*mz*i), yTop+height, NULL);
40
.7   LineTo(hDC,   zLeft + (int)(0.01*mz*i), yTop-1);
41
.7
42
.7 // drawing the electrodes:
43
.7  SelectObject(hDC, hBlackBrush);
44
.7  Rectangle(hDC,zLeft,yTop-4,zLeft+(int)(12.7*kzy*mz),yTop);
45
.7  Rectangle(hDC, zLeft + (int)((28.0-12.7)*kzy*mz), yTop-4,
46
.7                      zLeft + width, yTop);
47
.7  Rectangle(hDC, zLeft, yTop+height, zLeft + (int)(12.7*kzy*mz),
48
.7                      yTop + height + 4);
49
.7  Rectangle(hDC, zLeft+ (int)((28.0-12.7)*kzy*mz), yTop+height,
50
.7                zLeft + width, yTop + height + 4);
51
.7 // drawing the equipotential lines and labels of potentials:
52
.7  SelectObject(hDC, hPinkPen);
53
.7  DrawEquipotentialLines(hDC, fontPotential, lf, hBlackPen,
54
.7                            Particle::pF);Algorithm 8:Modal dialog box: function ModalDlgProc (part 4).
1
.8
// drawing the particles’ trajectories:
2
.8
SelectObject(hDC, hBluePen);
3
.8
int
z1, z2, y1, y2;
4
.8
for
(
int
i = 0; i < (
signed
)vpp.size(); ++i)
5
.8
for
(
int
j=0; j<(
signed
)(vpp[i].history.size()-1); ++j)
6
.8
z1 = (
int
)(mz*vpp[i].history[j].z) + zLeft;
7
.8
y1 = yTop + height2-(
int
)(my*vpp[i].history[j].y);
8
.8
z2 = (
int
)(mz*vpp[i].history[j+1].z) + zLeft;
9
.8
y2 = yTop + height2-(
int
)(my*vpp[i].history[j+1].y);
10
.8
if
(y2 > yTop + height)
11
.8
y2 = yTop + height;
12
.8
MoveToEx(hDC, z1, y1, NULL);
13
.8
LineTo(hDC, z2, y2);
14
.8
15
.8
// showing the number of a particle whose data
16
.8
// will be displayed in the list box:
17
.8
if
(particleListBox != -1)
18
.8
pLB = sprintf_s(bufferLB, "%d", particleListBox);
19
.8
SetBkMode(hDC, TRANSPARENT);
20
.8
TextOut(hDC, 720, 60, bufferLB, pLB);
21
.8
22
.8
EndPaint(hwnd, &psPaint);
23
.8
break
;
24
.8
case
WM_DESTROY:
25
.8
DeleteObject(g_hbrBackground);
26
.8
DeleteObject(hBlackBrush);
27
.8
DeleteObject(hBlackPen);
28
.8
DeleteObject(hPinkPen);
29
.8
DeleteObject(hBluePen);
30
.8
DeleteObject(hGreyPen);
31
.8
DeleteObject(hWhitePen);
32
.8
DeleteObject(hBlackThickPen);
33
.8
PostQuitMessage(0);
34
.8
break
;
35
.8
36
.8
return
0;
37
.8Algorithm 9:The second thread: function ThreadProc.
1
.9
DWORD CALLBACK ThreadProc(LPVOID lpdwThreadParam)
2
.9 const doubleht = 1.0e-9; //time step of integration, s
3
.9 static intcount = 0; //number of particles with z > zMax
4
.9 while(count < (signed)vpp.size())
5
.9 for(inti = 0; i < (int)vpp.size(); ++i)
6
.9
if(vpp[i].stop==false)
7
.9 RK4_4eq<Particle>(&vpp[i], ht, &Particle::t, &Particle::vz,
8
.9  &Particle::vy, &Particle::z, &Particle::y, &Particle::FzFy,
9
.9  &Particle::DvzDt, &Particle::DvyDt, &Particle::DzDt,
10
.9  &Particle::DyDt);
11
.9 vpp[i].v=sqrt(vpp[i].vy*vpp[i].vy + vpp[i].vz*vpp[i].vz);
12
.9 vpp[i].W=0.5*Particle::m*vpp[i].v*vpp[i].v/Particle::q;
13
.9 vpp[i].currentData.t = vpp[i].t;
14
.9 vpp[i].currentData.z = vpp[i].z;
15
.9 vpp[i].currentData.y = vpp[i].y;
16
.9 vpp[i].currentData.vz = vpp[i].vz;
17
.9 vpp[i].currentData.vy = vpp[i].vy;
18
.9 vpp[i].currentData.v = vpp[i].v;
19
.9 vpp[i].currentData.W = vpp[i].W;
20
.9 vpp[i].history.push_back(vpp[i].currentData);
21
.9 if(vpp[i].z >= Particle::pF->zMax)
22
.9  vpp[i].stop=true;
23
.9  ++count;
24
.9
25
.9
26
.9 if(!vpp[particleListBox].stop)
27
.9  sprintf_s(bufListBox, " t = %.3ey = %.5fz = %.5f",
28
.9            vpp[particleListBox].history.back().t,
29
.9            vpp[particleListBox].history.back().y,
30
.9            vpp[particleListBox].history.back().z);
31
.9  SendMessage(GetDlgItem(hModalDlg, IDC_ListBox),LB_ADDSTRING,
32
.9                      0, (LPARAM)bufListBox);
33
.9  SendMessage(GetDlgItem(hModalDlg, IDC_ListBox), LB_SETTOPINDEX,
34
.9    (WPARAM)(vpp[particleListBox].history.size()-1), 0);
35
.9
36
.9 InvalidateRect(hModalDlg, NULL, FALSE);
37
.9 if(hModelessDlg != 0)
38
.9  InvalidateRect(hModelessDlg, NULL, FALSE);
39
.9 Sleep(sleep);
40
.9
41
.9 return0;
42
.9As we can see in the prototype shown in Algorithm1, the function template imposes some restrictions on the content of the application class T; namely, the class needs to have five data members denoting both an independent variable (time t) and four state variables (y, z, vy, and vz), a helper function (pointed aspPrecompute), and four member functions for computing the right-hand sides of the corresponding differential equations. The helper function makes the calculations common for right-hand sides, thus reducing the run time. The classParticle is designed so that these requirements are met.After an integration step has been completed, the updated values of the state variables are pushed into theParticle’s vector containerhistory (lines 11.9–20.9). When thefor loop is completed, the messages are generated to be passed both to the modal dialog box (including the list box) and to the modeless box. In particular, the functionsInvalidateRect are invoked generating the messages WM_PAINT. As a result, the numerical outputs are updated. When sending messages to the list box via calling the functionsSendMessage in lines 31.9–34.9, the message LB_ADDSTRING results in adding the new text line to the end of the list, and the message LB_SETTOPINDEX ensures that the end of the list is visible. The call of the functionSleep allows setting the desired simulation rate kept in the variablesleep. Then thewhile loop starts the next iteration.


## 4.1. Description of the Modal Dialog Procedure

Next we describe the modal dialog box window procedureModalDlgProc; the definition of that is listed in Algorithms 5–8. The function has the following heading:int CALLBACK ModalDlgProc(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam).The function’s body begins with definitions of the variables used in designing the graphical interface. These are a handlehDC to the device context, a structure defining a set of graphic objects, with some of them also defined here (pens, brushes, and fonts), a variablepsPaint of type PAINTSTRUCT keeping the information necessary for drawing in a client area of the modal dialog box, a variablerect of type RECT used to keep coordinates of the client area, and temporary text buffers. It should be noted that most of the variables above must be declared asstatic ones; otherwise the graphical information will not be displayed properly. The basic part of the dialog box procedure is aswitch statement with the controlling expression. The function is intended to be processing the Windows messages sent to the dialog box and passed through the second formal parametermessage. The first message is WM_INITDIALOG which is sent by the system immediately before displaying the dialog box and carries out the required initializations. In the case of sending this message, the following actions are made:(i)
Creation of the second thread with the handlehThread in the suspended state (lines 27.5–32.5).(ii)
Initialization of the global handle to the modal dialog boxhModalDlg (line 33.5) in order to be used further in the thread procedure as a control variable.(iii)
Creation of the modeless dialog box with the global handlehModelessDlg, which can display more detailed console-like output for the particles selected during the simulation (lines 34.5-35.5).(iv)
Completion of creating an edit box (IDC_EDIT_ParticleModelessBox) with an up-down (spin) control (IDC_UpDown) which is sometimes referred to as a “spinner” control; this is done by calling the functionsSendMessage to set the edit box as a buddy one and to set the range and the initial zero value (lines 36.5–40.5).(v)
An analogous procedure accomplished concerning the trackbar control which provides changing the rate of simulation: the functionsSendMessage in the lines 48.5–51.5 define the range and set the slider to the initial position between two tick marks; anotherSendMessage function gets the slider’s logical position that is assigned to the global variablesleep (lines 52.5-53.5).(vi)
Statements in lines 42.5–47.5 and in lines 54.5-55.5 setting the initial values for all edit windows.


### 4.1.1. Processing the Control Related MessagesWM_COMMAND

Another important case we need to focus on is processing the messageWM_COMMAND which is sent when the user clicks a button at the modal dialog box. If the user chooses a button “Create a new particle,” the functionGetDlgItemText retrieves strings from the corresponding edit windows with control identifiers IDC_EDIT_W0 and IDC_EDIT_kVy to the text buffer (Algorithm 6, lines 8.6 and 10.6). Then the strings are converted into numerical values of the variablesW0 andkVy (lines 9.6 and 11.6) and are passed to theParticle’s constructor. The latter creates aParticle’s object that will be kept in the global STLvector containervpp:12.6   vpp.push_back(Particle(W0, kVy));The size of this container, that is, the total number N of particles involved in the simulation, is then passed to the edit window with an identifier IDS_EDIT_PartNum to be displayed (lines 13.6-14.6).The considered simulation model allows displaying not only graphs but also numerical data in the console-like fashion. Therefore, after at least one particle is created, the user may choose a particle whose state data could be displayed both at the above-mentioned modeless dialog box with the handlehModelessDlg and in the list box placed at the modal dialog box. It is accomplished in the edit box with the up-down control, where the required particle is chosen by the spin button. When the user clicks the button “Confirm,” the numeric input, that is, the particle’s number, is retrieved by the functionGetDlgItemInt and is assigned to the variableparticleModelessBox (lines 18.6-19.6). The particle chosen for the first time, that is, under the first click of the button “Confirm,” is selected to be displayed in the list box. The number of this particle kept in the variableparticleModelessBox is assigned to the variableparticleListBox in line 23.6 (and made visible in line 24.6) which is then used in both threads, remaining unchanged during the simulation. It should be noted that the user can change the particle, whose data are displayed at the modeless dialog box, at any time, using the above procedure.The modal dialog box contains also two buttons “Run” and “Pause” placing an important part in controlling the simulation process. When the user clicks the button “Run” the program checks if the global variablepause equalstrue. If so, the functionResumeThread is called and the value ofpause is reversed tofalse (lines 27.6–31.6). As a result, the hitherto suspended thread with the handlehThread is resumed and executes the functionThreadProc carrying out the model calculations. In the case of a need to stop the simulation temporarily, the user may choose the button “Pause.” Since the variablepause has thefalse value until this moment, the functionSuspendThread is invoked, thepause reverts totrue (lines 33.6–37.6), and all calculations in the functionThreadProc will stop. And, at last, if the user clicks a “Cancel” button, the dialog box procedure closes the dialog box by calling theEndDialog function (line 40.6) as it does in case of processing the WM_CLOSE message (line 2.6). Next up is the case of processing another windows message WM_HSCROLL that is sent if the user wants to change the simulation rate and moves the slider of the trackbar control to the left to increase the rate or to the right to slow it down. The simulation rate is controlled by the global variablesleep used further in the functionThreadProc. As mentioned above,sleep is assigned the value returned by the functionSendMessage in lines 45.6-46.6. For information, this value is also shown at the edit box with an identifier IDC_EDIT_Sleep (lines 48.6-49.6).


### 4.1.2. Painting at the Modal Dialog Box: Processing the MessageWM_PAINT

Drawing graphical objects at the modal dialog box is carried out when the system generates a messageWM_PAINT. It is done either implicitly when the window must be updated after sizing, moving, and so forth, or the application explicitly requests an update, invoking, for example, the functionInvalidateRect. In our case, these key control actions are accomplished in the functionThreadProc (Algorithm 9, lines 36.9–38.9).The typical processing of theWM_PAINT starts with calling the functionBeginPaint (Algorithm 6, line 51.6) which passes the painting information to the variablepsPaint and returns the handlehDC to the device context. Then a number of functions are called to prepare the client area at the modal box to draw the interface elements and data (lines 52.6–55.6). When calling the functionGetClientRect, a rectangle of the client area gets its coordinates; calling the functionSetMapMode sets the mapping mode between page space and device space. In case of a parameter MM_ISOTROPIC logical units are mapped to device (e.g., display) units with equally scaled axes. The functionSetWindowExtEx sets the maximum values for the horizontal and vertical axes of the window in logical units, whereas the functionSetViewportExtEx does the same in device units for the view port, that is, thedevice coordinate system. So, using both functions determines the scaling factor between the window and the view port.Shown below (Algorithm7, lines 2.7–5.7) is the fragment that draws the caption of the simulation application “A simulation model of the motion….” Next, in lines 6.7–50.7, the graphic functions are invoked such asRectangle, MoveToEx, andLineTo. These functions provide drawing a plot rectangle, axes, gridlines, and tick marks (see the screenshot in Figure 2(a)) necessary for displaying electrodes, field lines, particle’s trajectories, and so on. The equipotential lines are drawn by calling the helper functionDrawEquipotentialLines (lines 53.7-54.7). The principal painting, that is, drawing the particles’ trajectories in real time, is carried out in the fragments placed between lines 2.8 and 14.8 in Algorithm 8. Both the global vectorvpp and theParticle’s data members, vectorshistory keeping the particles’ states, are involved in the drawing of the trajectories y(z) in the nestedfor loop. The processing of the message WM_PAINT is completed with the fragment written in lines 17.8–21.8 which displays thevpp’s index of a particle whose data is to be output at the list box. The final statement of the processing is the call ofEndPaint.When the modal dialog box is being destroyed and is removed from the screen, the messageWM_DESTROY is sent to the functionModalDlgProc. The processing of this message includes the set of function calls ofDeleteObject to delete the logical pens and the brush.


## 4.1.1. Processing the Control Related MessagesWM_COMMAND

Another important case we need to focus on is processing the messageWM_COMMAND which is sent when the user clicks a button at the modal dialog box. If the user chooses a button “Create a new particle,” the functionGetDlgItemText retrieves strings from the corresponding edit windows with control identifiers IDC_EDIT_W0 and IDC_EDIT_kVy to the text buffer (Algorithm 6, lines 8.6 and 10.6). Then the strings are converted into numerical values of the variablesW0 andkVy (lines 9.6 and 11.6) and are passed to theParticle’s constructor. The latter creates aParticle’s object that will be kept in the global STLvector containervpp:12.6   vpp.push_back(Particle(W0, kVy));The size of this container, that is, the total number N of particles involved in the simulation, is then passed to the edit window with an identifier IDS_EDIT_PartNum to be displayed (lines 13.6-14.6).The considered simulation model allows displaying not only graphs but also numerical data in the console-like fashion. Therefore, after at least one particle is created, the user may choose a particle whose state data could be displayed both at the above-mentioned modeless dialog box with the handlehModelessDlg and in the list box placed at the modal dialog box. It is accomplished in the edit box with the up-down control, where the required particle is chosen by the spin button. When the user clicks the button “Confirm,” the numeric input, that is, the particle’s number, is retrieved by the functionGetDlgItemInt and is assigned to the variableparticleModelessBox (lines 18.6-19.6). The particle chosen for the first time, that is, under the first click of the button “Confirm,” is selected to be displayed in the list box. The number of this particle kept in the variableparticleModelessBox is assigned to the variableparticleListBox in line 23.6 (and made visible in line 24.6) which is then used in both threads, remaining unchanged during the simulation. It should be noted that the user can change the particle, whose data are displayed at the modeless dialog box, at any time, using the above procedure.The modal dialog box contains also two buttons “Run” and “Pause” placing an important part in controlling the simulation process. When the user clicks the button “Run” the program checks if the global variablepause equalstrue. If so, the functionResumeThread is called and the value ofpause is reversed tofalse (lines 27.6–31.6). As a result, the hitherto suspended thread with the handlehThread is resumed and executes the functionThreadProc carrying out the model calculations. In the case of a need to stop the simulation temporarily, the user may choose the button “Pause.” Since the variablepause has thefalse value until this moment, the functionSuspendThread is invoked, thepause reverts totrue (lines 33.6–37.6), and all calculations in the functionThreadProc will stop. And, at last, if the user clicks a “Cancel” button, the dialog box procedure closes the dialog box by calling theEndDialog function (line 40.6) as it does in case of processing the WM_CLOSE message (line 2.6). Next up is the case of processing another windows message WM_HSCROLL that is sent if the user wants to change the simulation rate and moves the slider of the trackbar control to the left to increase the rate or to the right to slow it down. The simulation rate is controlled by the global variablesleep used further in the functionThreadProc. As mentioned above,sleep is assigned the value returned by the functionSendMessage in lines 45.6-46.6. For information, this value is also shown at the edit box with an identifier IDC_EDIT_Sleep (lines 48.6-49.6).


## 4.1.2. Painting at the Modal Dialog Box: Processing the MessageWM_PAINT

Drawing graphical objects at the modal dialog box is carried out when the system generates a messageWM_PAINT. It is done either implicitly when the window must be updated after sizing, moving, and so forth, or the application explicitly requests an update, invoking, for example, the functionInvalidateRect. In our case, these key control actions are accomplished in the functionThreadProc (Algorithm 9, lines 36.9–38.9).The typical processing of theWM_PAINT starts with calling the functionBeginPaint (Algorithm 6, line 51.6) which passes the painting information to the variablepsPaint and returns the handlehDC to the device context. Then a number of functions are called to prepare the client area at the modal box to draw the interface elements and data (lines 52.6–55.6). When calling the functionGetClientRect, a rectangle of the client area gets its coordinates; calling the functionSetMapMode sets the mapping mode between page space and device space. In case of a parameter MM_ISOTROPIC logical units are mapped to device (e.g., display) units with equally scaled axes. The functionSetWindowExtEx sets the maximum values for the horizontal and vertical axes of the window in logical units, whereas the functionSetViewportExtEx does the same in device units for the view port, that is, thedevice coordinate system. So, using both functions determines the scaling factor between the window and the view port.Shown below (Algorithm7, lines 2.7–5.7) is the fragment that draws the caption of the simulation application “A simulation model of the motion….” Next, in lines 6.7–50.7, the graphic functions are invoked such asRectangle, MoveToEx, andLineTo. These functions provide drawing a plot rectangle, axes, gridlines, and tick marks (see the screenshot in Figure 2(a)) necessary for displaying electrodes, field lines, particle’s trajectories, and so on. The equipotential lines are drawn by calling the helper functionDrawEquipotentialLines (lines 53.7-54.7). The principal painting, that is, drawing the particles’ trajectories in real time, is carried out in the fragments placed between lines 2.8 and 14.8 in Algorithm 8. Both the global vectorvpp and theParticle’s data members, vectorshistory keeping the particles’ states, are involved in the drawing of the trajectories y(z) in the nestedfor loop. The processing of the message WM_PAINT is completed with the fragment written in lines 17.8–21.8 which displays thevpp’s index of a particle whose data is to be output at the list box. The final statement of the processing is the call ofEndPaint.When the modal dialog box is being destroyed and is removed from the screen, the messageWM_DESTROY is sent to the functionModalDlgProc. The processing of this message includes the set of function calls ofDeleteObject to delete the logical pens and the brush.


## 4.2. Description of the Modeless Dialog Box with the Console-Like Output

The modeless dialog box can be shown even while the modal dialog box exists. Its purpose in this application is to display the numerical data describing the history of the state of a particle having been selected at the edit box with an identifierIDC_EDIT_ParticleModelessBox during the simulation (see Figure 2(b)). The output is carried out by the window functionModelessDlgProc in the console-like fashion and requires the vertical and horizontal scrolling to get more display space the modeless box can provide. That is, vertical and horizontal scroll bars are used in the modeless box.The window function has the similar structure as in case of the modal dialog. It processes the messages in theswitch selection statement that has eight branches,case labels for processing the messages WM_INITDIALOG, WM_VSCROLL, WM_HSCROLL, WM_PAINT, and so on. As the most of the procedure code contains the common, near standard fragments (see, e.g., Petzold [14], Chapter 4, section “Scroll Bars”), the listing of the procedure is placed to Appendix. However, a short description of the procedure is still given below. The resource script placed in the filescript2.rc and associated with the modeless dialog contains styles WS_VSCROLL and WS_HSCROLL among other ones:STYLE DS_SETFONT ∣ WS_VISIBLE ∣ WS_CAPTION ∣WS_SYSMENU ∣ WS_VSCROLL ∣ WS_HSCROLL ∣WS_MINIMIZEBOX ∣ WS_OVERLAPPEDWINDOWA number of variables and constants are defined in the window procedure. The constantNUMLINES is the maximal number of lines of text involved into the vertical scrolling. The variabletm of type TEXTMETRIC defines the font and rows parameters such as width and height of characters and space between characters. The static variablesyPos andxPos are current positions of the scroll bar thumbs for vertical and horizontal scroll bars correspondingly, andyInc contains an incremental value for updatingyPos. The messages WM_VSCROLL and WM_HSCROLL are sent to the window procedure if the scroll events occur either in the window’s vertical scroll bar or in the horizontal scroll bar. Processing these messages made within nestedswitch statements (see Appendix, Algorithm 11, lines 46.11–63.11 and 73.11–89.11) with the parameter notification code SB_TOP, SB_BOTTOM, and so forth results in updatingyPos andxPos.When calling the functionScrollWindow in lines 68.11 and 96.11, the system invalidates the client area and generates the WM_PAINT message. One more origin of a WM_PAINT message is the thread procedure, where the functionInvalidateRect is called (see Algorithm 9, line 38.9) after completing the nestedfor loop of one step integration of charged particles’ motion. The code written in the WM_PAINT selection brunch provides drawing the full set of text lines from the beginning of simulation to the current instant. Each text line outputs the time, position, velocity, and kinetic energy of a particle (i.e., the set of t, y, z, vy, vz, v, W).


## 4.3. Thread Procedure as the Physics Engine

The physics engine of the considered simulation model is placed in the functionThreadProc. The function includes thewhile loop (Algorithm 9, lines 4.9–40.9) providing the simulation until the last particle reaches the rightmost edge of the lens. The nestedfor loop (lines 5.9–25.9) carries out one step of integration for all particles which did not reach the right lens edge (i.e., zi<zMax). When a particle gets moved beyond this boundary, its data memberstop is set totrue; that is, the particle is excluded from simulation, and the variablecounter keeping the number of excluded particles is incremented. The integration is carried out by the global function templateRK4_4eq (lines 7.9–10.9). This function is a solver that processes one step of integration of the system of four ODEs by the Runge-Kutta method of the 4th order. The function template is defined in the header filerk4_eq.h and has the prototype as shown in Algorithm 1.Algorithm 1
t
emplate
<
class
T>
inline void
RK4_4eq(T* p, //pointer to an object of the class
T
doubleh, //time step of integration (htin the class Particle)
doubleT::*pX0, // pointer to the independent variable-timet
doubleT::*pX1, // pointer to the state variable-velocityvz
doubleT::*pX2, // pointer to the state variable-velocityvy
doubleT::*pX3, // pointer to the state variable-coordinatez
doubleT::*pX4, // pointer to the state variable-coordinatey
void(T::*pPrecompute)(),//pointer to the helper functionFzFy
double(T::*pF1)(), //pointer to the equation of motionDvzDt
double(T::*pF2)(), //pointer to the equation of motionDvyDt
double(T::*pF3)(), //pointer to the equation of motionDzDt
double(T::*pF4)() //pointer to the equation of motionDyDt
);Algorithm 2:The header file particle.h defining the class Particle.
1.2#pragma once
2.2#include"field.h"
3.2#include"rk4_4eq.h"
4.2#include<vector>
5.2
6.2classParticle
7.2 public:
8.2  static const doublem, q; //mass and charge of a particle
9.2  doubleW0, W, v;
10
.2  doublet, z, y, vz, vy;
11
.2  structData
12
.2   doublet, z, y, vz, vy, v, W;
13
.2  currentData;
14
.2  doublefz, fy; //components of an electric force
15
.2  doubledz, dy; //spacing of the field grid along z and y axes
16
.2  staticField* pF;
17
.2  doubleuLeft, uRight, uTop, uBottom;
18
.2  doubleyCellTop, yCellBottom, zCellLeft, zCellRight;
19
.2  intiTopLeft, jTopLeft;
20
.2  vector<Data> history;
21
.2  doublekVy;
22
.2  boolstop;
23
.2  Particle(doubleW0 = 25., doublekVy = 0.): W0(W0), W(W0),
24
.2     t(0.), z(0.), y(0.), kVy(kVy), fz(0.), fy(0.),
25
.2     v(sqrt(2./m*W0*1.6022e-19)),
26
.2     vz(v/sqrt(1.+kVy*kVy)), vy(kVy*vz), stop(false)
27
.2   dy = dz = pF->h;
28
.2   zCellLeft = zCellRight = 0.;
29
.2   if(y == 0)
30
.2    yCellTop = yCellBottom = 0.;
31
.2
32
.2  voidFzFy(); //computing the force components fy and fz
33
.2  doubleDzDt()  return  vz;
34
.2  doubleDyDt()  return  vy;
35
.2  doubleDvzDt()  return  1./m*fz;
36
.2  doubleDvyDt()  return  1./m*fy;
37
.2;
38
.2const doubleParticle::m = 1.6726e-27;  //kg
39
.2const doubleParticle::q = 1.6022e-19;  //C (Coulomb)
40
.2Field* Particle::pF = NULL;Algorithm 3:The source file main.cpp containing the entry point to the program: function WinMain.
1.3#include<windows.h>
2.3#include<iostream>
3.3#include"resource.h"
4.3#include"particle.h"
5.3#include"field.h"
6.3#include<CommCtrl.h>
7.3#pragma comment(lib, "comctl32.lib")
8.3using namespace  std;
9.3
10
.3HWND hModalDlg, hModelessDlg = 0;
11
.3INT_PTR nResult;
12
.3HANDLE hThread;
13
.3bool  pause  =  true; // a control to make the pause in execution
14
.3int  sleep = 0;  //a control affecting the rate of running
15
.3const double  my = 200./0.06, mz = my, kzy = 0.004;
16
.3const int  height = 200, height2 = (int)(height*0.5),
17
.3                 width=(int)(height*28./15.);
18
.3const int  zLeft = 80, yTop = 70; //coordinates of the drawing area
19
.3vector<Particle> vpp; //container keeping the set of particles
20
.3int  particleModelessBox = -1;
21
.3int  particleListBox = -1;
22
.3char  bufListBox[180];
23
.3
24
.3int  CALLBACK ModalDlgProc(HWND, UINT, WPARAM, LPARAM);
25
.3int  CALLBACK ModelessDlgProc(HWND, UINT, WPARAM, LPARAM);
26
.3DWORD CALLBACK ThreadProc(LPVOID);
27
.3void  DrawEquipotentialLines(HDC, HFONT, LOGFONT, HPEN, Field*);
28
.3
29
.3int  WINAPI WinMain(HINSTANCE hI, HINSTANCE hI2, LPSTR p,  int  n)
30
.3  MSG msg;
31
.3  Particle::pF = new Field();
32
.3  nResult = DialogBox(NULL, "MYDIALOG", 0, (DLGPROC)ModalDlgProc);
33
.3  while(GetMessage(&msg, NULL, 0, 0) > 0)
34
.3   if(hModelessDlg == 0 || !IsDialogMessage(hModelessDialog, &msg))
35
.3   TranslateMessage(&msg);
36
.3   DispatchMessage(&msg);
37
.3
38
.3
39
.3  delete Particle::pF;
40
.3  returnmsg.wParam;
41
.3Algorithm 4:The resource script file script.rc for the modal dialog.
1.4#include<windows.h>
2.4#include"resource.h"
3.4
4.4MYDIALOG DIALOGEX 0, 0, zW, yW
5.4STYLE DS_MODALFRAME|WS_CAPTION|WS_SYSMENU| WS_MINIMIZEBOX
6.4CAPTION "MyDialogWindow"
7.4FONT 8, "MS Shell Dlg"
8.4
9.4 PUSHBUTTON "Create a new particle", IDB_NewParticle,
10
.4                        210, 363, 70, 14
11
.4 PUSHBUTTON "Confirm",   IDB_Confirm,    310, 400, 50, 14
12
.4 PUSHBUTTON "Run",     IDB_Run,      50, 430, 50, 14
13
.4 PUSHBUTTON "Pause",    IDB_Pause,  135, 430, 50, 14
14
.4 PUSHBUTTON "Cancel",      IDB_Cancel  220, 430, 50, 14
15
.4 EDITTEXT IDC_EDIT_W0      150, 353, 40, 15, ES_CENTER
16
.4 EDITTEXT IDC_EDIT_kVy     150, 375, 40, 15, ES_CENTER
17
.4 EDITTEXT IDC_EDIT_PartNum 390,363,25,15, ES_CENTER|ES_READONLY
18
.4 EDITTEXT IDC_EDIT_ParticleToModelessBox  270,400,30,15,ES_CENTER
19
.4 EDITTEXT IDC_EDIT_Sleep 570,400,40,15, ES_CENTER|ES_READONLY
20
.4 LISTBOX  IDC_ListBox   550, 70, 200, 250, WS_VSCROLL
21
.4 CONTROL "" IDC_UpDown, "msctls_updown32",
22
.4         UDS_SETBUDDYINT|UDS_ALIGNRIGHT,   0, 0, 0, 0
23
.4 CONTROL "" IDC_Trackbar, "msctls_trackbar32", WS_VISIBLE|
24
.4              WS_TABSTOP|TBS_HORZ, 400, 400, 150, 30
25
.4 LTEXT "Set initial data∖nfor a new particle:", 99, 50,360,65,20
26
.4 LTEXT "W0 = ",  100,  118, 356, 30, 10
27
.4 LTEXT "Vy/Vz = ", 101,  118, 378, 30, 10
28
.4 LTEXT "Total number N∖nof created particles:", 102,
29
.4                        315, 360,  70, 20
30
.4 LTEXT "Indicate the particle ( from 0 to N-1 )∖
31
.4   whose data you want to display: ", 103,   50, 400, 220, 10
32
.4 LTEXT "Displaying data of the first selected particle:", 104,
33
.4                       550,  55, 160,  10
34
.4 LTEXT "0 V",105,          150,58,  25,10
35
.4 LTEXT "-1000 V", 106,           360,58,25,10
36
.4 LTEXT "Simulation speed", 107,       445, 385, 70,10
37
.4 LTEXT "Increase”, 108,            410, 420,35,10
38
.4 LTEXT“Slowdown", 109,            508, 420,35,10
39
.4 LTEXT "Delay, ms", 110,           570, 385,40,10
40
.4 LTEXT "z, m", 111,               463, 169,15,10
41
.4 LTEXT "y, m", 112,             60,52,15,10
42
.4 LTEXT "0",    113,              70, 162,5,10
43
.4 //Two sets of LTEXT controls for displaying the numerical
44
.4 //values for both y-gridlines and z-tick marks of the plot.
45
.4 //Relating to the y-gridline:
46
.4 LTEXT "0.01", 114,    62, 129, 15, 10
47
.4 ...
48
.4 LTEXT "-0.03", 119,    60, 255, 16, 10
49
.4 //Relating to the z-tick marks:
50
.4 LTEXT "0.00", 120,   73, 288, 15, 10
51
.4 ...
52
.4 LTEXT "0.11", 131,   438, 288, 15, 10
53
.4Algorithm 5:Modal dialog box: function ModalDlgProc (part 1).
1.5int  CALLBACK ModalDlgProc(HWND hwnd, UINT message,
2.5             WPARAM wParam, LPARAM lParam)
3.5 static  HDC hDC;
4.5 PAINTSTRUCT psPaint;
5.5 RECT rect;
6.5 static  HBRUSH hBlackBrush=(HBRUSH)GetStockObject(BLACK_BRUSH),
7.5 g_hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
8.5 static  HPEN hBlackPen = (HPEN)GetStockObject(BLACK_PEN),
9.5 hBlackThickPen = CreatePen(PS_SOLID, 5, RGB(0,0,0)),
10
.5 hWhitePen = CreatePen(PS_SOLID,(int)0.5, RGB(255, 255, 255)),
11
.5 hGreyPen = CreatePen(PS_SOLID,  (int)0.5, RGB(200, 200, 200)),
12
.5 hPinkPen = CreatePen(PS_SOLID,  (int)0.5, RGB(255, 150, 150)),
13
.5 hBluePen = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
14
.5 static  HFONT fontPotential, fontCaption;
15
.5 static  LOGFONT lf, lf2;
16
.5 strcpy_s(lf.lfFaceName, "MS Sans Serif");
17
.5 lf.lfHeight = 8;
18
.5 strcpy_s(lf2.lfFaceName, "Century");
19
.5 lf2.lfHeight = 18;
20
.5 lf2.lfWeight = FW_MEDIUM;
21
.5 char  caption[]= "A simulation model of the motion of charged∖
22
.5  particles in the electrostatic field of an immersion lens";
23
.5 char  bufferLB[3], buffer[500];
24
.5 Particle temp;
25
.5 switch(message)
26
.5  case  WM_INITDIALOG:
27
.5  hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)
28
.5            &ThreadProc, NULL, CREATE_SUSPENDED, 0);
29
.5  if(hThread == NULL)
30
.5   MessageBox(0,"Error Creating Thread","Message",MB_OK);
31
.5  return  1;
32
.5
33
.5  hModalDlg = hwnd;
34
.5  hModelessDlg = CreateDialog(0, "MODELESS_DIALOG", 0,
35
.5                   (DLGPROC)ModelessDlgProc);
36
.5  SendMessage(GetDlgItem(hwnd, IDC_UpDown), UDM_SETBUDDY,
37
.5  (WPARAM)GetDlgItem(hwnd,IDC_EDIT_ParticleModelessBox),0);
38
.5  SendMessage(GetDlgItem(hwnd,IDC_UpDown),
39
.5                      UDM_SETRANGE, 0, 100);
40
.5  SendMessage(GetDlgItem(hwnd, IDC_UpDown),UDM_SETPOS,0, 0);
41
.5  int  pLB;
42
.5  sprintf_s(buffer, "%.2f", temp.W0);
43
.5  SetDlgItemText(hwnd, IDC_EDIT_W0, buffer);
44
.5  sprintf_s(buffer, "%.2f", temp.kVy);
45
.5  SetDlgItemText(hwnd, IDC_EDIT_kVy, buffer);
46
.5  sprintf_s(buffer, "%d", 0);
47
.5  SetDlgItemText(hwnd, IDC_EDIT_PartNum, buffer);
48
.5  SendMessage(GetDlgItem(hwnd, IDC_Trackbar), TBM_SETRANGE,
49
.5                    TRUE, MAKELONG(0, 1000));
50
.5  SendMessage(GetDlgItem(hwnd, IDC_Trackbar), TBM_SETPOS,
51
.5                           TRUE, 200);
52
.5  sleep = SendMessage(GetDlgItem(hwnd, IDC_Trackbar),
53
.5                        TBM_GETPOS, 0, 0);
54
.5  sprintf_s(buffer, "%d", sleep);
55
.5  SetDlgItemText(hwnd, IDC_EDIT_Sleep, buffer);
56
.5  break;Algorithm 6:Modal dialog box: function ModalDlgProc (part 2).
1.6 case  WM_CLOSE:
2.6  EndDialog(hwnd, nResult);
3.6  break;
4.6 case  WM_COMMAND:
5.6  double  kVy, W0;
6.6  switch(LOWORD(wParam))
7.6  case  IDB_NewParticle:
8.6   GetDlgItemText(hwnd,IDC_EDIT_W0,buffer,sizeof(buffer));
9.6   W0 = atof(buffer);
10
.6   GetDlgItemText(hwnd, IDC_EDIT_kVy, buffer,sizeof(buffer));
11
.6   kVy = atof(buffer);
12
.6   vpp.push_back(Particle(W0, kVy));
13
.6   sprintf_s(buffer, "%d", vpp.size());
14
.6   SetDlgItemText(hwnd, IDC_EDIT_PartNum, buffer);
15
.6   break;
16
.6  case  IDB_Confirm:  //the button  “Confirm”  is pressed
17
.6   if(vpp.empty())  break;
18
.6   particleModelessBox = GetDlgItemInt(hwnd,
19
.6      IDC_EDIT_ParticleModelessBox, NULL, FALSE);
20
.6   if(particleModelessBox >= (signed)vpp.size())
21
.6    particleModelessBox = vpp.size() - 1;
22
.6   if(particleListBox == -1 )
23
.6    particleListBox = particleModelessBox;
24
.6    InvalidateRect(hwnd, NULL, FALSE);
25
.6
26
.6   break;
27
.6  case  IDB_Run:  //the button  “Run”  is pressed
28
.6   if(pause  ==  true)
29
.6    ResumeThread(hThread);
30
.6    pause  =  false;
31
.6
32
.6   break;
33
.6  case  IDB_Pause: //the button  “Pause”  is pressed
34
.6   if(pause  ==  false)
35
.6    SuspendThread(hThread);
36
.6    pause  =  true;
37
.6
38
.6   break;
39
.6  case  IDB_Cancel: //the button  “Cancel”  is pressed
40
.6   EndDialog(hwnd, nResult);
41
.6   break;
42
.6
43
.6  break;
44
.6 case  WM_HSCROLL:
45
.6  sleep = SendMessage(GetDlgItem(hwnd, IDC_Trackbar),
46
.6                        TBM_GETPOS, 0, 0);
47
.6  sprintf_s(buffer, "%3d", sleep);
48
.6  SetDlgItemText(hwnd, IDC_EDIT_Sleep, buffer);
49
.6  break;
50
.6 case  WM_PAINT:
51
.6  hDC = BeginPaint(hwnd, &psPaint);
52
.6  GetClientRect(hwnd, &rect);
53
.6  SetMapMode(hDC, MM_ISOTROPIC);
54
.6   SetWindowExtEx(hDC, zW, yW, NULL);
55
.6  SetViewportExtEx(hDC, rect.right, rect.bottom, NULL);Algorithm 7:Modal dialog box: function ModalDlgProc (part 3).
1
.7 // drawing the caption:
2
.7  SetBkMode(hDC, TRANSPARENT);
3
.7  fontCaption = CreateFontIndirect(&lf2);
4
.7  SelectObject(hDC, fontCaption);
5
.7  TextOut(hDC, 130, 20, caption, strlen(caption));
6
.7 // drawing the plot rectangle:
7
.7  SelectObject(hDC, hWhitePen);
8
.7  Rectangle(hDC, zLeft, yTop-4, zLeft+width, yTop+height+4);
9
.7 // drawing the Z-axis with an arrow head:
10
.7  SelectObject(hDC, hBlackPen);
11
.7  MoveToEx(hDC, zLeft, yTop + height2, NULL);
12
.7  LineTo(hDC, zLeft + width + 15, yTop + height2);
13
.7  LineTo(hDC,   zLeft + width + 10, yTop + height2 -2);
14
.7  MoveToEx(hDC, zLeft + width + 15, yTop + height2, NULL);
15
.7  LineTo(hDC,   zLeft + width + 10, yTop + height2 +2);
16
.7 // drawing the horizontal grey gridlines:
17
.7  SelectObject(hDC, hGreyPen);
18
.7  MoveToEx(hDC, zLeft, yTop + height2*2/3, NULL);
19
.7  LineTo(hDC, zLeft + width, yTop + height2*2/3);
20
.7  MoveToEx(hDC, zLeft, yTop + height2/3, NULL);
21
.7  LineTo(hDC,   zLeft + width, yTop + height2/3);
22
.7  MoveToEx(hDC, zLeft, yTop + height2*4/3, NULL);
23
.7  LineTo(hDC,   zLeft + width, yTop + height2*4/3);
24
.7  MoveToEx(hDC, zLeft, yTop + height2*5/3, NULL);
25
.7  LineTo(hDC,   zLeft + width, yTop + height2*5/3);
26
.7 // drawing the horizontal black axis with tick marks:
27
.7  SelectObject(hDC, hBlackPen);
28
.7  MoveToEx(hDC, zLeft, yTop + height + 25, NULL);
29
.7  LineTo(hDC,   zLeft + width, yTop + height + 25);
30
.7 // drawing the y-axis with an arrow head:
31
.7  MoveToEx(hDC, zLeft, yTop + height + 25, NULL);
32
.7  LineTo(hDC,   zLeft, yTop - 15);
33
.7  LineTo(hDC,   zLeft - 2, yTop - 10);
34
.7  MoveToEx(hDC, zLeft, yTop - 15, NULL);
35
.7  LineTo(hDC,   zLeft + 2, yTop - 10);
36
.7 // drawing the vertical grey gridlines:
37
.7  SelectObject(hDC, hGreyPen);
38
.7  for(inti = 1; i <= 11; ++i)
39
.7   MoveToEx(hDC, zLeft+(int)(0.01*mz*i), yTop+height, NULL);
40
.7   LineTo(hDC,   zLeft + (int)(0.01*mz*i), yTop-1);
41
.7
42
.7 // drawing the electrodes:
43
.7  SelectObject(hDC, hBlackBrush);
44
.7  Rectangle(hDC,zLeft,yTop-4,zLeft+(int)(12.7*kzy*mz),yTop);
45
.7  Rectangle(hDC, zLeft + (int)((28.0-12.7)*kzy*mz), yTop-4,
46
.7                      zLeft + width, yTop);
47
.7  Rectangle(hDC, zLeft, yTop+height, zLeft + (int)(12.7*kzy*mz),
48
.7                      yTop + height + 4);
49
.7  Rectangle(hDC, zLeft+ (int)((28.0-12.7)*kzy*mz), yTop+height,
50
.7                zLeft + width, yTop + height + 4);
51
.7 // drawing the equipotential lines and labels of potentials:
52
.7  SelectObject(hDC, hPinkPen);
53
.7  DrawEquipotentialLines(hDC, fontPotential, lf, hBlackPen,
54
.7                            Particle::pF);Algorithm 8:Modal dialog box: function ModalDlgProc (part 4).
1
.8
// drawing the particles’ trajectories:
2
.8
SelectObject(hDC, hBluePen);
3
.8
int
z1, z2, y1, y2;
4
.8
for
(
int
i = 0; i < (
signed
)vpp.size(); ++i)
5
.8
for
(
int
j=0; j<(
signed
)(vpp[i].history.size()-1); ++j)
6
.8
z1 = (
int
)(mz*vpp[i].history[j].z) + zLeft;
7
.8
y1 = yTop + height2-(
int
)(my*vpp[i].history[j].y);
8
.8
z2 = (
int
)(mz*vpp[i].history[j+1].z) + zLeft;
9
.8
y2 = yTop + height2-(
int
)(my*vpp[i].history[j+1].y);
10
.8
if
(y2 > yTop + height)
11
.8
y2 = yTop + height;
12
.8
MoveToEx(hDC, z1, y1, NULL);
13
.8
LineTo(hDC, z2, y2);
14
.8
15
.8
// showing the number of a particle whose data
16
.8
// will be displayed in the list box:
17
.8
if
(particleListBox != -1)
18
.8
pLB = sprintf_s(bufferLB, "%d", particleListBox);
19
.8
SetBkMode(hDC, TRANSPARENT);
20
.8
TextOut(hDC, 720, 60, bufferLB, pLB);
21
.8
22
.8
EndPaint(hwnd, &psPaint);
23
.8
break
;
24
.8
case
WM_DESTROY:
25
.8
DeleteObject(g_hbrBackground);
26
.8
DeleteObject(hBlackBrush);
27
.8
DeleteObject(hBlackPen);
28
.8
DeleteObject(hPinkPen);
29
.8
DeleteObject(hBluePen);
30
.8
DeleteObject(hGreyPen);
31
.8
DeleteObject(hWhitePen);
32
.8
DeleteObject(hBlackThickPen);
33
.8
PostQuitMessage(0);
34
.8
break
;
35
.8
36
.8
return
0;
37
.8Algorithm 9:The second thread: function ThreadProc.
1
.9
DWORD CALLBACK ThreadProc(LPVOID lpdwThreadParam)
2
.9 const doubleht = 1.0e-9; //time step of integration, s
3
.9 static intcount = 0; //number of particles with z > zMax
4
.9 while(count < (signed)vpp.size())
5
.9 for(inti = 0; i < (int)vpp.size(); ++i)
6
.9
if(vpp[i].stop==false)
7
.9 RK4_4eq<Particle>(&vpp[i], ht, &Particle::t, &Particle::vz,
8
.9  &Particle::vy, &Particle::z, &Particle::y, &Particle::FzFy,
9
.9  &Particle::DvzDt, &Particle::DvyDt, &Particle::DzDt,
10
.9  &Particle::DyDt);
11
.9 vpp[i].v=sqrt(vpp[i].vy*vpp[i].vy + vpp[i].vz*vpp[i].vz);
12
.9 vpp[i].W=0.5*Particle::m*vpp[i].v*vpp[i].v/Particle::q;
13
.9 vpp[i].currentData.t = vpp[i].t;
14
.9 vpp[i].currentData.z = vpp[i].z;
15
.9 vpp[i].currentData.y = vpp[i].y;
16
.9 vpp[i].currentData.vz = vpp[i].vz;
17
.9 vpp[i].currentData.vy = vpp[i].vy;
18
.9 vpp[i].currentData.v = vpp[i].v;
19
.9 vpp[i].currentData.W = vpp[i].W;
20
.9 vpp[i].history.push_back(vpp[i].currentData);
21
.9 if(vpp[i].z >= Particle::pF->zMax)
22
.9  vpp[i].stop=true;
23
.9  ++count;
24
.9
25
.9
26
.9 if(!vpp[particleListBox].stop)
27
.9  sprintf_s(bufListBox, " t = %.3ey = %.5fz = %.5f",
28
.9            vpp[particleListBox].history.back().t,
29
.9            vpp[particleListBox].history.back().y,
30
.9            vpp[particleListBox].history.back().z);
31
.9  SendMessage(GetDlgItem(hModalDlg, IDC_ListBox),LB_ADDSTRING,
32
.9                      0, (LPARAM)bufListBox);
33
.9  SendMessage(GetDlgItem(hModalDlg, IDC_ListBox), LB_SETTOPINDEX,
34
.9    (WPARAM)(vpp[particleListBox].history.size()-1), 0);
35
.9
36
.9 InvalidateRect(hModalDlg, NULL, FALSE);
37
.9 if(hModelessDlg != 0)
38
.9  InvalidateRect(hModelessDlg, NULL, FALSE);
39
.9 Sleep(sleep);
40
.9
41
.9 return0;
42
.9As we can see in the prototype shown in Algorithm1, the function template imposes some restrictions on the content of the application class T; namely, the class needs to have five data members denoting both an independent variable (time t) and four state variables (y, z, vy, and vz), a helper function (pointed aspPrecompute), and four member functions for computing the right-hand sides of the corresponding differential equations. The helper function makes the calculations common for right-hand sides, thus reducing the run time. The classParticle is designed so that these requirements are met.After an integration step has been completed, the updated values of the state variables are pushed into theParticle’s vector containerhistory (lines 11.9–20.9). When thefor loop is completed, the messages are generated to be passed both to the modal dialog box (including the list box) and to the modeless box. In particular, the functionsInvalidateRect are invoked generating the messages WM_PAINT. As a result, the numerical outputs are updated. When sending messages to the list box via calling the functionsSendMessage in lines 31.9–34.9, the message LB_ADDSTRING results in adding the new text line to the end of the list, and the message LB_SETTOPINDEX ensures that the end of the list is visible. The call of the functionSleep allows setting the desired simulation rate kept in the variablesleep. Then thewhile loop starts the next iteration.


## 5. Some Simulation Results and Discussion

The considered object-oriented simulation model of particles motion in electric field combined with Win32 dialog-based graphical interface and framework has been tested within Visual C++ 2010 Express environment for different cases to estimate the performance of the simulation. The project was built inrelease configuration, so the program is fully optimized. The simulation is carried out on an AMD Athlon™ 64 × 2 Dual Core 2.40 GHz processor. With the aim of getting the CPU (central processing unit) time that elapses when executing the thread procedureThreadProc (physics engine), the functionclock defined in the header file <ctime> has been used. The time step of integration of the particle motion equations is ht=10-9 sec. Three cases of simulation were considered, which have different sets of output facilities. The first case covers the program version with the graphical output only, the second one adds the text output to the modeless box, and the third one provides also the text output to the list box. In all cases the time delay is set to zero. The results obtained for the cases depending on the sizes of the particle ensemble are presented in Table 1. Each value is an average of a small sample formed as a result of 5–7 runs.Table 1
The elapsed CPU time required for simulating the motion of an ensemble of particles in the thread functionThreadProc (no sleep time).
(a)
Graphical output only
Number of particles
1
10
100
1000
10000
CPU time, sec
0.016
0.041
0.122
1.125
10.32
(b)
Graphical output and text output to the modeless box
Number of particles
1
10
100
200
500
CPU time, sec
0.018
0.044
0.172
0.262
0.634
(c)
Graphical output and text output both to the modeless box and to the list box
Number of particles
1
10
100
200
500
CPU time, sec
9.255
34.19
264.2
513.3
1254The results show a high performance of the simulation model in the first (a) and the second (b) cases, even for large particle ensembles (104 particles). However, the third case (c), in which the text output is also displayed in the list box, is characterised by a much lower rate of computation and output. So this output mode should be applied only for applications not having the high requirements to the simulation speed.In addition to the above-mentioned simulation cases, a comparative evaluation study has been carried out with respect to the performance of a code written in C++ and two other popular object-oriented languages, Java and C#. As a test code, we take the solver for Laplace’s equation described shortly in Section3.1. The desired accuracy in the iterative Liebmann’s procedure is set to eps=10-7. Three projects with identical algorithm coding have been developed: the first is created as a Visual C++ 2010 Express console application, the second is written in Java and run in the Java SE 8 Runtime Environment, and the third is written on the base of the Visual C# 2015 Express as a console application. The C++ and C# projects are built in the release configuration and the Java project, in Run configuration (versus Debug). To determine the execution time in the Java program, we apply theSystem.nanoTime method. As to the C# application, the methods ofStopwatch class are used. The execution times obtained as an average of 5–7 runs are as follows: C#, 0.059 sec, Java, 0.036 sec, and C++, 0.016 sec. These results confirm once more such a key advantage of the compiled C++ as the running time efficiency against the widespread alternatives, Java and C#, even provided that the “just-in-time” compilation is applied.Summing up this and other advantages of C++, such as greater flexibility through the wide use of pointers and templates and the availability of extensive libraries (Win32 API, STL, Boost, etc.), we have every reason to consider C++ as a premier object-oriented language for scientific applications.


## 6. Conclusion

The case study of the simulation model considered in the paper provides some general guidelines on how to develop a desktop framework that would have the minimal set of means being sufficient for organizing the simulation process as such, as well as the online input and graphical and numerical output. The important feature of this framework as compared to alternative solutions is that it uses the free Win32-based platforms from Microsoft, such as Visual C++ Express 2010 Edition. This widespread IDE allows developing effective desktop interactive simulation models of complex dynamical systems by utilizing the basic Win32 API functions and standard unmanaged compiled C++. The main advantages of this versatile approach are the flexibility and run time efficiency of the solutions developed. Indeed, domain neutral simulator systems based on the usage of C++, the object-oriented, imperative, and compiled language, should run faster than simulators which use, for example, also object-oriented and imperative, but interpreted, languages like Java (see, e.g., Praehofer and Schoeppl [15]). The caveat connected with this approach is that a researcher involved in the simulation modelling has to possess a strong proficiency in C++ and Win32 API.It should also be noted that the considered multiwindows desktop framework may apparently have the possibilities to be used as a basis for more complex and expanded dynamical models with other powerful features, for example, double buffering, to prevent an excessive flickering and to speed up the redraw, parallel computing using MPI (Message Passing Interface), and so forth. Again, applying such up-to-date.NET technology as Windows Forms should be considered as well. Essentially, the presented results can be applied to all kinds of simulation: continuous, hybrid, and even discrete-event applications. The approach has already been used in developing the research software in the field of designing particle accelerators, which was carried out by S. Kozynchenko and V. Kozynchenko [16–18].



---

*Source: 1756124-2016-03-16.xml*