User manual (PDF 12 MB) - PC
Transcription
User manual (PDF 12 MB) - PC
DREAM Suite version 1 User Manual A software package for Bayesian inference of numerical simulation models March 2016, PC-Progress, Prague, Czech Republic © 2016 PC-Progress. All rights reserved. Copyright © 2016 by PC-Progress s.r.o.. All Rights Reserved. DREAM Suite 1 2 DREAM Suite 1 Table of contents 1. Introduction .............................................................................. 6 2. Getting started ........................................................................... 7 2.1. System requirements ............................................................................... 7 2.2. Authors and contact information ............................................................... 8 2.3. Installation ............................................................................................. 8 2.4. Authorization ........................................................................................ 11 2.4.1. Hardware key ................................................................................. 13 2.4.2. Software activation .......................................................................... 13 2.4.3. Software Deactivation ...................................................................... 18 2.4.4. Reinstallation and uninstallation ........................................................ 19 3. Graphical user interface ............................................................ 20 3.1. Project manager .................................................................................... 3.2. Library manager .................................................................................... 3.3. Project windows .................................................................................... 3.3.1. Project tree .................................................................................... 3.3.2. Project information ......................................................................... 3.3.3. Model definition .............................................................................. 3.3.4. Simulations .................................................................................... 3.3.5. Simulation case .............................................................................. 3.3.6. DREAM algorithmic variables ............................................................ 3.3.7. Parameter space ............................................................................. 3.3.8. Likelihood function .......................................................................... 3.3.9. Prior distribution ............................................................................. 3.3.10. Measurement data ......................................................................... 3.3.11. Calculation ................................................................................... 3.3.12. Post-processing - tables ................................................................. 3.3.13. Post-processing - charts ................................................................. 3.4. Program options .................................................................................... 3.5. Dialog About DREAM Suite ..................................................................... 3.6. Dialog DREAM Suite License ................................................................... 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 4. Demo examples ........................................................................ 39 4.1. Example 1 ............................................................................................ 4.2. Example 2 ............................................................................................ 4.3. Example 3 ............................................................................................ 4.4. Example 4 ............................................................................................ 4.5. Example 5 ............................................................................................ 4.6. Example 6 ............................................................................................ 4.7. Example 7 ............................................................................................ 4.8. Example 8 ............................................................................................ 4.9. Example 9 ............................................................................................ 4.10. Example 10 ......................................................................................... 4.11. Example 11 ......................................................................................... 4.12. Example 12 ......................................................................................... 3 40 45 49 54 55 55 57 65 66 68 70 70 DREAM Suite 1 4.13. 4.14. 4.15. 4.16. 4.17. 4.18. 4.19. 4.20. 4.21. 4.22. 4.23. Example 13 Example 14 Example 15 Example 16 Example 17 Example 18 Example 19 Example 20 Example 21 Example 22 Example 23 ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... ......................................................................................... 72 73 74 75 77 78 79 82 83 85 86 5. Using DREAM ........................................................................... 88 5.1. DREAM projects .................................................................................... 88 5.1.1. Project files .................................................................................... 90 5.2. DREAM applications ............................................................................... 92 5.2.1. DREAM console application .............................................................. 93 5.3. DREAM plugins ..................................................................................... 95 5.3.1. C/C++ Plugin ................................................................................. 96 5.3.2. MATLAB Plugin .............................................................................. 97 5.4. DREAM Solver ..................................................................................... 100 5.4.1. Calculation observer ...................................................................... 104 6. Programming references .......................................................... 104 6.1. DREAM SDK ........................................................................................ 6.2. Plugin module template ........................................................................ 6.2.1. DreamEvaluator.h ......................................................................... 6.2.2. DreamEvaluator.cpp ...................................................................... 6.2.3. TestApp.h .................................................................................... 6.2.4. TestApp.cpp ................................................................................. 6.3. Interfaces ............................................................................................ 6.3.1. IDreamInputParViewer .................................................................. 6.3.2. IDreamInputParams ...................................................................... 6.3.3. IDreamDataMinMax ....................................................................... 6.3.4. IDreamDataNormal ....................................................................... 6.3.5. IDreamDataPrior ........................................................................... 6.3.6. IDreamDataMeasurement ............................................................... 6.3.7. IDreamDataABC ............................................................................ 6.3.8. IDreamDataSource ........................................................................ 6.3.9. IDreamEvaluator ........................................................................... 6.3.10. IDreamObserver ......................................................................... 6.3.11. IDreamSolver ............................................................................. 6.4. Data structures .................................................................................... 6.4.1. IDreamPluginInfo ......................................................................... 6.4.2. IDreamCalcSettings ....................................................................... 6.4.3. IDreamErrorInfo ........................................................................... 6.4.4. IDreamMatrix ............................................................................... 6.4.5. IDreamVector ............................................................................... 6.5. Enumerators ....................................................................................... 6.5.1. eBoundHandling ........................................................................... 4 104 105 105 106 117 119 126 126 128 129 129 130 130 130 131 131 132 132 133 133 133 134 134 134 135 135 DREAM Suite 1 6.5.2. eDistanceFunction ......................................................................... 6.5.3. eDistributionMultivariate ................................................................ 6.5.4. eDistributionUnivariate .................................................................. 6.5.5. eDreamError ................................................................................ 6.5.6. eDreamInputPar ........................................................................... 6.5.7. eDreamPath ................................................................................. 6.5.8. eDreamWarning ............................................................................ 6.5.9. eErrType ...................................................................................... 6.5.10. eInitDistrib ................................................................................. 6.5.11. eLikelihood ................................................................................. 6.5.12. eMeasureError ............................................................................ 6.5.13. eOutlierTest ................................................................................ 6.5.14. eParallelMode ............................................................................. 6.5.15. ePluginType ............................................................................... 6.5.16. ePriorDistrib ............................................................................... 6.5.17. ePriorType ................................................................................. 6.5.18. eVectorization ............................................................................. 5 135 135 136 136 138 139 140 141 141 142 142 143 143 143 144 144 144 DREAM Suite 1 1 Introduction DREAM Suite is a software package for the rapid development of applications based on theory of Markov chain Monte Carlo (MCMC) simulation. This toolbox provides scientists and engineers with an arsenal of options and utilities to solve posterior sampling problems involving (amongst others) bi modality, highdimensionality, summary statistics, bounded parameter spaces, dynamic simulation models, formal/ informal likelihood functions, diagnostic model evaluation, data assimilation, Bayesian model averaging, distributed computation, and informative/non-informative prior distributions. DREAM Suite supports parallel computing and returns to the user graphical output and convergence diagnostics of the sampled chain trajectories. DREAM Suite components · · · · · Main Program - the graphical user interface for the management of DREAM Suite projects, preprocessing input data, running simulations and viewing results. DREAM Solver - the calculation module, distributed in binary form (COM server) or with source code (C+ + library). DREAM SDK - Software Development Kit with interfaces and C++ libraries for the development of DREAM Plugin modules. Console Application - a simple C++ application illustrating the use of DREAM Solver. Distributed with source code. Examples - demo examples illustrating the main capabilities and functionalities of the DREAM Suite package. These examples are available including C++ source code, are easy to adapt and can serve as templates for other projects. DREAM Editions and their features Runtime Edition Standard Edition DREAM calculation module - COM Server ✓ ✓ Support of programmable plugin modules ✓ ✓ 23 demo examples with results and C++ source code (DREAM plugins) ✓ ✓ DREAM TestApp console (client application) with C++ source code ✓ ✓ Authorization manager ✓ ✓ Project manager ✓ ✓ Features DREAM Solver Demo examples DREAM Suite main program (GUI) Data preprocessing - data input in dialogs and tables ✓ Calculation (including parallel calculation on multi-core PCs) ✓ Post-processing - graphical display of results in charts and tables ✓ DREAM SDK C++ library for the development of DREAM plugin modules ✓ Generator of source code of DREAM plugin modules ✓ DREAM Suite applications The DREAM Suite package enables users to rapidly create new Bayesian inference projects via plugin modules. DREAM Solver can also be used as a library/software component for the development of new standalone applications independent of DREAM Suite. DREAM Solver is available either in binary form (COM server) or with all source code (C++ library - requires a special contract). 6 DREAM Suite 1 Required programming skills Although DREAM Solver is a COM server, writing custom plugin modules does not require any special knowledge of COM technology. DREAM Suite can generate source code of a new plugin module and users just implement needed functions in C/C++ or another programming language (currently there is an interface to MATLAB and several other similar interfaces are in development). Most of demo examples (library D3) have been created in Visual C++ using STL and BOOST libraries, which can significantly speed up the development. However, some examples (library D1) have been written in a very simple style in C/C++ so that they were easy to understand even for less experienced programmers. Required programming tools Microsoft Visual Studio 2013 or later (free edition) and DREAM SDK. See also system requirements. 2 Getting started Important notes for new users · · · The full version of DREAM Suite requires a valid license and authorization - see also DREAM installation and activation. The demo version does not include the DREAM Server (the calculation module) and can therefore not be used to rerun existing built-in examples or to calculate new project. The DREAM installation package comes with many built-in examples which demonstrate same of the main capabilities of DREAM Suite. The source code of each of these examples (i.e. their plug-in modules) is available to users and can be accessed in a text editor and recompiled in Visual Studio. The built-in examples of DREAM Suite (available in GUI of the main program) are easy to execute. For each new project the user should have some basic understanding of the DREAM algorithm (DREAM Solver), otherwise this might cause problems with implementation (incorrect use of prior distribution or likelihood function, incorrect return argument from plugin, incorrect setup in GUI, etc.). The GUI evaluates the validity of most input variables of DREAM Solver but cannot check your plugin module. We therefore recommend that you carefully read the DREAM Technical manual before initiating a new project in DREAM Suite. Furthermore, you should read documentation on the plugin module, a key component of a key component of each DREAM Suite project. Useful links · · · · Web site: http://www.pc-progress.com/en/Default.aspx?dream Frequently asked questions: http://www.pc-progress.com/en/Default.aspx?dream-faq Discussion forum: http://www.pc-progress.com/forum Customer support: [email protected] 2.1 System requirements Supported operating systems · · · · · Windows Windows Windows Windows Windows 10 (32-bit and 64-bit) 8 (32-bit and 64-bit) 7 (32-bit and 64-bit) Vista (32-bit and 64-bit) Server 2008, 2012 DREAM Suite is not compatible with older Windows systems, Linux and Mac OS. 7 DREAM Suite 1 Minimum hardware requirements · · · · · X86 processor 2 GHz 2 GB RAM 10 GB free space on hard disk Graphic card with minimum resolution of 1024 x 768 pixels and 16-bit color depth Mouse Tools for the development of DREAM applications DREAM Solver is a standard COM server and therefore DREAM applications can be developed with any tool and compiler that support COM technology. Yet, we recommend that you use Visual Studio 2013 Community Edition (or a more recent version), as the source code of DREAM Suite has been written in C+ +. Visual Studio is available, free of charge, for non-commercial applications. · · Microsoft Visual Studio 2013 (with update 3 or newer) Microsoft Visual Studio 2015 (with update 2 or newer) 2.2 Authors and contact information Developers DREAM Suite has been developed by Miroslav Šejna, Jasper Vrugt and PC-Progress s.r.o.. Copyright © 2016 PC-Progress s.r.o.. All rights reserved. Contact Information PC-Progress s.r.o. Korunní 2569/108a Prague, 101 00 Czech Republic Phone: Fax: e-mail: web: (+420) 222 514 225 or (+420) 245 008 033 (+420) 245 008 099 [email protected] or [email protected] www.dreamsuite.eu or www.pc-progress.com Customer Support e-mail: [email protected] Working hours: 9:00-17:00 (CET) Disclaimer The software has been verified against a large number of test cases. However, no warranty is given that the program is completely error-free. If you do encounter problems with the code, find errors, or have suggestions for improvement, please contact customer support at [email protected] 2.3 Installation 8 DREAM Suite 1 Installation program The DREAM Suite installation program is available on the PC-Progress website http://www.pcprogress.com/en/Default.aspx?dream or in ELIS (PC-Progress client portal) at http://www.pc-progress.com/ en/Default.aspx?elis. Running the installation Download and run a self-extracting archive (e.g. DREAM_Suite_1.01.0010.exe), which will the extract installation files to a temporary directory and start the installation program of DREAM Suite. Selecting directories for DREAM Suite program files and data files We recommend that you install the DREAM Suite program files in the default directory (e.g. C:\Program Files (x86)\PC-Progress\DREAM Suite 1.x). Users can store their own data files in any other folder (see Figure 2.3.1. "Installation Directories"). DREAM users must have "read/write" access to this folder. Data files include demo examples, user's projects, files with user's settings and DREAM Suite SDK libraries. Figure 2.3.1. Installation Directories. Installation of HASP driver If your license is protected by a hardware key, it is necessary to check the "Install hardware-key driver" button (see Figure 2.3.2."Installation Features"). 9 DREAM Suite 1 Figure 2.3.2. Installation Features. Completing the installation At the end of the installation process, it is necessary to launch DREAM Suite (check-box "Launch DREAM Suite") so that the program can make the necessary changes in the Windows registration database and thereby completing the installation. 10 DREAM Suite 1 2.4 Authorization DREAM Suite is secured against unauthorized use by a hardware key (USB dongle - HASP) or software activation. The method of protection can be selected at the time of purchase of a user license. Both methods have their own advantages and disadvantages. Hardware key The hardware key is very simple to use and you can easily move the authorization from one computer to another one. You just need to insert this USB device into your computer and DREAM Suite will find it automatically. A problem may occur if the hardware key is lost, which can mean the loss of the license. Software activation The program activation is a process by which the authorization of DREAM Suite is based on a unique numerical code, generated for a particular computer and for one-time use. The code is tied to the hardware configuration, i.e. it cannot be used on another computer, or reused on the same computer if the authorization is lost for some reason. Each activation is time-limited (even if you have a permanent license) and must be prolonged before (or after) its expiration. The time-limited activation was introduced to prevent unwanted consequences resulting from computer crashes and similar hardware problems that require a new activation of DREAM Suite without its prior deactivation. The program can be deactivated manually and the license transferred to another computer. Verifying authorization Authorization is verified when starting the program. If any failure occurs, a warning is displayed that the program is running in a demo mode, in which DREAM Suite is not fully functional, i.e. it is not possible to run the calculation. DREAM Suite authorization dialog Dialog with the authorization information and for the activation/deactivation of the program may be accessed from the main menu - Help - DREAM Suite License. 11 DREAM Suite 1 Figure 2.4.1. Authorization status. 12 DREAM Suite 1 2.4.1 Hardware key A Hardware Key (HASP), also called a "dongle", is a software copy protection device that is plugged into the USB port of the computer. Upon startup, the application looks for the key and will run only if the key contains the appropriate code. Hardware keys are very effective copy protection devices, because they cannot be duplicated by the user. · · The HASP for DREAM Suite is sent (by PC Progress) by mail and its use is very simple. You just connect it to the computer via the USB port and DREAM Suite is then immediately authorized. The DREAM Suite software then does not require any further activation. Although the drivers for the HASP should normally be installed automatically when it is connected to the USB (Windows operating system and Plug-and-play should take care of that), we still recommend installing drivers at the same time the DREAM Suite software is installed (during the DREAM Suite installation). In one of the dialog windows that appears during the installation, there is a special checkbox "Install the hardware-key driver", which needs to be checked - see Figure 2.3.1. "Installation directories". Advantages of HASP · · · · Proven solutions by SafeNet, verified by hundreds of installations and users. No activation of the software (e.g., DREAM Suite) is needed. Activation of the program brings some disadvantages, such as that the program can be activated only on the allowed number of computers and that the activation is always time-limited (up to 1 year) and needs to be repeatedly renewed. Under certain circumstances, the activation code may not be immediately available and users will have to wait untill they get it (e.g., activation by e-mail). The hardware key (dongle) provides users assurance that the program can be easily installed and used, for example, on a new computer. The program (e.g., DREAM Suite) can be used on multiple computers (e.g., desktop and laptop) by transferring a small USB key. Easier and safer installation of a network version. The network installation using a software key (activation) is somewhat more complicated and some network administrators have complained about its lack of flexibility. The use of HASP eliminates these problems. 2.4.2 Software activation There are two options to activate DREAM Suite: · · On-line activation (recommended) Activation by e-mail (when the computer is not connected to the internet) Time-limited activation The activation of DREAM Suite is always time-limited (even if you have a permanent license) and the maximum activation period is one year. You can prolong the activation anytime before its expiration using the button "Extend activation on-line" in the DREAM Suite license dialog. After the authorization expires, you can reactivate DREAM Suite using the on-line activation or by e-mail (see "Installation and Activation" above). The time-limited activation was introduced to prevent unwanted consequences as the result of computer crashes and similar hardware problems that require a new activation of DREAM Suite without its prior deactivation. Activation requires administrator's privileges Activation of DREAM Suite requires elevated privileges, i.e. you need to run DREAM Suite "as administrator" - see Figure 2.4.2. " Running DREAM Suite with ...". 13 DREAM Suite 1 Figure 2.4.2. Running DREAM Suite with elevated privileges. 2.4.2.1 On-line activation For the on-line activation you will need the following information: · · · Your license number DREAM Suite Edition to which you have a license and you wish to activate Activation key All this information is available in the system of the customer support ELIS http://www.pc-progress.com/en/ Default.aspx?elis. After purchasing a license, a customer will receive login data to ELIS by e-mail. Figure 2.4.3. ELIS - on-line activation keys. On-line activation proceeds as follows: · · · Start DREAM Suite (with administrator privileges) to access the dialog for the activation (see Figure 2.4.4. "On-line activation of DREAM Suite") Fill in your license number, DREAM Suite edition you wish to activate and the activation code Press the button "Activate Now" After clicking on the Activate Now button, you will be asked to confirm all specified parameters (note that you may be prompted by your firewall to allow communication between your computer and the license 14 DREAM Suite 1 server of PC Progress). At this point, all specified information will be verified against the data of our electronic licensing system and if confirmed the actual activation of DREAM Suite will occur. This communication applies only to data entered in the On-line Activation window, and no other information stored on your PC is transferred. In case of unsuccessful activation, an error message is displayed explaining the problem. After correcting the problem, you can use the Activate Now command again. Figure 2.4.4. On-line activation of DREAM Suite. 2.4.2.2 Activation by e-mail Activation by e-mail proceeds as follows: · · · · · · · Start DREAM Suite (with administrator privileges) and access the dialog for the activation as shown in Figure 2.4.5."Activation by e-mail, generating request codes" Fill in your license number, customer name and DREAM Suite edition you wish to activate Press the button "Generate Request Codes" On the following page of the dialog press the button "Copy request codes to the clipboard..."shown in Figure 2.4.6. "Activation by e-mail, sending request codes to customer support" Open the program for sending e-mails, paste the generated license request from the clipboard and send it to customer support: [email protected] DREAM Suite can be closed Within one working day you will receive an activation code that should be inserted on the third page of the activation dialog as shown in Figure 2.4.7. "Activation by e-mail, entering the activation code". 15 DREAM Suite 1 Figure 2.4.5. Activation by e-mail, generating request codes. 16 DREAM Suite 1 Figure 2.4.6. Activation by e-mail, sending request codes to customer support. 17 DREAM Suite 1 Figure 2.4.7. Activation by e-mail, entering the activation code 2.4.2.3 Extending the activation The activation of DREAM Suite is always time-limited (even if you have a permanent license) and the maximum activation period is one year. The time-limited activation was introduced to prevent unwanted consequences as the result of computer crashes and similar hardware problems that require a new activation of DREAM Suite without its prior deactivation. You can prolong the activation any time before its expiration using the button "Extend activation on-line" in the DREAM Suite license dialog - see the instructions below. After the authorization expires, you can reactivate DREAM Suite using the on-line activation or by e-mail. Extending the activation of DREAM Suite · · · · · Run DREAM Suite "As Administrator", i.e. click on the DREAM Suite icon by right mouse button and select "Run as administrator". Go to the main menu and click on the command "Help->DREAM Suite License and Authorization" In the "DREAM Suite Authorization" dialog, press the button "Extend Activation on-line". In the "Extend Activation Online" dialog, enter the Activation Key. Press the button "Extend Activation Now". If you are prompted to allow DREAM Suite to connect to the internet, allow it. The activation process is finished by a message confirming the successful activation or displaying the reason of failure. If you need a help, please contact DREAM Suite customer support. 2.4.3 Software Deactivation 18 DREAM Suite 1 When you should deactivate DREAM Suite · · · · · · Before any hardware changes (motherboard, hard-drives, graphic card, BIOS, etc.) Before the re-installation of Windows Before reformatting the hard-drive with DREAM Suite Before changing the network path to DREAM Suite (applies to the network installation) If you wish to move your license to another computer If you know that you will not be using DREAM Suite for a long time Deactivation - Common instructions · · DREAM Suite deactivation requires administrator's privileges, i.e., you must run DREAM Suite “As Administrator” Open the DREAM Suite License and Activation dialog (main menu -> help -> DREAM Suite License and Activation) and press the “Deactivate on-line” or “Deactivate by E-mail” button. If your computer is connected to the internet, we recommend you use the on-line deactivation. On-line deactivation · · · · Press the "Deactivate on-line" button. Enter the deactivation key (the same key which was used for DREAM Suite activation). If you forget this key, you can obtain it in ELIS. If you have a firewall, allow all internet connections in the pop-up window which may be displayed. DREAM Suite will connect with our server and will be deactivated. Deactivation by e-mail · · · · Press the ”Deactivate by E-mail” button, which will deactivate DREAM Suite on your computer. DREAM Suite will generate a special deactivation code, which serves as proof of deactivation. This code will be displayed in the DREAM Suite License and Activation dialog. Login to ELIS, go to Licenses and Workplaces, select the Workplace corresponding to the computer that you just deactivated and deactivate this Workplace using the deactivation code. This will unlock the WP and make it available for the activation on another computer. You can also send the deactivation code to [email protected] or to your DREAM Suite reseller, who will unlock the deactivated workplace in ELIS instead for you 2.4.4 Reinstallation and uninstallation Information in this paragraph refers to the situation when DREAM Suite is secured via a software key (activation). If you use a hardware key, a license transfer to another computer is simple - we just transfer this USB key. Reinstallation of DREAM Suite If you reinstall DREAM Suite with the same version (or with a newer version) on an activated computer then the authorization remains active automatically, i.e., you need not deactivate DREAM Suite before the reinstallation and ask for new activation codes. This applies to the single-user license on a standalone computer where DREAM Suite was working as the full version. Moving DREAM Suite license to another computer Moving DREAM Suite license to another computer is simple and you can do it yourself (without assistance of customer support) either on-line or in ELIS in two steps: · Deactivate DREAM Suite on the old computer. 19 DREAM Suite 1 · Activate DREAM Suite on the new computer 3 Graphical user interface DREAM Suite main window allows you to open the Project Manager window and one or more Project windows. It also contains a main menu with all available commands needed for working with DREAM Suite. Main menu · File · · · · · · · · · · · · · New - creates a new project Open - opens an existing project Close - closes the active project Save - saves the active project Save As - saves the active project with a new name Project Manager - shows or hides the Project Manager window Library Manager - opens the Library Manager dialog Recently Opened Projects - opens a recently opened project Exit - quits the application Edit (only available for "Project Information" window) · Undo - undoes the previous action · Cut - cuts the selection and puts it on the Clipboard · Copy - copies the selection and puts it on the Clipboard · Paste - insert Clipboard contents View · Project Information Window - shows or hides the Project Information panel in the Project Manager window · Toolbars and Docking Windows · Standard - shows or hides the Standard toolbar. · Status Bar - shows or hides the Status bar · Reset Toolbars - resets all toolbars and docking panes to the default state Options · Program Options - opens a dialog with Program Options Help · Help - opens a window with DREAM Suite CHM help · Technical Manual - opens PDF with DREAM Suite Technical manual · User's Manual - opens PDF with DREAM Suite User's manual · DREAM Suite on-line - opens DREAM Suite web page · Check for updates - checks on-line for a new version of DREAM Suite · DREAM Suite License - opens a dialog with information about DREAM Suite license and authorization · About DREAM Suite - opens a dialog with information about DREAM Suite 3.1 Project manager Project Manager window displays DREAM Suite projects located in the current library directory and allows to perform basic operations on them: · · Button "New" - creates a new project Button "Open" - opens a selected project 20 DREAM Suite 1 · · · Button "Copy" - copies a selected project Button "Rename" - renames a selected project or changes its description Button "Delete" - deletes a selected project Figure 3.1.1. Project Manager window. Project Information window The Project Information window displays detailed information about the currently selected project. It displays HTML page ProjectInfo.htm located in the project directory, e.g. C:\Users\Public\Documents\PC-Progress \DREAM Suite 1.x\SDK\Examples\Drm_Example01\Model\Info\ProjectInfo.htm. Content of this this page can be changed in the built-in HTML editor (open the project and go to the "Project Information" page) or directly in any other external HTML editor. Location of projects The current location of DREAM Suite projects can be quickly changed by the "Project Group" combo-box or in the Project Group manager (button PG Manager). 3.2 Library manager A "Library" is simply a directory containing DREAM projects, i.e. a location of projects.The Library Manager window displays a list of all libraries and allows basic operations: 21 DREAM Suite 1 · · · · Button "New" - creates a new library, i.e. adds a new directory with DREAM projects Button "Edit" - allows to edit a selected libraries, i.e. to change its directory, name or descriptions Button "Remove" - removes selected libraries from the list. This operation does not delete any files or directories Button "Set Current" - marks a selected library as "current". Projects of this library are then displayed in the Project Manager window. Figure 3.2.1. Library Manager window 3.3 Project windows The Project window has two parts: left panel with the project tree and right dialog corresponding to the currently selected item in the tree (so called "Project dialogs"). 22 DREAM Suite 1 Figure 3.3.1. Project window example. Changing project data When you open a project, all of its data files are copied to a temporary directory and all changes are performed in this directory. This means that original files remain unchanged unless you utilize the "Save" command. This allows you to make various changes, including deleting or recalculating results, without losing the original data. A changed project can be easily recognized by the "*" symbol, which is added to the project name displayed in the project window titlebar. When closing a changed project, the user is prompted to save changes. If you make any changes in the active project dialog, these changes are automatically accepted (i.e. transferred from the dialog to project data in memory) when leaving the page. However, most project dialogs have the buttons "Apply Changes" and "Cancel Changes" that enable you to apply or cancel latest changes without leaving the page. If you enter an invalid data, you are not allowed to leave the page and you must either fix the incorrect data or cancel your changes using the "Cancel Changes" button. 3.3.1 Project tree The Project Tree window displays the entire structure of project data. In the upper part, you can find two items defining general properties of the project - Project Information (the name of this item actually is the project name) and Model Definition. The next item is called "Simulations", under which you can find so called "Simulation cases", representing a series of independent calculation variants. Each simulation case contains standard items, which may change dynamically according to options selected in the particular case. Hint: the user can quickly browse through all items of the tree using keys "Up" and "Down", which will display all project data in project dialogs. 23 DREAM Suite 1 Figure 3.3.2. Project Tree window 3.3.2 Project information Project Information dialog displays basic information about the project, i.e. its name, description and path to the project file. While the description can be modified here, project name and location can only be changed in the Project Manager. Figure 3.3.3. Project information dialog. 24 DREAM Suite 1 HTML window - keyboard commands Ctrl+B Ctrl+I Ctrl+U Ctrl+K Ctrl+spc Ctrl+bksp Ctrl+X Ctrl+C Ctrl+V Ctrl+F Ctrl+A Ctrl+L Ctrl+N Ctrl+P Bold Italics Underline Create a hyperlink Remove formatting Undo (last text edit or format change) Cut Copy Insert from clipboard Find (highlights all occurrences) Select All Open new local HTML file New browser window on current URL Print... 3.3.3 Model definition This dialog defines the number of model parameters and their names. It also specifies the name of the plugin module, which is a dynamic library implementing the evaluation of proposals (hereinafter "Evaluator"). A skeleton of this plugin module can be generated automatically using the "Generate plugin project" button. An existing project can be opened in the Visual Studio using the second button "Open plugin project". Plugin type and creating DREAM plugins in other languages DREAM Suite plugin can be implemented in various languages. This can be done either directly, when the plugin DLL is created in a different language than C/C++ and connected with DREAM via the COM interface, or indirectly, when the C++ plugin DLL serves just as an interface connecting DREAM with an external module/server. The second case is demonstrated by two interfaces to MATLAB - see details in MATLAB Plugin. For plugin types MATLAB_COM and MATLAB_Engine, plugin functions (definition of input data and evaluation of proposals) are actually implemented in MATLAB *.m files. Another similar example is Example 5. Loading the Plugin DLL By default, the plugin DLL is automatically loaded when opening the project (if the DLL is available). The plugin is then used to initialize data of new projects and check data of existing projects. During the calculation, the plugin is used to calculate the probability of samples (see Differential Evolution Adaptive Metropolis method). Check-box "Load plugin automatically..." allows users to disable this automatic loading, which can be useful especially when loading the DLL takes a long time (e.g. when loading the MATLAB server, etc.). If the automatic loading is turned off, plugin DLL is loaded just before the calculation. 25 DREAM Suite 1 Figure 3.3.4. Model definition dialog 3.3.4 Simulations This page is intended for the management of simulations. Each simulation case (hereinafter "Case") uses the same Evaluator but can have different DREAM input data. This allows the user to create multiple variants of the same project with different settings and results. Available operations with simulation cases · · · · · · · New Case - creates a new simulation case Copy Case - creates copy of a selected simulation case Rename Case - modifies case name and/or its description Delete Cases - deletes one or more selected simulation cases Delete Results of Selected Cases - deletes results of one or more selected simulation cases Save Selected Modified Cases - saves data of selected modified cases Restore Selected Modified Cases - cancels all changes in the selected cases and reloads their original data 26 DREAM Suite 1 Figure 3.3.5. Simulations dialog. 3.3.5 Simulation case This dialog displays basic information about a particular simulation case, i.e. its name, description and case file and directory. Available operations with the simulation case · · · · · · · New Case - creates a new simulation case Copy Case - creates copy of the simulation case Rename Case - modifies case name and/or its description Delete Case - deletes the simulation case Delete Result - deletes results of the simulation case Save Modifications - saves data of the simulation cases Cancel Modifications - cancels all changes in the case and reloads its original data 27 DREAM Suite 1 Figure 3.3.6. Simulation case dialog 3.3.6 DREAM algorithmic variables This dialog can be used to set the basic DREAM algorithmic variables: · · · · · · · · · · · Number of Markov chains Number of generations Number of crossover values Number of chain pairs for proposal Random error for ergodicity Randomization Test function to detect out-lier chains Probability of jump rate of 1 Option to adapt selection probability crossover Option to store each T-th sample Scaling factor of built-in jump rate 28 DREAM Suite 1 Figure 3.3.7. DREAM algorithmic variables dialog 3.3.7 Parameter space This dialog is used for specification of initial sampling distribution, boundary handling and the use of prior distribution. Initial sampling distribution options · · · · Uniform Normal Latin Prior Boundary handling options · · · · None Reflect Bound Fold Use prior distribution This option allows use of the prior distribution for initial sampling types different form "Prior" 29 DREAM Suite 1 Figure 3.3.8. Parameter space dialog. 3.3.8 Likelihood function This dialog can be used to specify the likelihood function type and corresponding nuisance variables (if applicable). Likelihood function options User-free likelihood functions · 1 – Likelihood, L(x| Y) · 2 – Log-likelihood, L(x| Y) Formal likelihood functions · 12 – Gaussian likelihood: homos/heteroscedastic data error · 13 – Gaussian likelihood: with AR-1 model of error residuals · 14 – Generalized likelihood function · 15 – Whittle's likelihood (spectral analysis) · 16 – Laplacian likelihood: homos/heteroscedastic data error · 17 – Skewed Student likelihood function ABC – diagnostic model evaluation · 21 – Noisy ABC: Gaussian likelihood · 22 – ABC: Boxcar likelihood 30 DREAM Suite 1 GLUE – limits of acceptability · 23 – Limits of acceptability GLUE – informal likelihood functions · 31 – Inverse error variance with shaping factor · 32 – Nash and Sutcliffe efficiency with shaping factor · 33 – Exponential transform error variance with shaping factor · 34 – Sum of absolute error residuals GLUE likelihood parameter - the value of the shaping factor used within the (pseudo)likelihood functions of GLUE. Diagnostic Bayes - switch Bayes diagnostic on or off. Figure 3.3.9. Likelihood function dialog. 3.3.9 Prior distribution This dialog is intended to define the prior distribution type and its values. Prior distribution types · · Univariate Multivariate 31 DREAM Suite 1 Figure 3.3.10. Prior distribution dialog. 3.3.10 Measurement data This dialog can be used to enter data from measurements. 32 DREAM Suite 1 Figure 3.3.11. Measurement data dialog. 3.3.11 Calculation This dialog is intended for specifying calculation parameters and running the simulation. Output options · · · · · · · Save results in binary format - enables the saving of output files in binary format or text format. Binary files have significantly smaller sizes and reading/writing is usually faster. Text files can us the check values in the files. Save within-chain diagnostic - creates file DREAM_Out_Diagnostic.txt with Coda diagnostic of each chain Save between-chain diagnostic - creates files DREAM_Out_BetweenChainDiagnostic_Rstat.txt (*.bin) and DREAM_Out_BetweenChainDiagnostic_MRstat.txt (*.bin) with Save R- and MR-statistics Save Markov chains - creates files DREAM_Out_ChainN.txt (*.bin) with Markov chains Save ParSet - creates files DREAM_Out_ParSet.txt (*.bin) with ParSet matrix Save model simulations - creates file DREAM_Out_FxSN.txt (*.bin) with calibration data of measurements or ABC-summary metrics data. Save summary statistics - creates file DREAM_Out_SN.txt (*.bin) with summary metrics in each generation. Calculation Options · Multi-core computation chains - enables the running of calculations in parallel mode 33 DREAM Suite 1 Calculation Options - Global Settings · · · Set the number of threads automatically - sets the number of calculation threads according to the number of available cores (including hyper-threading) Set custom number of threads - allows manual specification of the number of calculation threads Set the highest priority to calculation threads - calculation will run with the highest system priority Calculation commands · · · · Calculate - starts the calculation Stop - interrupts the running calculation Refresh - updates the content of the output window, which may not be up-to-date if user clicked on it by mouse or scrolled it. Delete results - deletes existing results of the current simulation case Figure 3.3.12. Calculation dialog 3.3.12 Post-processing - tables This dialog displays results in tables. Selected values can be copied to the clipboard using the "Copy" button. 34 DREAM Suite 1 Available tables · · Parameter values Correlation matrix Figure 3.3.13. Post-processing - tables dialog. 3.3.13 Post-processing - charts This dialog displays results in charts. The current chart may be copied to the clipboard as a metafile using the "Copy" button. Chart settings can be customized by the "Options" button or using the pop-up menu displayed after right-clicking on the chart. Available charts · · · · · Algorithmic behavior of DREAM Autocorrelation of sampled parameters Convergence of individual chains to target distribution Marginal densities of parameters Histogram of marginal densities of parameters 35 DREAM Suite 1 Figure 3.3.14. Post-processing - charts dialog. 3.4 Program options This dialog allows the specification and saving of some global options valid for a given computer. The meanings of all options are obvious from their names. w Program Startup § Open project manager § Open recently opened projects § Check for available updates (after a period of N days) w Calculation § Multi-core computation chains § Set number of cores automatically § Set the highest priority to calculation threads w Visual Studio § Path to Visual Studio IDE w DREAM Suite SDK § Path to DREAM Suite SDK. This path corresponds to the DREAM1_SDK system environment variable. Changing this path requires elevated privileges, i.e.DREAM Suite must be started in the "Run As Administrator" mode. 36 DREAM Suite 1 Figure 3.3.15. Program Options dialog 3.5 Dialog About DREAM Suite This dialog displays basic information about the program, e.g. program version, authors, copyright and license agreement. 37 DREAM Suite 1 Figure 3.3.16. About DREAM Suite dialog 3.6 Dialog DREAM Suite License This dialog displays information about DREAM Suite license and authorization. 38 DREAM Suite 1 Figure 3.3.17. DREAM Suite License dialog. 4 Demo examples DREAM Suite includes many examples illustrating the main capabilities and functionalities of the DREAM Suite package. These examples are available including source code, are easy to adapt and can serve as templates for other projects. Since DREAM Plugin modules can be written in various languages and also programming skills of DREAM users can be different, some selected examples are available in multiple implementations. For example, library D3 contains examples written in C++ by professional programmers using STL and BOOST libraries. Library D1 contains selected simplified examples (subset of D3) intended for beginners and less-experienced programmers. Library D2 contains examples implemented in MATLAB and demonstrates the ability of DREAM Suite to be used with other tools than Visual C++. Libraries with demo examples § § § D1 - Selected simplified examples in C/C++ D2 - Selected examples implemented in MATLAB (*.m script files) D3 - Advanced examples written in C++ using STL and BOOST 39 DREAM Suite 1 These examples and libraries can be found in the Library Manager. List of available examples (category D) Below you can find the list of all available examples and their mathematical description. Additional information can be found directly in the source code of these examples, which is included in the DREAM Suite package. Name Description Example01 n-dimensional banana shaped Gaussian distribution Example02 n-dimensional Gaussian distribution Example03 n-dimensional multimodal mixture distribution Example04 Real-world example using hymod rainfall - runoff model (HYMOD code in C++) Example05 Real-world example using hymod rainfall - runoff model (HYMOD code in external FORTRAN module) Example06 Rainfall-runoff model with generalized log-likelihood function Example07 HYDRUS-1D: using prior information on soil hydraulic parameters Example08 1D mixture distribution: Approximate Bayesian Computation Example09 Rainfall-runoff model with spectral likelihood function Example10 Multimodel mixture distribution: multivariate prior Example11 Multivariate student t-distribution Example12 Pedometrics problem involving variogram fitting Example13 Nash-Cascade hydrograph Example14 ABC inference for hydrologic model Example15 ABC inference using 10 bivariate normal distributions Example16 Hydrogeophysical inference Example17 Rainfall-runoff with inference discharge data error Example18 Informal likelihood (GLUE): Lotka-Volterra model Example19 Bayesian Model Averaging Example20 GLUE - limits of acceptability: Soil temperature modeling Example21 GLUE - limits of acceptability: HYDRUS-1D model Example22 GLUE - limits of acceptability: Nash-Cascade example Example23 GLUE - limits of acceptability: SAC-SMA model 4.1 Example 1 Case-Study I: d-dimensional banana shaped Gaussian distribution The first case study considers a d=10-dimensional twisted Gaussian probability density function which is given by the following unnormalized density (hence the proportionality sign) (1.01) where is a function that is used to the multivariate normal to a twisted (banana-shaped) distribution. Here, signifies the probability density function of a multivariate normal distribution, , and thus , where the vector stores the mean of the distribution, and the matrix signifies the variance-covariance matrix. The tilde 40 DREAM Suite 1 symbol ‟ ” means ‟distributed according to”. The probability density function of is given by (1.02) where the symbol T denotes transpose, and |·| signifies the determinant operator, The mean of the normal distribution, as a diagonal matrix, . was set to zero (all elements), and the covariance matrix is defined . The entries of this matrix outside the main diagonal are all zero (1.03) , and the value of b = 0.1. The initial sample was drawn from , a normal distribution centered at zero and with covariance matrix equal to five times the identity matrix, , a (square) matrix with ones on the main diagonal and zeros elsewhere. We use N = 10 different chains with DREAM and apply default values of the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D1\Drm_D1_Example01\Plugin \Src_Cpp /////////////////////////////////////////////////////////////////////////////////////////////////// // EvaluatorModel.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample01::GetInputParams //------------------------------------------------------------------------------------------------( IDreamInputParams* pIDreamInputParams // Pointer to DREAM input data to be defined ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define default DREAM parameters for this particular project. This function is called by the main program to initialize data of each newly created simulation case. This data can be later modified in the GUI (except parameters locked by flag DreamSolver::disable_edit) or can be overwritten while reading case data from a file. In the AppTest console application, there is no GUI and this functions actually defines all input parameters that are subsequently used by DREAM Solver. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ 41 DREAM Suite 1 /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIDreamInputParams pointer if(pIDreamInputParams == nullptr) { return E_INVALIDARG; } // Set default input parameters pIDreamInputParams->SetProblemDimension(2, DreamSolver::enable_edit); pIDreamInputParams->SetNumberOfMarkovChains(10, DreamSolver::enable_edit); pIDreamInputParams->SetNumberOfGenerations(25000, DreamSolver::enable_edit); pIDreamInputParams->SetLikelihoodChoice(eLikelihood::LIK_102, DreamSolver::disable_edit); pIDreamInputParams->SetInitialDistribution(eInitDistrib::eInitNormal, DreamSolver::enable_edit); pIDreamInputParams->SetOutlierTest(eOutlierTest::eOutlierIqr, DreamSolver::enable_edit); pIDreamInputParams->SetBoundHandling(eBoundHandling::eBoundUnbounded, DreamSolver::enable_edit); // Example can run in parallel mode (recommended mode) pIDreamInputParams->SetParallelMode(eParallelModeYes, DreamSolver::enable_edit); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample01::InitData //------------------------------------------------------------------------------------------------( IDreamPluginInfo* pIPluginInfo // Plugin information , IDreamInputParViewer* pIDreamInputParams // Current DREAM input parameters ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: This function is called to prepare: A/ DREAM input data before accessing them via the IDreamDataSource interface and B/ all other local data required by evaluator for the calculation. It can be also used to read needed data from a file in directory pIPluginInfo->m_strModelDataDir (directory ...Drm_ExampleXX\Model\Data). Remark 1: This function prepares DREAM input data in the evaluator according to current DREAM parameters defined by pIPluginInfo interface. Note that some parameters can be different from default parameters defined in function CEvaluatorExample::GetInputParams(). Remark 2: This function should be called before using functions CEvaluatorExample::GetMinMaxData, ::GetNormalData, ::GetPriorData, ::GetPriorDataCustom, ::GetMeasurementData and ::GetBayesData. However, function CEvaluatorExample::GetInputParams() can be called independently. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Check parameters if(pIPluginInfo == nullptr || pIDreamInputParams == nullptr) { // Invalid argument return E_INVALIDARG; } // Free memory from previous calculation FunctionsSC::DeleteMatrix(m_invC, m_invCSize); // Target covariance int iDim = m_invCSize = pIDreamInputParams->GetProblemDimension(); double** C = nullptr; FunctionsSC::IdentityMatrix(C, iDim); C[0][0] = 100.0; 42 DREAM Suite 1 FunctionsSC::CopyMatrix(m_invC, C, iDim); if(!FunctionsSC::Inv(m_invC, iDim)) { return E_FAIL; } // Calculate integration constant double temp = pow(2.0 * pi<double>(), -(double)iDim / 2.0); double det = FunctionsSC::DeterminantLU(C, iDim); double temp2 = pow(det, -0.5); m_logF = log(temp * temp2); // log_F becomes - Inf for large d--> hence we set log_F to zero. // Also need to resolve this in importance distribution as well!! if(iDim > 150) { m_logF = 0.0; } m_b = 0.1; // Free allocated memory FunctionsSC::DeleteMatrix(C, iDim); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample01::GetNormalData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataNormal* pINormalData // Interface to normal distribution data ) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pINormalData pointer if(pINormalData == nullptr) { return E_INVALIDARG; } // Fill mu data int iDim = pInputPar->GetProblemDimension(); for(int iIndex = 0; iIndex < iDim; iIndex++) { pINormalData->AddMeanItem(0.0); } // Covariance matrix diagonal value pINormalData->SetCovarianceDiagonalValue(10.0); // Data added successfully return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample01::EvaluateProposal //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , int iSim // input parameter (i-th simulation / Markov chain) , IDreamMatrix* x // input matrix (m_NumberOfMarkovChains x m_ProblemDimension) , IDreamMatrix* res // output matrix (Data_Dimension x m_NumberOfMarkovChains) , BSTR strWorkingDir // path to the current working directory (for current calculation thread) , BSTR strModelDataDir // path to the permanent directory with model data , BSTR strModelBinDir // path to the permanent directory with model executables ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to evaluate the current proposal (i.e. one single step of IDreamInputParams::GetNumberOfGenerations() steps) for iSim-th Markov chain. It computes the likelihood (or log-likelihood or the residual vector to be compared with the measurement - see the technical manual) for iSim-th row of input matrix "x" and returns the result 43 DREAM Suite 1 in output matrix "res". Parameter iSim is from interval <0, IDreamInputParams::GetNumberOfMarkovChains() - 1>. If pInputPar->GetVectorization() == eVectorization::eVectYes, then iSim = 0 and all proposals (for all Markov chains) should be evaluated in one step, i.e. during one call of this function. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // We should have m_invC initialized assert(m_invCSize != 0); // Temporary vector used for calculations double* tmpx = nullptr; FunctionsSC::CopyRowFromIDreamMatrix(iSim, tmpx, x); double logLtmp = 0.0; if(x->_colCount == 1) // 1-dimensional Gaussian { // 1-dimensional twisted Gaussian probability density function // logL = logF - 1/2 * invC * (x.^2)' // where: // x' - transposition of "x" // .^2 - power of 2 of each element logLtmp = m_logF - 0.5 * m_invC[0][0] * tmpx[0] * tmpx[0]; } else // N-dimensional Gaussian { // Introduce banana shaped nonlinearity between x(1) and x(2) // x(2) = x(2) + b * x(1)^2 - 100 * b tmpx[1] += m_b * tmpx[0] * tmpx[0] - 100.0 * m_b; // // // // // // N-dimensional twisted Gaussian probability density function logL = m_logF - 1/2 * sum(x'.*(invC * x')); where: x' - transposition of matrix "x" sum - returns the sum of the elements of input along the first array dimension .* - multiplies arrays A and B element by element // vector1 = invC * x' double* vector1 = nullptr; FunctionsSC::MatrixColumnVectorProduct(vector1, m_invC, m_invCSize, m_invCSize, tmpx, x->_colCount); // vector2 = x'.*(invC * x') = vector1 .* vector2 double* vector2 = nullptr; FunctionsSC::VectorVectorElementProduct(vector2, tmpx, x->_colCount, vector1, x->_colCount); // logL = m_logF - 1/2 * sum(x'.*(invC * x')) = m_logF - 0.5 sum(vector2) logLtmp = m_logF - 0.5 * FunctionsSC::VectorElementSum(vector2, x->_colCount); // Free allocated memory FunctionsSC::DeleteVector(vector1); FunctionsSC::DeleteVector(vector2); } // Replace content of res by tmp values res->_data[iSim] = logLtmp; // Free allocated memory FunctionsSC::DeleteVector(tmpx); return S_OK; } 44 DREAM Suite 1 4.2 Example 2 Case-Study II: d-dimensional Gaussian distribution To test the performance of DREAM in the presence of high-dimensionality, the second case study involves a d = 100-dimensional multivariate normal distribution (2.01) , where the vector stores the mean of the normal distribution, and the signifies the variance-covariance matrix. The probability density function of is given by , matrix (2.02) We assume a mean of zero, , and define the covariance matrix, , in such a way that the variance th th of the variable is equal to variable is equal to and all pairwise correlations are equivalent to 0.5 The main diagonal thus has values of . The correlation, , between two entries and of can be calculated from their respective covariance value and individual variances according to (2.03) . Entry of matrix can thus be calculated using (2.04) , where the variances of and and , respectively. are found on the main diagonal of , and thus equivalent to entries The initial population is drawn from the multivariate uniform distribution, , using Latin hypercube sampling. We assume a lower bound of each dimension equal to and upper bound of . The initial value of each parameter {1,…,d} is thus drawn from this range. We use N = 100 chains with DREAM and apply default values of the algorithmic variables, with the exception that we use thinning to reduce memory storage. Indeed, only every 10th sample is stored in each Markov chain. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D1\Drm_D1_Example02\Plugin \Src_Cpp /////////////////////////////////////////////////////////////////////////////////////////////////// // EvaluatorModel.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample02::GetInputParams //------------------------------------------------------------------------------------------------( IDreamInputParams* pIDreamInputParams // Pointer to DREAM input data to be defined ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define default DREAM parameters for this particular project. This function is called by the main program to initialize data of each newly created simulation case. This data can be later modified in the GUI (except parameters locked by flag DreamSolver::disable_edit) or can be overwritten while reading case data from a file. 45 DREAM Suite 1 In the AppTest console application, there is no GUI and this functions actually defines all input parameters that are subsequently used by DREAM Solver. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIDreamInputParams pointer if(pIDreamInputParams == nullptr) { return E_INVALIDARG; } // Set default input parameters pIDreamInputParams->SetProblemDimension(100, DreamSolver::enable_edit); pIDreamInputParams->SetNumberOfMarkovChains(50, DreamSolver::enable_edit); pIDreamInputParams->SetNumberOfGenerations(10000, DreamSolver::enable_edit); pIDreamInputParams->SetThinnigSampleToStore(10, DreamSolver::enable_edit); pIDreamInputParams->SetLikelihoodChoice(eLikelihood::LIK_102, DreamSolver::disable_edit); pIDreamInputParams->SetInitialDistribution(eInitDistrib::eInitLatin, DreamSolver::enable_edit); // Example can run in parallel mode (recommended mode) pIDreamInputParams->SetParallelMode(eParallelModeYes, DreamSolver::enable_edit); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample02::InitData //------------------------------------------------------------------------------------------------( IDreamPluginInfo* pIPluginInfo // Plugin information , IDreamInputParViewer* pIDreamInputParams // Current DREAM input parameters ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: This function is called to prepare: A/ DREAM input data before accessing them via the IDreamDataSource interface and B/ all other local data required by evaluator for the calculation. It can be also used to read needed data from a file in directory pIPluginInfo->m_strModelDataDir (directory ...Drm_ExampleXX\Model\Data). Remark 1: This function prepares DREAM input data in the evaluator according to current DREAM parameters defined by pIPluginInfo interface. Note that some parameters can be different from default parameters defined in function CEvaluatorExample::GetInputParams(). Remark 2: This function should be called before using functions CEvaluatorExample::GetMinMaxData, ::GetNormalData, ::GetPriorData, ::GetPriorDataCustom, ::GetMeasurementData and ::GetBayesData. However, function CEvaluatorExample::GetInputParams() can be called independently. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Check parameters if(pIPluginInfo == nullptr || pIDreamInputParams == nullptr) { // Invalid argument return E_INVALIDARG; } // Free memory from previous calculation 46 DREAM Suite 1 FunctionsSC::DeleteMatrix(m_invC, m_invCSize); int d = pIDreamInputParams->GetProblemDimension(); // Construct the d x d covariance matrix double** matrix1 = nullptr; FunctionsSC::IdentityMatrix(matrix1, d, d, 0.5); double** matrix2 = nullptr; FunctionsSC::CreateMatrix(matrix2, d, d, 0.5); double** A = nullptr; FunctionsSC::MatrixMatrixAddition(A, matrix1, d, d, matrix2, d, d); // Rescale to variance - covariance matrix of interest double** C = nullptr; FunctionsSC::CreateMatrix(C, d); for(int i = 0; i < d; i++) { for(int j = 0; j < d; j++) { C[i][j] = A[i][j] * sqrt((i + 1.0) * (j + 1.0)); } } m_invCSize = d; FunctionsSC::CopyMatrix(m_invC, C, d); if(!FunctionsSC::Inv(m_invC, d)) { return E_FAIL; } // Calculate integration constant double temp = pow(2 * pi<double>(), -(double)d / 2.0); double det = FunctionsSC::DeterminantLU(C, d); double temp2 = pow(det, -0.5); m_logF = log(temp * temp2); // log_F becomes - Inf for large d--> hence we set log_F to zero // Also need to resolve this in importance distribution as well!! if(d > 150) { m_logF = 0; } // Free allocated memory FunctionsSC::DeleteMatrix(matrix1, d); FunctionsSC::DeleteMatrix(matrix2, d); FunctionsSC::DeleteMatrix(A, d); FunctionsSC::DeleteMatrix(C, d); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample02::GetMinMaxData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataMinMax* pIMinMaxData // Interface to Min/Max data ) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIMinMaxData pointer if(pIMinMaxData == nullptr) { return E_INVALIDARG; } int d = pInputPar->GetProblemDimension(); // Fill min max data for(int i = 0; i < d; i++) { 47 DREAM Suite 1 pIMinMaxData->AddItem(-5.0, 15.0); } // Data added successfully return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample02::EvaluateProposal //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , int iSim // input parameter (i-th simulation / Markov chain) , IDreamMatrix* x // input matrix (m_NumberOfMarkovChains x m_ProblemDimension) , IDreamMatrix* res // output matrix (Data_Dimension x m_NumberOfMarkovChains) , BSTR strWorkingDir // path to the current working directory (for current calculation thread) , BSTR strModelDataDir // path to the permanent directory with model data , BSTR strModelBinDir // path to the permanent directory with model executables ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to evaluate the current proposal (i.e. one single step of IDreamInputParams::GetNumberOfGenerations() steps) for iSim-th Markov chain. It computes the likelihood (or log-likelihood or the residual vector to be compared with the measurement - see the technical manual) for iSim-th row of input matrix "x" and returns the result in output matrix "res". Parameter iSim is from interval <1, IDreamInputParams::m_NumberOfMarkovChains> except the case when pInputPar->GetVectorization() == eVectorization::eVectYes, when iSim = 0 and all proposals (for all Markov chains) are evaluated in one step. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Temporary vector used for calculations double* tmpx = nullptr; FunctionsSC::CopyRowFromIDreamMatrix(iSim, tmpx, x); double logLtmp = 0.0; if(x->_colCount == 1) // 1-dimensional Gaussian { // 1-dimensional twisted Gaussian probability density function logLtmp = m_logF - 0.5 * m_invC[0][0] * tmpx[0] * tmpx[0]; } else // N-dimensional Gaussian { // N-dimensional twisted Gaussian probability density function // logL = m_logF - 1/2 * sum(x'.*(invC * x')); // where: // x' - transposition of matrix "x" // sum - returns the sum of the elements of input along the first array dimension // .* - multiplies arrays A and B element by element // vector1 = invC * x' double* vector1 = nullptr; FunctionsSC::MatrixColumnVectorProduct(vector1, m_invC, m_invCSize, m_invCSize, tmpx, x->_colCount); // vector2 = x'.*(invC * x') = vector1 .* vector2 double* vector2 = nullptr; FunctionsSC::VectorVectorElementProduct(vector2, tmpx, x->_colCount, vector1, x->_colCount); // logL = m_logF - 1/2 * sum(x'.*(invC * x')) = m_logF - 0.5 sum(vector2) logLtmp = m_logF - 0.5 * FunctionsSC::VectorElementSum(vector2, x->_colCount); // Free allocated memory FunctionsSC::DeleteVector(vector1); 48 DREAM Suite 1 FunctionsSC::DeleteVector(vector2); } // Replace content of res by tmp values res->_data[iSim] = logLtmp; // Free allocated memory FunctionsSC::DeleteVector(tmpx); return S_OK; } 4.3 Example 3 Case-Study III: d-dimensional multimodal mixture distribution To test the performance of DREAM in the presence of multi-modality, the third case study involves a d = 10dimensional bimodal mixture of two Gaussian distributions (3.01) , where and -5 and 5 are d-dimensional vectors that define the mean of each normal distribution, and the covariance matrix is equivalent to the identity-matrix Id, a (square) matrix with ones on the main diagonal and zeros elsewhere. The density of the target distribution is simply the sum of the pdfs of two normal distributions + (3.02) . This equation can be simplified as harm. This leads to and the term + in the exponent can be removed without . (3.03) The initial state of each Markov chain (= starting point) is drawn from , the -variate normal distribution with mean zero and covariance matrix equal to a multiple (five) of the identity matrix. We use N = 20 different chains with DREAM and apply default values of the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D1\Drm_D1_Example03\Plugin \Src_Cpp /////////////////////////////////////////////////////////////////////////////////////////////////// // EvaluatorModel.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample03::GetInputParams //------------------------------------------------------------------------------------------------( IDreamInputParams* pIDreamInputParams // Pointer to DREAM input data to be defined ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define default DREAM parameters for this particular project. This function is called by the main program to initialize data of each newly created simulation 49 DREAM Suite 1 case. This data can be later modified in the GUI (except parameters locked by flag DreamSolver::disable_edit) or can be overwritten while reading case data from a file. In the AppTest console application, there is no GUI and this functions actually defines all input parameters that are subsequently used by DREAM Solver. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIDreamInputParams pointer if(pIDreamInputParams == nullptr) { return E_INVALIDARG; } // Set default input parameters pIDreamInputParams->SetProblemDimension(10, DreamSolver::enable_edit); pIDreamInputParams->SetNumberOfMarkovChains(pIDreamInputParams->GetProblemDimension(), DreamSolver::enable_edit); pIDreamInputParams->SetNumberOfGenerations(100000, DreamSolver::enable_edit); pIDreamInputParams->SetThinnigSampleToStore(10, DreamSolver::enable_edit); pIDreamInputParams->SetLikelihoodChoice(eLikelihood::LIK_102, DreamSolver::disable_edit); pIDreamInputParams->SetInitialDistribution(eInitDistrib::eInitNormal, DreamSolver::enable_edit); pIDreamInputParams->SetOutlierTest(eOutlierTest::eOutlierIqr, DreamSolver::enable_edit); pIDreamInputParams->SetBoundHandling(eBoundHandling::eBoundUnbounded, DreamSolver::enable_edit); // Example can run in parallel mode (recommended mode) pIDreamInputParams->SetParallelMode(eParallelModeYes, DreamSolver::enable_edit); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample03::InitData //------------------------------------------------------------------------------------------------( IDreamPluginInfo* pIPluginInfo // Plugin information , IDreamInputParViewer* pIDreamInputParams // Current DREAM input parameters ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: This function is called to prepare: A/ DREAM input data before accessing them via the IDreamDataSource interface and B/ all other local data required by evaluator for the calculation. It can be also used to read needed data from a file in directory pIPluginInfo->m_strModelDataDir (directory ...Drm_ExampleXX\Model\Data). Remark 1: This function prepares DREAM input data in the evaluator according to current DREAM parameters defined by pIPluginInfo interface. Note that some parameters can be different from default parameters defined in function CEvaluatorExample::GetInputParams(). Remark 2: This function should be called before using functions CEvaluatorExample::GetMinMaxData, ::GetNormalData, ::GetPriorData, ::GetPriorDataCustom, ::GetMeasurementData and ::GetBayesData. However, function CEvaluatorExample::GetInputParams() can be called independently. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Check parameters if(pIPluginInfo == nullptr || pIDreamInputParams == nullptr) { 50 DREAM Suite 1 // Invalid argument return E_INVALIDARG; } // Free memory from previous calculation FunctionsSC::DeleteMatrix(m_L, m_Lsize, m_Lsize); FunctionsSC::DeleteMatrix(m_invL, m_invLsize, m_invLsize); FunctionsSC::DeleteMatrix(m_mu, m_k, m_muSize); FunctionsSC::DeleteVector(m_logF); int d = pIDreamInputParams->GetProblemDimension(); // How many Gaussians? m_k = 2; // Determine weight of each respective Gaussian // log_prior = log ( [1/3 2/3] ); double* logPrior = nullptr; FunctionsSC::CreateVector(logPrior, m_k); logPrior[0] = log(1. / 3.); logPrior[1] = log(2. / 3.); // Mean of both modes //mu = [ -5*ones(1,d) ; 5*ones(1,d) ]; m_muSize = d; double* mu1 = nullptr; double* mu2 = nullptr; FunctionsSC::CreateVector(mu1, d, -5.0); FunctionsSC::CreateVector(mu2, d, 5.0); FunctionsSC::CreateMatrix(m_mu, m_k, d); FunctionsSC::MatrixSetRow(0, mu1, m_mu, m_k, d); FunctionsSC::MatrixSetRow(1, mu2, m_mu, m_k, d); // Now compute the inverse of the covariance matrix double** C = nullptr; FunctionsSC::IdentityMatrix(C, d, d); // compute the log determinant of covariance m_Lsize = d; if(!FunctionsSC::Cholesky(m_L, C, d)) { return E_FAIL; } m_invLsize = d; FunctionsSC::CopyMatrix(m_invL, m_L, d); if(!FunctionsSC::Inv(m_invL, d)) { return E_FAIL; } double* diagL = nullptr; FunctionsSC::MatrixDiagonal(diagL, m_L, d); // Calculate part of normalization constant // logDetSigma = 2 * sum ( log ( diagL ) ); FunctionsSC::VectorElementLog(diagL, d); double logDetSigma = 2.0 * FunctionsSC::VectorElementSum(diagL, d); // Calculate total normalization constant (k values) // m_log_F = -0.5 * logDetSigma + logPrior - d * log(2 * pi) / 2; double value = -0.5 * logDetSigma - d * log(2 * pi<double>()) / 2.0; double* vector2 = nullptr; FunctionsSC::CreateVector(vector2, m_k, value); FunctionsSC::VectorVectorAddition(m_logF, logPrior, m_k, vector2, m_k); FunctionsSC::DeleteVector(mu1); FunctionsSC::DeleteVector(mu2); FunctionsSC::DeleteVector(logPrior); FunctionsSC::DeleteVector(diagL); FunctionsSC::DeleteVector(vector2); FunctionsSC::DeleteMatrix(C, d, d); 51 DREAM Suite 1 return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample03::GetMinMaxData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataMinMax* pIMinMaxData // Interface to Min/Max data ) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIMinMaxData pointer if(pIMinMaxData == nullptr) { return E_INVALIDARG; } // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample03::GetNormalData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataNormal* pINormalData // Interface to normal distribution data ) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pINormalData pointer if(pINormalData == nullptr) { return E_INVALIDARG; } size_t d = (size_t)pInputPar->GetProblemDimension(); // Fill mu data for(size_t iIndex = 0; iIndex < d; iIndex++) { pINormalData->AddMeanItem(0.0); } // Covariance matrix diagonal value pINormalData->SetCovarianceDiagonalValue(5.0); // Data added successfully return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample03::EvaluateProposal //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , int iSim // input parameter (i-th simulation / Markov chain) , IDreamMatrix* x // input matrix (m_NumberOfMarkovChains x m_ProblemDimension) , IDreamMatrix* res // output matrix (Data_Dimension x m_NumberOfMarkovChains) , BSTR strWorkingDir // path to the current working directory (for current calculation thread) , BSTR strModelDataDir // path to the permanent directory with model data , BSTR strModelBinDir // path to the permanent directory with model executables ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to evaluate the current proposal (i.e. one single step of IDreamInputParams::GetNumberOfGenerations() steps) for iSim-th Markov chain. It computes the likelihood (or log-likelihood or the residual vector to be compared with the measurement - see the technical manual) for iSim-th row of input matrix "x" and returns the result in output matrix "res". 52 DREAM Suite 1 Parameter iSim is from interval <0, IDreamInputParams::GetNumberOfMarkovChains() - 1>. If pInputPar->GetVectorization() == eVectorization::eVectYes, then iSim = 0 and all proposals (for all Markov chains) should be evaluated in one step, i.e. during one call of this function. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { /* Vectorization: If vectorization is set to "eVectYes" then EvaluateProposal function is called only once with iSim = 0 and whole input matrix "x" has to be evaluated in one step to get output matrix res. If vectorization is set to "eVectYes" then EvaluateProposal function is called "x->_colCount"-th times with iSim = <0, x->_colCount-1> and input matrix "x" has to be avaluated for each column of matrix "x" separately. */ // Temporary vector used for calculations double* tmpx = nullptr; FunctionsSC::CopyRowFromIDreamMatrix(iSim, tmpx, x); // Now loop over each component of mixture double* loglh = nullptr; FunctionsSC::CreateVector(loglh, m_k); for(int j = 0; j < m_k; j++) { // Calculate log_likelihood of jth component // log_lh(:,j) = -0.5 * sum (x - mu(j,:)).^2 , 2) + logF(j); // vector2 = mu(j,:) double* vector2 = nullptr; FunctionsSC::Row(j, vector2, m_mu, m_k, x->_colCount); // mat1 = x - mu(j,:) double* mat1 = nullptr; FunctionsSC::VectorVectorSubtraction(mat1, tmpx, x->_colCount, vector2, x->_colCount); // mat1 = (x - mu(j,:)).^2 FunctionsSC::VectorElementPow(2.0, mat1, x->_colCount); // log_lh(j) = -0.5 * sum(mat1) + m_logF(j); loglh[j] = -0.5 * FunctionsSC::VectorElementSum(mat1, x->_colCount) + m_logF[j]; FunctionsSC::DeleteVector(vector2); FunctionsSC::DeleteVector(mat1); } // Now determine the overall log-likelihood double maxll = FunctionsSC::VectorMaxElement(loglh, m_k); // Minus maxll to avoid underflow double* vector1 = nullptr; FunctionsSC::CreateVector(vector1, m_k, -maxll); double* post = nullptr; FunctionsSC::VectorVectorAddition(post, loglh, m_k, vector1, m_k); FunctionsSC::VectorElementExp(post, m_k); // Density(i) is \sum_j \alpha_j P(x_i| \theta_j)/ exp(maxll(i)) double density = FunctionsSC::VectorElementSum(post, m_k); // Calculate log-L res->_data[iSim] = log(density) + maxll; FunctionsSC::DeleteVector(tmpx); FunctionsSC::DeleteVector(loglh); FunctionsSC::DeleteVector(vector1); 53 DREAM Suite 1 FunctionsSC::DeleteVector(post); return S_OK; } 4.4 Example 4 Case-Study IV: Bayesian inference of a conceptual watershed model (HYMOD code in C/C++) In this fifth study, we use the HYMOD conceptual watershed model, a parsimonious rainfall-runoff model whose parameters are thought to vary between watersheds. This model has been used in a numerous studies and has five parameters that need to be specified by the user. Inputs to the model include mean areal precipitation (MAP), and potential evapotranspiration (PET), while the outputs are estimated channel inflow. The HYMOD model has been discussed extensively in many previous papers that study streamflow forecasting and automatic model calibration (Boyle 2000; Wagener et al. 2001; Vrugt et al. 2003). Details of the model can be found therein. In summary, HYMOD consists of a simple two-parameter rainfall excess model connected with two series of linear reservoirs (three, identical, for the quick and a single reservoir for the slow response) in parallel as a routing component (see Figure 4.01). Figure 4.01: Conceptual representation of the HYMOD conceptual watershed model The rainfall excess model is described in detail by Moore (1985, 1999). The model assumes that the soil moisture storage capacity, c, varies across the catchment and, therefore, that the proportion of the catchment with saturated soils varies over time. The spatial variability of the soil moisture capacity is described by the following distribution function , (4.01) where c(t) is the simulated soil water storage capacity at time t and cmax (mm) and bexp (-) are unknown coefficients. HYMOD has five different parameters whose values need to be determined from a measured discharge record. The parameters and their prior uncertainty ranges are listed in Table 4.01. This includes cmax (L), the maximum storage capacity in the catchment, bexp (-) the degree of spatial variability of the soil moisture capacity within the catchment, α (-) a coefficient that distributes the flow between the fast and slow-flow reservoirs, and rs (days) and rq (days), the residence time of the slow and fast-flow reservoir reservoirs, respectively. The actual evapotranspiration is equal to its potential value if sufficient soil moisture is available, otherwise it is reduced depending on the soil water status. 54 DREAM Suite 1 Parameter Maximum interception Symbol Lower 10 Upper 1000 Units mm Soil water storage capacity 0 2 - Maximum percolation rate 0 1 - Recession constant slow-flow reservoir - Recession constant fast-flow reservoir 1 - Table 4.01: Parameters of HYMOD and their prior uncertainty ranges We use historical data from the Leaf River (1950 km2) watershed in Mississippi in the USA. The data consists of daily MAP (mm/day), PET (mm/day), and streamflow (mm/day) values. A two year data record is used for posterior inference of the HYMOD parameters. This includes the period from January 1, 1952 to September 30, 1954. A multivariate uniform prior distributed is assumed for the parameters using the ranges listed in Table 4.01. The posterior parameter distribution is now determined with DREAM using a simple Gaussian likelihood function (4.02) , where and are the observed and simulate discharge record, respectively, n denotes the number of measurements, and |·| denotes the modulus operator (absolute value). The initial population is drawn from the lower and upper ranges listed in Table 4.01 using Latin hypercube sampling. We use N = 10 chains with DREAM and use standard settings for the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example04\Plugin\Src_Cpp 4.5 Example 5 Case-Study V: Bayesian inference of a conceptual watershed model (HYMOD in external Fortran module) This case study is identical to the previous case study with the exception that the HYMOD model has been coded in Fortran instead. This demonstrates that DREAM can communicate with different computer languages. Note that the plugin module here serves just as an interface to call HYMODsilent.exe, created in Fortran and located in the Drm_Example05\Model\Bin subdirectory. Similar approach has been used to create MATLAB examples in library D2. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example05\Plugin\Src_Cpp 4.6 Example 6 Case-Study VI: A conceptual watershed model with generalized log-likelihood function The sixth case study involves flood forecasting, and consists of the calibration of a mildly complex lumped watershed model using historical data from the Guadalupe River at Spring Branch, Texas. This is the driest of the 12 MOPEX basins described in the study of Duan et al. (2006). The model structure and hydrologic process representations are found in Schoups and Vrugt (2010). The model transforms rainfall into runoff at the watershed outlet using explicit process descriptions of interception, throughfall, evaporation, runoff generation, percolation, and surface and subsurface routing (see Figure 6.01). 55 DREAM Suite 1 Figure 6.01. Schematic representation of the hmodel conceptual watershed model. Table 6.01 summarizes the seven different parameters of the hmodel and their prior uncertainty ranges. While some of the values of parameters in conceptual rainfall-runoff models can be derived directly from knowledge of physical watershed characteristics, others are effective quantities that cannot, in practice, be measured in the field, and therefore have to be estimated through calibration against a measured streamflow hydrograph using either a trial-and-error ‘manual approach' or an automated search algorithm (Boyle et al., 2000; Madsen, 2000). The parameters, which are estimated in this manner, represent effective conceptual representations of spatially and temporally heterogeneous watershed properties. A model calibrated by such means can be used for the simulation or prediction of hydrologic events outside of the historical record used for model calibration, if it can be reasonably assumed that the physical characteristics of the watershed and the hydrologic/climate conditions remain similar (Gupta et al., 2002; Vrugt et al., 2006). Parameter Symbol Lower Upper Units Maximum interception 1 10 mm Soil water storage capacity 10 1000 mm Maximum percolation rate 0 100 mm/day Evaporation parameter 0 100 - -10 10 - Time constant, fast reservoir 0 10 days Time constant, slow reservoir 0 150 days Runoff parameter Table 6.01: Parameters of the hmodel and their prior uncertainty ranges We calibrate the parameters of hmodel using daily discharge, mean areal precipitation, and mean areal potential evapotranspiration from the French Broad watershed at Asheville, North Carolina. We assume a multivariate uniform prior distribution for all seven model parameters using the ranges listed in Table 6.01. An assumption made in many studies published in the literature is that the residuals between modeled and observed discharge data are normally distributed. This then leads to a standard Gaussian likelihood function (see previous two studies). We deviate from this assumption in this case study and use instead the generalized likelihood function developed by Schoups and Vrugt (2010) which extends the applicability of previously used likelihood functions to situations where residual errors are correlated, heteroscedastic, and non-Gaussian with varying degrees of kurtosis and skewness. The approach focuses on a correct statistical description of the data and the total model residuals, without separating out various error sources. The generalized likelihood function is given by (6.01) 56 DREAM Suite 1 where is a n-vector with observed discharge data, n denotes the number of measurements, is the estimated measurement error of the discharge data, is a n- vector of filtered error residuals using an autoregressive model with coefficients, , and , , and are computed as function of the skewness parameter, , and kurtosis parameter, , and |·| denotes the modulus operator (absolute value). The scalars are so called nuisance variables whose values are either fixed or estimated jointly with the model parameters. These nuisance variables are discussed in Table 6.02 below. The discharge measurement error is computed using where is the hmodel simulated record of discharge values using the values of the model parameters and nuisance variables stored in the d-vector x. Parameter Lower Upper Units Default Heteroscedasticity intercept 0 1 mm/day 0.1 Heteroscedasticity slope 0 1 - 0 Autocorrelation coefficient 0 1 - 0 Kurtosis parameter -1 1 - 0 Skewness parameter 0.1 10 - 1 Bias parameter 0 100 (day/mm) 0 Box-Cox transformation parameter 0 1 mm/day 0 Box-Cox transformation parameter 0.1 1 - 1 † Symbol The listed units and ranges depend on units and characteristics of calibration data (discharge in present case) Table 6.02: Nuisance variables of the generalized log-likelihood function† The nuisance variables that are highlighted in blue are estimated along with the parameters of the hmodel. Their prior distribution is assumed uniform using the ranges listed above. The other nuisance variables in the generalized likelihood function of Equation (6.01) are set to their default values. This equates in a total of 11 parameters whose posterior distribution needs to be sampled with DREAM by calibration of the hmodel against the observed discharge data of the French Broad River. The initial population of the model parameters and nuisance variables is drawn from the lower and upper ranges listed in Table 6.01 and 6.02 using Latin hypercube sampling. We use N = 11 chains with DREAM to generate samples from the posterior parameter distribution using standard settings for the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example06\Plugin\Src_Cpp 4.7 Example 7 Case-Study VII: Bayesian inference of HYDRUS-1D using soil moisture data The seventh case study considers the modeling of the soil moisture regime of an agricultural field near Jülich, Germany. Soil moisture content was measured with Time Domain Reflectometry (TDR) probes at 6 cm deep at 61 locations in a 50 × 50 m plot. The TDR data were analysed using the algorithm described in Heimovaara et al. (1990) and the measured apparent dielectric permittivities were converted to soil moisture contents using the empirical relationship of Topp (1980). Measurements were taken on 29 days between 19 March and 14 October 2009, comprising a measurement campaign of 210 days. For the purpose of the present study, the observed soil moisture data at the 61 locations were averaged to obtain a single time series of water content. Precipitation and other meteorological variables were recorded at a meteorological station located 100 m west of the measurement site. Details of the site, soil properties, experimental design and measurements are given by Scharnagl et al. (2011) and interested readers are referred to this publication for further details. 57 DREAM Suite 1 The HYDRUS-1D model of Simunek et al. (2008) was used to simulate variably saturated water flow in the agricultural field (see Figure 7.01). This model solves Richards' equation for given (measured) initial and boundary conditions (7.1) , where θ (cm3/cm3) denotes moisture content, t (days) denotes time, z (cm) is the vertical (depth) coordinate, h (cm) signifies the pressure head, and K(h) (cm day-1) is the unsaturated soil hydraulic conductivity. Figure 7.01. Schematic representation of HYDRUS-1D model setup for a field plot near Jülich, Germany. To solve Equation (7.01) numerically the soil hydraulic properties need to be defined. We use herein the van Genuchten-Mualem (VGM) model (van Genuchten, 1980) (7.01) where θs (cm3/cm3) and θr (cm3/cm3) signify the saturated and residual soil water content, respectively, α (cm-1), n (-) and m = 1 - 1/n (-) are shape parameters, Ks (cm day-1) denotes the saturated hydraulic conductivity, and λ represents a pore-connectivity parameter. The effective saturation, Se (-) is defined as (7.03) 58 DREAM Suite 1 Observations of daily precipitation and potential evapotranspiration were used to define the upper boundary condition. In the absence of direct measurements, a constant head lower boundary condition was assumed, hbot (cm), whose value is subject to inference with DREAM. Table 7.01 lists the parameters of the HYDRUS-1D model and their prior ranges which are subject to inference using the 210-day period of observed soil moisture measurements. Parameter Symbol Lower Upper Units Residual water content 0.043 0.091 cm3/cm3 Saturated water content 0.409 0.481 cm /cm Reciprocal of air-entry value -2.553 -2.071 cm-1 0.179 0.267 - Saturated hydraulic conductivity -2.237 -0.080 cm hour Pore-connectivity -5.49 6.27 - Pressure head at lower boundary -250 -50 cm 3 Prior distribution † 3 £ Curve shape parameter n £ -1 £ † ‡ ‡ is the normal probability density function with mean a and standard deviation b is the uniform probability density function with lower bound a and upper bound b £ These parameters are sampled in the log space Table 7.01: Parameters of the HYDRUS-1D model and their prior uncertainty ranges The pedotransfer toolbox of ROSETTA was used with soil textural data from the field site to derive prior estimates of the MVG parameters (Scharnagl et al. 2011). These estimates were used to create an explicit prior distribution for each soil hydraulic parameter. These distributions are defined in the last column of Table 7.01, and make sure that the inference with DREAM honors the values derived separately from ROSETTA. Note that ROSETTA does not provide estimates of the parameter hbot, and this parameter was therefore assumed to have a uniform prior with ranges listed in the bottom right cell of the Table. A Gaussian likelihood was assumed to characterize in probabilistic terms the distance between the HYDRUS-1D simulated soil moisture data and their observed values. This likelihood function is given by (7.04) , where and are the observed and simulate soil moisture data, respectively, I denotes the number of measurements, and |·| denotes the modulus operator (absolute value). The initial population is drawn from the lower and upper ranges listed in Table 7.01 using Latin hypercube sampling. We use N = 10 chains with DREAM to generate samples from the posterior parameter distribution using standard settings for the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example07\Plugin\Src_Cpp /////////////////////////////////////////////////////////////////////////////////////////////////// // EvaluatorModel.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample07::GetInputParams //------------------------------------------------------------------------------------------------( 59 DREAM Suite 1 IDreamInputParams* pIDreamInputParams // Pointer to DREAM input data to be defined ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define default DREAM parameters for this particular project. This function is called by the main program to initialize data of each newly created simulation case. This data can be later modified in the GUI (except parameters locked by flag DreamSolver::disable_edit) or can be overwritten while reading case data from a file. In the AppTest console application, there is no GUI and this functions actually defines all input parameters that are subsequently used by DREAM Solver. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIDreamInputParams pointer if(pIDreamInputParams == nullptr) { return E_INVALIDARG; } // Set default input parameters pIDreamInputParams->SetProblemDimension(7, DreamSolver::disable_edit); pIDreamInputParams->SetNumberOfMarkovChains(10, DreamSolver::enable_edit); pIDreamInputParams->SetNumberOfGenerations(1000, DreamSolver::enable_edit); pIDreamInputParams->SetLikelihoodChoice(eLikelihood::LIK_102, DreamSolver::disable_edit); pIDreamInputParams->SetInitialDistribution(eInitDistrib::eInitUniform, DreamSolver::enable_edit); pIDreamInputParams->SetUsePriorDistribution(1, DreamSolver::enable_edit); pIDreamInputParams->SetPriorDistributionType(ePriorType::eUnivariate, DreamSolver::enable_edit); pIDreamInputParams->SetOutlierTest(eOutlierTest::eOutlierIqr, DreamSolver::enable_edit); pIDreamInputParams->SetBoundHandling(eBoundHandling::eBoundUnbounded, DreamSolver::enable_edit); // Example can run in parallel mode (recommended mode) pIDreamInputParams->SetParallelMode(eParallelModeYes, DreamSolver::enable_edit); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample07::InitData //------------------------------------------------------------------------------------------------( IDreamPluginInfo* pIPluginInfo // Plugin information , IDreamInputParViewer* pIDreamInputParams // Current DREAM input parameters ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: This function is called to prepare: A/ DREAM input data before accessing them via the IDreamDataSource interface and B/ all other local data required by evaluator for the calculation. It can be also used to read needed data from a file in directory pIPluginInfo->m_strModelDataDir (directory ...Drm_ExampleXX\Model\Data). Remark 1: This function prepares DREAM input data in the evaluator according to current DREAM parameters defined by pIPluginInfo interface. Note that some parameters can be different from default parameters defined in function CEvaluatorExample::GetInputParams(). Remark 2: This function should be called before using functions CEvaluatorExample::GetMinMaxData, ::GetNormalData, ::GetPriorData, ::GetPriorDataCustom, ::GetMeasurementData and ::GetBayesData. However, function CEvaluatorExample::GetInputParams() can be called independently. RETURN VALUE: 60 DREAM Suite 1 S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Check parameters if(pIPluginInfo == nullptr || pIDreamInputParams == nullptr) { // Invalid argument return E_INVALIDARG; } // Load data only one time if(LoadData(pIPluginInfo->m_strModelDataDir)) { return S_OK; } return E_FAIL; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample07::GetMinMaxData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataMinMax* pIMinMaxData // Interface to Min/Max data ) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIMinMaxData pointer if(pIMinMaxData == nullptr) { return E_INVALIDARG; } // Fill min max data pIMinMaxData->AddItem( 0.0430, 0.0910); pIMinMaxData->AddItem( 0.4090, 0.4810); pIMinMaxData->AddItem(-2.5528, -2.0706); pIMinMaxData->AddItem( 0.1790, 0.2670); pIMinMaxData->AddItem(-2.2366, -0.0800); pIMinMaxData->AddItem(-5.4900, 6.2700); pIMinMaxData->AddItem(-250.0, -50.0); // Data added successfully return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample07::GetPriorData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataPrior* pIPriorData // Interface to prior distribution data ) /////////////////////////////////////////////////////////////////////////////////////////////////// { pIPriorData->AddUnivariateItem(0.067, 0.006, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(0.445, 0.009, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(-2.310, 0.060, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(0.223, 0.011, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(-1.160, 0.270, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(0.390, 1.470, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(-250.0, -50.0, eDistributionUnivariate::eUnivariate_Uniform); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample07::PrepareWorkDir //------------------------------------------------------------------------------------------------- 61 DREAM Suite 1 ( BSTR strSourceDir , BSTR strDestinationDir ) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Copy all files to the new directory if(!DrxCopyFiles(strSourceDir, strDestinationDir)) { return E_FAIL; } // Create new level_01.dir with the correct path std::wstring LevelDirFile(strDestinationDir); LevelDirFile += L"\\level_01.dir"; std::wfstream ofs(LevelDirFile, std::ofstream::out | std::ofstream::trunc); if(!ofs) { std::wcerr << L"Unable to create " << LevelDirFile << L"\n"; return E_FAIL; } std::wstring NewPath(strDestinationDir); ofs << NewPath; ofs.flush(); ofs.close(); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CEvaluatorExample07::EvaluateProposal //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , int iSim // input parameter (i-th simulation / Markov chain) , IDreamMatrix* x // input matrix (m_NumberOfMarkovChains x m_ProblemDimension) , IDreamMatrix* res // output matrix (Data_Dimension x m_NumberOfMarkovChains) , BSTR strWorkingDir // path to the current working directory (for current calculation thread) , BSTR strModelDataDir // path to the permanent directory with model data , BSTR strModelBinDir // path to the permanent directory with model executables ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to evaluate the current proposal (i.e. one single step of IDreamInputParams::GetNumberOfGenerations() steps) for iSim-th Markov chain. It computes the likelihood (or log-likelihood or the residual vector to be compared with the measurement - see the technical manual) for iSim-th row of input matrix "x" and returns the result in output matrix "res". Parameter iSim is from interval <0, IDreamInputParams::GetNumberOfMarkovChains() - 1>. If pInputPar->GetVectorization() == eVectorization::eVectYes, then iSim = 0 and all proposals (for all Markov chains) should be evaluated in one step, i.e. during one call of this function. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { vector<double> ix(x->_colCount); // Copy row data for(int iCol = 0; iCol < x->_colCount; iCol++) { ix(iCol) = x->_data[iSim * x->_colCount + iCol]; } // Back-transform parameters matrix<double> xv(1, ix.size(), 0); row(xv, 0) = ix; 62 DREAM Suite 1 xv(0, 2) = pow(10.0, xv(0, 2)); xv(0, 3) = pow(10.0, xv(0, 3)); xv(0, 4) = pow(10.0, xv(0, 4)); // Working directory std::wstring path(strWorkingDir); // Modify SELECTOR.IN if(!CDreamMath<>::ReplaceData(path + L"\\SELECTOR.IN", "thr", project(xv, range(0, 1),range(0, 6)))) { return E_FAIL; } // Modify PROFILE.DAT matrix<double> initial(m_loadData.m_initial); column(initial, 2) = vector<double>(initial.size1(), xv(0, 6)); if(!CDreamMath<>::ReplaceData(path + L"\\PROFILE.DAT", "Mat", initial)) { return E_FAIL; } // Modify ATMOSPH.IN matrix<double> boundary(m_loadData.m_boundary); column(boundary, 6) = vector<double>(boundary.size1(), xv(0, 6)); if(!CDreamMath<>::ReplaceData(path + L"\\ATMOSPH.IN", "tAtm", boundary)) { return E_FAIL; } // Run HYDRUS-1D std::wstring strHydrusCalcExe = strModelBinDir; strHydrusCalcExe += L"\\H1D_CALC.EXE"; if(!CDreamMath<>::RunEXE(strHydrusCalcExe, path)) { return E_FAIL; } // Read text file containing the time series of simulated soil water contents matrix<double> outputData; if(!ReadDataHydrus1D(path + L"\\OBS_NODE.OUT", "time ", outputData)) { return E_FAIL; } vector<double> hoy = column(outputData, 0); vector<double> water = column(outputData, 2); // Filter sims for measurement dates size_t nData = m_loadData.m_hoy.size(); vector<size_t> indeces(nData, 0); for(size_t i = 0; i < nData; i++) { size_t iIndex; if(!Find<double>(iIndex, hoy, m_loadData.m_hoy(i), [](double a, double b) {return abs(a - b) < FLT_EPSILON ? true : false; })) { res->_data[iSim] = -1.e100; // If HYDRUS-1D did not converge, // set the log-likelihood to some arbitrary low value return S_OK; } indeces(i) = iIndex; } // Compute residuals vector<double> waterModify; CDreamMath<>::ObtainValuesFromIndeces(waterModify, indeces, water); vector<double> epsilon = m_loadData.m_water - waterModify; // Compute log-likelihood ElementPow<double>(epsilon, 2); res->_data[iSim] = -(double)nData / 2.0 * log(sum(epsilon)); return S_OK; 63 DREAM Suite 1 } /////////////////////////////////////////////////////////////////////////////////////////////////// // Local functions /////////////////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------bool CEvaluatorExample07::ReadDataHydrus1D //------------------------------------------------------------------------------------------------( const std::wstring& file , const std::string& keyWord , matrix<double>& loadData ) /////////////////////////////////////////////////////////////////////////////////////////////////// { std::ifstream ifs(file, std::ifstream::in); if(!ifs) { std::wcerr << "Unable to open " << file <<"\n"; return false; } typedef boost::tokenizer<boost::char_separator<char>> Tokenizer; boost::char_separator<char> sep(" "); std::string data; size_t iLine = 0; size_t startLine = 0; size_t endLine = 0; size_t nTok = 0; while(!ifs.eof()) { getline(ifs, data); Tokenizer tok(data, sep); if(data.find(keyWord) != std::string::npos) { nTok = std::distance(tok.begin(), tok.end()); startLine = iLine + 1; } else if(data.find("end") != std::string::npos) { endLine = iLine; } iLine++; } size_t nRow = endLine - startLine; loadData = matrix<double>(nRow, nTok); ifs.clear(); ifs.seekg(0, std::ios::beg); iLine = 0; size_t iRow = 0; while(!ifs.eof()) { getline(ifs, data); if(startLine <= iLine && iLine < endLine) { Tokenizer tok(data, sep); vector<double> values(nTok); size_t i = 0; for(Tokenizer::iterator iter = tok.begin(); iter != tok.end(); ++iter) { try { if(*iter == "T") { values(i) = 1; } else if(*iter == "F") { values(i) = 0; 64 DREAM Suite 1 } else { values(i) = boost::lexical_cast<double>(*iter); } } catch(boost::bad_lexical_cast&) { std::wcerr << "warning: value on Line" << iLine << ", Column " << i << "from " << file << " could not be converted to double = 0." << std::endl; values(i) = 0.; } i++; } row(loadData, iRow) = values; iRow++; } iLine++; } ifs.close(); return true; } //------------------------------------------------------------------------------------------------bool CEvaluatorExample07::LoadData(std::wstring path) //------------------------------------------------------------------------------------------------{ // Load structure with observation data if(!CDreamMath<bool>::ReadData(path + L"\\Meas_WaterInd.txt", m_loadData.m_waterInd)) return false; if(!CDreamMath<>::ReadData(path + L"\\Meas_Water.txt", m_loadData.m_water)) return false; vector<double> water; CDreamMath<double>::ObtainValuesFromBool(water, m_loadData.m_waterInd, m_loadData.m_water); m_loadData.m_water = water; if(!CDreamMath<>::ReadData(path + L"\\Meas_Hoy.txt", m_loadData.m_hoy)) return false; vector<double> hoy; CDreamMath<double>::ObtainValuesFromBool(hoy, m_loadData.m_waterInd, m_loadData.m_hoy); m_loadData.m_hoy = hoy; m_loadData.m_obsNode = 1; // Provide data needed to modify initial condition if(!CDreamMath<>::ReadData(path + L"\\ProfileDat_InitialConditions.txt", m_loadData.m_initial)) return false; // Provide data needed to modify the lower boundary condition if(!CDreamMath<>::ReadData(path + L"\\AtmosphIn_BoundConditions.txt", m_loadData.m_boundary)) return false; return true; } 4.8 Example 8 Case-Study VIII: Approximate Bayesian Computation of mixture distribution This case study illustrates the ability of DREAM to perform statistical inference involving the use of summary metrics. This functionality, also known as Approximate Bayesian Computation (ABC) has been implemented in DREAM and the underlying theory and concepts have been published by Sadegh and Vrugt (2014). The ABC approach is particularly useful for diagnostic model evaluation as it relaxes the need for an explicit likelihood function in favor of one or multiple different summary statistics rooted in the relevant theory 65 DREAM Suite 1 that together have a clearer and more compelling diagnostic power than some average (likelihood)-measure of the size of the error residuals. Vrugt and Sadegh (2013) have shown that this diagnostics approach enhances considerably our chances to diagnose and detect model structural errors. Indeed, the use of behavioral signatures helps to analyze and pinpoint which part of the model is malfunctioning and in need of further improvement. This eight case study benchmarks the implementation of the ABC method against a simple mixture of two univariate normal distributions, (8.01) , where and and and density function of denote the mean of the first and second normal pdf of the mixture distribution, define their corresponding variances, respectively. The probability in Equation (2.01) is given by the following weighted sum of two normal densities , (8.02) This Equation is easy to derive if you follow the steps in case study III. Indeed, the determinant of is simply equivalent to 1 and 1/10 respectively, and and 00. and We can easily generate samples from this target distribution with DREAM if we evaluate directly the density of Equation (2.02). Instead, we follow a different procedure herein and use the ABC procedure in DREAM. This requires the user to define signatures of system behavior, which in the present context is equivalent to a summary metric of Equation (2.02). This summary metric, , is defined as follows (8.03) , where is a vector with hundred elements and |·| denotes the modulus operator (absolute value). The values of the vector Y are drawn randomly from the univariate normal distribution with zero mean and unit standard deviation, thus , . The tilde symbol ‟ ” means ‟distributed according to". The following distance function, value of the parameter, x or not is used in DREAM to help determine whether we should accept the (8.04) . The variable in Equation (8.04) denotes the observed value of the summary metric. This value is equal to zero in the present study. If the value of the distance function is smaller than some small nominal value then is accepted, and otherwise the proposed parameter value is rejected. The initial population is drawn from the univariate uniform distribution with and using Latin hypercube sampling. A total of N = 8 chains are created with DREAM using standard settings for the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example08\Plugin\Src_Cpp 4.9 Example 9 66 DREAM Suite 1 Case-Study IX: Rainfall-runoff model with spectral likelihood function Calibration of hydrological models in ungauged basins is the subject of increasing attention by the scientific community. In fact, this is one of the main goals of the Prediction in Ungauged Basins (PUB) initiative promoted by the International Association of Hydrological Sciences (Sivapalan et al., 2003). The present study uses the spectral likelihood function of Whittle (1953) to derive the posterior distribution of the parameters of a hydrologic model. This estimator has good statistical properties, is asymptotically consistent, and has significant advantages over traditional goodness-of-fit criteria in that calibration can be carried out, in principle, with information available in poorly gauged basins. Unlike most statistical estimators that act on the residuals of the observed and simulated data, Whittle's estimator tries to match the spectral densities of the model output and observed data. Whittle's likelihood function is given by (9.01) where n is the number of calibration data measurements, are the Fourier frequencies, J is the periodogram (an estimate of the spectral density) of the n-vector of observations, is the spectral density of the simulated discharge time series of the hmodel (depends on the parameter values stored in d-vector x) and is the spectral density of the autoregressive operator , which is equivalent to (9.02) , where is the standard deviation of the residual vector, and simulated, discharge record, modulus operator (absolute value). The periodogram of some time series at the frequency 1987) between the observed, , and |·| denotes the can be computed as follows (Brockwell and Davis, (9.03) where is the sample autocovariance coefficient at lag k and i is the imaginary unit. A detailed derivation of Equation (9.01) appears in Whittle (1953) and Beran (1994) provides further analysis of how the spectral likelihood relates to a Gaussian likelihood. Interested readers are referred to these publications for further details. We now apply Whittle's estimator to the calibration of a mildly complex lumped watershed model using historical data from the Guadalupe River at Spring Branch, Texas. This is the driest of the 12 MOPEX basins described in the study of Duan et al. (2006). The model structure and hydrologic process representations are found in Schoups and Vrugt (2010). The model transforms rainfall into runoff at the watershed outlet using explicit process descriptions of interception, throughfall, evaporation, runoff generation, percolation, and surface and subsurface routing (see Figure 9.01). 67 DREAM Suite 1 Figure 9.01. Schematic representation of the hmodel conceptual watershed model Table 9.01 summarizes the seven different model parameters, and their prior uncertainty ranges. These parameters represent conceptual properties of the watershed under investigation, and cannot be measured directly in the field. We therefore derive their values by calibration of the hmodel against a historical record of discharge data. Parameter Symbol Maximum interception Soil water storage capacity Maximum percolation rate Evaporation parameter Runoff parameter Time constant, fast reservoir Time constant, slow reservoir Lower Upper Units 1 10 0 0 -10 0 0 10 1000 100 100 10 10 150 mm mm mm/day days days Table 9.01: Parameters of the hmodel and their prior uncertainty ranges We use daily discharge, mean areal precipitation, and mean areal potential evapotranspiration from the French Broad watershed at Asheville, North Carolina. We assume herein a multivariate uniform prior distribution for the parameters with ranges listed in Table 9.01. With the use of such flat prior, the posterior density (product of prior and likelihood) is simply proportional to the spectral likelihood function of Equation (9.01). The initial state of each of the N = 10 chains of DREAM is generated with Latin hypercube sampling by drawing from the uniform prior parameter distribution. Standard settings are used for the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example09\Plugin\Src_Cpp 4.10 Example 10 Case-Study X: d-dimensional multimodal mixture distribution with multiplicative prior According to Bayes law, the posterior density is equal to the product of the prior distribution and the likelihood function or, p(x) = pr(x) × L(x). In the previous case studies we have assumed that the prior distribution, , is multivariate uniform, and thus (10.01) . The value of this constant is thus fixed and independent of the model parameter values used. With the use of such noninformative (flat) prior, the posterior density, , is simply proportional to the value of the likelihood function, and thus, . The value of in Equation (10.01) is easily derived if a uniform prior is used. Certainly, we know that any prior distribution must integrate to unity – a requirement for a proper probability distribution. If we apply this principle to the uniform prior distribution of the hmodel 68 DREAM Suite 1 parameters of Table 9.01 we can write (10.02) . We also know that the uniform distribution produces the same density for each feasible solution within its domain. Thus, the value of the constant is easily derived from the listed ranges of the hmodel parameters. This gives (10.03) If we thus take into explicit consideration the effect of the prior distribution on the posterior density in the previous case study we should write (10.04) . Indeed, we can now use an equality sign rather than a proportionality sign. Nevertheless, this scaling factor of the posterior density has no effect on the parameter inference with DREAM. This changes however, if we use an informative prior distribution – that is – a distribution that is not flat but rather depends on the actual values of the parameters. Indeed, in case study XII we have considered such example with soil hydraulic parameters that were assumed to each have a Gaussian marginal prior distribution. Such distribution does not assign an equal prior density to the parameter values, but rather favors certain solutions over others – that is – parameter values that are close to the mean of the Gaussian prior will have a higher density than those further removed from the center of this distribution. This will affect the inference with DREAM as parameter values that do not agree with prior information are discouraged. To explicate the effects of a prior distribution on the results of DREAM we consider in this tenth case study, a simple multivariate normal prior distribution, with mean and covariance matrix . We assume that the mean of the prior distribution is equal to -2, and the covariance matrix is equivalent to Id, a matrix with values of one on the main diagonal and zero elsewhere, and thus . The tilde symbol ‟ ” means ‟distributed according to". We consider as likelihood function a mixture of two normal distributions (10.05) , where the mean of the first and second component of the Gaussian mixture is equal to -5 and 5, respectively, and the covariance matrix equal to the identity matrix, Id. Now we can calculate the posterior density, as product of the prior, and likelihood, using Bayes law (10.06) , The initial population is drawn randomly from (0,Id), the multivariate normal distribution with zero mean and covariance matrix equal to the identity matrix. We use N = 10 different chains with DREAM and apply default settings of the algorithmic variables. Thus this case study does not use a uniform prior distribution for the parameters, but rather assumes an informative prior distribution. Such prior allows users to take into explicit consideration in the present study, parameter estimates or distributions derived from previous data and/or analysis. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example10\Plugin\Src_Cpp 69 DREAM Suite 1 4.11 Example 11 Case-Study XI: d-dimensional multivariate student T distribution To test the performance of DREAM for distributions with a tail, the eleventh case study involves a d = 25dimensional student T distribution with 60 degrees of freedom. The target distribution can be written as (11.01) , where vector given by is the d-variate student distribution with v degrees of freedom (v > 1) centered at the and with scale (correlation) matrix . The probability density function of is (11.02) , where denotes the Gamma function, and T denotes transpose. In the special case of v = 1, Equation (11.02) reduces to the multivariate Cauchy distribution. The values of are set to zero and all-pairwise correlations in the matrix are set to 0.5, respectively. The initial states of each of the Markov chains are generated with Latin hypercube sampling by drawing randomly from , the -variate uniform distribution with lower bound values of and upper ranges equal to . Default values of the algorithmic variables are used. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example11\Plugin\Src_Cpp 4.12 Example 12 Case-Study XII: Pedometrics (variogram fitting) The past decades have seen a growing interest in soil characterization, not only because many highly interrelated water, carbon, and vegetation processes take place in this part of our ecosystem, but also because the subsurface plays a major role in carbon storage, exchange of water and soil vapor with the ambient atmosphere, and contaminant transport to the groundwater. Many soil properties not only exhibit significant spatial and temporal variability, but are also difficult to measure directly. Geostatistics is primarily concerned with the mathematical description, prediction, and uncertainty analysis of these spatially varying variables. The basis of geostatistical estimation is the assumption that an observation of a variable at location s is a realization of a random field . The random function is assumed to be intrinsically stationary (Webster and Oliver, 2009) (12.01) and (12.02) where h is a lag vector, and γ(h) is the variogram. The method of moments is usually used to estimate the so-called empirical variogram, and parameters of a variogram model are then estimated by fitting a model to 70 DREAM Suite 1 the empirical variogram. Thus, the accuracy of spatial prediction is determined by how the variogram is estimated. The paper of Diggle et al. (1998) introduced an alternative approach to geostatistical inference that is based on the application of formal statistical methods. This so-called model-based Geostatistics relies on general principles of statistical inference and use an explicit stochastic error model of the data. The use of a proper likelihood function and a posteriori check of the error residual distribution not only constitutes good statistical practice, but also facilitates the application of a powerful array of multivariate statistical analyses to explore the marginal and joint posterior probability density functions of the nugget, sill and range. Other formal statistical approaches include the generalized linear-mixed model and empirical best linear unbiased prediction (EBLUP) (Zimmerman and Cressie, 1992). Despite this progress made, it remains typically difficult to estimate the parameters of a variogram model and successfully solve the geostatistical inverse problem. That is, the covariance structure of the residuals is required for variogram fitting, yet in most cases is unknown a priori. The spatial covariance structure can only be obtained after fitting the trend. The residual maximum likelihood (REML) approach is therefore advocated (Lark et al., 2006), because it allows for independent estimation of the covariance structure by transforming the data into stationary increments that filtered out the trend. Nevertheless, REML or related methods only attempt to find the maximum likelihood values of the variogram parameters without recourse to estimating their underlying posterior uncertainty. This posterior probability distribution function (pdf) contains important information about the uncertainty and correlation of the various geostatistical parameters and can be used to derive meaningful estimates of spatial prediction uncertainty. In this twelfth case study we explore the use of Markov chain Monte Carlo simulation with DREAM to characterize the uncertainty of the variogram parameters and their effect on spatial prediction uncertainty. We assume herein a simple linear trend model for prediction of variable y at n different locations . This model can be written as (12.03) where , signifies a matrix with spatial coordinates, is the design matrix of the trend function , is a vector of trend parameters, and is the vector of residuals with a mean of zero and covariance matrix, K. This covariance can be described with the Matérn function (12.04) where Kij is the covariance between observation i and j, h represents the separation distance between i and j, denotes the Kronecker delta ( = 1 if i = j and = 0 when i ≠ j), c0 is the nugget variance, and c0 + c1 signifies the sill variance, Kn is a modified Bessel function of the second kind of order n, G is the gamma function, r denotes the distance or ‘range' parameter and n is the “smoothness”. This latter parameter allows for great flexibility in modelling of the local spatial covariance. The Matérn function is equivalent to the exponential function for , the Whittle model (1954) for and approaches the Gaussian model for . The corresponding semivariance of the Matérn function is (12.05) The parameters of this function can be summarized in a single vector, The value of at the unsampled location . can be computed from (12.06) , 71 DREAM Suite 1 where are the observed values at each of the n measurement locations, M is the design matrix , variance of the prediction at location , and . The associated is (12.07) , where and .The unknown parameters in Equations (12.06) – (12.07) are now combined in the vector, and estimated using Markov chain Monte Carlo simulation with DREAM. This allows for characterization of the uncertainty of the trend and variogram parameters and their effect on spatial prediction uncertainty. We use herein a single trend parameter for (also referred to as “mean”), thus resulting in a dimensional parameter estimation problem. Table 12.01 summarizes the trend and variogram parameters which are subject to inference and their prior uncertainty ranges. Parameter Symbol Trend parameter (“Mean”) Nugget variance Remaining variance to sill Smoothness parameter Distance or “range” parameter † Lower Upper Units 0 0 0 0 0 100 100 1000 1000 20 Cm cm2 cm2 cm Listed units and ranges depend on units and characteristics of calibration data Table 12.01: Trend and variogram parameters and their prior uncertainty ranges We use soil thickness data of the A horizon collected at an experimental field plot near Forbes, New South Wales, Australia (Pettitt and McBratney, 1993). A nested sampling design was used where the field was divided into 18 equal-sized blocks of 160 m2. In each block six sampling points were used along transects of 156 m long separated by 125 m, 25 m, 5 m, 1 m and 25 cm. To successfully implement DREAM we need to define the parameter ranges, an initial sampling distribution, and a likelihood function to compare the model predicted A-thickness with the observed data. In this case study, we assume a uniform prior distribution with upper and lower bounds of the parameters listed in Table 12.01, and use Latin Hypercube sampling over this d-dimensional hypercube to initialize the starting points of the N = 10 different Markov chains. The following formulation of the log-likelihood function, is used (Mardia and Marshall, 1984) (12.08) where is the covariance matrix derived from the Matérn function, signifies the determinant operator, and is a scalar whose value does not affect the posterior parameter distribution. This latter value is therefore ignored. We assume default values for the algorithmic variables of DREAM. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example12\Plugin\Src_Cpp 4.13 Example 13 72 DREAM Suite 1 Case-Study XIII: Nash-Cascade model of hydrograph The thirteenth case study considers the modeling of the instantaneous unit hydrograph using the ordinates of Nash (1960) defined as (13.01) where (mm/day) is the simulated streamflow at time t (days), g (-) denotes the number of reservoirs, α (days) signifies the recession constant, and is the gamma function (13.02) which satisfies the recursion . A n = 25-day period with synthetic daily streamflow data was generated by driving Equation (13.01) with an artificial precipitation record using g = 2 reservoirs, and a recession constant of α=4 days. This artificial data set is subsequently perturbed with a heteroscedastic measurement error (non-constant variance) with standard deviation equal to 10% of the original simulated discharge values. The DREAM algorithm is now used to derive the posterior distribution of both parameters g and α using a bivariate uniform prior distribution, [1,10] and Gaussian likelihood function (13.03) , where and are the observed and simulate discharge record, respectively, and n denotes the number of measurements. The initial population is drawn from the prior distribution using Latin hypercube sampling. We use N = 8 chains with DREAM to generate samples and use standard settings for the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example13\Plugin\Src_Cpp 4.14 Example 14 Case-Study XIV: Approximate Bayesian inference for hydrologic watershed model The fourteenth case study illustrates the ability of DREAM for diagnostic model evaluation. A rather parsimonious 7-parameter lumped watershed model (also known as hmodel) is used with historical data from the French Broad River at Asheville, North Carolina. This is the driest of the 12 MOPEX basins described in the study of Duan et al. (2006). The model is illustrated schematically in Figure 14.01. The model transforms rainfall into runoff at the watershed outlet using explicit process descriptions of interception, throughfall, evaporation, runoff generation, percolation, and surface and subsurface routing. 73 DREAM Suite 1 Figure 14.01. Schematic representation of the hmodel conceptual watershed Daily discharge, mean areal precipitation, and mean areal potential evapotranspiration were derived from Duan et al. (2006) and used for diagnostic model evaluation with DREAM. Details about the basin and experimental data, and likelihood function can be found there, and will not be discussed herein. The same model was used in case study six to illustrate the generalized likelihood function. Four different summary metrics of the discharge data are used for diagnostic inference with DREAM (activated with likelihood function 22), including S1 (-), the annual runoff coefficient, S2 (-) the annual baseflow coefficient, and S3 (day/mm) and S4 (-) two coefficients of the flow duration curve. The four different summary metrics are stored in the vector . . A detailed description of these summary metrics can be found in Sadegh and Vrugt (2013) and interested readers are referred to this publication. The seven different parameter values of the hmodel and their prior uncertainty ranges are listed in Table 6.01. Each time the hmodel is executed with the seven different parameter values stored in the vector x the simulated values of the summary metrics are computed from the modeled discharge record and stored in the vector . The following distance function, is used in DREAM to help determine whether we should accept the vector of proposed parameter values or not (14.01) , where |·| denotes the modulus operator (absolute value). If this distance function is smaller than the small positive threshold ϵ the proposed parameter values are considered to be a sample of the posterior distribution. The initial population is drawn from the parameter ranges listed in Table 6.01 using Latin hypercube sampling. The posterior target distribution is sampled with DREAM using N = 10 different chains using standard settings for the algorithmic variables (default ϵ=0.025). Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example14\Plugin\Src_Cpp 4.15 Example 15 Case-Study XV: Approximate Bayesian inference using 10 bivariate normal distributions In this fifteenth study we illustrate the use of Approximate Bayesian Computation (ABC) by application to a target distribution consisting of ten bivariate normal distributions. We first sample randomly ten times the mean, , of a bivariate normal distribution, by drawing randomly from a twodimensional uniform prior distribution, with and or , where the tilde symbol ‟ ” means ‟distributed according to”. We then treat these i = 10 values as observations, and store them in a vector, . We now use this vector of with observations to determine the observed means by drawing ten different times a sample from a bivariate normal distribution 74 DREAM Suite 1 (15.01) , where is the pair of parameter values created by DREAM and stored in vector x, and . The values of are stored in the vector, . The distance between the observed and simulated observations is not defined with a formal likelihood function, but rather with a distance function, as follows (Turner and Sederberg, 1980) (15.02) , The proposal is considered to be behavioral (= posterior solution) if the value of the distance function is smaller than , a small positive value. We approximate the posterior distribution of the ten means in DREAM using N = 20 different chains and the distance function of Equation (15.02). The initial state of each chain is sampled randomly from and standard values are used of the algorithmic variables (default ). Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example15\Plugin\Src_Cpp 4.16 Example 16 Case-Study XVI: Hydrogeophysics: Inference of the spatial distribution of soil properties The sixteenth case study considers the application of DREAM to distributed soil moisture estimation using travel-time observations from crosshole ground-penetrating radar experiments. This study differs from most other built-in studies of DREAM suite as it requires two- dimensional numerical simulation and high resolution spatial characterization. Such spatial inference problems can be much harder to solve than problems involving temporal characterization of one or more variables of interest. This all has to do with parameter selection. For temporal inference problems, the calibration parameters are usually unknowns in the underlying (differential) equations of the model. These parameters are easy to isolate. For spatial inference problems, it is not only clear how to describe mathematically or statistically the spatial properties of the variable of interest, but it is also unclear how many parameters to use to characterize the observed pattern. The parameterization of the inverse model should ideally provide enough details to capture all relevant variations in the Earth's property field and thereby avoid bias caused by model truncation (Trampert and Snieder, 1996). In global earth seismology, it is widely recognized that differences between deterministic inversion results based on the same data set are largely due to differences in spatial or spectral resolutions used in the (inverse) parameterizations (e.g., Chiao and Kuo, 2001). Compactly supported pixels that in a Cartesian coordinate system would be represented by, for example, uniform grid models, provide a very high spatial resolution, whereas spherical harmonics or discrete cosine transform (DCT) in its Cartesian counterpart provide a high spectral resolution. Many popular model parameterization schemes can be found in-between these two opposing extremes, such as wavelets (e.g., Chiao and Kuo, 2001) and slepian functions (e.g., Simons et al., 2006). The uniform grid parameterization has the key advantage of a localized and uniform spatial resolution. Inversion based on a uniform grid distribution is hence straightforward. One simply discretizes the spatial domain of interest into a number of cells, and then treats each cell as a different parameter, say, the soil moisture content. This Cartesian parameterization is perhaps straightforward to implement and use, but it is rather inefficient as many thousands of unknowns are required to represent with some spatial resolution and accuracy the soil moisture distribution. This inference problem is unnecessarily difficult and CPU-demanding to solve for DREAM. We therefore use herein a more parsimonious, and perhaps more intelligent, parameterization method and describe the value of the relative saturation (0-100%) of each grid cell using the discrete cosine transform. This transformation, hereafter referred to as the DCT has desirable 75 DREAM Suite 1 advantages for stochastic inversion, in that (i) the resolution and separation of scales is explicitly defined, (ii) the transformation is orthogonal and close to the optimal Karhunen-Loève transform, (iii) the computational efficiency is high, (iv) the basis vectors depend only on the dimensionality of the model, and (v) the transformation is linear and operates with real parameter values (Linde and Vrugt, 2013; Qin et al., 2016). The DCT coefficient, is computed using (16.01) where and denote the row and column number of the DCT coefficient-matrix, R and the stores a map of discretized values of the relative saturation of the spatial domain of interest and matrix Q (16.02) and Close inspection of Equation (16.01) demonstrates that the size of matrix R is exactly similar to that of Q, and thus the standard DCT operation does not reduce parameter dimensionality. Indeed, each coordinate of the matrix Q with value of the soil moisture content, has its own DCT coefficient. We can transform the matrix Q from the space domain to the frequency domain using the DCT coefficients stored in R. The information in this transformation is concentrated in the lower frequencies DCT coefficients. We can thus safely discard the higher frequency DCT coefficients without losing significant information about the spatial pattern of the soil moisture content. The lower frequency DCT coefficients are retained and define the model parameters, that will be estimated using DREAM. This approach significantly reduces the dimensionality of the parameter space (Linde and Vrugt, 2013; Qin et al., 2016) and has desirable advantages for stochastic inversion. For example, Figure 1 in Jafarpour et al. (2008) depicts the results for the first 8 ´ 8 DCT bases and shows how the DCT transform coefficients relate to a given geological model. The more DCT coefficients are used the better the reconstruction of the true field (see Qin et al., 2016). We use herein DCT coefficients, which jointly maintain about 95-97% of the variance of the original relative saturation space. As a synthetic example, we use a soil moisture model from Kowalsky et al. (2005). This model was constructed by simulating an infiltration experiment in a heterogeneous soil. The simulated soil moisture distribution is transformed into a radar velocity model using Topp's equation (Topp et al., 1980) (Fig. 1a). A synthetic data set of 900 travel-time observations is constructed for two different boreholes located 3 m apart using a transmitter-receiver geometry consisting of multiple-offset gathers between 0 and 3 m depth with sources and receiver intervals of 0.1 m. The resulting travel times calculated with the time3d algorithm (Podvin and Lecomte, 1991) are contaminated with zero mean uncorrelated Gaussian noise with a standard deviation of 0.5 nanoseconds, ns. This constitutes a high-quality GPR data set, which is subsequently used to compare our MCMC inversion methodology against exact theory, but with noisy data. We use a simple Gaussian likelihood function (16.03) , where and are the observed and simulate travel-time data respectively, and n denotes the number of measurements. The simulated travel-time data are derived from the DCT coefficients of the relative moisture distribution using a simple linear travel-time simulator. This model is a simplified version of the numerical model used by Linde and Vrugt (2013) as it considers straight rays only. This simplification reduces the CPU-cost of the model tremendously, yet can only provide approximate results. 76 DREAM Suite 1 The initial state of each Markov chain is drawn from , a normal distribution centered at zero and with covariance matrix equal to . All the off-diagonal elements of this matrix are set to zero and the main diagonal contains values of about 0.017 (first element) and 0.05 and 0.07, respectively. These values are deliberately set small so that DREAM needs relatively few iterations to converge to the posterior distribution. We use N = 32 chains with DREAM to generate samples of the posterior distribution of the moisture distribution and use thinning of the chains (each 5th sample is collected) to minimize memory storage. Default settings are assumed for all other algorithmic variables of DREAM. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example16\Plugin\Src_Cpp 4.17 Example 17 Case-Study XVII: Rainfall-runoff modeling: Inference of the discharge measurement error In this seventeenth study, we use the HYMOD conceptual watershed model, a parsimonious rainfall-runoff model whose parameters are thought to vary between watersheds. This model has been used in a numerous studies and has five parameters that need to be specified by the user. Inputs to the model include mean areal precipitation (MAP), and potential evapotranspiration (PET), while the outputs are estimated channel inflow. HYMOD consists of a simple two-parameter rainfall excess model connected with two series of linear reservoirs (three, identical, for the quick and a single reservoir for the slow response) in parallel as a routing component. A schematic representation and discussion of the model appears in case study IV (see Figure 4.01), and readers are referred to this section for further details. HYMOD has five different parameters whose values need to be determined from a measured discharge record. The parameters and their prior uncertainty ranges are listed in Table 4.01. This includes cmax (mm), the maximum storage capacity in the catchment, bexp (-) the degree of spatial variability of the soil moisture capacity within the catchment, α (-) a coefficient that distributes the flow between the fast and slow-flow reservoirs, and rs (days) and rq (days), the residence time of the slow and fast-flow reservoir reservoirs, respectively. The actual evapotranspiration is equal to its potential value if sufficient soil moisture is available, otherwise it is reduced depending on the soil water status. (17.01) . where and are the observed and simulate discharge record, respectively, and n denotes the number of measurements. (17.02) This formulation contains two coefficients, (mm/day) and (-) whose values are unknown and are therefore added to the vector of model parameters. This then leads to the inference of parameters with DREAM using the observed discharge data record and the likelihood function of Equation (17.01). The latent variables and are assigned a uniform prior distribution with ranges listed in Table 17.01. Parameter Symbol Intercept of measurement error function Slope of measurement error function † Lower Upper Units 0 0 1 1 mm/day - The listed units and ranges depend on units and characteristics of calibration data (discharge in present case) 77 DREAM Suite 1 Table 17.01: Nuisance variables of the measurement error function in Equation (17.01)† The initial population is drawn from the lower and upper ranges listed in Table 6.01 and 17.01 using Latin hypercube sampling. We use N = 10 chains with DREAM and use standard settings for the algorithmic variables. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example17\Plugin\Src_Cpp 4.18 Example 18 Case-Study XVIII: Lotka-Volterra: The use of informal likelihoods The eighteenth case study reports on GLUE and involves application of an informal likelihood function to the study of animal population dynamics. One of the first models to explain the interactions between predators and prey was proposed in 1925 by the American biophysicist Alfred Lotka and the Italian mathematician Vito Volterra. This model, one of the earliest in theoretical ecology, has been widely used to study population dynamics, and is given by the following system of two coupled differential equations (18.01) where and denote the size of the prey and predator population at time t respectively, (-) is the prey growth rate (assumed exponential in the absence of any predators), (-) signifies the attack rate (prey mortality rate for per-capita predation), (-) represents the exponential death rate for predators in the absence of any prey, and (-) is the efficiency of conversion from prey to predator. A synthetic monthly data set of a prey and predator population is created by solving Equation (18.01) numerically for a 20-year period using an implicit, time-variable, integration method. The initial states, and and parameter values , , and correspond to data collected by the Hudson Bay Company between 1900 and 1920. These synthetic monthly observations are subsequently perturbed with a homoscedastic error, and this corrupted data set is stored in the n-vector and used for inference with DREAM. We now use this data set of “observed” predator and prey abundances to determine the posterior parameter distribution of the four LotkaVolettera model parameters, hence the parameter vector, . Parameter Symbol Prey growth rate Attack rate Exponential death rate for predators without prey Efficiency of conversion from predator to prey Lower Upper Units 0 0 0 0 1 10 1 10 - Table 18.01: Parameters of the Lotka Volterra model in Equation (18.01) A uniform prior parameter distribution is assumed using the ranges listed in Table 18.01. The initial states of each of the N = 10 Markov chains in DREAM are sampled randomly from the prior ranges using Latin hypercube sampling. An informal GLUE-type likelihood function is used to determine the behavioral (= posterior) solution space. The log-likelihood, is given by 78 DREAM Suite 1 (18.02) where is a GLUE-coefficient which determines the peakedness of the likelihood surface, and the operator computes the variance of the error residuals between the simulated and observed data (numerator) and variance of the measurement data (denominator), respectively. We assume a value of and use default values of the algorithmic variables of DREAM. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example18\Plugin\Src_Cpp 4.19 Example 19 Case-Study XIX: Bayesian Model Averaging: Ensemble Forecasting Predictive uncertainty analyses is typically carried out using a single conceptual mathematical model of the system of interest, rejecting a priori valid 4 alternative plausible models and possibly underestimating uncertainty in the model itself (Raftery et al., 1999; Hoeting et al., 1999; Neuman, 2003; Raftery et al., 1999; Vrugt et al., 2006, Vrugt and Diks, 2010). Model averaging is a statistical methodology that is frequently utilized in the statistical and meteorological literature to account explicitly for conceptual model uncertainty. The motivating idea behind model averaging is that, with various competing models at hand, each having its own strengths and weaknesses, it should be possible to combine the individual model forecasts into a single new forecast that, up to one's favorite standard, is at least as good as any of the individual forecasts. As usual in statistical model building, the aim is to use the available information efficiently, and to construct a predictive model with the right balance between model flexibility and overfitting. Viewed as such, model averaging is a natural generalization of the more traditional aim of model selection. Indeed, the model averaging literature has its roots in the model selection literature, which continues to be a very active area of research. Figure 19.01 provides a simple overview of model averaging. Consider that at a given time we have available the output of multiple different models (calibrated or not). Now the goal is to weight the different models in such a way that the weighted estimate (model) is a better (point) predictor of the observed system behavior (data) than any of the individual models. What is more, the density of the averaged model is hopefully a good estimator of the total predictive uncertainty. 79 DREAM Suite 1 Figure 19.01. Schematic illustration of model averaging using a three member ensemble and single prediction of interest. The forecast of each models are displayed with the solid red circle, blue square and green diamond, respectively, and the verifying observation is indicated separately with the brown “x” symbol. The dotted black line connected with the symbol “o" denotes the weighted average of the forecasts of the three different models. This point predictor satisfies the underlying premise of model averaging as it is in better agreement with the data (smaller distance) than any of the three models of the ensemble. Some model averaging methods also construct a predictive density of this averaged forecast. This overall forecast pdf (solid black line) can be used for probabilistic forecasting and uncertainty analysis, and is simply a weighted average of each ensemble member's predictive distribution (indicated with solid red, blue and green lines) centered at their respective forecasts To formalize the various model averaging strategies considered herein, let us denote by a vector of measurements of a certain quantity of interest. Further assume that there is an ensemble of K different models available with associated point forecasts at one or more locations s and time, t. If we merge the different model forecasts in a n × K matrix Y (each model has its own column), we can combine their individual forecasts using weighted averaging (19.01) , where is the jth row of matrix Y which stores the forecasts of each of the K models at a given location and time, is a vector that stores the weights of each individual model, the symbol T denotes transpose, and is a white noise sequence, which will be assumed to have a normal distribution with zero mean and unknown variance. (19.02) , will often suffice to derive the bias-corrected forecasts, coefficients and for each of the models, simple regression model for each of the models of the ensemble. The are found by ordinary least squares using the (19.03) , and the observations in the calibration data set. Typically this bias correction leads to a small improvement of the predictive performance of the individual models, with close to zero and close to 1. If the calibration set has relatively few observations, the ordinary least squares estimates become unstable, and bias correction may distort the ensemble (Vrugt and Robinson, 2007). Although a (linear) bias correction is recommended for each of the constituent models of the ensemble, such correction is not made explicit in subsequent notation. For convenience, we simply continue to use the notation rather than for the bias corrected predictors of . The point forecasts associated with model (19.01) are (19.04) , where the superscript “e” is used to indicate the expected (predicted) value of the averaged model. Ensemble Bayesian Model Averaging (BMA) proposed by Raftery et al. (2005) is one popular method for model averaging that is widely used method for statistical post-processing of forecasts from an ensemble of different models. The BMA predictive distribution of any future quantity of interest is a weighted average of probability density functions centered on the bias-corrected forecasts from a set of individual models. The weights are the estimated posterior model probabilities, representing each model's relative forecast skill in the training (calibration) period. Depending on the type of application one has in mind, different flavors of BMA can be used. For instance, it makes a crucial difference whether one would like to average point forecasts (in which case some forecasts 80 DREAM Suite 1 may be assigned negative weights) or density forecasts (in which negative weights could lead to negative forecast densities). We now describe the most popular BMA method which is particularly useful when dealing with the output of dynamic simulation models. In BMA, each ensemble member forecast, , is associated with a conditional PDF, , which can be interpreted as the conditional PDF of on , given that is the best forecast in the ensemble. If we assume a conditional density, , that is centered on the forecasts of each of the individual models of the ensemble, we can derive the combined forecast density as follows (see also right-hand-side of Figure 19.01) (19.05) A popular choice for is a normal distribution with mean and variance, (19.06) , and thus the BMA predictive density, , consists of a mixture of normal distributions, each centered around their individual point forecast . To ensure that represents a proper density, the BMA weights are assumed to lie on the unit simplex, . Thus, the ‘s are nonnegative and add up to one (19.07) ; and they can be viewed as weights reflecting an individual model's relative contribution to predictive skill over the training (calibration) period. The BMA point predictor is simply a weighted average of the individual models of the ensemble (19.08) which is a deterministic forecast in its own way, whose predictive performance can be compared with the individual forecasts in the ensemble, or with the ensemble mean. The associated variance of Equation (19.08) can be computed as (Raftery et al. 2005) . (19.09) The variance of the BMA prediction defined in Equation (19.08) consists of two terms, the first representing the ensemble spread, and the second representing the within-ensemble forecast variance. Successful implementation of the BMA method described in the previous section requires estimates of the weights and variances of the PDFs of the individual forecasts. Following Raftery et al. (2005), we use the following formulation of the log-likelihood function, to estimate the values of and in the BMA model (19.10) where n denotes the total number of measurements in the training data set. This formulation builds on the assumption that the forecasts errors of the models are independent in space and time. Note, for reasons of numerical stability we work with the log-likelihood function rather than the likelihood function itself. In the case of a normal conditional pdf for the formulation of Equation (19.10) is equivalent to 81 DREAM Suite 1 (19.11) with and . Unfortunately, no analytical solutions exist that conveniently maximize Equation (19.10). We therefore use DREAM to derive the posterior distribution of the BMA weights and variances. In this nineteenth study we apply the BMA method using 48-h forecasts of surface temperature and sea level pressure in the Pacific Northwest in January - June 2000 using the University of Washington (UW) mesoscale short-range ensemble system. This is a five member multianalysis ensemble (hereafter referred to as the UW ensemble) consisting of different runs of the fifth-generation Pennsylvania State University National Center for Atmospheric Research Mesoscale Model (MM5), in which initial conditions are taken from different operational centers. We assume that all models have a common BMA variance – and thus – which involves inference of parameters with DREAM. Note, we estimate the standard deviation of the normal predictive pdf, rather than its variance, as this has the advantage of requiring a smaller search space. A uniform prior distribution is assumed for the BMA weights and variance, and The initial states of the chains are derived by sampling from the prior distribution of default values are assumed for the other algorithmic variables. . and Note, the BMA method of Raftery et al. (2005) was developed for weather quantities such as temperature and sea-level pressure whose conditional pdfs are well described with a normal distribution. The DREAM solver also implements other conditional pdfs that might be more appropriate if the data is skewed. This includes the gamma distribution which much better describes data with a skew (19.12) , where is a shape parameter, and denotes a scale parameter. These two values depend on the value of but this is beyond of the present case study. Interested readers are referred to Vrugt and Robinson (2007) for an explanation and treatment of three different conditional pdfs. This includes also treatment of heteroscedasticity in the choice of the BMA variance (variance dependent on magnitude of model forecast). Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example19\Plugin\Src_Cpp 4.20 Example 20 Case-Study XX: Limits of Acceptability: Soil Temperature Modeling In the manifesto for the equifinality thesis, Beven (2006) suggested that a more rigorous approach to model evaluation would involve the use of limits of acceptability for each individual observation against which model simulated values are compared. Within this framework, behavioral models are defined as those that satisfy the limits of acceptability for each calibration observation. The twentieth case study briefly describes the application of DREAM to sampling the behavioral parameter space that satisfies the limits of acceptability of each observation. We use a simple illustrative example involving modeling of the soil temperature, T, in degrees Celsius using the following analytic equation , 82 (20.01) DREAM Suite 1 where z (cm) is the depth in the soil profile (positive downward), t (hour) denotes time, T0 (oC) is the annual average temperature at the soil surface, A0 (oC) is the amplitude of the temperature fluctuation, (hour-1) signifies the angular frequency, (hour) is a phase constant, and z0 (cm) denotes the characteristic damping depth. A synthetic record of hourly soil temperature observations at 5, 10, and 15 cm depth is used to illustrate the application of DREAM to informal Bayesian inference using a limits of acceptability approach. This data set was created by solving Equation (20.01) numerically for a 2-day period using T0=20oC, A0=5oC, ϕ=8 hr and z0=20 cm. The hourly data was subsequently perturbed with a normally distributed error of 0.5 oC and stored as the n-vector . The limits of acceptability were set to be equal to two degrees Celsius for each of the n = 144 temperature observations at three depths. The four model parameters are listed in Table 20.01 and stored in the d-vector . We now determine the behavioral parameter space from the observed temperature data using the following pseudo-type likelihood (20.02) , where is an indicator function that returns one if the condition a is satisfied and zero otherwise. A behavioral solution will satisfy the limits of acceptability of each temperature observation in the soil and thus receive a score of n. Parameter Symbol Annual average temperature at soil surface Amplitude of temperature fluctuations soil surface Phase constant Characteristic damping depth Lower Upper Units 10 0 0 0 30 10 24 50 C C hour cm o o Table 20.01: Parameters of the soil temperature model in Equation (20.01) We now explore the behavioral solution space (might not exist!) with DREAM. We assume a noninformative (uniform) prior distribution for each of the four parameters using the ranges listed in Table 20.01. A total of N = 10 different Markov chains are used with DREAM. Their initial position is drawn randomly from the multivariate uniform prior using Latin hypercube sampling. Default values of the algorithmic variables are used. Note, in the present study each observation is assumed to have the same limits of acceptability. DERAM allows the use of a different limits of acceptability for each individual observation. This will be demonstrated explicitly in the next case study involving characterization of the spatial variability of soil moisture in a field plot using numerical solution of Richards' equation. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example20\Plugin\Src_Cpp 4.21 Example 21 Case-Study XXI: Limits of Acceptability: HYDRUS-1D model This twenty-first case study considers the application of the limits of acceptability framework to the modeling of the spatial distribution of soil moisture in a field plot. Beven (2006) has suggested that this framework constitutes a more rigorous approach to model evaluation. Within this framework, behavioral 83 DREAM Suite 1 models are defined as those that satisfy the limits of acceptability for each calibration observation. The twentieth case study briefly describes the application of DREAM to sampling the behavioral parameter space that satisfies the limits of acceptability of each observation. We use soil moisture data from an agricultural field near Jülich, Germany. This data was measured over a period of 210-days using Time Domain Reflectometry (TDR) probes installed at 6 cm deep and at 61 different locations in a 50 × 50 m plot. The TDR data were analysed using the algorithm described in Heimovaara et al. (1990) and the measured apparent dielectric permittivities were converted to soil moisture contents using the empirical relationship of Topp (1980). Measurements were taken on 29 days between 19 March and 14 October 2009, comprising a measurement campaign of 210 days. The observed soil moisture data at the 61 different locations were averaged to obtain a single mean time series of water content for the experimental plot. We store this data in the n-vector . The HYDRUS-1D model of Simunek et al. (2008) was used to simulate variably saturated water flow in the agricultural field. This model solves Richards' equation for given (measured) initial and boundary conditions (21.01) , where (cm3/cm3) denotes moisture content, t (days) denotes time, z (cm) is the vertical (depth) coordinate, h (cm) signifies the pressure head, and K(h) (cm day-1) is the unsaturated soil hydraulic conductivity. Observations of daily precipitation and potential evapotranspiration were used to define the upper boundary condition of the field plot. Precipitation and other meteorological variables were recorded at a meteorological station located 100 m west of the measurement site. A schematic overview of the model setup appears in Figure 7.01. Details of the site, soil properties, experimental design and measurements are given by Scharnagl et al. (2011) and interested readers are referred to this publication for further details. We have used a similar setup as in case study VII and interested readers are referred to this study for further details. The MVG parameters (cm3/cm3), (cm3/cm3), (cm-1), n (-) and (cm day-1) are subject to inference. In the absence of direct measurements, a constant head lower boundary condition, (cm) was assumed. The value of is assumed to be temporally invariant and subject to inference with DREAM. Table 21.01 lists the parameters of the HYDRUS-1D model and their prior ranges. These parameters are now subject to inference using the mean soil moisture values at the field plot and their associated limits of acceptability. Parameter Symbol Residual water content Saturated water content Reciprocal of air-entry value Curve shape parameter Saturated hydraulic conductivity Pressure head at lower boundary n Lower Upper Units 0.0 0.30 0.02 1.05 0.01 -500 0.1 0.55 0.50 2.50 4.17 -10 cm3/cm3 cm3/cm3 cm-1 cm hour-1 cm Table 21.01: HYDRUS-1D model parameters and their prior uncertainty ranges We now determine the behavioral parameter space from the observed temperature data using the following pseudo-type likelihood (21.02) , where is an indicator function that returns one if the condition a is satisfied and zero otherwise. A behavioral solution will satisfy the limits of acceptability of each temperature observation in the soil and thus receive a score of n. 84 DREAM Suite 1 We now explore the behavioral solution space (might not exist!) with DREAM by using the fitness function of Equation (21.02). We assume a uniform prior distribution with ranges of the parameters listed in Table 21.01. We run a total of N = 8 different Markov chains whose initial state is drawn randomly from the uniform prior distribution using Latin hypercube sampling. Default values of the algorithmic variables are used. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example21\Plugin\Src_Cpp 4.22 Example 22 Case-Study XXII: Limits of Acceptability: Nash-Cascade model The twenty-second case study considers the modeling of the instantaneous unit hydrograph using the ordinates of Nash (1960) defined as (see case study thirteen) (22.01) where (mm/day) is the simulated streamflow at time t (days), g (-) denotes the number of reservoirs, (days) signifies the recession constant, and is the gamma function (22.02) which satisfies the recursion . A n = 25-day period with synthetic daily streamflow data was generated by driving Equation (22.01) with an artificial precipitation record using g = 2 reservoirs, and a recession constant of days. This artificial data set is subsequently perturbed with a heteroscedastic measurement error (non-constant variance) with standard deviation equal to 10% of the original simulated discharge values. We store this record in the nvector, and use data set to derive the posterior distribution of the two Nash-Cascade parameters of Equation (22.01). We do not use a likelihood function herein (see case study XIII) but rather apply the concept of limits of acceptability. We define these limits to be for all the different observations, and use the following goodness-of-fit function to differentiate between behavioral and nonbehavioral solutions (22.03) , where is an indicator function that returns one if the condition a is satisfied and zero otherwise. Parameter values whose Nash-Cascade simulation leads to a score of Equation (22.03) equal to , honor the limits of acceptability of each discharge observation, and are called behavioral solutions. We now explore the behavioral solution space (might not exist!) with DREAM. We assume a bivariate uniform prior distribution, [1,10], for the parameters and g and draw the initial position of the N = 8 different Markov chains using Latin hypercube sampling. Default values of the algorithmic variables are used. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example22\Plugin\Src_Cpp 85 DREAM Suite 1 4.23 Example 23 Case-Study XXIII: Limits of Acceptability: The SAC-SMA flood forecasting model The twenty-third case study involves the modeling of the rainfall-runoff transformation of the Leaf River watershed in Mississippi. This temperate 1944 km2 watershed has been studied extensively in the hydrologic literature which simplifies comparative analysis of the results. The rainfall-discharge relationship of the Leaf River basin is simulated using the Sacramento soil moisture accounting (SAC-SMA) model of Burnash (1973). This lumped conceptual watershed model is used by the National Weather Service for flood forecasting through the United States. The SAC-SMA model uses six reservoirs (state variables) to represent the rainfall-runoff transformation. These reservoirs represent the upper and lower part of the soil and are filled with "tension" and "free" water, respectively. The upper zone simulates processes such as direct runoff, surface runoff, and interflow, whereas the lower zone is used to mimic groundwater storage and the baseflow component of the hydrograph. Figure 23.01 provides a schematic overview of the SAC-SMA model. Nonlinear equations are used to relate the absolute and relative storages of water within each reservoir and their states control the main watershed hydrologic processes such as the partitioning of precipitation into overland flow, surface runoff, direct runoff, infiltration to the upper zone, interflow, percolation to the lower zone, and primary and supplemental baseflow. Saturation excess overland flow occurs when the upper zone is fully saturated and the rainfall rate exceeds interflow and percolation capacities. Percolation from the upper to the lower layer is controlled by a nonlinear process that depends on the storage in both soil zones. Figure 23.01. Schematic representation of the Sacramento soil moisture accounting (SAC-SMA) conceptual watershed model. The parameters of the SAC-SMA model appear in Comic Sans font type (black), whereas Courier font type is used to denote the individual fluxes computed by the model. Numbers are used to denote the different SAC-SMA state variables, (1) ADIMC, (2) UZTWC, (3) UZFWC, (4) LZTWC, (5) LZFPC, and (6) LZFSC. The ratio of deep recharge to channel base ow (SIDE) and other remaining SAC-SMA parameters RIVA and RSERV are set to their default values of 0.0, 0.0 and 0.3, respectively The SAC-SMA model has thirteen user-specifiable (and three fixed) parameters and an evapotranspiration demand curve (or adjustment curve). Inputs to the model include mean areal precipitation (MAP) and potential evapotranspiration (PET) while the outputs are estimated evapotranspiration and channel inflow. A unit hydrograph or kinematic wave routing model is often used to rout channel inflow downstream to the gauging point. Here, I use instead a Nash-Cascade series of three linear reservoirs to rout the upper zone channel inflow whereas the baseflow generated by the lower zone recession is passed directly to the gauging point. This configuration adds one parameter and three state variables to the SAC-SMA model. The 86 DREAM Suite 1 use of the three reservoirs improves considerably the CPU-efficiency as it avoids the need for computationally expensive convolution. Our formulation of the model therefore has fourteen time-invariant parameters which are subject to inference using observed discharge data. Table 23.01 summarizes the fourteen SAC-SMA parameters and their prior uncertainty ranges. We also list the six main state variables. Parameter UZTWM UZFWM LZTWM LZFPM LZFSM ADIMP UZK LZPK LZSK ZPERC REXP PCTIM PFREE RQOUT Description upper zone tension water maximum storage upper zone free water maximum storage lower zone tension water maximum storage lower zone free water primary maximum storage lower zone free water supplemental maximum storage additional impervious area upper zone free water lateral depletion rate lower zone primary free water depletion rate lower zone supplemental free water depletion rate maximum percolation rate exponent of the percolation equation impervious fraction of the watershed area fraction that percolates from upper to lower zone free water Recession constant three linear routing reservoirs Lower Upper Units 1 1 1 1 1 0 0.1 0.0001 0.01 1 0 0 0 0 150 150 500 1000 1000 0.4 0.5 0.025 0.25 250 5 0.1 0.1 1.0 mm mm mm mm mm day-1 day-1 day-1 - State variables UZTWC Upper-zone tension water storage content 0 150 mm UZFWC LZTWC LZFPC LZFSC ADIMC Upper-zone free water storage content Lower-zone tension water storage content Lower-zone free primary water storage content Lower-zone free secondary water storage content Additional impervious area content 0 0 0 0 0 150 500 1000 1000 650 mm mm mm mm mm Table 23.01: Parameters of the SAC-SMA model and their prior uncertainty ranges In the manifesto for the equifinality thesis, Beven (2006) suggested that a more rigorous approach to model evaluation would involve the use of limits of acceptability for each individual observation against which model simulated values are compared. Within this framework, behavioral models are defined as those that satisfy the limits of acceptability for each observation. Ideally, the limits of acceptability should reflect the observational error of the variable being compared, together with the effects of input error and commensurability errors resulting from time or space scale differences between observed and predicted values Beven (2014). The limits of acceptability approach has been used by various authors (Blazkova and Beven, 2009; Dean et al., 2009; Krueger et al., 2009; Liu et al., 2009; Mcmillan et al., 2010; Westerberg et al., 2011), although earlier publications used similar ideas within GLUE based on fuzzy measures (Page et al., 2003; Freer et al.,2004; Page et al., 2004, 2007, Pappenberger et al., 2005, 2007). The limits of acceptability framework might be considered more objective than the standard GLUE approach advocated in Beven (1992) as the limits are defined before running the model on the basis of best available hydrologic knowledge. In this study we apply the limits of acceptability approach to the SAC-SMA model using data from the Leaf River watershed in the USA. A 10-year historical record (1/10/1952 - 30/9/1962) with daily data of discharge (mm/day), mean areal precipitation (mm/day), and mean areal potential evapotranspiration (mm/day) is used herein for SAC-SMA model calibration. A 65-day spin-up period is used to reduce sensitivity of the model to state-value initialization. We store the daily discharge observations in the n-vector, . We are now left with definition of the effective observation error (limits of acceptability) of each discharge 87 DREAM Suite 1 observation. This error varies dynamically with flow level and constitutes the combined effect of input data, model structural and calibration data measurement error. Here, we follow the approach of Sadegh and Vrugt (2013) and define the limits of acceptability as a multiple of the actual discharge measurement error. I follow Vrugt et al. (2005) and use a nonparametric estimator to calculate the measurement data error of the n discharge observations, hereafter referred to as computed as multiple of or . The limits of acceptability are now using . This leads to effective observation errors on the order of . The following pseudo-likelihood function is used to determine the goodness-of-fit of each simulated discharge record (23.01) , where is an indicator function that returns one if the condition a is satisfied and zero otherwise. Parameter values whose SAC-SMA simulation leads to a score of Equation (23.01) equal to , honor the limits of acceptability of each discharge observation, and are called behavioral solutions. We now explore the behavioral solution space (might not exist!) with DREAM. We assume a uniform prior parameter distribution using the ranges listed in Table 23.01 and draw the initial position of the different Markov chains using Latin hypercube sampling. Default values of the algorithmic variables are used. Implementation of plugin functions The complete source code can be found in DREAM SDK - Examples\D3\Drm_Example23\Plugin\Src_Cpp 5 Using DREAM The DREAM Suite package can be used to create new Bayesian inference projects via plugin modules or can be also used as a library/software component for the development of new standalone applications independent of DREAM Suite GUI. In the first case, one can work with the project (i.e. define input data, run the calculation and view results) using the DREAM Suite GUI. This kind of work can be demonstrated by opening demo examples in DREAM Suite main program. In the second case, one can develop his own application that prepares input data, calls DREAM Solver and performs a custom post-processing of results. An example of this situation is the DREAM console application. 5.1 DREAM projects Working with existing projects in DREAM Suite is quite easy. One can simply change input data in the GUI and recalculate results. However, developing a new project is more difficult, since one has to define the model and create a plugin module for the evaluation of proposals during the Markov chain calculation and implementing other needed functions. This may require a thorough understanding to mathematical methods used in DREAM Solver, which are described in DREAM Technical manual. We recommend you to read this manual before you start developing a new project in DREAM Suite. Creating a new project from scratch There are two ways how to create a new project: create a project from scratch or copy an existing project and modify it according to your needs. The following text explains how to create a project from scratch. · In the Project Manager, click on the "New"button. Fill in a project name and description and press OK. This action will create files and directories of the new project and open a project window. 88 DREAM Suite 1 Figure 5.1. New Project. · On the first project page, you can modify project description (both short one and detailed one). Figure 5.2. First Project page. · On the Model Definition page, you should specify a number of model parameters and their names (if you wish). The next step is to create the plugin module. 89 DREAM Suite 1 Figure 5.3. Model Definition page. · · To create a plugin module, enter a plugin name on the Model Definition page and click on button "Generate plugin project". This action will generate plugin files from a source code template and prompt the user to open the project in Visual Studio (you must have installed VS 2013 or VS 2015). The next step is to implement all needed functions of the plugin and build the plugin DLL. More information can be found in plugin module details and programming references. Once the plugin module is ready, can start creating new simulations. 5.1.1 Project files DREAM Suite project data is stored in the main project file and a directory containing other files and subdirectories. Project directory name is derived from the project name by adding Drm_ prefix (see Figure 5.1.1. "Project file and directory"). This means that, if you are copying of deleting a project, you must copy/ delete both - the file and the directory. The main project file (*.drm) and simulation files (so called "case files" - *.drs) are text files with a very simple format and can be easily edited using Notepad or another text editor. 90 DREAM Suite 1 Figure 5.1.1. Project File and Directory. Project Directory · Drm_Examle01 - project directory of project "Example01" · Model - directory for model-specific files · Bin - external executable files (see Example07) · Data - static model data, such as measurement data, etc. (see Example07) · Info - contains file ProjectInfo.htm with detailed description of the project · Plugin - directory for plugin files · Bin - contains the plugin 32-bit dynamic library · Bin_x64 - contains the plugin 64-bit dynamic library · Src_Cpp - contains plugin C/C++ source code (Visual Studio project and plugin source code) · Src_Matlab - contains MATLAB *.m files if the plugin type is MATLAB COM or MATLAB Engine · Src_Python - contains Python files if the plugin type is Python (not available in the current version) Simulations - directory for simulations. Each simulation has its data in a file and a special · directory · Case1.drs - so called "Case File" with input data of simulation "Case1" · Case1 - so called "Case Directory" for output files of simulation "Case1" · CaseX.drs - file with input data of simulation "CaseX" · CaseX - directory for output files of simulation "CaseX". Files can be in text format (*.txt) or binary format (*.bin) according to the selected option "Save results in binary format" · DREAM_Out_AR.txt (*.bin) - Evolution of acceptance rate. · DREAM_Out_AutoCorrN.txt (*.bin) - Autocorrelation of sampled parameters. · DREAM_Out_BetweenChainDiagnostic_Rstat.txt (*.bin) - Between-chain diagnostic with R-statistics. Optional - see "Save between-chain diagnostic". · DREAM_Out_BetweenChainDiagnostic_MRstat.txt (*.bin) - Between-chain 91 DREAM Suite 1 · diagnostic with MR-statistics. Optional - see "Save between-chain diagnostic". · DREAM_Out_Corr.txt (*.bin) - d-dimensional parameter correlation matrix. · DREAM_Out_CR.txt (*.bin) - Evolution of crossover selection probabilities. · DREAM_Out_Diagnostic.txt - Coda diagnostic of each chain. Optional - see "Save within-chain diagnostic". This file is always in text format. · DREAM_Out_FxSN.txt (*.bin) - calibration data of measurements or ABC summary metrics data. Optional - see "Save model simulations". · DREAM_Out_HistsMargDensitiesN.txt (*.bin) - Data for histograms of marginal densities for each chain. · DREAM_Out_HistsSummaryStatisticsN.txt (*.bin) - Data for histograms of summary statistics for each chain. Files are exported only for likelihood 21, 22 and 23. · DREAM_Out_ChainN.txt (*.bin) - Markov chains. Optional - see "Save Markov chains". · DREAM_Out_ChainCovergenceN.txt (*.bin) - Convergence of individual chains to target distribution. · DREAM_Out_ChainSizes.txt (*.bin) - Sizes of Markov chains. Optional - see "Save Markov chains". · DREAM_Out_LogObs.txt - Calculation observer log file with information about the calculation progress. This file is always in text format. · DREAM_Out_LogLikelihoodData.txt - Statistic likelihood data · DREAM_Out_LogPriorData.txt - Statistic prior data. Available only if prior is used · DREAM_Out_Map.txt (*.bin) - The maximum aposteriori parameter values. · DREAM_Out_MargDensitiesN.txt (*.bin) - Marginal densities of each parameter. · DREAM_Out_Mean.txt (*.bin) - The mean posterior value of each parameter. · DREAM_Out_Median.txt (*.bin) - The median posterior values of each parameter. · DREAM_Out_MRstat.txt (*.bin) - Multivariate convergence of sampled chains. · DREAM_Out_ParSet.txt (*.bin) - Single matrix with values sampled by chains. Optional - see "Save ParSet". · DREAM_Out_Rstat.txt (*.bin) - Univariate convergence of sampled chains. · DREAM_Out_SN.txt (*.bin) - Summary metrics in each generation. Optional see "Save summary statistics". · DREAM_Out_Std.txt (*.bin) - The posterior standard deviation of the parameters. · DREAM_Out_SummaryMeasurementsData.txt (*.bin) - Input measurement data Temp - temporary directory. Contains a working copy of the Simulations directory while the project is open and its content is deleted when closing the project. Case directories may contain additional subdirectores named 1,2,3,...,N that are created during parallel calculation and their names 1,...,N correspond to the number of calculation threads (cores). 5.2 DREAM applications DREAM application is a program consisting of three components: · · · Main program (GUI) - allows to enter input data, run the calculation (DREAM Solver) and view results DREAM Solver - the calculation module available as COM server or C++ library, calls the DREAM Plugin to evaluate proposals DREAM Plugin - user-programmable DLL implementing the evaluation of proposals and optionally defining some input data 92 DREAM Suite 1 The main program of DREAM Suite represents a kind of DREAM application, which has been designed to work with many different examples and demonstrate capabilities of DREAM Suite. However, DREAM Solver can also be used to develop independent DREAM applications with own GUI and custom data preprocessing and post-processing. A very simple example of such application is the DREAM console application, available including source code and showing how to call DREAM Solver and other components from your own program. Figure 5.2. DREAM Application schema. 5.2.1 DREAM console application DREAM Suite installation includes a simple console application, which calls DREAM Solver and plugin modules of demo examples. It can be used to recalculate all demo examples (under assumption that the user has a valid license for DREAM Solver). The C++ source code of this application is available in DREAM SDK\DreamAppTest directory (the full path is usually C:\Users\Public\Documents\PC-Progress\DREAM Suite 1.x\SDK\DreamAppTest) and demonstrates how to initialize DREAM Solver (COM Server), attach a plugin module and calculation observer and run the calculation. It simply shows how to use DREAM Solver outside DREAM Suite main program (GUI). 93 DREAM Suite 1 Figure 5.2.1. DREAM Console Application schema. Running DREAM Console Application Compiled executable DreamTest.exe is available in DREAM Suite program files directory (the full path is usually C:\Program Files (x86)\PC-Progress\DREAM Suite 1.x\Bin) and its shortcut is available in All Programs (All apps) – PC-Progress – DREAM Test Console. Note that when working with DREAM Console application, most of input data are defined by the plugin module - unlike the DREAM Suite main program, which allows entering data via GUI. Opening DREAM Console Application in Visual Studio To open DREAM Console Application in Visual Studio, open solution DreamAppTest.sln located in DREAM SDK directory (the full path is usually C:\Users\Public\Documents\PC-Progress\DREAM Suite 1.x\SDK \DreamAppTest.sln). Note that all DREAM Suite projects have been developed in Visual Studio 2013. If you are using Visual Studio 2015 (or a newer version), you will need to upgrade the projects, which can be done automatically when opening the solution in Visual Studio (see figure 6.1.2) - just click the OK button. More information about using the DREAM Solver can be found in DREAM Solver documentation. 94 DREAM Suite 1 Figure 6.1.2. Convert DREAM Console Application solution (developed in VS 2013) to VS 2015 format 5.3 DREAM plugins Each DREAM project requires a special plugin module, implementing the evaluation of proposals and other project-specific functions. This plugin can be written in C/C++ or other languages and is linked with DREAM Suite as a dynamic library. To simplify the development of this module, DREAM Suite can generate a skeleton of the plugin module, which should be then modified according to needs of the particular project. Main functions of the DREAM Plugin module and the order in which they are called · · · Function defining DREAM input parameters (required, called always) § InitPlugin - Plugin initialization (can connect an external server, etc.) § GetInputParams - Defines initial/default values of DREAM parameters § InitData - Prepares input data needed for the calculation. Called only once. Functions defining other input data (optional, called according to project settings) § GetMinMaxData § GetNormalData § GetPriorData § GetPriorDataCustom § GetMeasurementData § GetBayesData Function evaluating each proposal during DREAM calculation (required, called always) § EvaluateProposal Additional information can be found in the documentation to programming interfaces IDreamDataSource and IDreamEvaluator. Plugin types and implementation in other languages We believe that C/C++ is the ideal programming language for the development of DREAM Suite plugin modules. However, DREAM Suite plugins can be also written in other languages, such as Fortran, MATLAB and other. To demonstrate this feature, we have created a special interface that allows users to implement DREAM plugins using MATLAB *.m files. MATLAB plugin examples can be found in library D2 of demo examples. Other interfaces (e.g. for Python, etc.) can be developed later according to demands of DREAM Suite users. · · C/C++ plugin modules MATLAB plugin modules 95 DREAM Suite 1 5.3.1 C/C++ Plugin We believe that C/C++ is the best language for the development of DREAM Suite plugin modules because of the following reasons: · · · · · High performance (C++ is about as fast as C or Fortran) Great level of abstraction and organization of code Large number of libraries of all kinds, usually free. In our examples we use STL, BOOST and EIGEN. Professional development tools (Microsoft Visual Studio, including free editions) Accessibility of all latest technologies for scientific computing To simplify the development of this module, DREAM Suite can generate a skeleton of the plugin module and create a new Visual Studio project, which can be immediately recompiled and is automatically linked with DREAM Suite (see button "Generate plugin project" on the Model Definition page). The user should then implement project-specific functions into the existing C++ source code. The code contains many useful comments and one can also learn form the source code of many examples distributed with DREAM Suite. Remark 1: Note that all DREAM Suite projects have been developed in Visual Studio 2013. If you are using Visual Studio 2015 (or a newer version), you will need to upgrade the projects, which can be done automatically when opening the project/solution in Visual Studio (see figure 6.1.2). Remark 2: Although DREAM Solver is a COM server, writing custom plugin modules does not require any knowledge of COM technology. Developing the plugin module The automatically generated Visual Studio solution contains two projects: AppTest and the plugin project (see "MyPlugin" in Figure 5.3.1. "Plugin Test Application"). The AppTest project is a simple console application, which enables to develop and test the Plugin module independently of DREAM Suite. You can compile both projects and run AppTest, which connects to DREAM COM Server and subsequently calls functions from your evaluator (MyPlugin.dll). You can also place breakpoints to these functions if you wish to debug your code. However, please note that your plugin should define all input data needed for the given problem in DREAM Solver. AppTest does not offer any other way to define the input data and transfer them to the solver (unlike DREAM Suite, in which input data can be entered via GUI). This input data should be specified in functions CDreamEvaluator::GetEvaluationParams (always required) and GetMinMaxData, GetNormalData, GetPriorData, CalcCustomPriorData, GetMeasurementData and GetBayesCompData (optional). The next key function CDreamEvaluator::Evaluate implements the evaluation of samples similarly as can be seen in demo examples. 96 DREAM Suite 1 Figure 5.3.1. Plugin Test Application. 5.3.2 MATLAB Plugin DREAM Suite plugin modules can also be implemented in MATLAB script files (*.m). To prepare such a plugin, take the following steps: 1. On the Model Definition page, select plugin type MATLAB COM or MATLAB Engine. MATLAB COM interface is more general in terms of combining 32-bit/64-bit program versions, i.e. you can then use 64bit MATLAB with 32-bit DREAM Suite, which is not possible with the MATLAB Engine interface (64-bit MATLAB requires 64-bit DREAM Suite). On the other hand, the MATLAB Engine interface is a bit faster than MATLAB COM (but still significantly slower than C/C++ plugins). 97 DREAM Suite 1 Figure 5.3.2. MATLAB Plugin Type 2. Create two *.m files named according to the project name in the Src_Matlab subdirectory. The first file (e.g. Example01.m) should contain definitions of DREAM parameters and the second file (Example01_Evaluate.m) contains the function for evaluations of proposals. Names of DREAM parameters are identical with names described in the DREAM Suite technical manual or in the manual for MATLAB Implementation of DREAM (J.Vrugt). 98 DREAM Suite 1 Figure 5.3.3. MATLAB files Figure 5.3.4. MATLAB file with DREAM Parameters 99 DREAM Suite 1 Figure 5.3.5. MATLAB file with the evaluation function Remarks on using the MATLAB interface · · · · · · When using the MATLAB interface in DREAM Suite, you need to have MATLAB installed and activated on your computer. Demo examples using the MATLAB interface can be found in library D2 in the Library Manager. All demo examples in library D2 have been tested in MATLAB R2016a, 64-bit version. We cannot guarantee that the interface will work correctly with older version of MATLAB. The parallel computing is disabled in the MATLAB interface. The MATLAB interface (both COM and Engine) is in general significantly slower that the standard C/C+ + plugins. The source code of both MATLAB interfaces is available in DREAM SDK (subdirectory Templates/ PluginMatlabCom and Templates/PluginMatlabEng) 5.4 DREAM Solver DREAM Solver is the main calculation module implementing mathematical methods described in the Technical Manual. It actually is a C++ library wrapped by C/COM interfaces, which enable using this library in a binary form. Main functions of DREAM Server · · · · LoadPlugin - loads the plugin DLL InitEvaluatorExt - initializes the evaluator and sets input data from an external source (e.g. GUI) InitEvaluatorDef - initializes the evaluator and sets input data from the evaluator StartCalculation - starts DREAM calculation Additional information about DREAM Solver functions and interfaces can be found in IDreamSolver and 100 DREAM Suite 1 programming documentation. Using DREAM Server (an example) The use of DREAM Solver is demonstrated by the C++ code below, which is part of a simple console application (DREAM Client) generated by DREAM Suite when creating a plugin module for a new project. Another example of the DREAM Console Application. Please note that DREAM COM server must be properly registered, which can be done during the installation process (see Figure 2.3.2. "Installation Features"). The use of DREAM COM server also requires a valid license and authorization. //------------------------------------------------------------------------------------------------int _tmain(int argc, _TCHAR* argv[]) //------------------------------------------------------------------------------------------------{ // Return value HRESULT hRes = S_OK; // Initialize COM subsystem hRes = CoInitialize(NULL); if(SUCCEEDED(hRes)) { // Display info wprintf(L"##################################################\n"); wprintf(L" DREAM Suite 1.0 - Plugin Test Application\n"); wprintf(L"##################################################\n"); wprintf(L"This application is intended for testing of DREAM plugin modules.\n"); int iRunTest = GetUserChoice(L"Do you want to run the test? (Yes/No = 1/0) : ", 0, 1); if(iRunTest == 0) return 0; // We will assume that the current directory is "Project\Plugin\Bin" _bstr_t bstrPluginBin = boost::filesystem::current_path().c_str(); // Path to the project directory _bstr_t bstrExampleDir = bstrPluginBin; bstrExampleDir += L"\\..\\.."; // Path to Evaluator DLL _bstr_t bstrPluginDllName = L"$DREAM(ProjectName)"; _bstr_t bstrEvaluatorPath = bstrPluginBin; bstrEvaluatorPath += L"\\"; bstrEvaluatorPath += bstrPluginDllName; bstrEvaluatorPath += L".dll"; // Path to directory with Example data _bstr_t bstrModelData = bstrExampleDir; bstrModelData += L"\\Model\\Data"; // Path to directory with Example executables _bstr_t bstrModelBin = bstrExampleDir; bstrModelBin += L"\\Model\\Bin"; // Path to working directory _bstr_t bstrWorkingDir = bstrExampleDir; bstrWorkingDir += L"\\Temp\\Simulations\\Case1"; // Delete old working directory (to clear old files) DrxDeleteDirectory(std::wstring(bstrWorkingDir)); // Create new working directory DrxCreateDirectory(std::wstring(bstrWorkingDir)); // Calc observer for communication, logging... CCalcObserver calcObserver(bstrWorkingDir); ///////////////////////////////////////////////////////////////////////////////////////////////// // Run DREAM Solver ///////////////////////////////////////////////////////////////////////////////////////////////// bool bDisplayInfoAboutCalculationResults = false; bool bLogInfoAvailable = false; try { wprintf(L"Connecting DREAM Server...\n"); 101 DREAM Suite 1 // Try to create DreamSolver in COM way IDreamSolverPtr pSolver(__uuidof(IDreamSolver)); // Check if the creation of solver succeeded if(pSolver != nullptr) { // Setup calculation observer IDreamObserverPtr pIDreamCalcObserver = nullptr; hRes = calcObserver.QueryInterface(IID_IDreamObserver, (void**)&pIDreamCalcObserver); if(SUCCEEDED(hRes)) { // Establish communication with solver pSolver->AttachObserver(pIDreamCalcObserver); bLogInfoAvailable = true; } // Set directories pSolver->SetPath(ePathProjectDir, bstrExampleDir); pSolver->SetPath(ePathModelData, bstrModelData); pSolver->SetPath(ePathModelBin, bstrModelBin); pSolver->SetPath(ePathPluginBin, bstrPluginBin); pSolver->SetPath(ePathWorkingDir, bstrWorkingDir); // Load plugin module hRes = pSolver->LoadPlugin(bstrEvaluatorPath); if(SUCCEEDED(hRes)) { // Plugin info CDreamPluginInfo pluginInfo; pluginInfo.m_PluginType = ePluginType::ePlugin_DLL; pluginInfo.m_strPluginName = bstrPluginDllName.copy(); pluginInfo.m_strModelDataDir = bstrModelData.copy(); // DREAM calculation parameters CDreamCalcParams calcParamInfo; // Convergence diagnostics? calcParamInfo.m_SaveWithinChainDiagnostics = GetUserChoice(L"Do you want convergence diagnostics? (Yes/No = 1/0) : ", 0, 1); // Export Markov chains? calcParamInfo.m_SaveMarkovChains = GetUserChoice(L"Do you want to export Markov chains? No = 1/0) : ", 0, 1); // Number of cores calcParamInfo.m_NumberOfCPUs = GetUserChoice(L"Number of cores <1,20>, N > 1 = parallel calculation : ", 1, 20); calcParamInfo.m_RunParallel = calcParamInfo.m_NumberOfCPUs > 1 ? 1 : 0; // Initialize the evaluator and all input data by values obtained from the evaluator hRes = pSolver->InitEvaluatorDef(&pluginInfo, &calcParamInfo); if(SUCCEEDED(hRes)) { // Get pointer to evaluator IDreamEvaluatorPtr pEvaluator = nullptr; hRes = pSolver->GetEvaluator(&pEvaluator); if(SUCCEEDED(hRes)) { // Set signal handler (Ctrl+C) pTheOnlySolverInThisProcess = pSolver; SetConsoleCtrlHandler((PHANDLER_ROUTINE)SignalHandler, TRUE); // Prepare the console to display calculation progress (%) wprintf(L"Starting calculation...\n"); wprintf(L"(press Ctrl+C to interrupt the calculation)\n"); // Perform calculations hRes = pSolver->StartCalculation(); if(SUCCEEDED(hRes)) { wprintf(L"Calculation succeeded.\n"); } else { // Check errors _bstr_t message; CDreamErrorInfo lastErrorInfo; 102 (Yes/ DREAM Suite 1 if(pSolver->GetLastError(&lastErrorInfo) != S_OK && lastErrorInfo.GetErrType() == eTypeError) message = L"Calculation failed with error:\n" + _bstr_t(lastErrorInfo.GetErrDescription()) + L"\n"; else message = L"Calculation failed.\n"; wprintf(message); } bDisplayInfoAboutCalculationResults = true; } // Failed to get pointer to evaluator else { wprintf(L"Failed to get pointer to evaluator.\n"); } } // Failed to initialize evaluator else { wprintf(L"Failed to initialize evaluator.\n"); } } // Failed to load plugin module else { wprintf(L"Failed to load plugin module.\n"); } } // Failed to create Dream solver else { wprintf(L"Failed to create Dream solver.\n"); } } catch(_com_error& e) { // Dream solver creation failed std::wstring message = L"COM error: "; message += e.ErrorMessage(); message += L"\n"; PrintMessageUTF8(message); } // Clean-up if(pTheOnlySolverInThisProcess != nullptr) { // Release solver interface - it must be done here, because it fails after CoUnitialize() pTheOnlySolverInThisProcess = nullptr; } // Output information if(bDisplayInfoAboutCalculationResults) { // Output files wprintf(L"Output and log files are available in directory:\n" + bstrWorkingDir + L"\n"); } // Error info if(bLogInfoAvailable) { // Number of errors and warnings returned by the solver int nErrors = calcObserver.GetNoOfErrors(); int nWarnings = calcObserver.GetNoOfWarnings(); wprintf(L"Number of errors: %d, Number of warnings: %d\n", nErrors, nWarnings); // Print logged messages (errors, warnings, messages and calculation time)? int iPrintLogInfo = GetUserChoice(L"Do you want to display log-file content? (Yes/No = 1/0) : ", 0, 1); if(iPrintLogInfo == 1) 103 DREAM Suite 1 { wprintf(L"Log file contents:\n"); calcObserver.PrintMessages(); } } // Clean-up COM services CoUninitialize(); } // Wait for ENTER std::wcin.ignore(1024, '\n'); std::cout << "\nPress Enter to continue..."; std::wcin.get(); // Return result return hRes; } 5.4.1 Calculation observer Calculation Observer is an optional object, which can be connected to the DREAM Solver to receive a variety of information during the calculation, such as information needed for updating the progress bar, error messages, convergence information, signal to interrupt the calculation by user, error messages, etc. More details can be found in IDreamObserver documentation. An example of DREAM calculation observer is available in the DREAM Console application. 6 Programming references 6.1 DREAM SDK DREAM Suite Software Development Kit is a package of C++ libraries and source files needed for the development of DREAM plugin modules or DREAM applications. This SDK is installed to the “DREAM Data” directory selected during installation of DREAM Suite. The default location is C:\Users\Public\Documents \PC-Progress\DREAM Suite 1.x\SDK_102 ("102" corresponds to version 1.02) DREAM SDK components · · · · · DreamAppTest – contains the project and source code of the DREAM console application. VS solution DreamAppTest.sln is located in the DREAM SDK root directory. DreamShared – contains files with common C++ functions used by multiple Examples. It also includes DREAM Solver type-library DreamServer.tlb Examples - contains directories with all demo examples. Each example contains source code of its plugin module in “Plugin\Src” subdirectory Templates – contains templates for generating the source code of DREAM plugin modules Tools – contains third-party libraries BOOST and EIGEN Using DREAM SDK Although DREAM Solver is a COM server and its use is not limited to C++ language, all demo examples have been developed in C++ using Microsoft Visual Studio. For a hassle-free development of DREAM plugin modules, we recommend using VS 2013 or 2015 (e.g. the Community Edition, which is free for individual programmers). Using other compilers may require additional work and modification of prepared examples and templates. When compiling a DREAM plugin module, Visual Studio needs to know the path to the DREAM SDK directory to locate libraries and files described above. This path is defined by system environment variable DREAM1_SDK, which is created by the DREAM Suite installation program or can be created / modified manually (see Figure 6.1.1. "DREAM1_SDK environment variable"). Please note that a change of this 104 DREAM Suite 1 environment variable always requires restarting Visual Studio and may also require restarting Windows to reflect this change in command prompt and console applications. You can change the path to DREAM SDK directory in DREAM Program Options dialog or directly in Windows system settings - see figure 6.1.1. Figure 6.1.1. DREAM1_SDK environment variable. 6.2 Plugin module template The plugin template is located in directory DREAM1_SDK\Templates\PluginGeneratorSrc and contains source code used to generate the plugin project. 6.2.1 DreamEvaluator.h /////////////////////////////////////////////////////////////////////////////////////////////////// // DreamEvaluator.h /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma once /////////////////////////////////////////////////////////////////////////////////////////////////// // CDreamEvaluator class CDreamEvaluator : public IDreamEvaluator { public: /// <summary>Constructor</summary> CDreamEvaluator(); /// <summary>Destructor</summary> ~CDreamEvaluator(); /// <summary>Plugin initialization. The first function called before using the evaluator</summary> virtual HRESULT STDMETHODCALLTYPE InitPlugin(IDreamPluginInfo* pIPluginInfo) override; /// <summary>Prepare input data and all other local data needed for the calculation.</summary> virtual HRESULT STDMETHODCALLTYPE InitData(IDreamPluginInfo* pIPluginInfo, IDreamInputParViewer* pIDreamInputParams 105 DREAM Suite 1 ) override; /// <summary>Prepare files in working directory for parallel calculation (one thread)</summary> virtual HRESULT STDMETHODCALLTYPE PrepareWorkDir(BSTR strSourceDir, BSTR strDestinationDir) override; /// <summary>Calculate the likelihood of each proposal during DREAM calculation</summary> virtual HRESULT STDMETHODCALLTYPE EvaluateProposal(IDreamInputParViewer* pInputPar, int iSim, IDreamMatrix* x, IDreamMatrix* res, BSTR strWorkingDir, BSTR strModelDataDir, BSTR strModelBinDir) override; /// <summary>Called after finishing the calculation</summary> virtual HRESULT STDMETHODCALLTYPE OnCalculationFinished() override; /// <summary>Return description of the last error</summary> virtual HRESULT STDMETHODCALLTYPE GetLastError(BSTR* strErrorText) override; /// <summary>Return default DREAM parameters</summary> virtual HRESULT STDMETHODCALLTYPE GetInputParams(IDreamInputParams* pIDreamInputParams) override; /// <summary>Return MinMax data</summary> virtual HRESULT STDMETHODCALLTYPE GetMinMaxData(IDreamInputParViewer* pInputPar, IDreamDataMinMax* pIMinMaxData) override; /// <summary>Return Normal data</summary> virtual HRESULT STDMETHODCALLTYPE GetNormalData(IDreamInputParViewer* pInputPar, IDreamDataNormal* pINormalData) override; /// <summary>Return Prior data</summary> virtual HRESULT STDMETHODCALLTYPE GetPriorData(IDreamInputParViewer* pInputPar, IDreamDataPrior* pIPriorData) override; /// <summary>Return Custom Prior data</summary> virtual HRESULT STDMETHODCALLTYPE GetPriorDataCustom(IDreamInputParViewer* pInputPar, IDreamMatrix* x, IDreamMatrix* PR, ePriorDistrib callType) override; /// <summary>Return Measurement data</summary> virtual HRESULT STDMETHODCALLTYPE GetMeasurementData(IDreamInputParViewer* pInputPar, IDreamDataMeasurement* pIMeasureData, BSTR strModelDataDir) override; /// <summary>Return Approximate Bayesian Computation data</summary> virtual HRESULT STDMETHODCALLTYPE GetBayesData(IDreamInputParViewer* pInputPar, IDreamDataABC* pIBayesCompData, BSTR strModelDataDir) override; /// <summary>COM implementation</summary> virtual HRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid, void** ppv) override; virtual ULONG STDMETHODCALLTYPE AddRef() override; virtual ULONG STDMETHODCALLTYPE Release() override; private: /// <summary>Reference counter</summary> long m_cRef; }; /////////////////////////////////////////////////////////////////////////////////////////////////// 6.2.2 DreamEvaluator.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// // DreamEvaluator.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // CDreamEvaluator //------------------------------------------------------------------------------------------------CDreamEvaluator::CDreamEvaluator() : m_cRef(0) //------------------------------------------------------------------------------------------------/* Constructor. To initialize member variables, use rather CDreamEvaluator::InitData */ 106 DREAM Suite 1 /////////////////////////////////////////////////////////////////////////////////////////////////// { } //------------------------------------------------------------------------------------------------CDreamEvaluator::~CDreamEvaluator() //------------------------------------------------------------------------------------------------/* Destructor */ /////////////////////////////////////////////////////////////////////////////////////////////////// { } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::InitPlugin //------------------------------------------------------------------------------------------------( IDreamPluginInfo* pIPluginInfo ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: This function is called immediately after creation of CDreamEvaluator and before using the evaluator (i.e. calling its other functions). It is intended for initialization of the dynamic library and connecting possible external servers. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetInputParams //------------------------------------------------------------------------------------------------( IDreamInputParams* pIDreamInputParams // Pointer to DREAM input data to be defined ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define default DREAM parameters for this particular project. This function is called by the main program to initialize data of each newly created simulation case. This data can be later modified in the GUI (except parameters locked by flag DreamSolver::disable_edit) or can be overwritten while reading case data from a file. In the AppTest console application, there is no GUI and this functions actually defines all input parameters that are subsequently used by DREAM Solver. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIDreamInputParams pointer if(pIDreamInputParams == nullptr) { return E_INVALIDARG; } // Dimensionality target distribution d pIDreamInputParams->SetProblemDimension(2, DreamSolver::disable_edit); 107 DREAM Suite 1 // Number of Markov chains N pIDreamInputParams->SetNumberOfMarkovChains(10, DreamSolver::enable_edit); // Number of generations T pIDreamInputParams->SetNumberOfGenerations(1000, DreamSolver::enable_edit); // Choice of likelihood function pIDreamInputParams->SetLikelihoodChoice(eLikelihood::LIK_101, DreamSolver::enable_edit); // Number of crossover values nCR pIDreamInputParams->SetNumberOfCrossoverValues(3, DreamSolver::enable_edit); // Number chain pairs for proposal delta pIDreamInputParams->SetNumberChainPairs(3, DreamSolver::enable_edit); // Random error for ergodicity lambda pIDreamInputParams->SetRandomErrorForErgodicity(0.05, DreamSolver::enable_edit); // Randomization zeta pIDreamInputParams->SetRandomization(1.0e-12, DreamSolver::enable_edit); // Test to detect outlier chains pIDreamInputParams->SetOutlierTest(eOutlierTest::eOutlierIqr, DreamSolver::enable_edit); // Probability of jump rate of 1 pJumpRate_one pIDreamInputParams->SetProbabilityOfJumprate(0.2, DreamSolver::enable_edit); // Adapt selection prob. crossover pCR pIDreamInputParams->SetAdaptSelection(1, DreamSolver::enable_edit); // Each Tth sample is stored thinning pIDreamInputParams->SetThinnigSampleToStore(1, DreamSolver::enable_edit); // GLUE likelihood parameter pIDreamInputParams->SetGlueLikelihood(10, DreamSolver::enable_edit); // Scaling factor of built-in jump rate beta0 pIDreamInputParams->SetScalingFactorOfJumpRate(1.0, DreamSolver::enable_edit); // Bayesian Model Averaging (BMA) with hydrologic data. Number of different models pIDreamInputParams->SetNumberOfDifferentModelsBMA(0, DreamSolver::enable_edit); // Initial sampling distribution type pIDreamInputParams->SetInitialDistribution(eInitDistrib::eInitPrior, DreamSolver::enable_edit); // Boundary handling type pIDreamInputParams->SetBoundHandling(eBoundHandling::eBoundUnbounded, DreamSolver::enable_edit); // Prior distribution type pIDreamInputParams->SetPriorDistributionType(ePriorType::eUnivariate, DreamSolver::enable_edit); // Use prior distribution even for m_InitialDistribution != eInitPrior? Values: 1=true, 0=false pIDreamInputParams->SetUsePriorDistribution(0, DreamSolver::enable_edit); // Can model run in parallel? // Values: eParallelModeYes, eParallelModeNotRecommended, eParallelModeNotPossible pIDreamInputParams->SetParallelMode(eParallelModeYes, DreamSolver::enable_edit); // Model vectorization? For eVectorization::eVectYes, function CDreamEvaluator::EvaluateProposal // must evaluate proposals for all Markov chains in one step/call. Parallelization is then // automatically switched off. pIDreamInputParams->SetVectorization(eVectorization::eVectNone, DreamSolver::disable_edit); // ToDo: // 1. Modify the above parameters according to this particular project // 2. Remove the following MessageBox and return S_OK std::wstring sMessage; sMessage = L"Incorrect DREAM input data!\n"; sMessage += L"Please modify function CDreamEvaluator::GetInputParams()\n"; sMessage += L"in DREAM plugin module. Set correct parameters and implement\n"; sMessage += L"all other plugin functions needed for the project."; MessageBox(NULL, sMessage.c_str(), L"DREAM Plugin Module", MB_OK | MB_ICONSTOP); return E_FAIL; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::InitData //------------------------------------------------------------------------------------------------( IDreamPluginInfo* pIPluginInfo // Plugin information , IDreamInputParViewer* pIDreamInputParams // Current DREAM input parameters ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: This function is called to prepare: 108 DREAM Suite 1 A/ DREAM input data before accessing them via the IDreamDataSource interface and B/ all other local data required by evaluator for the calculation. It can be also used to read needed data from a file in directory pIPluginInfo->m_strModelDataDir (directory ...Drm_ExampleXX\Model\Data). Remark 1: This function prepares DREAM input data in the evaluator according to current DREAM parameters defined by pIPluginInfo interface. Note that some parameters can be different from default parameters defined in function CEvaluatorExample::GetInputParams(). Remark 2: This function should be called before using functions CEvaluatorExample::GetMinMaxData, ::GetNormalData, ::GetPriorData, ::GetPriorDataCustom, ::GetMeasurementData and ::GetBayesData. However, function CEvaluatorExample::GetInputParams() can be called independently. Remark 3: When using this evaluator for parallel calculations, member variables can be shared by multiple threads and thus their values should not be changed during the calculation or you should make the code thread-safe using standard tools (e.g. critical sections, etc.). Another option is to disable running in parallel mode, which can be done in function CDreamEvaluator::GetInputParams - pIDreamInputParams->m_ParallelMode = eParallelModeNotPossible; RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetMeasurementData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataMeasurement* pIMeasureData // Interface to measurement data , BSTR strModelDataDir // Path to directory with measurement data ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to load measurement data from files located in strModelDataDir and fill the data structure pIMeasureData. Measurement data are required by some types of likelihood functions. Types of measurement data: 1. Calibration data (Y) 2. Measurement error data (Sigma) RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) EXAMPLE OF IMPLEMENTATION: // Specific file with measurement data (each line one number) std::wstring file(strModelDataDir); file += L"\\abundances.txt"; // Load data to Y vector<double> Y; if(!CDreamMath<>::ReadData(file, Y)) { return E_FAIL; } // Data are set to solver by function with length and data itself: pIMeasureData->AddCalibrationData((int)Y.size(), &Y(0)); 109 DREAM Suite 1 return S_OK; */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIMeasureData pointer if(pIMeasureData == nullptr) { return E_INVALIDARG; } // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetMinMaxData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataMinMax* pIMinMaxData // Interface to Min/Max data ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define min/max values for initial LATIN and UNIFORM sampling distribution or to define min/max additional data (Measurement Error, Nuisance variables) for likelihood functions LIK_211, LIK_212, LIK_213, LIK_214 and LIK_217. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) EXAMPLE OF IMPLEMENTATION: // Normal use for Latin sampling // Fill min, max data pIMinMaxData->AddItem(0.00, 1.0); // alpha or pIMinMaxData->AddExtendedItem(0.00, 10.0, 0, 1); // delta // Special use for LIK_211, LIK_212 and LIK_213 to add measurement error variables // Fill min, max, value , is variable selected (1) or not (0) pIMinMaxData->AddMeasurementErrorItem(0.0, 1.0, 1.0, 0); // Special use for LIK_213, LIK_214 and LIK_217 to add Nuisance variables // Fill min, max, value of nuisance variable, is variable selected (1) or not (0) pIMinMaxData->AddLikelihoodItem(0.0, 1.0, 1.0, 0); // ONLY FOR LIK_217 // Additional x-range values for PCHIP (Piecewise Cubic Hermite Interpolating Polynomial) // Fill x-range with non-decreasing data pIMinMaxData->SetLVInterpolationValues(0, 1, 2, 3); return S_OK */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIMinMaxData pointer if(pIMinMaxData == nullptr) { return E_INVALIDARG; } // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetNormalData 110 DREAM Suite 1 //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataNormal* pINormalData // Interface to normal distribution data ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define mean vector and Covariance matrix data for initial NORMAL sampling distribution. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) EXAMPLE OF IMPLEMENTATION: // Fill mean vector data for(size_t iIndex = 0; iIndex < 10; iIndex++) { pINormalData->AddItem(0); } // Covariance matrix diagonal value pINormalData->SetCovarianceDiagonalValue(5.0); return S_OK */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pINormalData pointer if(pINormalData == nullptr) { return E_INVALIDARG; } // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetPriorData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataPrior* pIPriorData // Interface to prior distribution data ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define data for INITIAL PRIOR and PRIOR sampling distribution. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) EXAMPLE OF IMPLEMENTATION: // Fill prior univariate data pIPriorData->AddUnivariateItem(0.067, 0.006, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(0.445, 0.009, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(-2.310, 0.060, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(0.223, 0.011, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(-1.160, 0.270, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(0.390, 1.470, eDistributionUnivariate::eUnivariate_Normal); pIPriorData->AddUnivariateItem(-250.0, -50.0, eDistributionUnivariate::eUnivariate_Uniform); // OR 111 DREAM Suite 1 // Fill prior multivariate normal data vector<double> mean(m_dimension, -2); matrix<double> cov = identity_matrix<double>(m_dimension); CDreamVector cmean(mean); CDreamMatrix ccov(cov); pIPriorData->SetMultivariateNormalItem(&cmean, &ccov); return S_OK */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetPriorDataCustom //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamMatrix* x // Input matrix , IDreamMatrix* PR // Output matrix , ePriorDistrib callType // Type of call of this function ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define CUSTOM distribution type of prior distribution instead of GetPriorData() function. This function can be called in two different situations specified by the callType parameter: A) during initialization of dream solver (callType = ePriorInitialize) B) during DREAM calculation (callType = ePriorCalculate) The initial state (callType = ePriorInitialize) is usually defined by a function generating random numbers (e.g. PR = NormRnd(mu, sigma)), while the second type of call (callType = ePriorCalculate) typically uses a function dependent on x-matrix (e.g. PR = NormPdf(x, mu, sigma)). RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) EXAMPLE OF IMPLEMENTATION (Example07): // Temporary matrices used for calculations matrix<double> tmpx(x->_rowCount, x->_colCount); // Copy data for(int iRow = 0; iRow < x->_rowCount; iRow++) { for(int iCol = 0; iCol < x->_colCount; iCol++) { tmpx(iRow, iCol) = x->_data[iRow * x->_colCount + iCol]; } } matrix<double> tmpPR(PR->_rowCount, PR->_colCount); size_t d = tmpPR.size2(); size_t N = tmpPR.size1(); vector<double> mu(d); mu(0) = 0.067; mu(1) = 0.445; mu(2) = -2.310; mu(3) = 0.223; mu(4) = -1.160; mu(5) = 0.390; mu(6) = -250.0; vector<double> sigma(d); 112 DREAM Suite 1 sigma(0) sigma(1) sigma(2) sigma(3) sigma(4) sigma(5) sigma(6) = = = = = = = 0.006; 0.009; 0.060; 0.011; 0.270; 1.470; -50.0; enum ePriorFunction { NormPdf, UnifPdf, NormRnd, UnifRnd vector<ePriorFunction> funcType(d); funcType(0) = callType == ePriorDistrib::ePriorCalculate ePriorFunction::NormRnd; funcType(1) = callType == ePriorDistrib::ePriorCalculate ePriorFunction::NormRnd; funcType(2) = callType == ePriorDistrib::ePriorCalculate ePriorFunction::NormRnd; funcType(3) = callType == ePriorDistrib::ePriorCalculate ePriorFunction::NormRnd; funcType(4) = callType == ePriorDistrib::ePriorCalculate ePriorFunction::NormRnd; funcType(5) = callType == ePriorDistrib::ePriorCalculate ePriorFunction::NormRnd; funcType(6) = callType == ePriorDistrib::ePriorCalculate ePriorFunction::UnifRnd; double dRandValue = 0.0; for(size_t i = 0; i < d; i++) { for(size_t j = 0; j < N; j++) { // Compute prior density of proposal switch(funcType(i)) { case(ePriorFunction::NormPdf): { dRandValue = CDreamMath<double>::NormPdf(tmpx(j, tmpPR(j, i) = max(dRandValue, 1.e-299); break; } case(ePriorFunction::UnifPdf): { dRandValue = CDreamMath<double>::UnifPdf(tmpx(j, tmpPR(j, i) = max(dRandValue, 1.e-299); break; } case(ePriorFunction::NormRnd): { tmpPR(j, i) = CDreamMath<double>::NormRnd(mu(i), break; } case(ePriorFunction::UnifRnd): { tmpPR(j, i) = CDreamMath<double>::UnifRnd(mu(i), break; } default: { assert(false); } } } } }; ? ePriorFunction::NormPdf : ? ePriorFunction::NormPdf : ? ePriorFunction::NormPdf : ? ePriorFunction::NormPdf : ? ePriorFunction::NormPdf : ? ePriorFunction::NormPdf : ? ePriorFunction::UnifPdf : i), mu(i), sigma(i)); i), mu(i), sigma(i)); sigma(i)); sigma(i)); // Replace content of res by tmp values for(int iRow = 0; iRow < PR->_rowCount; iRow++) { for(int iCol = 0; iCol < PR->_colCount; iCol++) { PR->_data[iRow * PR->_colCount + iCol] = tmpPR(iRow, iCol); } } */ ////////////////////////////////////////////////////////////////////////////////////////////////// 113 DREAM Suite 1 { // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetBayesData //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , IDreamDataABC* pIBayesCompData // Interface to Approximate Bayesian Computation data , BSTR strModelDataDir // Directory with permanent data of the model ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to define summary metrics vector (S), corresponding ABC Epsilon vector and distance function which can be used for likelihood LIK_321 and LIK_322. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) EXAMPLE OF IMPLEMENTATION: // Set ABC distance function type pIBayesCompData->SetABCFunctionType(eDistanceFunction::eSqrt_1Over20_MultiplyBy_Sum_AminusBSquared); // Scalar/vector with summary metrics (S) and ABC Epsilon data vector<double> eps(m_d, 0.025); vector<double> rnd(m_d); Rand(rnd); vector<double> sumMetrics = m_min + element_prod(rnd, m_max - m_min); pIBayesCompData->AddComputationData((int)sumMetrics.size(), &sumMetrics[0], &eps(0)); */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Always check pIBayesCompData pointer if(pIBayesCompData == nullptr) { return E_INVALIDARG; } // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::PrepareWorkDir //------------------------------------------------------------------------------------------------( BSTR strSourceDir, // Path to the permanent "Model\Data" directory BSTR strDestinationDir // Path to the temporary directory designated for the current thread ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to prepare files in special directories needed for DREAM multi-core calculations. These folders may be required by some models working with data in external files. Each calculation thread should then have its files in a designated directory to prevent sharing violation problems. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will continue) E_FAIL - Operation failed (program will stop) */ 114 DREAM Suite 1 /////////////////////////////////////////////////////////////////////////////////////////////////// { // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::EvaluateProposal //------------------------------------------------------------------------------------------------( IDreamInputParViewer* pInputPar // Interface to DREAM input parameters , int iSim // input parameter (i-th simulation / Markov chain) , IDreamMatrix* x // input matrix (m_NumberOfMarkovChains x m_ProblemDimension) , IDreamMatrix* res // output matrix (Data_Dimension x m_NumberOfMarkovChains) , BSTR strWorkingDir // path to the current working directory (for current calculation thread) , BSTR strModelDataDir // path to the permanent directory with model data , BSTR strModelBinDir // path to the permanent directory with model executables ) /////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: The purpose of this function is to evaluate the current proposal (i.e. one single step of IDreamInputParams::GetNumberOfGenerations() steps) for iSim-th Markov chain. It computes the likelihood (or log-likelihood or the residual vector to be compared with the measurement - see the technical manual) for iSim-th row of input matrix "x" and returns the result in output matrix "res". Parameter iSim is from interval <0, IDreamInputParams::GetNumberOfMarkovChains() - 1>. If pInputPar->GetVectorization() == eVectorization::eVectYes, then iSim = 0 and all proposals (for all Markov chains) should be evaluated in one step, i.e. during one call of this function. Data_Dimension: ************************************************************************************************* ** ROW DIMENSION OF "RES" OUTPUT MATRIX: ** ** if(calibration_data_avaliable && bayes_diagnostic && summary_metrics_data) ** { ** data_dimension = calibration_data_count + summary_metrics_data_count ** } ** else if(calibration_data_avaliable && (!bayes_diagnostic || !summary_metrics_data)) ** { ** data_dimension = calibration_data_count ** } ** else if(summary_metrics_data_avaliable) ** { ** data_dimension = summary_metrics_data_count ** } ** else if(calibration_data_avaliable && summary_metrics_data_avaliable) ** { ** data_dimension = calibration_data_count > summary_metrics_data_count ? ** calibration_data_count : summary_metrics_data_count ** } ** else ** { ** data_dimension = 1 ** } ************************************************************************************************* RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented (program will stop - this function must be implemented) E_FAIL - Operation failed (program will stop) EXAMPLE OF IMPLEMENTATION: // Copy data of iSim-row of x-matrix to BOOST vector type vector<double> ix(x->_colCount); for(int iCol = 0; iCol < x->_colCount; iCol++) { ix(iCol) = x->_data[iSim * x->_colCount + iCol]; } 115 DREAM Suite 1 // Calculate log-likelihood of vector ix and store the result in vector tmpLog vector<double> tmpLog(res->_rowCount); for(int iRow = 0; iRow < res->_rowCount; iRow++) { tmpLog(iRow) = ... (F(ix)) } // Replace content of res by calculated values for(int iRow = 0; iRow < res->_rowCount; iRow++) { res->_data[iRow * res->_colCount + iSim] = tmpLog(iRow); } return S_OK; */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // TODO: Implement this function and return S_OK return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::OnCalculationFinished() //------------------------------------------------------------------------------------------------/////////////////////////////////////////////////////////////////////////////////////////////////// /* DESCRIPTION: This function is called after finishing the calculation to perform possible cleanup, etc. RETURN VALUE: S_OK - Operation successful S_FALSE - Function not implemented E_FAIL - Operation failed */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Not needed/implemented return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::GetLastError(BSTR* strErrorText) //------------------------------------------------------------------------------------------------{ // If there is an error, set the description and return S_OK. For example : // std::wstring m_MyLastError = ... // *strErrorText = SysAllocString(m_MyLastError.c_str()); // return (SysStringLen(*strErrorText)>0) ? S_OK : S_FALSE; // If there is no error, return S_FALSE return S_FALSE; } /////////////////////////////////////////////////////////////////////////////////////////////////// // Implementation of COM IUnknown interface /////////////////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CDreamEvaluator::QueryInterface(const IID& iid, void** ppv) //------------------------------------------------------------------------------------------------/* Implementation of standard COM interface. No changes needed. */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Check parameters if(ppv == nullptr) { // Invalid argument return E_INVALIDARG; } 116 DREAM Suite 1 // Always set pointer to nullptr *ppv = nullptr; if(InlineIsEqualGUID(iid, IID_IUnknown) || InlineIsEqualGUID(iid, IID_IDreamEvaluator)) { // Return pointer to IDreamSolver interface *ppv = static_cast<IDreamEvaluator*>(this); } else { // Unimplemented interface *ppv = nullptr; return E_NOINTERFACE; } // Increment reference count reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; } //------------------------------------------------------------------------------------------------ULONG STDMETHODCALLTYPE CDreamEvaluator::AddRef() //------------------------------------------------------------------------------------------------/* Implementation of standard COM interface. No changes needed. */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Increment reference count return ::InterlockedIncrement(&m_cRef); } //------------------------------------------------------------------------------------------------ULONG STDMETHODCALLTYPE CDreamEvaluator::Release() //------------------------------------------------------------------------------------------------/* Implementation of standard COM interface. No changes needed. */ /////////////////////////////////////////////////////////////////////////////////////////////////// { // Decrement reference count if(::InterlockedDecrement(&m_cRef) == 0) { // Object is not referenced, it is safe to delete it delete this; return 0; } // Return actual reference count return m_cRef; } 6.2.3 TestApp.h /////////////////////////////////////////////////////////////////////////////////////////////////// // DreamTestApp.h /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma once; /////////////////////////////////////////////////////////////////////////////////////////////////// // CCalcObserver class CCalcObserver : public IDreamObserver { public: /// <summary>Constructor</summary> CCalcObserver(); CCalcObserver(_bstr_t path); /// <summary>Destructor</summary> virtual ~CCalcObserver(); 117 DREAM Suite 1 /// <summary>Print logged messages</summary> void PrintMessages() const; /// <summary>Returs number of errors</summary> int GetNoOfErrors() const {return m_iNoOfErrors;} /// <summary>Returs number of warnings</summary> int GetNoOfWarnings() const {return m_iNoOfWarnings;} /// <summary>Adds new message to log</summary> virtual HRESULT STDMETHODCALLTYPE OnLogMessage(BSTR strLogMessage) override; /// <summary>Provides info about calculation error</summary> virtual HRESULT STDMETHODCALLTYPE OnError(IDreamErrorInfo* pErrorInfo) override; /// <summary>Set current evaluation step</summary> virtual HRESULT STDMETHODCALLTYPE SetCurrentStep(float fStep) override; /// <summary>Set convergence information</summary> virtual HRESULT STDMETHODCALLTYPE SetConvergenceInfo(float fInfo) override; /// <summary>Called after the calculation was terminated by user</summary> virtual HRESULT STDMETHODCALLTYPE OnCalculationTerminatedByUser() override; /// <summary>Called after finishing the calculation</summary> virtual HRESULT STDMETHODCALLTYPE OnCalculationFinished() override; /// <summary>Called before exporting output data</summary> virtual HRESULT STDMETHODCALLTYPE OnPreparingOutputData() override; /// <summary>Was calculation terminated by user? Yes (S_OK) or not (S_FALSE)</summary> virtual HRESULT STDMETHODCALLTYPE CalculationTerminatedByUser() override; /// <summary>IUnknown implementation</summary> virtual HRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid,void** ppv) override; virtual ULONG STDMETHODCALLTYPE AddRef() override; virtual ULONG STDMETHODCALLTYPE Release() override; private: /// <summary>Log file name</summary> _bstr_t m_LogFile; /// <summary>Current step</summary> int m_iCurrentStep; /// <summary>Convergence info</summary> float m_fConvergenceInfo; /// <summary>Reference counter</summary> long m_cRef; /// <summary>Number of errors</summary> int m_iNoOfErrors; /// <summary>Number of warnings</summary> int m_iNoOfWarnings; }; /////////////////////////////////////////////////////////////////////////////////////////////////// // CDreamErrorInfo class CDreamErrorInfo : public IDreamErrorInfo { public: /// <summary>Constructor</summary> CDreamErrorInfo() {} /// <summary>Destructor</summary> virtual ~CDreamErrorInfo() {} int GetErrID() const { return _errorID; } int GetErrType() const { return _type; } BSTR GetErrDescription() const { return _errorDesc; } }; /////////////////////////////////////////////////////////////////////////////////////////////////// // Struct for example info struct CExample { const wchar_t* m_strName; const wchar_t* m_strText; }; 118 DREAM Suite 1 /////////////////////////////////////////////////////////////////////////////////////////////////// // Help functions /// <summary>Get user's choice - a number from interval <0,N></summary> int GetUserChoice(std::wstring wsPromptLine, int iMinNo, int iMaxNo); /// <summary>Single handler - interrupts the calculation after Ctrl+C</summary> BOOL SignalHandler(DWORD fdwCtrlType); /// <summary>Prints text to console using UTF8</summary> void PrintMessageUTF8(const std::wstring sLine); /////////////////////////////////////////////////////////////////////////////////////////////////// 6.2.4 TestApp.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// // TestApp.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "testapp.h" #include #include #include #include <iostream> <limits> <signal.h> <boost/filesystem.hpp> // Dictionaries manipulation #include #include #include #include <codecvt> <fcntl.h> <io.h> <tchar.h> /////////////////////////////////////////////////////////////////////////////////////////////////// // Global pointer to DreamSolver (used for signal handling) static IDreamSolverPtr pTheOnlySolverInThisProcess = nullptr; //------------------------------------------------------------------------------------------------int _tmain(int argc, _TCHAR* argv[]) //------------------------------------------------------------------------------------------------{ // Return value HRESULT hRes = S_OK; // Initialize COM subsystem hRes = CoInitialize(NULL); if(SUCCEEDED(hRes)) { // Display info wprintf(L"##################################################\n"); wprintf(L" DREAM Suite 1.0 - Plugin Test Application\n"); wprintf(L"##################################################\n"); wprintf(L"This application is intended for testing of DREAM plugin modules.\n"); int iRunTest = GetUserChoice(L"Do you want to run the test? (Yes/No = 1/0) : ", 0, 1); if(iRunTest == 0) return 0; // We will assume that the current directory is "Project\Plugin\Bin" _bstr_t bstrPluginBin = boost::filesystem::current_path().c_str(); // Path to the project directory _bstr_t bstrExampleDir = bstrPluginBin; bstrExampleDir += L"\\..\\.."; // Path to Evaluator DLL _bstr_t bstrPluginDllName = L"$DREAM(ProjectName)"; _bstr_t bstrEvaluatorPath = bstrPluginBin; bstrEvaluatorPath += L"\\"; bstrEvaluatorPath += bstrPluginDllName; bstrEvaluatorPath += L".dll"; // Path to directory with Example data _bstr_t bstrModelData = bstrExampleDir; bstrModelData += L"\\Model\\Data"; 119 DREAM Suite 1 // Path to directory with Example executables _bstr_t bstrModelBin = bstrExampleDir; bstrModelBin += L"\\Model\\Bin"; // Path to working directory _bstr_t bstrWorkingDir = bstrExampleDir; bstrWorkingDir += L"\\Temp\\Simulations\\Case1"; // Delete old working directory (to clear old files) DrxDeleteDirectory(std::wstring(bstrWorkingDir)); // Create new working directory DrxCreateDirectory(std::wstring(bstrWorkingDir)); // Calc observer for communication, logging... CCalcObserver calcObserver(bstrWorkingDir); ///////////////////////////////////////////////////////////////////////////////////////////////// // Run DREAM Solver ///////////////////////////////////////////////////////////////////////////////////////////////// bool bDisplayInfoAboutCalculationResults = false; bool bLogInfoAvailable = false; try { wprintf(L"Connecting DREAM Server...\n"); // Try to create DreamSolver in COM way IDreamSolverPtr pSolver(__uuidof(IDreamSolver)); // Check if the creation of solver succeeded if(pSolver != nullptr) { // Setup calculation observer IDreamObserverPtr pIDreamCalcObserver = nullptr; hRes = calcObserver.QueryInterface(IID_IDreamObserver, (void**)&pIDreamCalcObserver); if(SUCCEEDED(hRes)) { // Establish communication with solver pSolver->AttachObserver(pIDreamCalcObserver); bLogInfoAvailable = true; } // Set directories pSolver->SetPath(ePathProjectDir, bstrExampleDir); pSolver->SetPath(ePathModelData, bstrModelData); pSolver->SetPath(ePathModelBin, bstrModelBin); pSolver->SetPath(ePathPluginBin, bstrPluginBin); pSolver->SetPath(ePathWorkingDir, bstrWorkingDir); // Load plugin module hRes = pSolver->LoadPlugin(bstrEvaluatorPath); if(SUCCEEDED(hRes)) { // Plugin info CDreamPluginInfo pluginInfo; pluginInfo.m_PluginType = ePluginType::ePlugin_DLL; pluginInfo.m_strPluginName = bstrPluginDllName.copy(); pluginInfo.m_strModelDataDir = bstrModelData.copy(); // DREAM calculation parameters CDreamCalcParams calcParamInfo; // Convergence diagnostics? calcParamInfo.m_SaveWithinChainDiagnostics = GetUserChoice(L"Do you want convergence diagnostics? (Yes/No = 1/0) : ", 0, 1); // Export Markov chains? calcParamInfo.m_SaveMarkovChains = GetUserChoice(L"Do you want to export Markov chains? No = 1/0) : ", 0, 1); // Number of cores calcParamInfo.m_NumberOfCPUs = GetUserChoice(L"Number of cores <1,20>, N > 1 = parallel calculation : ", 1, 20); calcParamInfo.m_RunParallel = calcParamInfo.m_NumberOfCPUs > 1 ? 1 : 0; // Initialize the evaluator and all input data by values obtained from the evaluator hRes = pSolver->InitEvaluatorDef(&pluginInfo, &calcParamInfo); if(SUCCEEDED(hRes)) 120 (Yes/ DREAM Suite 1 { // Get pointer to evaluator IDreamEvaluatorPtr pEvaluator = nullptr; hRes = pSolver->GetEvaluator(&pEvaluator); if(SUCCEEDED(hRes)) { // Set signal handler (Ctrl+C) pTheOnlySolverInThisProcess = pSolver; SetConsoleCtrlHandler((PHANDLER_ROUTINE)SignalHandler, TRUE); // Prepare the console to display calculation progress (%) wprintf(L"Starting calculation...\n"); wprintf(L"(press Ctrl+C to interrupt the calculation)\n"); // Perform calculations hRes = pSolver->StartCalculation(); if(SUCCEEDED(hRes)) { wprintf(L"Calculation succeeded.\n"); } else { // Check errors _bstr_t message; CDreamErrorInfo lastErrorInfo; if(pSolver->GetLastError(&lastErrorInfo) != S_OK && lastErrorInfo.GetErrType() == eTypeError) message = L"Calculation failed with error:\n" + _bstr_t(lastErrorInfo.GetErrDescription()) + L"\n"; else message = L"Calculation failed.\n"; wprintf(message); } bDisplayInfoAboutCalculationResults = true; } // Failed to get pointer to evaluator else { wprintf(L"Failed to get pointer to evaluator.\n"); } } // Failed to initialize evaluator else { wprintf(L"Failed to initialize evaluator.\n"); } } // Failed to load plugin module else { wprintf(L"Failed to load plugin module.\n"); } } // Failed to create Dream solver else { wprintf(L"Failed to create Dream solver.\n"); } } catch(_com_error& e) { // Dream solver creation failed std::wstring message = L"COM error: "; message += e.ErrorMessage(); message += L"\n"; PrintMessageUTF8(message); } // Clean-up 121 DREAM Suite 1 if(pTheOnlySolverInThisProcess != nullptr) { // Release solver interface - it must be done here, because it fails after CoUnitialize() pTheOnlySolverInThisProcess = nullptr; } // Output information if(bDisplayInfoAboutCalculationResults) { // Output files wprintf(L"Output and log files are available in directory:\n" + bstrWorkingDir + L"\n"); } // Error info if(bLogInfoAvailable) { // Number of errors and warnings returned by the solver int nErrors = calcObserver.GetNoOfErrors(); int nWarnings = calcObserver.GetNoOfWarnings(); wprintf(L"Number of errors: %d, Number of warnings: %d\n", nErrors, nWarnings); // Print logged messages (errors, warnings, messages and calculation time)? int iPrintLogInfo = GetUserChoice(L"Do you want to display log-file content? (Yes/No = 1/0) : ", 0, 1); if(iPrintLogInfo == 1) { wprintf(L"Log file contents:\n"); calcObserver.PrintMessages(); } } // Clean-up COM services CoUninitialize(); } // Wait for ENTER std::wcin.ignore(1024, '\n'); std::cout << "\nPress Enter to continue..."; std::wcin.get(); // Return result return hRes; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CCalcObserver //------------------------------------------------------------------------------------------------CCalcObserver::CCalcObserver() //------------------------------------------------------------------------------------------------: m_cRef(1) , m_iCurrentStep(0) , m_fConvergenceInfo(0.0f) , m_iNoOfErrors(0) , m_iNoOfWarnings(0) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Path to logfile m_LogFile = boost::filesystem::current_path().c_str(); m_LogFile += "\\DREAM_Out_LogObs.txt"; } //------------------------------------------------------------------------------------------------CCalcObserver::CCalcObserver(_bstr_t path) //------------------------------------------------------------------------------------------------: m_cRef(1) , m_iCurrentStep(0) , m_fConvergenceInfo(0.f) , m_iNoOfErrors(0) , m_iNoOfWarnings(0) /////////////////////////////////////////////////////////////////////////////////////////////////// { // Path to logfile m_LogFile = path; 122 DREAM Suite 1 m_LogFile += "\\DREAM_Out_LogObs.txt"; } //------------------------------------------------------------------------------------------------CCalcObserver::~CCalcObserver() //------------------------------------------------------------------------------------------------{ } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::OnLogMessage(BSTR strLogMessage) //------------------------------------------------------------------------------------------------{ // Use stream to log messages to a file std::wofstream fs(m_LogFile.GetBSTR(), std::ofstream::out | std::ofstream::app); std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>); fs.imbue(loc); // Write message to stream fs << strLogMessage << L"\n"; // Write fs.flush(); fs.close(); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::OnError(IDreamErrorInfo* pErrorInfo) //------------------------------------------------------------------------------------------------{ // Check input parameter if(pErrorInfo == nullptr) { return E_INVALIDARG; } // Use stream to log messages to a file std::wofstream fs(m_LogFile.GetBSTR(), std::ofstream::out | std::ofstream::app); // String for message std::wstring message; if(pErrorInfo->_type == eTypeWarning) { message = L"Warning No. "; m_iNoOfWarnings++; } else { message = L"Error No. "; m_iNoOfErrors++; } // Write message to stream fs << message << pErrorInfo->_errorID << " - " << pErrorInfo->_errorDesc << "\n"; // Write fs.flush(); fs.close(); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::SetCurrentStep(float fStep) //------------------------------------------------------------------------------------------------{ m_iCurrentStep = (int)fStep; std::cout << "Finished: " << m_iCurrentStep << " % " << "\r"; return S_OK; } 123 DREAM Suite 1 //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::SetConvergenceInfo(float fInfo) //------------------------------------------------------------------------------------------------{ m_fConvergenceInfo = fInfo; return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::OnCalculationTerminatedByUser() //------------------------------------------------------------------------------------------------{ // Use stream to write info to a file std::wofstream fs(m_LogFile.GetBSTR(), std::ofstream::out | std::ofstream::app); // Write message to stream fs << "Calculation was terminated by user. Please wait..." << "\n"; // Write fs.flush(); fs.close(); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::CalculationTerminatedByUser() //------------------------------------------------------------------------------------------------{ // In this application, calculation is terminated directly by calling // pTheOnlySolverInThisProcess->BreakCalculation(); // Terminating the calculation via observer is important when the calculation runs // in a worker thread and solver cannot be accessed from GUI. return S_FALSE; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::OnPreparingOutputData() //------------------------------------------------------------------------------------------------{ wprintf(L"Calculation finished, preparing output data...\n"); return S_OK; } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::OnCalculationFinished() //------------------------------------------------------------------------------------------------{ // Use stream to write info to a file std::wofstream fs(m_LogFile.GetBSTR(), std::ofstream::out | std::ofstream::app); // Write message to stream fs << "Calculation finished." << "\n"; // Write fs.flush(); fs.close(); return S_OK; } //------------------------------------------------------------------------------------------------void CCalcObserver::PrintMessages() const //------------------------------------------------------------------------------------------------{ // Get messages from the log file _bstr_t ff = m_LogFile; std::wifstream fs(ff.GetBSTR(), std::ofstream::in | std::ofstream::app); std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>); fs.imbue(loc); // Print all messages to std output (convert to UTF8) UINT oldcp = GetConsoleOutputCP(); SetConsoleOutputCP(CP_UTF8); 124 DREAM Suite 1 std::wstring wsLine; while (std::getline(fs, wsLine)) { wsLine += L"\n"; std::string utf8str = DrxWStr2Str(wsLine); printf(utf8str.c_str()); } fs.close(); SetConsoleOutputCP(oldcp); } //------------------------------------------------------------------------------------------------HRESULT STDMETHODCALLTYPE CCalcObserver::QueryInterface(const IID& iid, void** ppv) //------------------------------------------------------------------------------------------------{ // Check parameters if(ppv == nullptr) { // Invalid argument return E_INVALIDARG; } // Always set pointer to nullptr *ppv = nullptr; if(InlineIsEqualGUID(iid, IID_IUnknown) || InlineIsEqualGUID(iid, IID_IDreamObserver)) { // Return pointer to IDreamObserver interface *ppv = static_cast<IDreamObserver*>(this); } else { // Unimplemented interface *ppv = nullptr; return E_NOINTERFACE; } // Increment reference count reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; } //------------------------------------------------------------------------------------------------ULONG STDMETHODCALLTYPE CCalcObserver::AddRef() //------------------------------------------------------------------------------------------------{ // Increment reference count return ::InterlockedIncrement(&m_cRef); } //------------------------------------------------------------------------------------------------ULONG STDMETHODCALLTYPE CCalcObserver::Release() //------------------------------------------------------------------------------------------------{ // Decrement reference count if(::InterlockedDecrement(&m_cRef) == 0) { // Object is not referenced, it is safe to delete it delete this; return 0; } // Return actual reference count return m_cRef; } /////////////////////////////////////////////////////////////////////////////////////////////////// // Help functions //------------------------------------------------------------------------------------------------BOOL SignalHandler(DWORD fdwCtrlType) //------------------------------------------------------------------------------------------------// Signal handler - Ctrl+C 125 DREAM Suite 1 { switch (fdwCtrlType) { // Handle the CTRL-C signal case CTRL_C_EVENT: { if(pTheOnlySolverInThisProcess != nullptr) { pTheOnlySolverInThisProcess->BreakCalculation(); wprintf(L"Calculation interrupted by user!\n"); wprintf(L"Terminating process...\n"); } return TRUE; } default: return FALSE; } } //------------------------------------------------------------------------------------------------int GetUserChoice(std::wstring wsPromptLine, int iMinNo, int iMaxNo) //------------------------------------------------------------------------------------------------// Get user's choice (an integer number from interval <iMinNo, iMaxNo>) { int iUserChoice = -1; do { // Display the prompt line wprintf(wsPromptLine.c_str()); // Read user's input if(scanf(" %d", &iUserChoice) > 0) { // Check whether the number is correct if(iUserChoice >= iMinNo && iUserChoice <= iMaxNo) return iUserChoice; } // Failed wprintf(L"Incorrect input.\n"); // Needed getchar(); } while (1); // Wrong choice return -1; } //------------------------------------------------------------------------------------------------void PrintMessageUTF8(const std::wstring sLine) //------------------------------------------------------------------------------------------------{ // Print a message converted to UTF8 UINT oldcp = GetConsoleOutputCP(); SetConsoleOutputCP(CP_UTF8); std::string utf8str = DrxWStr2Str(sLine); printf(utf8str.c_str()); SetConsoleOutputCP(oldcp); } /////////////////////////////////////////////////////////////////////////////////////////////////// 6.3 Interfaces The documentation of COM interfaces contains just copies of corresponding IDL code with short descriptions in the "helpstring" items. A more detailed description can be found in the plugin source code template or demo in examples. 6.3.1 IDreamInputParViewer 126 DREAM Suite 1 /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamInputParViewer [ object, uuid(E895898B-5DA1-4E74-B636-7991FCF85396), local, helpstring("IDreamInputParViewer - reader interface to DreamParams"), pointer_default(unique) ] interface IDreamInputParViewer : IUnknown { [helpstring("Dimensionality target distribution d")] int GetProblemDimension(); [helpstring("Number of Markov chains N")] int GetNumberOfMarkovChains(); [helpstring("Number of generations T")] int GetNumberOfGenerations(); [helpstring("Choice of likelihood function")] eLikelihood GetLikelihoodChoice(); [helpstring("Number of crossover values nCR")] int GetNumberOfCrossoverValues(); [helpstring("Number chain pairs for proposal delta")] int GetNumberChainPairs(); [helpstring("Random error for ergodicity lambda")] double GetRandomErrorForErgodicity(); [helpstring("Randomization zeta")] double GetRandomization(); [helpstring("Test to detect outlier chains")] eOutlierTest GetOutlierTest(); [helpstring("Probability of jump rate of 1 pJumpRate_one")] double GetProbabilityOfJumprate(); [helpstring("Adapt selection prob. crossover pCR")] int GetAdaptSelection(); [helpstring("Each Tth sample is stored thinning")] int GetThinnigSampleToStore(); [helpstring("GLUE likelihood parameter")] int GetGlueLikelihood(); [helpstring("Diagnostic Bayes? Values: 1=true, 0=false")] int GetBayesDiagnostic(); [helpstring("Scaling factor of built-in jump rate beta0")] double GetScalingFactorOfJumpRate(); [helpstring("Bayesian Model Averaging (BMA) with hydrologic data. Number of different models")] int GetNumberOfDifferentModelsBMA(); [helpstring("Model vectorization type")] eVectorization GetVectorization(); [helpstring("Number of steps after which the convergence is checked and updated")] int GetSteps(); [helpstring("Initial sampling distribution type")] eInitDistrib GetInitialDistribution(); [helpstring("Boundary handling type")] eBoundHandling GetBoundHandling(); [helpstring("Use prior distribution even for m_InitialDistribution != eInitPrior? Values: 1/0")] int GetUsePriorDistribution(); 127 DREAM Suite 1 [helpstring("Prior distribution type")] ePriorType GetPriorDistributionType(); [helpstring("Evaluator can run in parallel?")] eParallelMode GetParallelMode(); [helpstring("Parameter p is locked and cannot be changed in GUI. Values: 1/0 = yes/no")] int IsParLocked([in] eDreamInputPar p); }; 6.3.2 IDreamInputParams /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamInputParams [ object, uuid(DF761E08-C84F-4AF4-8E86-77FEEE8B046A), local, helpstring("IDreamInputParams - reader/writer interface to DreamParams"), pointer_default(unique) ] interface IDreamInputParams : IDreamInputParViewer { [helpstring("Dimensionality target distribution d")] HRESULT SetProblemDimension([in] int problemDimension, [in] int iLock); [helpstring("Number of Markov chains N")] HRESULT SetNumberOfMarkovChains([in] int numberOfMarkovChains, [in] int iLock); [helpstring("Number of generations T")] HRESULT SetNumberOfGenerations([in] int numberOfGenerations, [in] int iLock); [helpstring("Choice of likelihood function")] HRESULT SetLikelihoodChoice([in] eLikelihood likelihoodChoice, [in] int iLock); [helpstring("Number of crossover values nCR")] HRESULT SetNumberOfCrossoverValues([in] int numberOfCrossoverValues, [in] int iLock); [helpstring("Number chain pairs for proposal delta")] HRESULT SetNumberChainPairs([in] int numberChainPairs, [in] int iLock); [helpstring("Random error for ergodicity lambda")] HRESULT SetRandomErrorForErgodicity([in] double randomErrorForErgodicity, [in] int iLock); [helpstring("Randomization zeta")] HRESULT SetRandomization([in] double randomization, [in] int iLock); [helpstring("Test to detect outlier chains")] HRESULT SetOutlierTest([in] eOutlierTest outlierTest, [in] int iLock); [helpstring("Probability of jump rate of 1 pJumpRate_one")] HRESULT SetProbabilityOfJumprate([in] double probabilityOfJumprate, [in] int iLock); [helpstring("Adapt selection prob. crossover pCR")] HRESULT SetAdaptSelection([in] int adaptSelection, [in] int iLock); [helpstring("Each Tth sample is stored thinning")] HRESULT SetThinnigSampleToStore([in] int thinnigSampleToStore, [in] int iLock); [helpstring("GLUE likelihood parameter")] HRESULT SetGlueLikelihood([in] int glueLikelihood, [in] int iLock); [helpstring("Diagnostic Bayes? Values: 1=true, 0=false")] HRESULT SetBayesDiagnostic([in] int bayesDiagnostic, [in] int iLock); [helpstring("Scaling factor of built-in jump rate beta0")] HRESULT SetScalingFactorOfJumpRate([in] double scalingFactorOfJumpRate, [in] int iLock); [helpstring("Bayesian Model Averaging (BMA) with hydrologic data. Number of different models")] HRESULT SetNumberOfDifferentModelsBMA([in] int numberOfDifferentModelsBMA, [in] int iLock); 128 DREAM Suite 1 [helpstring("Model vectorization type")] HRESULT SetVectorization([in] eVectorization vectorization, [in] int iLock); [helpstring("Number of steps after which the convergence is checked and updated")] HRESULT SetSteps([in] int steps, [in] int iLock); [helpstring("Initial sampling distribution type")] HRESULT SetInitialDistribution([in] eInitDistrib initialDistribution, [in] int iLock); [helpstring("Boundary handling type")] HRESULT SetBoundHandling([in] eBoundHandling boundHandling, [in] int iLock); [helpstring("Use prior distribution even for m_InitialDistribution != eInitPrior? Values: 1/0")] HRESULT SetUsePriorDistribution([in] int usePriorDistribution, [in] int iLock); [helpstring("Prior distribution type")] HRESULT SetPriorDistributionType([in] ePriorType priorDistributionType, [in] int iLock); [helpstring("Evaluator can run in parallel?")] HRESULT SetParallelMode([in] eParallelMode parallelMode, [in] int iLock); [helpstring("Lock/unlock parameter p to prevent changes in GUI. Values of p: 1/0 = lock/unlock")] HRESULT LockParameter([in] eDreamInputPar p, [in] int iLock); }; 6.3.3 IDreamDataMinMax /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamDataMinMax [ object, uuid(8421C9F5-51EE-44E2-A8AA-BA6712A2FD2F), local, helpstring("IDreamDataMinMax - interface to min/max data"), pointer_default(unique) ] interface IDreamDataMinMax : IUnknown { [helpstring("Min/Max values will be defined in solver? Values: 1/0")] HRESULT SetMinMaxValuesDefinedInSolver([in] int value); [helpstring("Add new MinMaxItem")] HRESULT AddItem([in] double minimum, [in] double maximum); [helpstring("Add new MinMaxItem")] HRESULT AddExtendedItem([in] double minimum, [in] double maximum, [in] double value, [in] int selected); [helpstring("Add new MinMaxItem for measurement error")] HRESULT AddMeasurementErrorItem([in] double minimum, [in] double maximum); [helpstring("Add new MinMaxItem for Likelihood")] HRESULT AddLikelihoodItem([in] double minimum, [in] double maximum, [in] double value, [in] int selected); [helpstring("Additional x-range values for PCHIP (Piecewise Cubic Hermite Interpol. Polynom.)")] HRESULT SetLVInterpolationValues([in] double a, [in] double b, [in] double c, [in] double d); }; 6.3.4 IDreamDataNormal /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamDataNormal [ object, uuid(B5A5CAA7-922E-414F-A1B8-4076BF85C879), local, 129 DREAM Suite 1 helpstring("IDreamDataNormal - interface to normal data"), pointer_default(unique) ] interface IDreamDataNormal : IUnknown { [helpstring("Add new MuItem")] HRESULT AddMeanItem([in] double mu); [helpstring("Set diagonal value for covariance matrix")] HRESULT SetCovarianceDiagonalValue([in] double diagonalValue); [helpstring("Set diagonal values for covariance matrix")] HRESULT SetCovarianceDiagonalVector([in] int nCount, [in] const double* pValues); }; 6.3.5 IDreamDataPrior /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamDataPrior [ object, uuid(3D4B197C-184F-4EC2-AC06-4D3ECA76156D), local, helpstring("IDreamDataPrior - interface to prior data"), pointer_default(unique) ] interface IDreamDataPrior : IUnknown { [helpstring("Add new item of univariate distribution")] HRESULT AddUnivariateItem([in] double mu, [in] double sigma, [in] eDistributionUnivariate type); [helpstring("Set multivariate normal data")] HRESULT SetMultivariateNormalData([in] IDreamVector* mean, [in] IDreamMatrix* covariance); [helpstring("Set item for multivariate student T distribution")] HRESULT SetMultivariateTdistributionData([in] IDreamMatrix* correlation, [in] int degreeOfFreedom); }; 6.3.6 IDreamDataMeasurement /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamDataMeasurement [ object, uuid(DF82B5CD-0DBE-4C85-9415-0AE60DCC7F72), local, helpstring("IDreamDataMeasurement - interface to measurement data"), pointer_default(unique) ] interface IDreamDataMeasurement : IUnknown { [helpstring("Set measurement error function type")] HRESULT SetMeasurementErrorType(eMeasureError type); [helpstring("Add scalar/vector with corresponding calibration data and measurement errors")] HRESULT AddMeasurementData([in] int nCount, [in] const double* pCalibrationValues, [in] const double* pErrorValues); }; 6.3.7 IDreamDataABC /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamDataABC [ object, uuid(628FE6EF-2086-4A6B-BBFA-0961E6755A7F), 130 DREAM Suite 1 local, helpstring("IDreamDataABC - interface to Approximate Bayesian Computation data"), pointer_default(unique) ] interface IDreamDataABC : IUnknown { [helpstring("Set ABC distance function type")] HRESULT SetABCFunctionType([in] eDistanceFunction eABCParam); [helpstring("Scalar/vector with summary metrics and ABC Epsilon data")] HRESULT AddComputationData([in] int nCount, [in] double* pMetricsValues, [in] double* pEpsValues); }; 6.3.8 IDreamDataSource /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamDataSource [ object, uuid(63AACA44-751A-402B-A0EB-21DF33841473), local, helpstring("IDreamDataSource - interface to DREAM data source"), pointer_default(unique) ] interface IDreamDataSource : IUnknown { [helpstring("Get initial/default values of DREAM parameters")] HRESULT GetInputParams([in, out] IDreamInputParams* pIDreamInputParams); [helpstring("Get MinMax data")] HRESULT GetMinMaxData([in] IDreamInputParViewer* pInputPar, [in] IDreamDataMinMax* pIMinMaxData); [helpstring("Get Normal data")] HRESULT GetNormalData([in] IDreamInputParViewer* pInputPar, [in] IDreamDataNormal* pINormalData); [helpstring("Get Prior data")] HRESULT GetPriorData([in] IDreamInputParViewer* pInputPar, [in] IDreamDataPrior* pIPriorData); [helpstring("Get Custom Prior data")] HRESULT GetPriorDataCustom([in] IDreamInputParViewer* pInputPar, [in] IDreamMatrix* x, [out] IDreamMatrix* PR, [in] ePriorDistrib callType); [helpstring("Get Measurement data")] HRESULT GetMeasurementData([in] IDreamInputParViewer* pInputPar, [in] IDreamDataMeasurement* pIMeasureData, [in] BSTR strModelDataDir); [helpstring("Get Approximate Bayesian Computation data")] HRESULT GetBayesData([in] IDreamInputParViewer* pInputPar, [in] IDreamDataABC* pIBayesCompData, [in] BSTR strModelDataDir); }; 6.3.9 IDreamEvaluator /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamEvaluator [ object, uuid(FF5B9D3D-C36B-49BB-A0A2-E6818BB79367), local, helpstring("IDreamEvaluator - interface to DREAM Evaluator"), pointer_default(unique) ] interface IDreamEvaluator : IDreamDataSource { [helpstring("Plugin initialization - the first function called before using the evaluator")] HRESULT InitPlugin([in] IDreamPluginInfo* pIPluginInfo); [helpstring("Prepare a directory for parallel calculation")] HRESULT PrepareWorkDir([in] BSTR strSourceDir, [in] BSTR strDestinationDir); 131 DREAM Suite 1 [helpstring("Prepare input data needed for the calculation. Called only once.")] HRESULT InitData([in] IDreamPluginInfo* pIPluginInfo, [in] IDreamInputParViewer* pIDreamInputParams); [helpstring("Calculate the likelihood of each proposal during DREAM calculation")] HRESULT EvaluateProposal([in] IDreamInputParViewer* pInputPar, [in] int sim, [in] IDreamMatrix* x, [in, out] IDreamMatrix* res, [in] BSTR strWorkingDir, [in] BSTR strModelDataDir, [in] BSTR strModelBinDir); [helpstring("Get description of the last error.")] HRESULT GetLastError([out] BSTR* strErrorText); [helpstring("Called after finishing the calculation.")] HRESULT OnCalculationFinished(); }; 6.3.10 IDreamObserver /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamObserver [ object, uuid(403837B3-648A-4EEB-ACDC-24209CEF3F31), local, helpstring("IDreamObserver - interface to calculation observer"), pointer_default(unique) ] interface IDreamObserver : IUnknown { [helpstring("Add new message to log")] HRESULT OnLogMessage([in] BSTR strLogMessage); [helpstring("Provides information about calculation error")] HRESULT OnError([in] IDreamErrorInfo* pErrorInfo); [helpstring("Progress evaluation step")] HRESULT SetCurrentStep([in] float iStep); [helpstring("Set convergence information")] HRESULT SetConvergenceInfo([in] float fInfo); [helpstring("Called after the calculation was terminated by user")] HRESULT OnCalculationTerminatedByUser(); [helpstring("Called after finishing the calculation")] HRESULT OnCalculationFinished(); [helpstring("Called before exporting output data")] HRESULT OnPreparingOutputData(); [helpstring("Was the calculation terminated by user? Yes (S_OK) or not (S_FALSE)")] HRESULT CalculationTerminatedByUser(); }; 6.3.11 IDreamSolver /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamSolver [ object, uuid(BD3A86B4-805E-48D7-8366-A96191D9A0E6), local, helpstring("IDreamSolver - interface to DREAM Solver"), pointer_default(unique) ] interface IDreamSolver : IUnknown { [helpstring("Load plugin module")] 132 DREAM Suite 1 HRESULT LoadPlugin([in] BSTR strPluginPath); [helpstring("Return pointer to evaluator")] HRESULT GetEvaluator([out] IDreamEvaluator** pIEvaluator); [helpstring("Initialize evaluator and set input data from external source")] HRESULT InitEvaluatorExt([in] IDreamPluginInfo* pIPluginInfo, [in] IDreamCalcSettings* pISettings, [in] IDreamDataSource* pIDataSource); [helpstring("Initialize evaluator and set default input data from the evaluator")] HRESULT InitEvaluatorDef([in] IDreamPluginInfo* pIPluginInfo, [in] IDreamCalcSettings* pISettings); [helpstring("Attach calculation observer")] HRESULT AttachObserver([in] IDreamObserver* pICalcObserver); [helpstring("Start DREAM calculation")] HRESULT StartCalculation(); [helpstring("Interrupt DREAM calculation")] HRESULT BreakCalculation(); [helpstring("Return path of given type")] BSTR GetPath([in] eDreamPath pathType); [helpstring("Set path of given type")] HRESULT SetPath([in] eDreamPath pathType, [in] BSTR strPath); [helpstring("Return the last error")] HRESULT GetLastError([in] IDreamErrorInfo* pErrorInfo); }; 6.4 Data structures 6.4.1 IDreamPluginInfo /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamPluginInfo [helpstring("IDreamPluginInfo - Plugin information data structure")] typedef struct IDreamPluginInfo { [helpstring("Path to model data directory")] BSTR m_strModelDataDir; [helpstring("Path to plugin script directory")] BSTR m_strPluginScriptDir; [helpstring("Path to plugin engine directory (MATLAB, etc.)")] BSTR m_strEngineDir; [helpstring("Plugin name (used for names of script files)")] BSTR m_strPluginName; [helpstring("Plugin type")] ePluginType m_PluginType; } IDreamPluginInfo; 6.4.2 IDreamCalcSettings /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamCalcSettings [helpstring("IDreamCalcSettings - structure with calculation options")] typedef struct IDreamCalcSettings { [helpstring("Save DREAM output during the run? Values: 1=true, 0=false")] int m_SaveOutput; 133 DREAM Suite 1 [helpstring("Restart calculation? int m_RestartRun; Values: 1=true, 0=false")] [helpstring("Save results in binary format? Values: 1=true, 0=false")] int m_SaveResultsBin; [helpstring("Save within-chain diagnostics? Values: 1=true, 0=false")] int m_SaveWithinChainDiagnostics; [helpstring("Save R_stat and MR_stat? int m_SaveBetweenChainDiagnostics; Values: 1=true, 0=false")] [helpstring("Save Markov chains? Values: 1=true, 0=false")] int m_SaveMarkovChains; [helpstring("Save ParSet matrix result? Values: 1=true, 0=false")] int m_SaveParSetMatrix; [helpstring("Save model (function) simulations? int m_SaveModelSimulations; [helpstring("Save Summary statistics? int m_SaveSummaryStatistics; Values: 1=true, 0=false")] Values: 1=true, 0=false")] [helpstring("Number of used CPUs")] int m_NumberOfCPUs; [helpstring("Run in parallel? int m_RunParallel; } IDreamCalcSettings; Values: 1=true, 0=false")] 6.4.3 IDreamErrorInfo /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamErrorInfo [helpstring("Error info structure")] typedef struct IDreamErrorInfo { [helpstring("Type - error/warning")] eErrType _type; [helpstring("Error ID")] int _errorID; [helpstring("Error description")] BSTR _errorDesc; } IDreamErrorInfo; 6.4.4 IDreamMatrix /////////////////////////////////////////////////////////////////////////////////////////////////// // Interface IDreamMatrix [helpstring("Matrix structure")] typedef struct IDreamMatrix { [helpstring("Row count")] int _rowCount; [helpstring("Column count")] int _colCount; [helpstring("Matrix data")] double* _data; } IDreamMatrix; 6.4.5 IDreamVector /////////////////////////////////////////////////////////////////////////////////////////////////// 134 DREAM Suite 1 // Interface IDreamVector [helpstring("Vector structure")] typedef struct IDreamVector { [helpstring("Item count")] int _itemCount; [helpstring("Vector data")] double* _data; } IDreamVector; 6.5 Enumerators 6.5.1 eBoundHandling /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eBoundHandling [helpstring("Boundary handling types.")] typedef enum eBoundHandling { [helpstring("No boundary handling (see Technical Manual)")] eBoundUnbounded, [helpstring("\"Reflect\" boundary handling (see Technical Manual)")] eBoundReflect, [helpstring("\"Bound\" boundary handling (see Technical Manual)")] eBoundBound, [helpstring("\"Fold\" boundary handling (see Technical Manual)")] eBoundFold } eBoundHandling; 6.5.2 eDistanceFunction /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eABC Distance Function [helpstring("ABC distance function between the simulated and observed summary statistics.")] typedef enum eDistanceFunction { [helpstring("A-B distance function")] eAminusB, [helpstring("Abs(A-B) distance function")] eAbsOfAminusB, [helpstring("Sqrt(1/20*(A-B)^2)) distance function")] eSqrt_1Over20_MultiplyBy_Sum_AminusBSquared } eDistanceFunction; 6.5.3 eDistributionMultivariate /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eDistributionMultivariate [helpstring("Probability density function for Multivariate Prior type.")] typedef enum eDistributionMultivariate { [helpstring("Multivariate Normal distribution")] eMultivariate_Normal, [helpstring("Multivariate T-distribution")] eMultivariate_T } eDistributionMultivariate; 135 DREAM Suite 1 6.5.4 eDistributionUnivariate /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eDistributionUnivariate [helpstring("Probability density function for Univariate Prior type.")] typedef enum eDistributionUnivariate { [helpstring("Univariate F-distribution")] eUnivariate_F, [helpstring("Univariate Gamma-distribution")] eUnivariate_Gamma, [helpstring("Univariate Uniform-distribution")] eUnivariate_Uniform, [helpstring("Univariate T-distribution")] eUnivariate_T, [helpstring("Univariate Normal distribution")] eUnivariate_Normal } eDistributionUnivariate; 6.5.5 eDreamError /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eDreamError [helpstring("DREAM errors")] typedef enum eDreamError { [helpstring("No error")] ERR_NONE = 0, [helpstring("No authorization to run DREAM Solver")] ERR_NO_AUTHORIZATION, [helpstring("Incorrect path to ePathProjectDir directory")] ERR_INCORRECT_PROJECT_DIRECTORY, [helpstring("Incorrect path to ePathModelBin directory")] ERR_INCORRECT_MODELBIN_DIRECTORY, [helpstring("Incorrect path to ePathModelData directory")] ERR_INCORRECT_MODELDATA_DIRECTORY, [helpstring("Incorrect path to ePathPluginBin directory")] ERR_INCORRECT_PLUGINBIN_DIRECTORY, [helpstring("Incorrect path to ePathWorkingDir directory")] ERR_INCORRECT_WORKING_DIRECTORY, [helpstring("Source directory does not exist or is not a directory")] ERR_INCORRECT_SOURCE_DIRECTORY, [helpstring("Access to working directory denied")] ERR_INCORRECT_DESTINATION_DIRECTORY, [helpstring("Unable to create destination directory")] ERR_FILE_SYSTEM_ERROR, [helpstring("File system error")] ERR_WORKDIR_ACCES_DENIED, [helpstring("Dimensionality should be larger than zero")] ERR_INPUT_PARAMETER_D, [helpstring("Evaluation cannot be run in parallel mode")] ERR_INPUT_PARAMETER_PARALLEL, 136 DREAM Suite 1 [helpstring("Unknown choice of likelihood function")] ERR_INPUT_PARAMETER_LIK, [helpstring("Not enough data from input")] ERR_INPUT_PARAMETER_LIK_217, [helpstring("Wrong input data for LIK_217. Constants a, b, c, d must be non-decreasing")] ERR_INPUT_PARAMETER_LIK_217_INTERPOLATION, [helpstring("Not enough chains pairs for sampling")] ERR_INPUT_PARAMETER_DELTA, [helpstring("Not enough chains pairs for sampling")] ERR_INPUT_PARAMETER_N, [helpstring("Not enough generations")] ERR_INPUT_PARAMETER_T, [helpstring("At least one crossover value")] ERR_INPUT_PARAMETER_NCR, [helpstring("Thinning parameter should be positive")] ERR_INPUT_PARAMETER_THINNING, [helpstring("Jump rate multiplier should be larger than zero")] ERR_INPUT_PARAMETER_BETA0, [helpstring("GLUE likelihood variable larger than zero")] ERR_INPUT_PARAMETER_GLUE, [helpstring("Lambda have to be positive")] ERR_INPUT_PARAMETER_LAMBDA, [helpstring("Zeta have to be positive")] ERR_INPUT_PARAMETER_ZETA, [helpstring("Unit jump rate probability between 0 and 1")] ERR_INPUT_PARAMETER_PUNITGAMMA, [helpstring("Adaptation of crossover values should be true (default) or false")] ERR_INPUT_PARAMETER_ADAPTPCR, [helpstring("Sigma needs to be specified")] ERR_INPUT_PARAMETER_LIKELIHOOD, [helpstring("Latin hypercube sampling selected but minimum/maximum parameters not defined")] ERR_INPUT_PARAMETER_INIT_DIST_LATIN, [helpstring("Uniform initial sampling selected but minimum, maximum parameters not defined")] ERR_INPUT_PARAMETER_INIT_DIST_UNIFORM, [helpstring("Normal distribution selected to sample from but unknown mean, covariance")] ERR_INPUT_PARAMETER_INIT_DIST_NORMAL_1, [helpstring("Mean of normal distribution mu should be a row vector")] ERR_INPUT_PARAMETER_INIT_DIST_NORMAL_2, [helpstring("Covariance of normal distribution cov should be a square matrix")] ERR_INPUT_PARAMETER_INIT_DIST_NORMAL_3, [helpstring("Prior distribution selected but unknown prior array defined")] ERR_INPUT_PARAMETER_INIT_DIST_PRIOR, [helpstring("Dimension of univariate prior data mismatch")] ERR_INPUT_PARAMETER_DIST_PRIOR_1, [helpstring("Dimension of multivariate normal prior data mismatch")] ERR_INPUT_PARAMETER_DIST_PRIOR_2, [helpstring("Dimension of multivariate students T prior data mismatch")] ERR_INPUT_PARAMETER_DIST_PRIOR_3, [helpstring("Boundary handling is used but minimum, maximum parameter values not defined")] ERR_INPUT_PARAMETER_BOUNDING, 137 DREAM Suite 1 [helpstring("Number of elements of field min, max should be equal to d")] ERR_INPUT_PARAMETER_BOUNDING_INIT_DIST, [helpstring("Field Y of measurement data has to be defined")] ERR_INPUT_MEASURE_PARAM_Y, [helpstring("Field S of measurement data has to be defined")] ERR_INPUT_MEASURE_PARAM_S, [helpstring("Sigma incorrect length")] ERR_INPUT_MEASURE_PARAM_SIGMA_1, [helpstring("At least one value of the specified Sigma is negative or zero")] ERR_INPUT_MEASURE_PARAM_SIGMA_2, [helpstring("Number of elements of epsilon does not match that of S")] ERR_INPUT_SETTING_PARAM_EPSILON_1, [helpstring("Value of epsilon should be larger than zero")] ERR_INPUT_SETTING_PARAM_EPSILON_2, [helpstring("Loading additional input data (MinMax/CovMu) failed")] ERR_INPUT_LOAD_ADDITIONAL_DATA, [helpstring("Loading measurement data failed")] ERR_INPUT_LOAD_MEASUREMENT_DATA, [helpstring("Diagnostic Bayes is allowed only for likelihood 11, 31, 32, 33, 34")] ERR_INPUT_DIAGNOSTIC_BAYES, [helpstring("Evaluation likelihood and log-likelihood failed")] ERR_SOLVER_LIKELIHOOD_EVALUATION, [helpstring("Unssuported model of CalcDensity")] ERR_SOLVER_LIKELIHOOD_UNKNOWN, [helpstring("Calculation of density failed")] ERR_SOLVER_CALC_DENSITY, [helpstring("Calculation of distance function failed")] ERR_SOLVER_CALC_DISTANCE_FUNCTION_RHO, [helpstring("Log-likelihood and simulation of regression model failed")] ERR_SOLVER_SIMULATION_OF_REGRESSION_MODELS, [helpstring("Implementation of likelihood function not available")] ERR_SOLVER_NOT_IMPLEMENTED_LIKELIHOOD_FUNCTION, [helpstring("Wrong Min/Max data dimension for measurement error function")] ERR_SOLVER_MIN_MAX_FOR_ERROR_FUNCTION } eDreamError; 6.5.6 eDreamInputPar /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eDreamInputPar [helpstring("DREAM Input parameters")] typedef enum eDreamInputPar { [helpstring("Dimensionality target distribution d")] eParProblemDimension, [helpstring("Number of Markov chains N")] eParNumberOfMarkovChains, [helpstring("Number of generations T")] eParNumberOfGenerations, [helpstring("Choice of likelihood function")] 138 DREAM Suite 1 eParLikelihoodChoice, [helpstring("Number of crossover values nCR")] eParNumberOfCrossoverValues, [helpstring("Number chain pairs for proposal delta")] eParNumberChainPairs, [helpstring("Random error for ergodicity lambda")] eParRandomErrorForErgodicity, [helpstring("Randomization zeta")] eParRandomization, [helpstring("Test to detect outlier chains")] eParOutlierTest, [helpstring("Probability of jump rate of 1 pJumpRate_one")] eParProbabilityOfJumprate, [helpstring("Adapt selection prob. crossover pCR")] eParAdaptSelection, [helpstring("Each Tth sample is stored thinning")] eParThinnigSampleToStore, [helpstring("GLUE likelihood parameter")] eParGlueLikelihood, [helpstring("Diagnostic Bayes? Values: 1=true, 0=false")] eParBayesDiagnostic, [helpstring("Scaling factor of built-in jump rate beta0")] eParScalingFactorOfJumpRate, [helpstring("Bayesian Model Averaging (BMA) with hydrologic data. Number of different models")] eParNumberOfDifferentModelsBMA, [helpstring("Model vectorization type")] eParVectorization, [helpstring("Number of steps after which the convergence is checked and updated")] eParSteps, [helpstring("Initial sampling distribution type")] eParInitialDistribution, [helpstring("Boundary handling type")] eParBoundHandling, [helpstring("Use prior distribution even for m_InitialDistribution != eInitPrior? Values: 1/0")] eParUsePriorDistribution, [helpstring("Prior distribution type")] eParPriorDistributionType, [helpstring("Evaluator can run in parallel?")] eParParallelMode, [helpstring("Dummy: number if input parameters")] eParMax, } eDreamInputPar; 6.5.7 eDreamPath /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eDreamPath [helpstring("Paths to subdirectories of a DREAM project.")] typedef enum eDreamPath { [helpstring("Project directory, e.g. ...\\Projects\\Drm_Example07")] ePathProjectDir, 139 DREAM Suite 1 [helpstring("Directory with model executables, e.g. ...\\Projects\\Drm_Example07\\Model\\Bin")] ePathModelBin, [helpstring("Directory with model data files, e.g. ...\\Projects\\Drm_Example07\\Model\\Data")] ePathModelData, [helpstring("Directory with plugin DLL, e.g. ...\\Projects\\Drm_Example07\\Plugin\\Bin")] ePathPluginBin, [helpstring("Working directory, e.g. ...\\Projects\\Drm_Example07\\Temp\\Case1")] ePathWorkingDir, [helpstring("Number of possible paths (not a path)")] ePathMax, } eDreamPath; 6.5.8 eDreamWarning /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eDreamWarning [helpstring("DREAM warnings")] typedef enum eDreamWarning { [helpstring("No warning")] WAR_NONE = 1, [helpstring("Parallel mode of evaluation is not recommended")] WAR_INPUT_PARAMETER_PARALLEL, [helpstring("Delta set rather large")] WAR_INPUT_PARAMETER_DELTA, [helpstring("Parameter N set rather large")] WAR_INPUT_PARAMETER_N, [helpstring("Parameter T set rather large")] WAR_INPUT_PARAMETER_T, [helpstring("Too many crossover values")] WAR_INPUT_PARAMETER_NCR, [helpstring("Parameter thinning set rather large")] WAR_INPUT_PARAMETER_THINNING, [helpstring("Parameter beta0 set rather large")] WAR_INPUT_PARAMETER_BETA0, [helpstring("Parameter GLUE set rather large")] WAR_INPUT_PARAMETER_GLUE, [helpstring("Parameter lambda set rather large")] WAR_INPUT_PARAMETER_LAMBDA, [helpstring("Parameter GLUE set rather large")] WAR_INPUT_PARAMETER_ZETA, [helpstring("Peirce will use r-values of N = 60")] WAR_INPUT_PARAMETER_OUTLIER, [helpstring("Thinning reduces length of the sampled chain")] WAR_INPUT_PARAMETERS_T_THINNING_1, [helpstring("Thinning reduces length of the sampled chain")] WAR_INPUT_PARAMETERS_T_THINNING_2, [helpstring("Likelihood function selected that contains nuisance variables")] WAR_INPUT_PARAMETER_LIKELIHOOD_2, [helpstring("Only a single calibration data observation is used")] WAR_INPUT_MEASURE_PARAM_Y, 140 DREAM Suite 1 [helpstring("Only a single summary metric value is used")] WAR_INPUT_MEASURE_PARAM_S, [helpstring("ABC approach: Default value of epsilon will be used")] WAR_INPUT_SETTING_PARAM_EPSILON_1, [helpstring("If so desired you can use a different value of epsilon")] WAR_INPUT_SETTING_PARAM_EPSILON_2, [helpstring("Enough RAM memory to store model simulation")] WAR_SOLVER_STORE_FX, [helpstring("Can not allocate enough memory")] WAR_SOLVER_ALLOC, [helpstring("Model simulation variable fx is too large and can not be allocated in memory. Results will not be avaliable.")] WAR_SOLVER_MODEL_SIMULATION, [helpstring("Wrong dimension of Bayesian Model Averaging (BMA). Bayesian Model Averaging will be skiped.")] WAR_SOLVER_BAYESIAN_MODEL_AVERAGING, [helpstring("Be sure that function \"GetPriorDataCustom\" is implemented in Evaluator")] WAR_INPUT_PARAMETER_DIST_PRIOR, [helpstring("At least 200 iterations is needed for coda diagnostic.")] WAR_OUTPUT_CODA_DIAGNOSTIC_200_ITERATIONS, [helpstring("Finalization of outputs failed")] WAR_OUTPUT_CODA_DIAGNOSTIC_GENERAL_PROBLEM, [helpstring("Minimum draws for coda diagnostic is 50. Diagnostic will not be avaliable.")] WAR_OUTPUT_CODA_DIAGNOSTIC_MIN_50_DRAWS } eDreamWarning; 6.5.9 eErrType /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eErrType [helpstring("DREAM error message types")] typedef enum eErrType { [helpstring("No error - just information")] eTypeNone, [helpstring("No error - just a warning")] eTypeWarning, [helpstring("An error")] eTypeError } eErrType; 6.5.10 eInitDistrib /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eInitDistrib [helpstring("Initial distribution types (initial state of of the Markov chain(s)).")] typedef enum eInitDistrib { [helpstring("Uniform initial sampling")] eInitUniform, [helpstring("Latin initial sampling")] eInitLatin, [helpstring("Normal initial sampling")] eInitNormal, 141 DREAM Suite 1 [helpstring("Prior initial sampling")] eInitPrior } eInitDistrib; 6.5.11 eLikelihood /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eLikelihood [helpstring("Likelihood function types.")] typedef enum eLikelihood { [helpstring("Lik=1, Likelihood, L(x|~Y)")] LIK_101 = 0, [helpstring("Lik=2, Log-likelihood, L(x|~Y)")] LIK_102, [helpstring("Lik=11, Gaussian likelihood: measurement error integrated out")] LIK_211, [helpstring("Lik=12, Gaussian likelihood: homos/heteroscedastic data error")] LIK_212, [helpstring("Lik=13, Gaussian likelihood: with AR-1 model of error residuals")] LIK_213, [helpstring("Lik=14, Generalized likelihood function")] LIK_214, [helpstring("Lik=15, Whittle's likelihood (spectral analysis)")] LIK_215, [helpstring("Lik=16, Laplacian likelihood: homos/heteroscedastic data error")] LIK_216, [helpstring("Lik=17, Skewed Student likelihood function")] LIK_217, [helpstring("Lik=21, Noisy ABC: Gaussian likelihood")] LIK_321, [helpstring("Lik=22, ABC: Boxcar likelihood")] LIK_322, [helpstring("Lik=23, Limits of acceptability")] LIK_323, [helpstring("Lik=31, Inverse error variance with shaping factor")] LIK_431, [helpstring("Lik=32, Nash and Sutcliffe efficiency with shaping factor")] LIK_432, [helpstring("Lik=33, Exponential transform error variance with shaping factor")] LIK_433, [helpstring("Lik=34, Sum of absolute error residuals")] LIK_434, [helpstring("Undefined likelihood function")] unknown } eLikelihood; 6.5.12 eMeasureError /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eMeasureError [helpstring("Measurement error types.")] typedef enum eMeasureError 142 DREAM Suite 1 { [helpstring("Measurement error set by user")] eMeasUserDefError, [helpstring("Homoscedastic (constant) error")] eMeasConstantError, [helpstring("Heteroscedastic (variable) error")] eMeasVariableError } eMeasureError; 6.5.13 eOutlierTest /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eOutlierTest [helpstring("Functions for detection of outlier chains")] typedef enum eOutlierTest { [helpstring("Iqr - Upton and Cook, 1996")] eOutlierIqr, [helpstring("Grubbs - Grubbs, 1950")] eOutlierGrubbs, [helpstring("Peirce - Peirce, 1852")] eOutlierPeirce, [helpstring("Chauvenet - Chauvenet, 1960")] eOutlierChauvenet } eOutlierTest; 6.5.14 eParallelMode /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eParallelMode [helpstring("Options for the parallel mode of evaluation")] typedef enum eParallelMode { [helpstring("Parallel mode is possible and recommended")] eParallelModeYes, [helpstring("Parallel mode is possible but not recommended")] eParallelModeNotRecommended, [helpstring("Parallel mode is not possible")] eParallelModeNotPossible } eParallelMode; 6.5.15 ePluginType /////////////////////////////////////////////////////////////////////////////////////////////////// // enum ePluginType [helpstring("Plugin types")] typedef enum ePluginType { [helpstring("Plugin is a standard DLL")] ePlugin_DLL, [helpstring("Plugin uses MATLAB COM server")] ePlugin_MatlabCOM, [helpstring("Plugin uses MATLAB Engine")] ePlugin_MatlabEngine, [helpstring("Plugin uses Python")] ePlugin_Python, } ePluginType; 143 DREAM Suite 1 6.5.16 ePriorDistrib /////////////////////////////////////////////////////////////////////////////////////////////////// // enum ePriorDistribution [helpstring("Reason of calling function CDreamEvaluator::GetPriorDataCustom")] typedef enum ePriorDistrib { [helpstring("Function called during initialization of dream solver")] ePriorInitialize, [helpstring("Function called during DREAM calculation")] ePriorCalculate, } ePriorDistrib; 6.5.17 ePriorType /////////////////////////////////////////////////////////////////////////////////////////////////// // enum ePriorType [helpstring("Type of prior distribution.")] typedef enum ePriorType { [helpstring("Univariate prior distribution")] eUnivariate, [helpstring("Multivariate prior distribution")] eMultivariate, [helpstring("Distribution calculated in CDreamEvaluator::GetPriorDataCustom")] eCustom } ePriorType; 6.5.18 eVectorization /////////////////////////////////////////////////////////////////////////////////////////////////// // enum eVectorization [helpstring("Option for vectorization.")] typedef enum eVectorization { [helpstring("Vectorization not used")] eVectNone, [helpstring("Vectorization used")] eVectYes } eVectorization; 144