5 Debugging OOMMF

5.1 Configuration Files

There are several OOMMF configuration settings that impact debug operations. The controlling files are config/options.tcl and config/platforms/<platform>.tcl, where the <platform> is windows-x86_64, linux-x86_64, or darwin for Windows, Linux, or macOS operating systems respectively. In practice, rather than modifying the default distribution files directly, you should place your modifications in local files config/local/options.tcl and config/platforms/local/<platform>.tcl. The local/ directories and files are not part of the OOMMF distribution; you will need to create them manually. The files can be empty initially, and then populated as desired.

The options.tcl file contains platform-agnostic settings that are stored in the Oc_Option database. Some of these settings affect the build process, while others control post-build runtime behavior. All are set using the Oc_Option command, which takes name + value pairs. The cflags and optlevel settings control compiler options. The default setting for cflags is

Oc_Option Add * Platform cflags {-def NDEBUG}

which causes the C macro “NDEBUG” to be defined. If this is not set then various run-time checks such as assert statements and some array index checks are activated. These checks slow execution but may be helpful in diagnosing errors. Other cflag options include -warn, which enables compiler warning messages, and -debug, which tells the compiler to generate debugging symbols. A good cflags setting for debugging is

Oc_Option Add * Platform cflags {-warn 1 -debug 1}

There is also an lflags option, similar to cflags, that controls options to the linker. The default is an empty string (no options), and you generally don’t need to change this.

The optlevel option sets the compiler optimization level, with an integer value between 0 and 3. The default value is 2, which selects for a high but reliable level of optimizations. Some optimizations may reorder and combine source code statements, making it harder to debug code, so you may want to use

Oc_Option Add * Platform optlevel 0

to disable all optimizations.

The config/platforms/<platform>.tcl files set default platform and compiler specific options. For example, config/platforms/windows-x86_64.tcl is the base platform file for 64-bit Windows. There are separate sections inside this file for the various supported compilers. You can make local changes to the default settings by creating a subdirectory of config/platforms/ named local/, and creating there an initially empty file with the same name as the base platform file. Inside the base platform file is a code block labeled LOCAL CONFIGURATION, which lists all the available local modifications. You can copy some or all of this Tcl code block to your new config/platforms/local/ file, and then uncomment and modify options as desired. For example, if you are using the Visual C++ compiler on Windows, you may want to include the /RTCus compiler flag to enable some run-time error checks. You can do that with these lines in your local/windows-x86_64.tcl file:

$config SetValue program_compiler_c++_remove_flags {/O2}
$config SetValue program_compiler_c++_remove_valuesafeflags {/O2}
$config SetValue program_compiler_c++_add_flags {/RTCus}
$config SetValue program_compiler_c++_add_valuesafeflags {/RTCus}

The *_valuesafeflags options are for code with sensitive floating-point operations that must be evaluated exactly as specified. This pertains primarily to the double-double routines in pkg/xp/. The *_flags options are for everything else. The *_remove_* controls remove options from the default compile command. This can be a (Tcl) list, with each element matching as a regular expression. (Refer to the Tcl documentation on the regexp command for details.) The *_add_* controls append options. OOMMF sets /O2 optimization by default, but /O2 is incompatible with /RTCus, so in this example /O2 is removed to allow /RTCus to be added. (Setting optlevel 0 in the config/local/options.tcl file, as explained above, replaces /O2 with /Od. So strictly speaking it is not necessary to remove /O2 in that case, but it doesn’t hurt either.)

You can run the command “oommf.tcl +platform +v” to see the effects of your current options.tcl and <platform>.tcl settings. For example,

$ tclsh oommf.tcl +platform +v
[...]
--- Local config options ---
[...]
   Oc_Option Add * Platform cflags -debug 1 -warn 1
   Oc_Option Add * Platform optlevel 0
[...]
--- Local platform options ---
   $config SetValue program_compiler_c++_remove_flags /O2
   $config SetValue program_compiler_c++_remove_valuesafeflags /O2
   $config SetValue program_compiler_c++_add_flags /RTCus
   $config SetValue program_compiler_c++_add_valuesafeflags /RTCus

