Chaste Commit::fa89f2b838c1edb21a1eaec92ee3a2eacc9255dd
ExecutableSupport.cpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, 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
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF 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#include <sys/utsname.h> // For uname
43#define ChasteGetCurrentTime() ChasteBuildInfo::GetCurrentTime()
44#include <hdf5.h>
45#include <parmetis.h>
46
47
49#include "CommandLineArguments.hpp"
50#include "PetscException.hpp"
51#include "PetscSetupUtils.hpp"
52#include "PetscTools.hpp"
53
54#ifdef CHASTE_VTK
55#define _BACKWARD_BACKWARD_WARNING_H 1 //Cut out the strstream deprecated warning for now (gcc4.3)
56#include <vtkVersion.h>
57#endif
58
59#ifdef CHASTE_CVODE
60#include <sundials/sundials_config.h>
61#if CHASTE_SUNDIALS_VERSION >= 20600
62#if CHASTE_SUNDIALS_VERSION >= 30000
63// SUNDIALS 3.0 upwards uses SUNDIALS_VERSION instead of SUNDIALS_PACKAGE_VERSION.
64#define CHASTE_SUNDIALS_PACKAGE_VERSION SUNDIALS_VERSION
65#else
66// SUNDIALS 2.6 upwards defines SUNDIALS_PACKAGE_VERSION with quotes...
67#include <boost/preprocessor/stringize.hpp>
68#define CHASTE_SUNDIALS_PACKAGE_VERSION BOOST_PP_STRINGIZE(SUNDIALS_PACKAGE_VERSION)
69#endif // SUNDIALS >= 3.0.0
70#else
71#define CHASTE_SUNDIALS_PACKAGE_VERSION SUNDIALS_PACKAGE_VERSION
72#endif // SUNDIALS >= 2.6.0
73#endif
74
75// Note: the following are not a requirement for cell-based Chaste so may not be present!
76//#include <xsd/cxx/version.hxx>
77#ifdef CHASTE_XERCES
78#include <xercesc/util/XercesVersion.hpp>
79#endif
80
81// Check whether the version of ParMETIS being used is the one we wanted
82#ifdef CHASTE_PARMETIS_REQUIRED
83#ifdef PARMETIS_MAJOR_VERSION
84#if PARMETIS_MAJOR_VERSION != CHASTE_PARMETIS_REQUIRED
85#error "Wrong ParMETIS version found: " #CHASTE_PARMETIS_REQUIRED " requested but " #PARMETIS_MAJOR_VERSION " present"
86#endif
87#endif
88#endif
89
90#ifndef PARMETIS_MAJOR_VERSION
91// If there's no PARMETIS then assume we have Scotch
92#include <scotch/ptscotch.h>
93#endif
94
96
97void ExecutableSupport::SetOutputDirectory(const std::string& rOutputDirectory)
98{
99 if (FileFinder::IsAbsolutePath(rOutputDirectory))
100 {
102 }
103 else
104 {
106 }
107}
108
109void ExecutableSupport::InitializePetsc(int* pArgc, char*** pArgv)
110{
111 // Store the arguments in case other code needs them
114 // Initialise PETSc
115 PETSCEXCEPT(PetscInitialize(pArgc, pArgv, CHASTE_PETSC_NULLPTR, CHASTE_PETSC_NULLPTR));
116 // Set default output folder
118 {
119 // LCOV_EXCL_START
120 //depends on order of calls. Extract to method?
122 // LCOV_EXCL_STOP
123 }
124}
125
127{
128 // Compilation information
129 std::stringstream provenance_msg;
130 provenance_msg << "This version of Chaste was compiled on:\n";
131 provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
132 provenance_msg << "from revision number " << std::hex << ChasteBuildInfo::GetRevisionNumber() << std::dec << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
133
134 // Only show one copy of copyright/header
136 {
137 std::cout << ChasteBuildInfo::GetLicenceText() << std::endl;
138
139 // Write provenance information to stdout
140 std::cout << provenance_msg.str() << std::flush;
141 }
142}
143
145{
147 {
148 // Information to show that Chaste is being run in parallel
150 std::cout << "Chaste launched on process " << PetscTools::GetMyRank()
151 << " of " << PetscTools::GetNumProcs() << "." << std::endl
152 << std::flush;
154 }
155}
156
157void ExecutableSupport::WriteMachineInfoFile(std::string fileBaseName)
158{
160 {
161 // LCOV_EXCL_START
162 //depends on order of calls. Extract to method?
164 // LCOV_EXCL_STOP
165 }
166 OutputFileHandler out_file_handler(mOutputDirectory, false);
167 std::stringstream file_name;
168 file_name << fileBaseName << "_" << PetscTools::GetMyRank() << ".txt";
169 out_stream out_file = out_file_handler.OpenOutputFile(file_name.str());
170 *out_file << "Process " << PetscTools::GetMyRank() << " of "
171 << PetscTools::GetNumProcs() << "." << std::endl
172 << std::flush;
173
174 struct utsname uts_info;
175 uname(&uts_info);
176
177 *out_file << "uname sysname = " << uts_info.sysname << std::endl
178 << std::flush;
179 *out_file << "uname nodename = " << uts_info.nodename << std::endl
180 << std::flush;
181 *out_file << "uname release = " << uts_info.release << std::endl
182 << std::flush;
183 *out_file << "uname version = " << uts_info.version << std::endl
184 << std::flush;
185 *out_file << "uname machine = " << uts_info.machine << std::endl
186 << std::flush;
187 char buffer[100];
188 FILE* system_info;
189
190#ifdef __APPLE__
191 *out_file << "\nInformation on number and type processors, and cache and memory sizes (in bytes)\n";
192 system_info = popen("sysctl hw.ncpu hw.physicalcpu machdep.cpu.brand_string hw.l1icachesize hw.l1dcachesize hw.l2cachesize hw.l3cachesize hw.memsize", "r");
193 while (fgets(buffer, 100, system_info) != NULL)
194 {
195 *out_file << buffer;
196 }
197 pclose(system_info);
198#else
199 //GNU
200 *out_file << "\nInformation on number and type of processors:\n";
201 system_info = popen("grep ^model.name /proc/cpuinfo", "r");
202 while (fgets(buffer, 100, system_info) != nullptr)
203 {
204 *out_file << buffer;
205 }
206 pclose(system_info);
207
208 *out_file << "\nInformation on processor caches, in the same order as above:\n";
209 system_info = popen("grep ^cache.size /proc/cpuinfo", "r");
210 while (fgets(buffer, 100, system_info) != nullptr)
211 {
212 *out_file << buffer;
213 }
214 pclose(system_info);
215
216 *out_file << "\nInformation on system memory:\n";
217 system_info = popen("grep ^MemTotal /proc/meminfo", "r");
218 while (fgets(buffer, 100, system_info) != nullptr)
219 {
220 *out_file << buffer;
221 }
222 pclose(system_info);
223#endif //end of __APPLE__ not defined
224
225 out_file->close();
226}
227
229{
231 {
232 // LCOV_EXCL_START
233 //depends on order of calls. Extract to method?
235 // LCOV_EXCL_STOP
236 }
237 OutputFileHandler out_file_handler(mOutputDirectory, false);
238 out_stream out_file = out_file_handler.OpenOutputFile("provenance_info_", PetscTools::GetMyRank(), ".txt");
239
240 // Compilation information
241 std::stringstream provenance_msg;
242 provenance_msg << "This version of Chaste was compiled on:\n";
243 provenance_msg << ChasteBuildInfo::GetBuildTime() << " by " << ChasteBuildInfo::GetBuilderUnameInfo() << " (uname)\n";
244 provenance_msg << "from revision number " << std::hex << ChasteBuildInfo::GetRevisionNumber() << std::dec << " with build type " << ChasteBuildInfo::GetBuildInformation() << ".\n\n";
245 *out_file << provenance_msg.str();
246
247 std::string output;
248 GetBuildInfo(output);
249 *out_file << output;
250
251 out_file->close();
252}
253
254void ExecutableSupport::GetBuildInfo(std::string& rInfo)
255{
256 std::stringstream output;
257 output << "<ChasteBuildInfo>\n";
258
259 output << "\t<ProvenanceInfo>\n";
260 output << "\t\t<VersionString>" << ChasteBuildInfo::GetVersionString() << "</VersionString> <!-- build specific -->\n";
261 output << "\t\t<IsWorkingCopyModified>" << ChasteBuildInfo::IsWorkingCopyModified() << "</IsWorkingCopyModified>\n";
262 output << "\t\t<BuildInformation>" << ChasteBuildInfo::GetBuildInformation() << "</BuildInformation>\n";
263 output << "\t\t<BuildTime>" << ChasteBuildInfo::GetBuildTime() << "</BuildTime>\n";
264 output << "\t\t<CurrentTime>" << ChasteGetCurrentTime() << "</CurrentTime>\n";
265 output << "\t\t<BuilderUnameInfo>" << ChasteBuildInfo::GetBuilderUnameInfo() << "</BuilderUnameInfo>\n";
266 output << "\t\t<ChasteTestOutputDirectory>" << OutputFileHandler::GetChasteTestOutputDirectory() << "</ChasteTestOutputDirectory>\n";
267
268 output << "\t\t<Projects>\n";
269 {
270 const std::map<std::string, std::string>& r_projects_modified = ChasteBuildInfo::rGetIfProjectsModified();
271 const std::map<std::string, std::string>& r_projects_versions = ChasteBuildInfo::rGetProjectVersions();
272 for (const auto& r_project_version : r_projects_versions)
273 {
274 // LCOV_EXCL_START
275 // No projects are checked out for continuous builds normally!
276 output << "\t\t\t<Project>" << std::endl;
277 output << "\t\t\t\t<Name>" << r_project_version.first << "</Name>" << std::endl;
278 output << "\t\t\t\t<Version>" << r_project_version.second << "</Version>" << std::endl;
279 output << "\t\t\t\t<Modified>" << r_projects_modified.at(r_project_version.first) << "</Modified>" << std::endl;
280 output << "\t\t\t</Project>" << std::endl;
281 // LCOV_EXCL_STOP
282 }
283 }
284 output << "\t\t</Projects>\n";
285
286 output << "\t</ProvenanceInfo>\n";
287
288 output << "\t<Compiler>\n";
289 output << "\t\t<NameAndVersion>" << ChasteBuildInfo::GetCompilerType() << ", version " << ChasteBuildInfo::GetCompilerVersion() << "</NameAndVersion>\n";
290 output << "\t\t<Flags>" << ChasteBuildInfo::GetCompilerFlags() << "</Flags>\n";
291 output << "\t</Compiler>\n";
292
293 output << "\t<Libraries>\n";
294
295 output << "\t\t<CompiledIn>\n";
296 output << "\t\t\t<PETSc>" << PETSC_VERSION_MAJOR << "." << PETSC_VERSION_MINOR << "." << PETSC_VERSION_SUBMINOR << "</PETSc>\n";
297 output << "\t\t\t<Boost>" << BOOST_VERSION / 100000 << "." << BOOST_VERSION / 100 % 1000 << "." << BOOST_VERSION % 100 << "</Boost>\n";
298 output << "\t\t\t<HDF5>" << H5_VERS_MAJOR << "." << H5_VERS_MINOR << "." << H5_VERS_RELEASE << "</HDF5>\n";
299#ifdef PARMETIS_MAJOR_VERSION
300 output << "\t\t\t<Parmetis>" << PARMETIS_MAJOR_VERSION << "." << PARMETIS_MINOR_VERSION;
301#ifdef PARMETIS_SUBMINOR_VERSION // they only added this in v4.? !!
302 output << "." << PARMETIS_SUBMINOR_VERSION;
303#endif
304 output << "</Parmetis>" << std::endl;
305#else //PARMETIS_MAJOR_VERSION
306 // Assume we have Scotch
307 output << "\t\t\t<Parmetis>[NONE]</Parmetis>" << std::endl;
308 output << "\t\t\t<PT-Scotch>" << SCOTCH_VERSION<<"."<<SCOTCH_RELEASE<<"."<<SCOTCH_PATCHLEVEL<<"</PT-Scotch>"<< std::endl;
309#endif //no PARMETIS_MAJOR_VERSION
310
311 output << "\t\t</CompiledIn>\n";
312
313 output << "\t\t<Binaries>\n";
314 output << "\t\t\t<XSD>" << ChasteBuildInfo::GetXsdVersion() << "</XSD>\n";
315 output << "\t\t</Binaries>\n";
316
317 output << "\t\t<Optional>\n";
318#ifdef CHASTE_CVODE
319 output << "\t\t\t<SUNDIALS>" << CHASTE_SUNDIALS_PACKAGE_VERSION << "</SUNDIALS>";
320#if CHASTE_SUNDIALS_VERSION < 30000
321 output << "<!-- includes Cvode of a different version number -->";
322#endif
323 output << std::endl;
324#else
325 output << "\t\t\t<SUNDIALS>no</SUNDIALS>\n";
326#endif
327#ifdef CHASTE_VTK
328 output << "\t\t\t<VTK>" << VTK_MAJOR_VERSION << "." << VTK_MINOR_VERSION << "</VTK>\n";
329#else
330 output << "\t\t\t<VTK>no</VTK>\n";
331#endif
332#ifdef CHASTE_XERCES
333 output << "\t\t\t<Xerces>" << XERCES_FULLVERSIONDOT << "</Xerces>\n"; // Note: not a requirement for cell-based so may not be present!
334#else
335 output << "\t\t\t<Xerces>no</Xerces>\n";
336#endif
337 output << "\t\t</Optional>\n";
338
339 output << "\t</Libraries>\n";
340
341 output << "\t<ChasteCodegenVersion>" << ChasteBuildInfo::GetChasteCodegenVersion() << "</ChasteCodegenVersion>\n";
342
343 output << "</ChasteBuildInfo>" << std::endl;
344 rInfo = output.str();
345}
346
347void ExecutableSupport::StandardStartup(int* pArgc, char*** pArgv)
348{
349 InitializePetsc(pArgc, pArgv);
352}
353
355{
356 InitializePetsc(pArgc, pArgv);
358}
359
360void ExecutableSupport::PrintError(const std::string& rMessage, bool masterOnly)
361{
362 if (!masterOnly || PetscTools::AmMaster())
363 {
364 // Write the error message to stderr
365 std::cerr << rMessage << std::endl;
366 }
367
368 // Write the error message to file
370 {
371 // LCOV_EXCL_START
372 //depends on order of calls. Extract to method?
374 // LCOV_EXCL_STOP
375 }
376 OutputFileHandler out_file_handler(mOutputDirectory, false);
377 out_stream out_file = out_file_handler.OpenOutputFile("chaste_errors_", PetscTools::GetMyRank(), ".txt", std::ios::out | std::ios::app);
378 *out_file << rMessage << std::endl;
379 out_file->close();
380}
381
382void ExecutableSupport::Print(const std::string& rMessage)
383{
385 {
386 // Write the error message to stdout
387 std::cout << rMessage << std::endl
388 << std::flush;
389 }
390}
391
393{
394 // Causes memory failure (and seg fault) in PETSc 3.2 with MPICH-1
396}
#define CHASTE_PETSC_NULLPTR
A macro to define PETSc null pointer based on the PETSc version.
static const std::map< std::string, std::string > & rGetIfProjectsModified()
static unsigned long long GetRevisionNumber()
static const char * GetBuilderUnameInfo()
static const char * GetCompilerFlags()
static const char * GetBuildTime()
static std::string GetChasteCodegenVersion()
static std::string GetVersionString()
static const char * GetBuildInformation()
static const std::map< std::string, std::string > & rGetProjectVersions()
static bool IsWorkingCopyModified()
static const char * GetCompilerVersion()
static const char * GetCompilerType()
static const char * GetXsdVersion()
static std::string GetLicenceText()
static CommandLineArguments * Instance()
static void Print(const std::string &rMessage)
static void SetOutputDirectory(const std::string &rOutputDirectory)
static void GetBuildInfo(std::string &rInfo)
static void WriteMachineInfoFile(std::string fileBaseName)
static void ShowParallelLaunching()
static void ShowCopyright()
static FileFinder mOutputDirectory
static void StartupWithoutShowingCopyright(int *pArgc, char ***pArgv)
static void StandardStartup(int *pArgc, char ***pArgv)
static void FinalizePetsc()
static void WriteProvenanceInfoFile()
static void PrintError(const std::string &rMessage, bool masterOnly=false)
static void InitializePetsc(int *pArgc, char ***pArgv)
static bool IsAbsolutePath(const std::string &rPath)
virtual void SetPath(const std::string &rPath, RelativeTo::Value relativeTo)
bool IsPathSet() const
static std::string GetChasteTestOutputDirectory()
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static void CommonFinalize()
static bool AmMaster()
static bool IsParallel()
static void EndRoundRobin()
static unsigned GetMyRank()
static void BeginRoundRobin()
static unsigned GetNumProcs()