https://mooseframework.inl.gov
Capabilities.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 // Needs to be included before Capabilities.h, which
11 // includes nlohmann/json_fwd.h
12 #include "nlohmann/json.h"
13 
14 #include "Capabilities.h"
15 #include "CapabilityException.h"
16 #include "MooseUtils.h"
17 #include "Conversion.h"
18 
19 #include <vector>
20 
21 #include "libmesh/libmesh_config.h"
22 #include "petscconf.h"
23 #include "petscpkg_version.h"
24 
25 #ifdef MOOSE_LIBTORCH_ENABLED
26 #include <torch/version.h>
27 #endif
28 
29 #if __has_include(<torch/xpu.h>)
30 #include <torch/xpu.h>
31 #define MOOSE_HAVE_XPU 1
32 #endif
33 
34 #ifdef MOOSE_MFEM_ENABLED
35 #include "mfem/config/config.hpp"
36 #endif
37 
38 #ifdef LIBMESH_HAVE_NETGEN
39 #include "netgen/netgen_version.hpp"
40 #endif
41 
42 namespace Moose::internal
43 {
44 
46 {
47  // Register the moose capabilities, just once
49 }
50 
53 {
54  // We need a naked new here (_not_ a smart pointer or object instance) due to what seems like a
55  // bug in clang's static object destruction when using dynamic library loading.
56  static Capabilities * capability_registry = nullptr;
57  if (!capability_registry)
58  capability_registry = new Capabilities();
59  return *capability_registry;
60 }
61 
62 std::string
64 {
65  nlohmann::json root;
66  for (const auto & [name, capability] : _registry)
67  {
68  auto & entry = root[name];
69  std::visit([&entry](const auto & v) { entry["value"] = v; }, capability.getValue());
70  entry["doc"] = capability.getDoc();
71  if (const auto enumeration_ptr = capability.queryEnumeration())
72  entry["enumeration"] = *enumeration_ptr;
73  if (!capability.hasBoolValue())
74  entry["explicit"] = capability.getExplicit();
75  }
76  return root.dump(2);
77 }
78 
79 void
80 Capabilities::augment(const nlohmann::json & input, const Capabilities::AugmentPassKey)
81 {
82  for (const auto & [name_json, entry] : input.items())
83  {
84  const std::string name = name_json;
85 
86  const auto error = [&name](const std::string & message)
87  { throw CapabilityException("Capabilities::augment: Capability '" + name + "' " + message); };
88 
89  std::string doc;
90  if (const auto it = entry.find("doc"); it != entry.end())
91  doc = *it;
92  else
93  error("missing 'doc' entry");
94 
96  if (const auto it = entry.find("value"); it != entry.end())
97  {
98  if (it->is_boolean())
99  value = it->get<bool>();
100  else if (it->is_number_integer())
101  value = it->get<int>();
102  else
103  value = it->get<std::string>();
104  }
105  else
106  error("missing 'value' entry");
107 
108  auto & capability = add(name, value, doc);
109 
110  if (const auto it = entry.find("explicit"); it != entry.end() && it->get<bool>())
111  capability.setExplicit();
112 
113  if (const auto it = entry.find("enumeration"); it != entry.end())
114  capability.setEnumeration(it->get<std::set<std::string>>());
115  }
116 }
117 
118 bool
119 Capabilities::isInstallationType(const std::string & installation_type) const
120 {
121  const auto & capability = get("installation_type");
122  mooseAssert(capability.getEnumeration().count(installation_type), "Not a valid enumeration");
123  return capability.getStringValue() == installation_type;
124 }
125 
126 void
128 {
129  // helper lambdas for explicitly adding typed capabilities
130  const auto add_bool = [&](const std::string_view capability,
131  const bool value,
132  const std::string_view doc) -> Capability &
133  { return add(capability, value, doc); };
134  const auto add_int = [&](const std::string_view capability,
135  const int value,
136  const std::string_view doc) -> Capability &
137  { return add(capability, value, doc); };
138  const auto add_string = [&](const std::string_view capability,
139  const std::string_view value,
140  const std::string_view doc) -> Capability &
141  { return add(capability, std::string(value), doc); };
142 
143  // helper lambdas for adding capabilities
144  const auto have = [&](const std::string & capability, const std::string & doc) -> Capability &
145  { return add_bool(capability, true, doc + " is available."); };
146  const auto missing = [&](const std::string & capability,
147  const std::string & doc,
148  const std::string & help = "") -> Capability &
149  { return add_bool(capability, false, doc + " is not available. " + help); };
150 
151  const auto have_version = [&](const std::string & capability,
152  const std::string & doc,
153  const std::string & version) -> Capability &
154  { return add_string(capability, version, doc + " version " + version + " is available."); };
155  const auto petsc_missing = [&](const std::string & capability,
156  const std::string & doc) -> Capability &
157  {
158  return add_bool(
159  capability, false, doc + " is not available. Check your PETSc configure options.");
160  };
161  const auto libmesh_missing = [&](const std::string & capability,
162  const std::string & doc,
163  const std::string & config_option) -> Capability &
164  {
165  return add_bool(capability,
166  false,
167  doc + " is not available. It is controlled by the `" + config_option +
168  "` libMesh configure option.");
169  };
170 
171  {
172  const auto doc = "LibTorch machine learning and parallel tensor algebra library";
173 #ifdef MOOSE_LIBTORCH_ENABLED
174  add_string("libtorch", TORCH_VERSION, doc);
175 #else
176  missing("libtorch",
177  doc,
178  "Check "
179  "https://mooseframework.inl.gov/moose/getting_started/installation/"
180  "install_libtorch.html for "
181  "instructions on how to configure and build moose with libTorch.");
182 #endif
183  }
184 
185  {
186  const auto doc = "MFEM finite element library";
187 #ifdef MOOSE_MFEM_ENABLED
188  add_string("mfem", MFEM_VERSION_STRING, doc);
189 #else
190  missing("mfem",
191  doc,
192  "Install mfem using the scripts/update_and_rebuild_mfem.sh script after "
193  "first running scripts/update_and_rebuild_conduit.sh. Finally, configure "
194  "moose with ./configure --with-mfem");
195 #endif
196  }
197 
198  {
199  const auto doc = "New Engineering Material model Library, version 2";
200 #ifdef NEML2_ENABLED
201  have("neml2", doc);
202 #else
203  missing("neml2",
204  doc,
205  "Install neml2 using the scripts/update_and_rebuild_neml2.sh script, then "
206  "configure moose with ./configure --with-neml2 --with-libtorch");
207 #endif
208  }
209 
210  {
211  const auto doc = "gperftools code performance analysis and profiling library";
212 #ifdef HAVE_GPERFTOOLS
213  have("gperftools", doc);
214 #else
215  missing("gperftools",
216  doc,
217  "Check https://mooseframework.inl.gov/application_development/profiling.html "
218  "for instructions on profiling MOOSE based applications.");
219 #endif
220  }
221 
222  {
223  const auto doc = "libPNG portable network graphics format library";
224 #ifdef MOOSE_HAVE_LIBPNG
225  have("libpng", doc);
226 #else
227  missing("libpng",
228  doc,
229  "Install libpng through conda or your distribution and check that it gets "
230  "detected through pkg-config, then reconfigure and rebuild MOOSE.");
231 #endif
232  }
233 
234  {
235  const auto doc = "NVIDIA GPU parallel computing platform";
236 #ifdef PETSC_HAVE_CUDA
237  const std::string version = QUOTE(PETSC_PKG_CUDA_VERSION_MAJOR) "." QUOTE(
238  PETSC_PKG_CUDA_VERSION_MINOR) "." QUOTE(PETSC_PKG_CUDA_VERSION_SUBMINOR);
239  add_string("cuda", version, doc);
240 #else
241  missing("cuda", doc, "Add the CUDA bin directory to your path and rebuild PETSc.");
242 #endif
243  }
244 
245  {
246  const auto doc = "AMD GPU parallel computing platform";
247 #ifdef PETSC_HAVE_HIPROCM
248  const std::string version = QUOTE(PETSC_PKG_HIP_VERSION_MAJOR) "." QUOTE(
249  PETSC_PKG_HIP_VERSION_MINOR) "." QUOTE(PETSC_PKG_HIP_VERSION_SUBMINOR);
250  add_string("hip", version, doc);
251 #else
252  missing("hip", doc, "Add the HIP bin directory to your path and rebuild PETSc.");
253 #endif
254  }
255 
256  {
257  const auto doc = "Intel GPU parallel computing platform";
258 #ifdef PETSC_HAVE_SYCL
259  const std::string version = QUOTE(PETSC_PKG_SYCL_VERSION_MAJOR) "." QUOTE(
260  PETSC_PKG_SYCL_VERSION_MINOR) "." QUOTE(PETSC_PKG_SYCL_VERSION_SUBMINOR);
261  add_string("sycl", version, doc);
262 #else
263  missing("sycl", doc, "Add the SYCL bin directory to your path and rebuild PETSc.");
264 #endif
265  }
266 
267  {
268  const auto doc = "Kokkos performance portability programming ecosystem";
269 #ifdef MOOSE_KOKKOS_ENABLED
270  const std::string version = QUOTE(PETSC_PKG_KOKKOS_VERSION_MAJOR) "." QUOTE(
271  PETSC_PKG_KOKKOS_VERSION_MINOR) "." QUOTE(PETSC_PKG_KOKKOS_VERSION_SUBMINOR);
272  add_string("kokkos", version, doc);
273 #else
274  missing("kokkos",
275  doc,
276  "Rebuild PETSc with Kokkos support and libMesh. Then, reconfigure MOOSE with "
277  "--with-kokkos.");
278 #endif
279  }
280 
281  {
282  const auto doc = "Kokkos support for PETSc";
283 #ifdef PETSC_HAVE_KOKKOS
284  const std::string version = QUOTE(PETSC_PKG_KOKKOS_VERSION_MAJOR) "." QUOTE(
285  PETSC_PKG_KOKKOS_VERSION_MINOR) "." QUOTE(PETSC_PKG_KOKKOS_VERSION_SUBMINOR);
286  add_string("petsc_kokkos", version, doc);
287 #else
288  missing(
289  "petsc_kokkos", doc, "Rebuild PETSc with Kokkos support, then rebuild libMesh and MOOSE.");
290 #endif
291  }
292 
293  {
294  const auto doc = "Intel OneAPI XPU accelerator support";
295 #ifdef MOOSE_HAVE_XPU
296  if (torch::xpu::is_available())
297  have("xpu", doc);
298  else
299  missing("xpu", doc, "No usable XPU devices have been found.");
300 #else
301  missing("xpu", doc, "The torch version used to build this app has no XPU support.");
302 #endif
303  }
304 
305  add_int(
306  "ad_size",
307  MOOSE_AD_MAX_DOFS_PER_ELEM,
308  "MOOSE was configured and built with a dual number backing store size of " +
309  Moose::stringify(MOOSE_AD_MAX_DOFS_PER_ELEM) +
310  ". Complex simulations with many variables or contact problems may require larger "
311  "values. Reconfigure MOOSE with the --with-derivative-size=<n> option in the root of the "
312  "repository.")
313  .setExplicit();
314 
315  {
316  const std::string method = QUOTE(METHOD);
317  add_string("method", method, "The executable was built with METHOD=\"" + method + "\"")
318  .setExplicit()
319  .setEnumeration({"dbg", "devel", "oprof", "opt"});
320  }
321 
322  {
323  const std::string version = QUOTE(LIBMESH_DETECTED_PETSC_VERSION_MAJOR) "." QUOTE(
324  LIBMESH_DETECTED_PETSC_VERSION_MINOR) "." QUOTE(LIBMESH_DETECTED_PETSC_VERSION_SUBMINOR);
325  add_string("petsc", version, "Using PETSc version " + version + ".");
326  }
327 
328 #ifdef LIBMESH_PETSC_USE_DEBUG
329  add_bool("petsc_debug", true, "PETSc was built with debugging options.");
330 #else
331  add_bool("petsc_debug", false, "PETSc was built without debugging options.");
332 #endif
333 
334  {
335  const auto doc = "SuperLU direct solver";
336 #ifdef LIBMESH_PETSC_HAVE_SUPERLU_DIST
337  const std::string version = QUOTE(PETSC_PKG_SUPERLU_DIST_VERSION_MAJOR) "." QUOTE(
338  PETSC_PKG_SUPERLU_DIST_VERSION_MINOR) "." QUOTE(PETSC_PKG_SUPERLU_DIST_VERSION_SUBMINOR);
339  add_string("superlu", version, doc);
340 #else
341  petsc_missing("superlu", doc);
342 #endif
343  }
344 
345  {
346  const auto doc = "MUltifrontal Massively Parallel sparse direct Solver (MUMPS)";
347 #ifdef LIBMESH_PETSC_HAVE_MUMPS
348  const std::string version = QUOTE(PETSC_PKG_MUMPS_VERSION_MAJOR) "." QUOTE(
349  PETSC_PKG_MUMPS_VERSION_MINOR) "." QUOTE(PETSC_PKG_MUMPS_VERSION_SUBMINOR);
350  add_string("mumps", version, doc);
351 #else
352  petsc_missing("mumps", doc);
353 #endif
354  }
355 
356  {
357  const auto doc = "STRUMPACK - STRUctured Matrix PACKage solver library";
358 #ifdef LIBMESH_PETSC_HAVE_STRUMPACK
359  const std::string version = QUOTE(PETSC_PKG_STRUMPACK_VERSION_MAJOR) "." QUOTE(
360  PETSC_PKG_STRUMPACK_VERSION_MINOR) "." QUOTE(PETSC_PKG_STRUMPACK_VERSION_SUBMINOR);
361  add_string("strumpack", version, doc);
362 #else
363  petsc_missing("strumpack", doc);
364 #endif
365  }
366 
367  {
368  const auto doc = "Parmetis partitioning library";
369 #if defined(LIBMESH_PETSC_HAVE_PARMETIS)
370  const std::string version = QUOTE(PETSC_PKG_PARMETIS_VERSION_MAJOR) "." QUOTE(
371  PETSC_PKG_PARMETIS_VERSION_MINOR) "." QUOTE(PETSC_PKG_PARMETIS_VERSION_SUBMINOR);
372  add_string("parmetis", version, doc);
373 #elif defined(LIBMESH_HAVE_PARMETIS)
374  have("parmetis", doc);
375 #else
376  petsc_missing("parmetis", doc);
377 #endif
378  }
379 
380  {
381  const auto doc = "Chaco graph partitioning library";
382 #ifdef LIBMESH_PETSC_HAVE_CHACO
383  have("chaco", doc);
384 #else
385  petsc_missing("chaco", doc);
386 #endif
387  }
388 
389  {
390  const auto doc = "Party matrix or graph partitioning library";
391 #ifdef LIBMESH_PETSC_HAVE_PARTY
392  have("party", doc);
393 #else
394  petsc_missing("party", doc);
395 #endif
396  }
397 
398  {
399  const auto doc = "PT-Scotch graph partitioning library";
400 #ifdef LIBMESH_PETSC_HAVE_PTSCOTCH
401  const std::string version = QUOTE(PETSC_PKG_PTSCOTCH_VERSION_MAJOR) "." QUOTE(
402  PETSC_PKG_PTSCOTCH_VERSION_MINOR) "." QUOTE(PETSC_PKG_PTSCOTCH_VERSION_SUBMINOR);
403  add_string("ptscotch", version, doc);
404 #else
405  petsc_missing("ptscotch", doc);
406 #endif
407  }
408 
409  {
410  const auto doc = "Optimized BLAS library";
411 #ifdef PETSC_HAVE_OPENBLAS
412  const std::string version = QUOTE(PETSC_PKG_OPENBLAS_VERSION_MAJOR) "." QUOTE(
413  PETSC_PKG_OPENBLAS_VERSION_MINOR) "." QUOTE(PETSC_PKG_OPENBLAS_VERSION_SUBMINOR);
414  add_string("openblas", version, doc);
415 #else
416  petsc_missing("openblas", doc);
417 #endif
418  }
419 
420  {
421  const auto doc = "Umpire resource management library";
422 #ifdef PETSC_HAVE_UMPIRE
423  have("umpire", doc);
424 #else
425  petsc_missing("umpire", doc);
426 #endif
427  }
428 
429  {
430  const auto doc = "Scalable Library for Eigenvalue Problem Computations (SLEPc)";
431 #ifdef LIBMESH_HAVE_SLEPC
432  const auto version = QUOTE(LIBMESH_DETECTED_SLEPC_VERSION_MAJOR) "." QUOTE(
433  LIBMESH_DETECTED_SLEPC_VERSION_MINOR) "." QUOTE(LIBMESH_DETECTED_SLEPC_VERSION_SUBMINOR);
434  have_version("slepc", doc, version);
435 #else
436  petsc_missing("slepc", doc);
437 #endif
438  }
439 
440  {
441  const auto doc = "Exodus mesh file format library";
442 #ifdef LIBMESH_HAVE_EXODUS_API
443  const std::string version = QUOTE(LIBMESH_DETECTED_EXODUS_VERSION_MAJOR) "." QUOTE(
444  LIBMESH_DETECTED_EXODUS_VERSION_MINOR);
445  have_version("exodus", doc, version);
446 #else
447  libmesh_missing("exodus", doc, "--enable-exodus");
448 #endif
449  }
450 
451  {
452  const auto doc = "Netgen meshing library";
453 #ifdef LIBMESH_HAVE_NETGEN
454  const std::string version =
455  QUOTE(NETGEN_VERSION_MAJOR) "." QUOTE(NETGEN_VERSION_MINOR) "." QUOTE(NETGEN_VERSION_PATCH);
456  add_string("netgen", version, doc);
457 #else
458  libmesh_missing("netgen", doc, "--enable-netgen");
459 #endif
460  }
461 
462  {
463  const auto doc = "Visualization Toolkit (VTK)";
464 #ifdef LIBMESH_HAVE_VTK
465  const std::string version = QUOTE(LIBMESH_DETECTED_VTK_VERSION_MAJOR) "." QUOTE(
466  LIBMESH_DETECTED_VTK_VERSION_MINOR) "." QUOTE(LIBMESH_DETECTED_VTK_VERSION_SUBMINOR);
467  have_version("vtk", doc, version);
468 #else
469  libmesh_missing("vtk", doc, "--disable-vtk and --enable-vtk-required");
470 #endif
471  }
472 
473  {
474  const auto doc = "libcurl - the multiprotocol file transfer library";
475 #ifdef LIBMESH_HAVE_CURL
476  have("curl", doc);
477 #else
478  libmesh_missing("curl", doc, "--enable-curl");
479 #endif
480  }
481 
482  {
483  const auto doc = "Tecplot post-processing tools API";
484 #ifdef LIBMESH_HAVE_TECPLOT_API
485  have("tecplot", doc);
486 #else
487  libmesh_missing("tecplot", doc, "--enable-tecplot");
488 #endif
489  }
490 
491  {
492  const auto doc = "NVIDIA Tools Extension Library API";
493 #ifdef LIBMESH_HAVE_NVTX_API
494  have("nvtx_api", doc);
495 #else
496  libmesh_missing("nvtx_api", doc, "--with-nvtx");
497 #endif
498  }
499 
500  {
501  const auto doc = "libMesh performance logging";
502 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
503  have("libmesh_perflog", doc);
504 #else
505  libmesh_missing("libmesh_perflog", doc, "--enable-perflog");
506 #endif
507  }
508 
509  {
510  const auto doc = "Boost C++ library";
511 #ifdef LIBMESH_HAVE_EXTERNAL_BOOST
512  have("boost", doc);
513 #else
514  libmesh_missing("boost", doc, "--with-boost");
515 #endif
516  }
517 
518  // libmesh stuff
519  {
520  const auto doc = "Adaptive mesh refinement";
521 #ifdef LIBMESH_ENABLE_AMR
522  have("amr", doc);
523 #else
524  libmesh_missing("amr", doc, "--disable-amr");
525 #endif
526  }
527 
528  {
529  const auto doc = "nanoflann library for Nearest Neighbor (NN) search with KD-trees";
530 #ifdef LIBMESH_HAVE_NANOFLANN
531  have("nanoflann", doc);
532 #else
533  libmesh_missing("nanoflann", doc, "--disable-nanoflann");
534 #endif
535  }
536 
537  {
538  const auto doc = "sfcurves library for space filling curves (required by geometric "
539  "partitioners such as SFCurves, Hilbert and Morton - not LGPL compatible)";
540 #ifdef LIBMESH_HAVE_SFCURVES
541  have("sfcurves", doc);
542 #else
543  libmesh_missing("sfcurves", doc, "--disable-sfc");
544 #endif
545  }
546 
547  {
548 #ifdef LIBMESH_HAVE_FPARSER
549 #ifdef LIBMESH_HAVE_FPARSER_JIT
550  const auto value = "jit";
551  const auto doc = "FParser enabled with just in time compilation support.";
552 #else
553  const auto value = "byte_code";
554  const auto doc = "FParser enabled.";
555 #endif
556  add_string("fparser", value, doc);
557 #else
558  add_bool("fparser",
559  false,
560  "FParser is disabled, libMesh was likely configured with --disable-fparser.");
561 #endif
562  }
563 
564 #ifdef LIBMESH_HAVE_DLOPEN
565  add_bool("dlopen", true, "The dlopen() system call is available to dynamically load libraries.");
566 #else
567  add_bool("dlopen",
568  false,
569  "The dlopen() system call is not available. Dynamic library loading is "
570  "not supported on this system.");
571 #endif
572 
573  {
574  const auto doc = "LibMesh support for threaded execution";
575 #ifdef LIBMESH_USING_THREADS
576  have("threads", doc);
577 #else
578  libmesh_missing("threads", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
579 #endif
580  }
581 
582  {
583  const auto doc = "OpenMP multi-platform shared-memory parallel programming API";
584 #ifdef LIBMESH_HAVE_OPENMP
585  have("openmp", doc);
586 #else
587  libmesh_missing("openmp", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
588 #endif
589  }
590  {
591  const auto doc = "POSIX Threads API";
592 #ifdef LIBMESH_HAVE_PTHREAD
593  have("pthread", doc);
594 #else
595  libmesh_missing("pthread", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
596 #endif
597  }
598  {
599  const auto doc = "oneAPI Threading Building Blocks (TBB) API";
600 #ifdef LIBMESH_HAVE_TBB_API
601  have("tbb", doc);
602 #else
603  libmesh_missing("tbb", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
604 #endif
605  }
606 
607  {
608  const auto doc = "libMesh unique ID support";
609 #ifdef LIBMESH_ENABLE_UNIQUE_ID
610  have("unique_id", doc);
611 #else
612  libmesh_missing("unique_id", doc, "--enable-unique-id");
613 #endif
614  }
615 
616  {
617 #ifdef LIBMESH_ENABLE_PARMESH
618  const auto value = "distributed";
619 #else
620  const auto value = "replicated";
621 #endif
622  add_string("mesh_mode", value, "libMesh default mesh mode")
623  .setExplicit()
624  .setEnumeration({"distributed", "replicated"});
625  }
626 
627  add_int("dof_id_bytes",
628  static_cast<int>(sizeof(dof_id_type)),
629  "Degree of freedom (DOF) identifiers use " + Moose::stringify(sizeof(dof_id_type)) +
630  " bytes for storage. This is controlled by the "
631  "--with-dof-id-bytes=<1|2|4|8> libMesh configure option.")
632  .setExplicit();
633 
634  {
635 #ifdef LIBMESH_HAVE_STATIC_LIBS
636  const auto value = "static";
637 #else
638  const auto value = "dynamic";
639 #endif
640  add_string("library_mode",
641  value,
642  "The libMesh library mode. This is controlled by the --enable-static libMesh "
643  "configure option.")
644  .setExplicit()
645  .setEnumeration({"dynamic", "static"});
646  }
647 
648  // compiler
649  {
650  const auto doc = "Compiler used to build the MOOSE framework.";
651 #if defined(__INTEL_LLVM_COMPILER)
652  const auto value = "intel";
653 #elif defined(__clang__)
654  const auto value = "clang";
655 #elif defined(__GNUC__) || defined(__GNUG__)
656  const auto value = "gcc";
657 #elif defined(_MSC_VER)
658  const auto value = "msvc";
659 #else
660  mooseDoOnce(mooseWarning("Failed to determine compiler; setting capability compiler=unknown"));
661  const auto value = "unknown";
662 #endif
663  add_string("compiler", value, doc)
664  .setExplicit()
665  .setEnumeration({"clang", "gcc", "intel", "msvc", "unknown"});
666  }
667 
668  // OS related
669  {
670 #ifdef __APPLE__
671  const auto value = "darwin";
672 #elif __WIN32__
673  const auto value = "win32";
674 #elif __linux__
675  const auto value = "linux";
676 #elif __unix__
677  const auto value = "unix";
678 #else
679  mooseDoOnce(mooseWarning("Failed to determine platform; setting capability platform=unknown"));
680  const auto value = "unknown";
681 #endif
682  add_string("platform", value, "Operating system this executable is running on.")
683  .setExplicit()
684  .setEnumeration({"darwin", "linux", "unix", "unknown", "win32"});
685  }
686 
687  // Installation type (in tree or installed)
688  {
689  // Try to find the path to the running executable
690  std::optional<std::string> executable_path;
691  {
692  Moose::ScopedThrowOnError scoped_throw_on_error;
693  try
694  {
695  executable_path = Moose::getExec();
696  }
697  catch (const MooseException &)
698  {
699  }
700  }
701 
702  std::string value = "unknown";
703 
704  if (executable_path)
705  {
706  // Try to follow all symlinks to get the real path
707  std::error_code ec;
708  const auto resolved_path =
709  std::filesystem::weakly_canonical(std::filesystem::path(*executable_path), ec);
710  if (ec)
711  mooseDoOnce(mooseWarning("Failed to resolve executable path '",
712  *executable_path,
713  "':\n",
714  ec.message(),
715  "\n\nSetting capability installation_type=unknown"));
716  else
717  {
718  // If the binary is in a folder "bin", we'll consider it installed.
719  // This isn't the best check, but it works with how we currently
720  // install applications in app.mk
721  value = resolved_path.parent_path().filename() == "bin" ? "relocated" : "in_tree";
722  }
723  }
724  else
725  mooseDoOnce(mooseWarning(
726  "Failed to determine executable path; setting capability installation_type=unknown"));
727 
728  add_string("installation_type", value, "The installation type of the application.")
729  .setExplicit()
730  .setEnumeration({"in_tree", "relocated", "unknown"});
731 
732  mooseAssert(isInstallationType(value), "Value mismatch");
733  }
734 }
735 
736 } // namespace Moose
std::string name(const ElemQuality q)
void registerMooseCapabilities()
Register the MOOSE capabilities.
Definition: Capabilities.C:127
static Capabilities & getCapabilities(const GetCapabilitiesPassKey)
Get the singleton Capabilities.
Definition: Capabilities.C:52
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:345
std::string dump() const
create a JSON dump of the capabilities registry
Definition: Capabilities.C:63
std::string getExec()
Gets the full path to the running executable on Mac OS X and linux.
void augment(const nlohmann::json &input, const AugmentPassKey)
Augment the capabilities with the given input capabilities.
Definition: Capabilities.C:80
std::variant< bool, int, std::string > Value
A capability can have a bool, int, or string value.
Definition: Capability.h:33
Holds the public (to MooseApp) facing CapabilityRegistry for storing and checking capabilities...
Definition: Capabilities.h:50
RegistryType _registry
Registry storage.
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
Capability & add(const std::string_view name, const Moose::Capability::Value &value, const std::string_view doc)
Add a capability.
An entry for a single capability.
Definition: Capability.h:29
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
std::string help
Common execption to be thrown when interacting with capabilities.
Provides a way for users to bail out of the current solve.
Registry of capabilities that checks capability requirements.
Scoped helper for setting Moose::_throw_on_error during this scope.
Definition: Moose.h:297
bool isInstallationType(const std::string &installation_type) const
Helper for isRelocated() and isInTree()
Definition: Capabilities.C:119
uint8_t dof_id_type