Chaste  Release::3.4
ExecutableSupport.cpp
1 /*
2 
3 Copyright (c) 2005-2016, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "ExecutableSupport.hpp"
37 
38 #include "Version.hpp"
39 
40 #include <iostream>
41 #include <sstream>
42 #ifdef _MSC_VER
43 #include <windows.h> // For system info on Windows
44 //GetCurrentTime clashes with a similarly-named API in <windows.h>
45 #define GetCurrentTime() ChasteBuildInfo::GetCurrentTime()
46 #define ChasteGetCurrentTime() GetCurrentTime()
47 #else
48 #include <sys/utsname.h> // For uname
49 #define ChasteGetCurrentTime() ChasteBuildInfo::GetCurrentTime()
50 #endif
51 #include <hdf5.h>
52 #include <parmetis.h>
53 
54 #include <boost/foreach.hpp>
55 typedef std::pair<std::string, std::string> StringPair;
56 
57 #include "CommandLineArguments.hpp"
58 #include "Exception.hpp"
59 #include "PetscTools.hpp"
60 #include "PetscSetupUtils.hpp"
61 #include "PetscException.hpp"
62 #include "ChasteSerialization.hpp"
63 
64 #ifdef CHASTE_VTK
65 #define _BACKWARD_BACKWARD_WARNING_H 1 //Cut out the strstream deprecated warning for now (gcc4.3)
66 #include <vtkVersion.h>
67 #endif
68 
69 #ifdef CHASTE_CVODE
70 #include <sundials/sundials_config.h>
71 #if CHASTE_SUNDIALS_VERSION >= 20600
72 // SUNDIALS 2.6 defined SUNDIALS_PACKAGE_VERSION without quotes...
73 # include <boost/preprocessor/stringize.hpp>
74 # define CHASTE_SUNDIALS_PACKAGE_VERSION BOOST_PP_STRINGIZE(SUNDIALS_PACKAGE_VERSION)
75 #else
76 # define CHASTE_SUNDIALS_PACKAGE_VERSION SUNDIALS_PACKAGE_VERSION
77 #endif // SUNDIALS >= 2.6.0
78 #endif
79 
80 // Note: the following are not a requirement for cell-based Chaste so may not be present!
81 //#include <xsd/cxx/version.hxx>
82 #ifdef CHASTE_XERCES
83 #include <xercesc/util/XercesVersion.hpp>
84 #endif
85 
86 // Check whether the version of ParMETIS being used is the one we wanted
87 #ifdef CHASTE_PARMETIS_REQUIRED
88 # if PARMETIS_MAJOR_VERSION != CHASTE_PARMETIS_REQUIRED
89 # error "Wrong ParMETIS version found: " #CHASTE_PARMETIS_REQUIRED " requested but " #PARMETIS_MAJOR_VERSION " present"
90 # endif
91 #endif
92 
94 
95 void ExecutableSupport::SetOutputDirectory(const std::string& rOutputDirectory)
96 {
97  if (FileFinder::IsAbsolutePath(rOutputDirectory))
98  {
100  }
101  else
102  {
104  }
105 }
106 
107 void ExecutableSupport::InitializePetsc(int* pArgc, char*** pArgv)
108 {
109  // Store the arguments in case other code needs them
112  // Initialise PETSc
113  PETSCEXCEPT(PetscInitialize(pArgc, pArgv, PETSC_NULL, PETSC_NULL));
114  // Set default output folder
116  {
117 #define COVERAGE_IGNORE
118  //depends on order of calls. Extract to method?
120 #undef COVERAGE_IGNORE
121  }
122 }
123 
125 {
126  // Compilation information
127  std::stringstream provenance_msg;
128  provenance_msg << "This version of Chaste was compiled on:\n";
129  provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
130  provenance_msg << "from revision number " << ChasteBuildInfo::GetRevisionNumber() << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
131 
132  // Only show one copy of copyright/header
133  if (PetscTools::AmMaster())
134  {
135  std::cout << ChasteBuildInfo::GetLicenceText() << std::endl;
136 
137  // Write provenance information to stdout
138  std::cout << provenance_msg.str() << std::flush;
139  }
140 }
141 
143 {
145  {
146  // Information to show that Chaste is being run in parallel
148  std::cout << "Chaste launched on process " << PetscTools::GetMyRank()
149  << " of " << PetscTools::GetNumProcs() << "." << std::endl << std::flush;
151  }
152 }
153 
154 void ExecutableSupport::WriteMachineInfoFile(std::string fileBaseName)
155 {
157  {
158 #define COVERAGE_IGNORE
159  //depends on order of calls. Extract to method?
161 #undef COVERAGE_IGNORE
162  }
163  OutputFileHandler out_file_handler(mOutputDirectory, false);
164  std::stringstream file_name;
165  file_name << fileBaseName << "_" << PetscTools::GetMyRank() << ".txt";
166  out_stream out_file = out_file_handler.OpenOutputFile(file_name.str());
167  *out_file << "Process " << PetscTools::GetMyRank() << " of "
168  << PetscTools::GetNumProcs() << "." << std::endl << std::flush;
169 
170 #ifdef _MSC_VER
171  //use native windows equivalent of system info. from uname and /proc/cpuinfo
172 
173  //operating system and machine name
174  *out_file << "uname sysname = " << "Microsoft Windows" << std::endl;
175  #define INFO_BUFFER_SIZE 32767
176  TCHAR info_buffer[INFO_BUFFER_SIZE];
177  DWORD buffer_char_count = INFO_BUFFER_SIZE;
178  if(!GetComputerName(info_buffer, &buffer_char_count))
179  *out_file << "uname nodename = " << "Windows machine name is unknown" << std::endl;
180  else
181  *out_file << "uname nodename = " << info_buffer << std::endl;
182  //more detailed operating system version information
183  OSVERSIONINFOEX os_info;
184  ZeroMemory(&os_info, sizeof(OSVERSIONINFO));
185  os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
186  //copy os version info into the structure
187  GetVersionEx((OSVERSIONINFO*) &os_info);
188  //Pivot around Windows Vista (dwMajorVersion >= 6)
189  //See http://msdn.microsoft.com/en-us/library/ms724834%28v=vs.85%29.aspx for details
190  if(os_info.dwMajorVersion < 6)
191  { //earlier than Windows Vista
192  *out_file << "uname release = " << "Microsoft Windows Server 2003 R2 (or earlier)" << std::endl;
193  }
194  else {
195  //reverse chronological order (simply add newer OS version to the top)
196  if(os_info.dwMajorVersion > 6)
197  {
198  *out_file << "uname release = " << "Microsoft Windows (Later than Microsoft Windows 8)" << std::endl;
199  }
200  else //os_info.dwMajorVersion == 6
201  {
202  if(os_info.dwMinorVersion == 2)
203  {
204  if(os_info.wProductType == VER_NT_WORKSTATION)
205  *out_file << "uname release = " << "Microsoft Windows 8" << std::endl;
206  else
207  *out_file << "uname release = " << "Microsoft Windows Server 2012" << std::endl;
208  }
209  else if(os_info.dwMinorVersion == 1)
210  {
211  if(os_info.wProductType == VER_NT_WORKSTATION)
212  *out_file << "uname release = " << "Microsoft Windows 7" << std::endl;
213  else
214  *out_file << "uname release = " << "Microsoft Windows Server 2008 R2" << std::endl;
215  }
216  else if(os_info.dwMinorVersion == 0)
217  {
218  if(os_info.wProductType == VER_NT_WORKSTATION)
219  *out_file << "uname release = " << "Microsoft Windows Server 2008" << std::endl;
220  else
221  *out_file << "uname release = " << "Microsoft Windows Vista" << std::endl;
222  }
223  }
224  }
225  *out_file << "uname version = " << os_info.dwMajorVersion << "." << os_info.dwMinorVersion << std::endl;
226 
227  //hardware information
228  // See http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx for details of the SYSTEM_INFO structure
229  SYSTEM_INFO sys_info;
230  GetSystemInfo(&sys_info);
231  switch (sys_info.wProcessorArchitecture)
232  {
233  case PROCESSOR_ARCHITECTURE_AMD64:
234  *out_file << "uname machine = " << "x64 (AMD or Intel)" << std::endl;
235  break;
236  case PROCESSOR_ARCHITECTURE_ARM:
237  *out_file << "uname machine = " << "ARM" << std::endl;
238  break;
239  case PROCESSOR_ARCHITECTURE_IA64:
240  *out_file << "uname machine = " << "Intel Itanium-based" << std::endl;
241  break;
242  case PROCESSOR_ARCHITECTURE_INTEL:
243  *out_file << "uname machine = " << "x86" << std::endl;
244  break;
245  case PROCESSOR_ARCHITECTURE_UNKNOWN:
246  *out_file << "uname machine = " << "Unknown Architecture" << std::endl;
247  break;
248  default:
249  *out_file << "uname machine = " << "Other Architecture. Code = " << sys_info.wProcessorArchitecture << std::endl;
250  break;
251  }
252 
253  *out_file << "\nInformation on number and type of processors:" << std::endl;
254  *out_file << sys_info.dwNumberOfProcessors;
255  *out_file << "\nInformation on processor caches, in the same order as above:" << std::endl;
256  *out_file << "Unknown" << std::endl;
257 
258  //get physical memory
259  MEMORYSTATUSEX mem_status;
260  mem_status.dwLength = sizeof (mem_status);
261  GlobalMemoryStatusEx (&mem_status);
262  *out_file << "\nInformation on system memory:" << std::endl;
263  *out_file << mem_status.ullTotalPhys/1024 << " kB" << std::endl;
264 #else
265  struct utsname uts_info;
266  uname(&uts_info);
267 
268  *out_file << "uname sysname = " << uts_info.sysname << std::endl << std::flush;
269  *out_file << "uname nodename = " << uts_info.nodename << std::endl << std::flush;
270  *out_file << "uname release = " << uts_info.release << std::endl << std::flush;
271  *out_file << "uname version = " << uts_info.version << std::endl << std::flush;
272  *out_file << "uname machine = " << uts_info.machine << std::endl << std::flush;
273  char buffer[100];
274  FILE* system_info;
275 
276 #ifdef __APPLE__
277  *out_file << "\nInformation on number and type processors, and cache and memory sizes (in bytes)\n";
278  system_info = popen("sysctl hw.ncpu hw.physicalcpu machdep.cpu.brand_string hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize hw.memsize", "r");
279  while ( fgets(buffer, 100, system_info) != NULL )
280  {
281  *out_file << buffer;
282  }
283  fclose(system_info);
284 #else
285  //GNU
286  *out_file << "\nInformation on number and type of processors:\n";
287  system_info = popen("grep ^model.name /proc/cpuinfo", "r");
288  while ( fgets(buffer, 100, system_info) != NULL )
289  {
290  *out_file << buffer;
291  }
292  fclose(system_info);
293 
294  *out_file << "\nInformation on processor caches, in the same order as above:\n";
295  system_info = popen("grep ^cache.size /proc/cpuinfo", "r");
296  while ( fgets(buffer, 100, system_info) != NULL )
297  {
298  *out_file << buffer;
299  }
300  fclose(system_info);
301 
302  *out_file << "\nInformation on system memory:\n";
303  system_info = popen("grep ^MemTotal /proc/meminfo", "r");
304  while ( fgets(buffer, 100, system_info) != NULL )
305  {
306  *out_file << buffer;
307  }
308  fclose(system_info);
309 #endif //end of __APPLE__ not defined
310 #endif //end of _MSC_VER not defined
311 
312  out_file->close();
313 }
314 
316 {
318  {
319 #define COVERAGE_IGNORE
320  //depends on order of calls. Extract to method?
322 #undef COVERAGE_IGNORE
323  }
324  OutputFileHandler out_file_handler(mOutputDirectory, false);
325  out_stream out_file = out_file_handler.OpenOutputFile("provenance_info_", PetscTools::GetMyRank(), ".txt");
326 
327  // Compilation information
328  std::stringstream provenance_msg;
329  provenance_msg << "This version of Chaste was compiled on:\n";
330  provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
331  provenance_msg << "from revision number " << ChasteBuildInfo::GetRevisionNumber() << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
332  *out_file << provenance_msg.str();
333 
334  std::string output;
335  GetBuildInfo(output);
336  *out_file << output;
337 
338  out_file->close();
339 }
340 
341 void ExecutableSupport::GetBuildInfo(std::string& rInfo)
342 {
343  std::stringstream output;
344  output << "<ChasteBuildInfo>\n";
345 
346  output << "\t<ProvenanceInfo>\n";
347  output << "\t\t<VersionString>"<< ChasteBuildInfo::GetVersionString() << "</VersionString> <!-- build specific -->\n";
348  output << "\t\t<IsWorkingCopyModified>"<< ChasteBuildInfo::IsWorkingCopyModified() << "</IsWorkingCopyModified>\n";
349  output << "\t\t<BuildInformation>"<< ChasteBuildInfo::GetBuildInformation() << "</BuildInformation>\n";
350  output << "\t\t<BuildTime>"<< ChasteBuildInfo::GetBuildTime() << "</BuildTime>\n";
351  output << "\t\t<CurrentTime>"<< ChasteGetCurrentTime() << "</CurrentTime>\n";
352  output << "\t\t<BuilderUnameInfo>"<< ChasteBuildInfo::GetBuilderUnameInfo() << "</BuilderUnameInfo>\n";
353  output << "\t\t<Projects>\n";
354  BOOST_FOREACH(const StringPair& r_project_version, ChasteBuildInfo::rGetProjectVersions())
355  {
356 #define COVERAGE_IGNORE
357  // No projects are checked out for continuous builds normally!
358  output<< "\t\t\t<Name>" << r_project_version.first << "</Name><Version>"
359  << r_project_version.second << "</Version>\n";
360 #undef COVERAGE_IGNORE
361  }
362  output << "\t\t</Projects>\n";
363  output << "\t</ProvenanceInfo>\n";
364 
365  output << "\t<Compiler>\n";
366  output << "\t\t<NameAndVersion>" << ChasteBuildInfo::GetCompilerType() << ", version " << ChasteBuildInfo::GetCompilerVersion() << "</NameAndVersion>\n" ;
367  output << "\t\t<Flags>" << ChasteBuildInfo::GetCompilerFlags() << "</Flags>\n" ;
368  output << "\t</Compiler>\n";
369 
370  output << "\t<Libraries>\n";
371 
372  output << "\t\t<CompiledIn>\n";
373  output << "\t\t\t<PETSc>" << PETSC_VERSION_MAJOR << "." << PETSC_VERSION_MINOR << "." << PETSC_VERSION_SUBMINOR << "</PETSc>\n";
374  output << "\t\t\t<Boost>" << BOOST_VERSION / 100000 << "." << BOOST_VERSION / 100 % 1000 << "." << BOOST_VERSION % 100 << "</Boost>\n";
375  output << "\t\t\t<HDF5>" << H5_VERS_MAJOR << "." << H5_VERS_MINOR << "." << H5_VERS_RELEASE << "</HDF5>\n";
376  output << "\t\t\t<Parmetis>" << PARMETIS_MAJOR_VERSION << "." << PARMETIS_MINOR_VERSION;
377 #ifdef PARMETIS_SUBMINOR_VERSION // they only added this in v4.? !!
378  output << "." << PARMETIS_SUBMINOR_VERSION;
379 #endif
380  output << "</Parmetis>" << std::endl;
381  output << "\t\t</CompiledIn>\n";
382 
383  output << "\t\t<Binaries>\n";
384  output << "\t\t\t<XSD>" << ChasteBuildInfo::GetXsdVersion() << "</XSD>\n";
385  output << "\t\t</Binaries>\n";
386 
387  output << "\t\t<Optional>\n";
388 #ifdef CHASTE_CVODE
389  output << "\t\t\t<SUNDIALS>" << CHASTE_SUNDIALS_PACKAGE_VERSION << "</SUNDIALS> <!-- includes Cvode of a different version number --> \n";
390 #else
391  output << "\t\t\t<SUNDIALS>no</SUNDIALS>\n";
392 #endif
393 #ifdef CHASTE_VTK
394  output << "\t\t\t<VTK>" << VTK_MAJOR_VERSION << "." << VTK_MINOR_VERSION << "</VTK>\n";
395 #else
396  output << "\t\t\t<VTK>no</VTK>\n";
397 #endif
398 #ifdef CHASTE_XERCES
399  output << "\t\t\t<Xerces>" << XERCES_FULLVERSIONDOT << "</Xerces>\n"; // Note: not a requirement for cell-based so may not be present!
400 #else
401  output << "\t\t\t<Xerces>no</Xerces>\n";
402 #endif
403  output << "\t\t</Optional>\n";
404 
405  output << "\t</Libraries>\n";
406 
407  output << "</ChasteBuildInfo>" << std::endl;
408  rInfo = output.str();
409 }
410 
411 void ExecutableSupport::StandardStartup(int* pArgc, char*** pArgv)
412 {
413  InitializePetsc(pArgc, pArgv);
414  ShowCopyright();
416 }
417 
418 void ExecutableSupport::PrintError(const std::string& rMessage, bool masterOnly)
419 {
420  if (!masterOnly || PetscTools::AmMaster())
421  {
422  // Write the error message to stderr
423  std::cerr << rMessage << std::endl;
424  }
425 
426  // Write the error message to file
428  {
429 #define COVERAGE_IGNORE
430  //depends on order of calls. Extract to method?
432 #undef COVERAGE_IGNORE
433  }
434  OutputFileHandler out_file_handler(mOutputDirectory, false);
435  out_stream out_file = out_file_handler.OpenOutputFile("chaste_errors_", PetscTools::GetMyRank(), ".txt", std::ios::out | std::ios::app);
436  *out_file << rMessage << std::endl;
437  out_file->close();
438 }
439 
440 void ExecutableSupport::Print(const std::string& rMessage)
441 {
442  if (PetscTools::AmMaster())
443  {
444  // Write the error message to stdout
445  std::cout << rMessage << std::endl << std::flush;
446  }
447 }
448 
450 {
451  // Causes memory failure (and seg fault) in PETSc 3.2 with MPICH-1
453 }
static void FinalizePetsc()
static std::string GetLicenceText()
static const char * GetCompilerType()
static const char * GetBuildInformation()
static bool IsAbsolutePath(const std::string &rPath)
Definition: FileFinder.cpp:528
bool IsPathSet() const
Definition: FileFinder.cpp:175
static void Print(const std::string &rMessage)
static bool AmMaster()
Definition: PetscTools.cpp:120
static void CommonFinalize()
static const char * GetCompilerFlags()
static void ShowParallelLaunching()
static void WriteProvenanceInfoFile()
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static const char * GetBuilderUnameInfo()
static const char * GetBuildTime()
static bool IsWorkingCopyModified()
static void EndRoundRobin()
Definition: PetscTools.cpp:160
static void PrintError(const std::string &rMessage, bool masterOnly=false)
static void BeginRoundRobin()
Definition: PetscTools.cpp:150
static void StandardStartup(int *pArgc, char ***pArgv)
static unsigned GetRevisionNumber()
static const char * GetXsdVersion()
static FileFinder mOutputDirectory
static void InitializePetsc(int *pArgc, char ***pArgv)
static bool IsParallel()
Definition: PetscTools.cpp:97
static void GetBuildInfo(std::string &rInfo)
static CommandLineArguments * Instance()
static const char * GetCompilerVersion()
static unsigned GetNumProcs()
Definition: PetscTools.cpp:108
virtual void SetPath(const std::string &rPath, RelativeTo::Value relativeTo)
Definition: FileFinder.cpp:99
static std::string GetVersionString()
static void ShowCopyright()
static unsigned GetMyRank()
Definition: PetscTools.cpp:114
static void WriteMachineInfoFile(std::string fileBaseName)
static const std::map< std::string, std::string > & rGetProjectVersions()
static void SetOutputDirectory(const std::string &rOutputDirectory)