--- Compiler options ---
     Standard options: /Od /D_CRT_SECURE_NO_DEPRECATE /RTCus
   Value-safe options: /Od /fp:precise /D_CRT_SECURE_NO_DEPRECATE /RTCus

To see the exact, full platform-specific compile and link commands, you can delete and rebuild individual executables in the OOMMF package. Two examples, one using the standard build options (pkg/oc/<platform>/varinfo) and one using the value-safe options (pkg/xp/<platform>/build_port) are presented below. (The response lines have been edited for clarity.)

% cd pkg/oc
% tclsh ../../oommf.tcl pimake clean
% tclsh ../../oommf.tcl pimake darwin/varinfo
clang++ -c -DNDEBUG -m64 -std=c++11 -Ofast -o darwin/varinfo.o varinfo.cc
clang++ -m64 darwin/varinfo.o -o darwin/varinfo

% cd ../..
% cd pkg/xp
% tclsh ../../oommf.tcl pimake clean
% tclsh ../../oommf.tcl pimake darwin/build_port
clang++ -c -DNDEBUG -m64 -std=c++11 -O3 -DXP_USE_MPFR=0
   -o darwin/build_port.o build_port.cc
clang++ -m64 darwin/build_port.o -o darwin/build_port
The above is for macOS. Adjust the <platform> field as appropriate, and on Windows append .exe to the executable targets (varinfo and build_port).

You can also use this method to manually compile and/or link individual files: (1) Change to the relevant build directory (always one level below either pkg or app), (2) delete the file you want to rebuild from the <platform> directory, (3) run pimake as above to build the file, (4) copy and paste the compile/link command to the shell prompt, edit as desired, and rerun.

The varinfo and build_port executables are used to construct the platform-specific header files pkg/oc/<platform>/ocport.h and pkg/xp/<platform>/xpport.h. These files contain C++ macro definitions, typedefs, and function wrappers, and are an important adjunct when reading the OOMMF source code.

For in-depth investigations Tcl can be used to directly query and debug OOMMF initialization scripts. Start a Tcl shell, and from inside the shell append the OOMMF pkg/oc directory to the Tcl global auto_path variable. Next run package require Oc to load the Tcl-only portion of the OOMMF Oc library into the shell. Then you can check any and all Oc_Option values from config/options.tcl, platform configuration settings from config/platforms/<platform>.tcl, and perform various other types of introspection from the Tcl shell. See Fig. 5.1 for a sample session.

 

Figure 5.1: Sample Tcl-level OOMMF introspection session. Shell commands are colored cyan (with $ prompt) and Tcl commands are colored red (with % prompt). (description)
$ pwd
/Users/barney/oommf
$ tclsh
% set env(OOMMF_BUILD_ENVIRONMENT_NEEDED) 1
% lappend auto_path [file join [pwd] pkg oc]
% package require Oc

% # Miscellaneous utilities from Oc_Main (oommf/pkg/oc/main.tcl)
% Oc_Main GetOOMMFRootDir    ;# OOMMF root directory
/Users/barney/oommf
% Oc_Main GetPid             ;# Process id
17423

% # Oc_Option database (oommf/config/options.tcl)
% # Code details in oommf/pkg/oc/option.tcl
% Oc_Option Get *            ;# Registered Option classes (glob-match)
Net_Link Oc_Url Platform Menu Nb_InputFilter Net_Server Oc_Class Color
Net_Host MIFinterp OxsLogs 
% Oc_Option Get Platform *   ;# All options for class Platform (glob-match)
cflags lflags optlevel
% Oc_Option GetValue Platform cflags  ;# Platform,cflags value
-def NDEBUG

% # Configuration values (oommf/config/platforms/<platform>.tcl)
% # Code details in oommf/pkg/oc/config.tcl
% set config [Oc_Config RunPlatform]
% $config GetValue platform_name                          ;# Platform name
darwin
% $config GetValue program_compiler_c++_name              ;# C++ compiler
clang++
% $config GetValue program_compiler_c++_typedef_realwide  ;# realwide typedef
long double
% $config Features program_linker*             ;# GetValue names (glob-match)
program_linker_option_lib program_linker program_linker_rpath
program_linker_uses_-L-l program_linker_option_out program_linker_option_obj

% exit                                ;# Exit Tcl shell