### Setup Training Hyperparameters and SVI (Python) Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.ipynb This code sets up the guide for parameter estimation using AutoDelta and configures the Stochastic Variational Inference (SVI) with a specified optimizer, loss function, and number of particles. It prepares the training environment. ```python guide = pyro.infer.autoguide.guides.AutoDelta(hsmodel) lr = 1.0e-3 niter = 150 num_samples = 1 optimizer = pyro.optim.ClippedAdam({"lr": lr}) loss = Trace_ELBO(num_particles=num_samples) svi = SVI(hsmodel, guide, optimizer, loss=loss) ``` -------------------------------- ### Configure C++ Examples Build with CMake and NEML2 Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/CMakeLists.txt This CMake script configures the build process for C++ examples. It sets the C++ standard to 17, finds the NEML2 package, and iterates through all .cxx files to create executable targets. Each executable is linked against the NEML2 library and configured with specific output properties. ```cmake cmake_minimum_required(VERSION 3.26) project(examples LANGUAGES CXX) find_package(neml2 CONFIG REQUIRED) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) file(GLOB_RECURSE ex_srcs CONFIGURE_DEPENDS *.cxx) set(ex_paths "") foreach(ex_src ${ex_srcs}) # example paranet directory and name get_filename_component(ex_src_dir ${ex_src} DIRECTORY) get_filename_component(ex_name ${ex_src} NAME_WE) cmake_path(RELATIVE_PATH ex_src BASE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE ex_src_relpath) cmake_path(RELATIVE_PATH ex_src_dir BASE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE ex_parent_relpath) # target name string(REPLACE "/" "_" ex_target ${ex_src_relpath}) get_filename_component(ex_target ${ex_target} NAME_WE) # create target add_executable(${ex_target} ${ex_src}) target_link_libraries(${ex_target} PRIVATE neml2::neml2) set_target_properties(${ex_target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ex_parent_relpath} OUTPUT_NAME ${ex_name} DISABLE_PRECOMPILE_HEADERS ON ) # add to list of examples list(APPEND ex_paths "${CMAKE_CURRENT_BINARY_DIR}/${ex_parent_relpath}/${ex_name}") endforeach() # Dump list of examples set(FILE "${CMAKE_CURRENT_BINARY_DIR}/examples.txt") file(WRITE ${FILE} "") foreach(ex_path IN LISTS ex_paths) file(APPEND ${FILE} "${ex_path}\n") endforeach() ``` -------------------------------- ### Define Input File Syntax Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/extension/connection_to_input_files/main.md Example of the input file structure used to configure a custom model, mapping variables and parameters. ```text [Models] [accel] type = ProjectileAcceleration velocity = v acceleration = a g = 9.81 nu = 0.5 [] [] ``` -------------------------------- ### Thermosetting Pyrolysis Input File - NEML2 Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/modules/thermosetting_pyrolysis.md An example input file for NEML2 demonstrating the setup for thermosetting pyrolysis. It defines simulation parameters, reaction yield, order, rate coefficient, and activation energy. ```NEML2 nbatch = '(1)' nstep = 100 # reaction mechanism Y = 0.5835777126099713 # yield n = 1.0 # reaction order k0 = 0.04210147513030456 # reaction rate coefficient Q = 21191.61425138572 # J/mol R = 8.31446261815324 # J/K/mol ``` -------------------------------- ### Implement Convergence Criteria Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/system/solver.md Example implementation of a convergence check for a custom nonlinear solver. It compares the current residual norm against absolute and relative tolerances using ATensor operations. ```cpp bool MySolver::converged(const ATensor & nR, const ATensor & nR0) const { return at::all(at::logical_or(nR < atol, nR / nR0 < rtol)).item(); } ``` -------------------------------- ### Generate and Install NEML2 pkg-config File Source: https://github.com/applied-material-modeling/neml2/blob/main/src/neml2/CMakeLists.txt This section details the generation and installation of the NEML2 pkg-config file. It uses a template (`neml2.pc.in`) and CMake's `configure_file` and `file(GENERATE)` commands to create the final `.pc` file, including configuration-specific suffixes. The generated file is then installed to the appropriate system location. ```cmake configure_file( ${NEML2_SOURCE_DIR}/cmake/neml2.pc.in ${NEML2_BINARY_DIR}/neml2.pc.in @ONLY ) set(NEML2_PKGCONFIG_SUFFIX "$,,_$>") file(GENERATE OUTPUT ${NEML2_BINARY_DIR}/neml2${NEML2_PKGCONFIG_SUFFIX}.pc INPUT ${NEML2_BINARY_DIR}/neml2.pc.in ) if(NOT SKBUILD_STATE STREQUAL "editable") install( FILES ${NEML2_BINARY_DIR}/neml2Config.cmake ${NEML2_BINARY_DIR}/neml2ConfigVersion.cmake DESTINATION share/cmake/neml2 COMPONENT libneml2 ) install( FILES ${NEML2_BINARY_DIR}/neml2${NEML2_PKGCONFIG_SUFFIX}.pc DESTINATION share/pkgconfig COMPONENT libneml2 ) endif() ``` -------------------------------- ### Find and Install 'hit' Dependency (CMake) Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt This snippet handles the 'hit' dependency. It first tries to find the package. If not found, it downloads the 'hit' repository from GitHub, copies source files, configures a custom CMakeLists.txt, and installs it. Finally, it finds the 'hit' package again and installs its library and include directories as part of the NEML2 installation. ```cmake find_package(hit MODULE) if(NOT hit_FOUND) if(NOT hit_SOURCE_DIR) download_from_git(hit https://github.com/idaholab/hit.git ${NEML2_CONTRIB_PREFIX} ${hit_VERSION}) set(hit_SOURCE_DIR ${NEML2_CONTRIB_PREFIX}/hit-src) endif() file(COPY ${hit_SOURCE_DIR}/include DESTINATION ${NEML2_CONTRIB_PREFIX}/hit-build FILES_MATCHING PATTERN "*.h") file(COPY ${hit_SOURCE_DIR}/src DESTINATION ${NEML2_CONTRIB_PREFIX}/hit-build FILES_MATCHING PATTERN "*.cpp" PATTERN "*.cc") configure_file(contrib/install_hit.cmake ${NEML2_CONTRIB_PREFIX}/hit-build/CMakeLists.txt @ONLY) set(hit_INSTALL_PREFIX ${NEML2_CONTRIB_PREFIX}/hit CACHE PATH "hit install prefix") custom_install(hit contrib/install_hit.sh ${NEML2_CONTRIB_PREFIX}/hit-build ${NEML2_CONTRIB_PREFIX}/hit-build ${hit_INSTALL_PREFIX}) find_package(hit MODULE REQUIRED) endif() # check if hit is downloaded path_has_prefix(${hit_ROOT} ${NEML2_CONTRIB_PREFIX} hit_CONTRIB) # hit will be packaged as part of the NEML2 installation if it was downloaded by us (or if it is being built as a wheel). if(hit_CONTRIB OR NEML2_WHEEL) install(FILES ${hit_LIBRARY} DESTINATION ${INSTALL_LIBDIR} COMPONENT libneml2) if(NOT SKBUILD_STATE STREQUAL "editable") install(DIRECTORY ${hit_INCLUDE_DIR}/hit TYPE INCLUDE COMPONENT libneml2) endif() endif() if(NOT SKBUILD_STATE STREQUAL "editable") install(FILES ${NEML2_SOURCE_DIR}/cmake/Modules/Findhit.cmake DESTINATION share/cmake/neml2/Modules COMPONENT libneml2) endif() ``` -------------------------------- ### Define Installation Directories for Editable Builds Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt Configures library and binary installation paths based on whether the project is being installed as an editable Python wheel. This ensures that CPython libraries are correctly located within the source tree during development. ```cmake if(NEML2_WHEEL AND DEFINED SKBUILD_STATE AND SKBUILD_STATE STREQUAL "editable") set(INSTALL_LIBDIR ${NEML2_SOURCE_DIR}/python/neml2/lib) set(INSTALL_BINDIR ${NEML2_SOURCE_DIR}/python/neml2/bin) else() set(INSTALL_LIBDIR lib) set(INSTALL_BINDIR bin) endif() ``` -------------------------------- ### Execute Training Loop with SVI Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.md Sets up an AutoDelta guide for MAP estimation and runs a training loop using Stochastic Variational Inference (SVI) with the ClippedAdam optimizer. ```python guide = pyro.infer.autoguide.guides.AutoDelta(hsmodel) optimizer = pyro.optim.ClippedAdam({"lr": 1.0e-3}) svi = SVI(hsmodel, guide, optimizer, loss=Trace_ELBO(num_particles=1)) for i in range(150): closs = svi.step(time, temperature, loading, results=data) ``` -------------------------------- ### Setup Model for Training with Random Guesses (Python) Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.ipynb This snippet sets up the model for training by replacing parameter values with random initial guesses. The variability of these guesses is controlled by the `guess_cov` parameter. Original parameter values are stored before updating, and then the model's discrete equations are updated. ```python # Now replace our original parameter with random values over a range guess_parameter_values = {} for n, p in model.named_parameters(): p.data = torch.normal( actual_parameter_values[n], torch.abs(actual_parameter_values[n]) * guess_cov ).to(device) guess_parameter_values[n] = p.data.detach().clone() model.discrete_equations._update_parameter_values() ``` -------------------------------- ### Manage Third-Party Dependencies Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt Automates the discovery of dependencies like Torch and WASP. If a dependency is missing, it triggers a download and custom installation process to ensure the build environment is complete. ```cmake find_package(wasp MODULE COMPONENTS core hit) if(NOT wasp_FOUND) download_from_git(wasp https://code.ornl.gov/neams-workbench/wasp.git ${NEML2_CONTRIB_PREFIX} ${wasp_VERSION}) set(wasp_INSTALL_PREFIX ${NEML2_CONTRIB_PREFIX}/wasp CACHE PATH "wasp install prefix") custom_install(wasp contrib/install_wasp.sh ${NEML2_CONTRIB_PREFIX}/wasp-src ${NEML2_CONTRIB_PREFIX}/wasp-build ${wasp_INSTALL_PREFIX}) find_package(wasp MODULE REQUIRED COMPONENTS core hit) endif() ``` -------------------------------- ### Tensor Slicing in C++ and Python Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/tensors/indexing/main.md Demonstrates tensor slicing using the 'start:stop:step' notation, which is analogous to NumPy and PyTorch. Optional parameters allow for flexible slice construction, and 'step' must be positive. ```cpp #include #include #include int main() { // Create a tensor neml2::Tensor tensor({{1.0, 2.0, 3.0, 4.0}, {5.0, 6.0, 7.0, 8.0}}); // Slicing auto sliced_tensor = tensor(neml2::Slice(0, 2, 1), neml2::Slice(1, 3, 1)); std::cout << "Sliced tensor:\n" << sliced_tensor << std::endl; return 0; } ``` ```python import neml2 # Create a tensor tensor = neml2.Tensor([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]]) # Slicing sliced_tensor = tensor[0:2, 1:3] print(f"Sliced tensor:\n{sliced_tensor}") ``` -------------------------------- ### Install NEML2 Target and Export CMake Configuration (CMake) Source: https://github.com/applied-material-modeling/neml2/blob/main/src/neml2/CMakeLists.txt This section handles the installation of the NEML2 library target and the creation of CMake export files. It ensures that the library and its associated configuration files are correctly placed for other projects to find and use. ```cmake # Export targets install(TARGETS neml2 LIBRARY DESTINATION ${INSTALL_LIBDIR} COMPONENT libneml2 ) if(NOT SKBUILD_STATE STREQUAL "editable") install(TARGETS neml2 EXPORT neml2targets FILE_SET HEADERS DESTINATION include COMPONENT libneml2 ) install(EXPORT neml2targets NAMESPACE neml2:: DESTINATION share/cmake/neml2 COMPONENT libneml2) endif() # cmake config include(CMakePackageConfigHelpers) configure_package_config_file( ${NEML2_SOURCE_DIR}/cmake/neml2Config.cmake.in ${NEML2_BINARY_DIR}/neml2Config.cmake INSTALL_DESTINATION share/cmake/neml2 NO_CHECK_REQUIRED_COMPONENTS_MACRO ) write_basic_package_version_file( ${NEML2_BINARY_DIR}/neml2ConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) ``` -------------------------------- ### Define and Configure Executable Tools (CMake) Source: https://github.com/applied-material-modeling/neml2/blob/main/src/tools/CMakeLists.txt This CMake function, `add_tool`, defines an executable target for a tool. It compiles the CXX source file, sets compiler options, links necessary libraries (neml2, argparse, and optionally gperftools for profiling), and installs the executable. It also manages header file inclusion and sets installation properties based on build configurations. ```cmake function(add_tool name) add_executable(${name} ${name}.cxx) target_compile_options(${name} PRIVATE -Wall -Wextra -pedantic) target_link_libraries(${name} PRIVATE neml2 argparse::argparse) if(CMAKE_BUILD_TYPE STREQUAL "Profiling") target_link_libraries(${name} PRIVATE gperftools::profiler) endif() target_sources(${name} PRIVATE FILE_SET HEADERS BASE_DIRS ${NEML2_SOURCE_DIR}/include/tools FILES ${NEML2_SOURCE_DIR}/include/tools/utils.h ) set_target_properties(${name} PROPERTIES DISABLE_PRECOMPILE_HEADERS ON) if(NEML2_WHEEL AND NOT SKBUILD_STATE STREQUAL "editable") set_target_properties(${name} PROPERTIES INSTALL_RPATH "${INSTALL_REL_PATH}/../lib;${INSTALL_REL_PATH}/../../torch/lib") else() set_target_properties(${name} PROPERTIES INSTALL_RPATH "${INSTALL_REL_PATH}/../lib;${torch_LINK_DIR}") endif() add_dependencies(tools ${name}) install(TARGETS ${name} DESTINATION ${INSTALL_BINDIR} COMPONENT libneml2-bin) endfunction() ``` -------------------------------- ### Create Input Tensors for NEML2 Simulation (Python) Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.ipynb This section provides Python code for setting up the input tensors required for NEML2 simulations. It includes the creation of time, loading, and temperature tensors, with specific examples for both batched and single-value inputs, ensuring correct reshaping and broadcasting for compatibility with the model. ```python time = torch.zeros((ntime, nrate, ntemperature), device=device) loading = torch.zeros((ntime, nrate, ntemperature, 6), device=device) temperature = torch.zeros((ntime, nrate, ntemperature), device=device) for i, rate in enumerate(rates): time[:, i] = torch.linspace(0, max_strain / rate, ntime, device=device)[:, None] loading[..., 0] = torch.linspace(0, max_strain, ntime, device=device)[:, None, None] for i, T in enumerate(temperatures): temperature[:, :, i] = T time = time.reshape((ntime, -1, 1)) temperature = temperature.reshape((ntime, -1, 1)) loading = loading.reshape((ntime, -1, 6)) single_times = ( torch.linspace(0, max_strain / single_rate, ntime, device=device) .unsqueeze(-1) .expand((ntime, nrepeat)) .unsqueeze(-1) ) single_temperatures = torch.full_like(single_times, single_temperature) single_loading = torch.zeros((ntime, nrepeat, 6), device=device) single_loading[..., 0] = torch.linspace(0, max_strain, ntime, device=device).unsqueeze(-1) ``` -------------------------------- ### Setup Synthetic Experimental Conditions Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.ipynb Defines the parameters for generating synthetic experimental data, including the number of strain rates, temperatures, and batches. It also sets the maximum strain and number of time steps for integration. ```python nrate = 5 ntemperature = 10 nbatch = nrate * ntemperature max_strain = 0.25 ntime = 100 rates = torch.logspace(-6, 0, nrate, device=device) temperatures = torch.linspace(310.0, 1190.0, ntemperature, device=device) ``` -------------------------------- ### Sample Trained Model for Comparison (Python) Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.ipynb After training, this code samples the model using the learned guide to visualize its performance. It compares the trained model's predictions against the original data, similar to the prior model sampling. ```python nreps = 5 predict = Predictive(hsmodel, guide=guide, num_samples=nreps) with torch.no_grad(): trained_single = predict( single_times[:, :nbatch], single_temperatures[:, :nbatch], single_loading[:, :nbatch] )["obs"] ``` ```python flat_trained = trained_single.transpose(0, 1).reshape(ntime, nreps * nbatch, 1) plt.figure() plt.plot( single_loading[:, 0, 0].cpu(), torch.mean(flat_trained, dim=1)[:, 0].cpu(), ls="-", color="k", lw=4, label="Trained mean", ) p = 0.05 n_lb = int(p * nreps * nbatch) n_ub = int((1 - p) * nreps * nbatch) plt.fill_between( single_loading[:, 0, 0].cpu(), torch.kthvalue(flat_trained, n_lb, dim=1)[0][:, 0].cpu(), torch.kthvalue(flat_trained, n_ub, dim=1)[0][:, 0].cpu(), color="tab:blue", alpha=0.8, label="90% prediction", ) plt.plot(single_loading.cpu()[..., 0], single_data[..., 0].cpu(), color="k", lw=0.3, label="Data") handles, labels = plt.gca().get_legend_handles_labels() plt.xlabel("Strain") plt.ylabel("Stress") plt.legend(handles[:3], labels[:3], loc="best") plt.show() ``` -------------------------------- ### Sample Prior Model for Visualization (Python) Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.ipynb This code samples the prior model to visualize its starting point relative to the true distribution. It uses the Predictive class for sampling and torch.no_grad() for efficiency. The output is used for plotting. ```python nreps = 5 predict = Predictive(hsmodel, num_samples=nreps) with torch.no_grad(): untrained_single = predict( single_times[:, :nbatch], single_temperatures[:, :nbatch], single_loading[:, :nbatch] )["obs"] ``` ```python flat_untrained = untrained_single.transpose(0, 1).reshape(ntime, nreps * nbatch, 1) plt.figure() plt.plot( single_loading[:, 0, 0].cpu(), torch.mean(flat_untrained, dim=1)[:, 0].cpu(), ls="-", color="k", lw=4, label="Prior mean", ) p = 0.05 n_lb = int(p * nreps * nbatch) n_ub = int((1 - p) * nreps * nbatch) plt.fill_between( single_loading[:, 0, 0].cpu(), torch.kthvalue(flat_untrained, n_lb, dim=1)[0][:, 0].cpu(), torch.kthvalue(flat_untrained, n_ub, dim=1)[0][:, 0].cpu(), color="tab:blue", alpha=0.8, label="90% prediction", ) plt.plot( single_loading.cpu()[..., 0], single_data[..., 0].cpu(), color="k", lw=0.3, label="Data", ) handles, labels = plt.gca().get_legend_handles_labels() plt.xlabel("Strain") plt.ylabel("Stress") plt.legend(handles[:3], labels[:3], loc="best") plt.show() ``` -------------------------------- ### Implement Object Constructor Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/extension/connection_to_input_files/main.md Shows how the constructor utilizes the OptionSet to initialize the object with values parsed from the input file. ```cpp ProjectileAcceleration::ProjectileAcceleration(const OptionSet & options) : NEML2Object(options), _velocity(options.get("velocity")), _acceleration(options.get("acceleration")), _g(options.get("g")), _nu(options.get("nu")) {} ``` -------------------------------- ### Get Project Version and Hash using Git (CMake) Source: https://github.com/applied-material-modeling/neml2/blob/main/src/neml2/CMakeLists.txt This snippet uses CMake's execute_process to run Git commands to retrieve the project's version and the latest commit hash. The results are written to files and then installed. ```cmake find_package(Git) if(Git_FOUND) execute_process( COMMAND ${GIT_EXECUTABLE} describe --abbrev=0 WORKING_DIRECTORY ${NEML2_SOURCE_DIR} OUTPUT_VARIABLE NEML2_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) file(WRITE ${NEML2_BINARY_DIR}/version "${NEML2_VERSION}\n") execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY ${NEML2_SOURCE_DIR} OUTPUT_VARIABLE NEML2_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) file(WRITE ${NEML2_BINARY_DIR}/hash "${NEML2_HASH}\n") install( FILES ${NEML2_BINARY_DIR}/version ${NEML2_BINARY_DIR}/hash DESTINATION . COMPONENT libneml2 ) endif() ``` -------------------------------- ### Create tensors using factory methods Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/tensors/tensor_creation/main.md Shows the usage of factory methods to initialize new tensors with specific shapes, data types, devices, and gradient requirements. ```cpp neml2::TensorOptions options; options.dtype(torch::kFloat32); options.device(torch::kCPU); options.requires_grad(false); auto t = neml2::SR2::zeros({5, 3}, options); ``` ```python t = neml2.SR2.zeros((5, 3), dtype=torch.float32, device='cpu', requires_grad=False) ``` -------------------------------- ### Factory Object Instantiation Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/extension/connection_to_input_files/main.md Demonstrates how to use the NEML2 factory to create an object from an input file and verify the configuration. ```cpp int main() { Parser parser("input.i"); auto & factory = parser.get_factory(); auto model = factory.get_object("Models/accel"); return 0; } ``` -------------------------------- ### CMake Installation Message Setting Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt Configures the CMake installation message behavior to be 'LAZY'. This setting controls when installation messages are displayed during the build process. ```cmake set(CMAKE_INSTALL_MESSAGE LAZY) ``` -------------------------------- ### Initialize NEML2 and PyTorch environment Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/crystal_plasticity/compare_formulations.md Imports necessary libraries for crystal plasticity modeling and configures the execution device (GPU if available) and simulation parameters. ```python import matplotlib.pyplot as plt from matplotlib.lines import Line2D import torch import neml2 import neml2.tensors from pyzag import nonlinear, chunktime import neml2.postprocessing torch.set_default_dtype(torch.double) dev = "cuda:0" if torch.cuda.is_available() else "cpu" device = torch.device(dev) nchunk = 10 ncrystal = 500 ``` -------------------------------- ### Find and Install 'nlohmann_json' Dependency (CMake) Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt This CMake snippet manages the 'nlohmann_json' dependency. It searches for the package using 'CONFIG' mode. If not found, it downloads the repository from GitHub, sets an installation prefix, and uses a custom install script. It then finds the package again and installs its include directories and share files if it was downloaded or if building a wheel, and if not in editable mode. ```cmake if(NEML2_JSON) find_package(nlohmann_json CONFIG HINTS ${NEML2_CONTRIB_PREFIX}/nlohmann_json) if(NOT nlohmann_json_FOUND) download_from_git(nlohmann_json https://github.com/nlohmann/json.git ${NEML2_CONTRIB_PREFIX} ${nlohmann_json_VERSION}) set(nlohmann_json_INSTALL_PREFIX ${NEML2_CONTRIB_PREFIX}/nlohmann_json CACHE PATH "nlohmann json install prefix") custom_install(nlohmann_json contrib/install_nlohmann_json.sh ${NEML2_CONTRIB_PREFIX}/nlohmann_json-src ${NEML2_CONTRIB_PREFIX}/nlohmann_json-build ${nlohmann_json_INSTALL_PREFIX}) find_package(nlohmann_json CONFIG REQUIRED PATHS ${nlohmann_json_INSTALL_PREFIX} NO_DEFAULT_PATH) endif() file(REAL_PATH "../../../" nlohmann_json_DIR BASE_DIRECTORY ${nlohmann_json_DIR}) # check if nlohmann json is downloaded path_has_prefix(${nlohmann_json_DIR} ${NEML2_CONTRIB_PREFIX} nlohmann_json_CONTRIB) # nlohmann json will be packaged as part of the NEML2 installation if it was downloaded by us (or if it is being built as a wheel). if(nlohmann_json_CONTRIB OR NEML2_WHEEL) if(NOT SKBUILD_STATE STREQUAL "editable") install(DIRECTORY ${nlohmann_json_DIR}/include/nlohmann TYPE INCLUDE COMPONENT libneml2) endif() endif() if(NOT SKBUILD_STATE STREQUAL "editable") install(DIRECTORY ${nlohmann_json_DIR}/share/ DESTINATION share COMPONENT libneml2) endif() endif() ``` -------------------------------- ### Prepare Model for Training Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.md Initializes model parameters with random values based on a guess covariance and updates internal discrete equations to prepare for the training phase. ```python guess_parameter_values = {} for n, p in model.named_parameters(): p.data = torch.normal( actual_parameter_values[n], torch.abs(actual_parameter_values[n]) * guess_cov ).to(device) guess_parameter_values[n] = p.data.detach().clone() model.discrete_equations._update_parameter_values() ``` -------------------------------- ### Load and Summarize NEML2 Model in C++ Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/models/running_your_first_model/main.md This C++ code snippet demonstrates how to load a NEML2 model from an input file and print its summary to the console. It requires the NEML2 library and assumes the input file 'input.i' exists. ```C++ #include using namespace neml2; int main(int argc, char **argv) { // Initialize NEML2 neml2::init(argc, argv); // Load the model from the input file // The input file is specified as the first argument to the program // The model name is 'my_model' as defined in the input file auto model = neml2::Model::load("my_model"); // Print a summary of the model to the console std::cout << *model << std::endl; return 0; } ``` -------------------------------- ### Find and Install 'csv-parser' Dependency (CMake) Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt This CMake code block handles the 'csv-parser' dependency. It first attempts to find the package. If not found, it downloads the 'csv-parser' repository, copies the 'csv.hpp' header file to a specific location, and then finds the package again. It includes logic to install the header files as part of the NEML2 installation if the parser was downloaded or if building a wheel, and not in editable mode. ```cmake if(NEML2_CSV) find_package(csvparser MODULE) if(NOT csvparser_FOUND) download_from_git(csvparser https://github.com/vincentlaucsb/csv-parser.git ${NEML2_CONTRIB_PREFIX} ${csvparser_VERSION}) set(csvparser_INSTALL_PREFIX ${NEML2_CONTRIB_PREFIX}/csvparser CACHE PATH "csv-parser install prefix") file(COPY ${NEML2_CONTRIB_PREFIX}/csvparser-src/single_include/csv.hpp DESTINATION ${NEML2_CONTRIB_PREFIX}/csvparser/csvparser) find_package(csvparser MODULE REQUIRED) endif() # check if csvparser is downloaded path_has_prefix(${csvparser_ROOT} ${NEML2_CONTRIB_PREFIX} csvparser_CONTRIB) # csv-parser will be packaged as part of the NEML2 installation if it was downloaded by us (or if it is being built as a wheel). if(csvparser_CONTRIB OR NEML2_WHEEL) if(NOT SKBUILD_STATE STREQUAL "editable") install(DIRECTORY ${csvparser_ROOT}/csvparser/csvparser TYPE INCLUDE COMPONENT libneml2) endif() endif() if(NOT SKBUILD_STATE STREQUAL "editable") install(FILES ${NEML2_SOURCE_DIR}/cmake/Modules/Findcsvparser.cmake DESTINATION share/cmake/neml2/Modules COMPONENT libneml2) endif() endif() ``` -------------------------------- ### Find and Configure Catch2 for Testing (CMake) Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt This snippet handles the configuration of the Catch2 testing framework. It searches for an installed Catch2 package and, if not found, downloads and installs it from its Git repository. This is typically used when NEML2_TESTS is enabled. ```cmake if(NEML2_TESTS) include(CTest) find_package(Catch2 CONFIG HINTS ${NEML2_CONTRIB_PREFIX}/Catch2) if(NOT Catch2_FOUND) download_from_git(Catch2 https://github.com/catchorg/Catch2.git ${NEML2_CONTRIB_PREFIX} ${catch2_VERSION}) set(Catch2_INSTALL_PREFIX ${NEML2_CONTRIB_PREFIX}/Catch2 CACHE PATH "Catch2 install prefix") custom_install(Catch2 contrib/install_Catch2.sh ${NEML2_CONTRIB_PREFIX}/Catch2-src ${NEML2_CONTRIB_PREFIX}/Catch2-build ${Catch2_INSTALL_PREFIX}) find_package(Catch2 CONFIG REQUIRED PATHS ${Catch2_INSTALL_PREFIX} NO_DEFAULT_PATH) endif() endif() ``` -------------------------------- ### Evaluate Composed Models Sequentially Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/models/model_composition/main.md Demonstrates how to load and evaluate the defined models in sequence using the NEML2 C++ and Python APIs. ```C++ #include "neml2/models/Model.h" // Load the input file auto model = neml2::Model::create("input.i"); // Evaluate models sequentially model->evaluate("inv_a"); model->evaluate("inv_b"); model->evaluate("comb"); ``` ```Python import neml2 # Load the input file model = neml2.Model.create("input.i") # Evaluate models sequentially model.evaluate("inv_a") model.evaluate("inv_b") model.evaluate("comb") ``` -------------------------------- ### C++ Example: Simulating Projectile Trajectories Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/extension/model_composition/main.md This C++ code implements the main logic for simulating projectile trajectories. It sets up the simulation environment, defines initial conditions, and runs the transient driver to compute the trajectories for multiple projectiles with different dynamic viscosities. It relies on NEML2's core functionalities for model definition and integration. ```cpp #include using namespace neml2; int main(int argc, char **argv) { neml2::init(argc, argv); // Load the input file const auto &model = NEML2::load("input.i"); // Get the transient driver const auto &driver = NEML2::load("input.i"); // Run the simulation auto results = driver.run(model); // Save the results results.save("result.pt"); return 0; } ``` -------------------------------- ### Define NEML2Object Interface and Expected Options Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/extension/connection_to_input_files/main.md Shows the required static method signature for defining expected input options and the constructor signature for runtime-manufacturable objects in NEML2. ```cpp static OptionSet expected_options(); ProjectileAcceleration(const OptionSet & options); ``` ```cpp OptionSet ProjectileAcceleration::expected_options() { OptionSet options; options.set_parameters("velocity", "Name of the velocity variable"); options.set_parameters("acceleration", "Name of the acceleration variable"); options.set_parameters("g", 9.81, "Gravitational acceleration"); options.set_parameters("nu", 1.0, "Dynamic viscosity"); return options; } ``` -------------------------------- ### Initialize NEML2 Simulation Environment Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/crystal_plasticity/compare_formulations.ipynb Imports necessary libraries including PyTorch and NEML2, and configures the execution device (GPU/CUDA or CPU). Sets global parameters for chunk size and crystal orientation count. ```python import matplotlib.pyplot as plt from matplotlib.lines import Line2D import torch import neml2 import neml2.tensors from pyzag import nonlinear, chunktime import neml2.postprocessing torch.set_default_dtype(torch.double) if torch.cuda.is_available(): dev = "cuda:0" else: dev = "cpu" device = torch.device(dev) nchunk = 10 ncrystal = 500 ``` -------------------------------- ### Define Model Composition in NEML2 Input File Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/models/model_composition/main.md An example of an input file configuration for NEML2 that utilizes the SR2Invariant and LinearCombination models to represent a system of tensor equations. ```NEML2 Input [Models] [./inv_a] type = SR2Invariant input = a output = a_bar invariant = I1 [../] [./inv_b] type = SR2Invariant input = b output = b_bar invariant = J2 [../] [./comb] type = SR2LinearCombination input1 = b_bar input2 = a input3 = a_bar input4 = b output = b_dot [../] [] ``` -------------------------------- ### Simulate Integrated Multiplicative Model Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/crystal_plasticity/compare_formulations.ipynb Loads a nonlinear system for an integrated multiplicative model and initializes the `SolveIntegrated` class for simulation. This setup is used to perform rolling deformation simulations. ```python nmodel_integrated = neml2.load_nonlinear_system("crystal_integrated.i", "eq_sys") nmodel_integrated.to(device=device) model_integrated = SolveIntegrated(neml2.pyzag.NEML2PyzagModel(nmodel_integrated), nchunk=nchunk) ``` ```python with torch.no_grad(): results_integrated = model_integrated(times, F, initial_orientations=initial_orientations) end_results_integrated = results_integrated[-1] ``` -------------------------------- ### Load and Summarize NEML2 Model in Python Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/models/running_your_first_model/main.md This Python script shows how to load a NEML2 model from an input file and display its summary. It utilizes the NEML2 Python API and expects the input file 'input.i' to be accessible. ```Python import neml2 # Load the model from the input file # The input file is specified as the first command-line argument # The model name is 'my_model' as defined in the input file model = neml2.Model.load("my_model") # Print a summary of the model to the console print(model) ``` -------------------------------- ### Configure Platform-Specific RPATH Source: https://github.com/applied-material-modeling/neml2/blob/main/CMakeLists.txt Sets the installation relative path variable based on the operating system to ensure correct library linking. It distinguishes between macOS loader paths and standard Unix origin paths. ```cmake if(UNIX AND APPLE) set(INSTALL_REL_PATH "@loader_path") elseif(UNIX AND NOT APPLE) set(INSTALL_REL_PATH "$ORIGIN") endif() ``` -------------------------------- ### Initialize Input Tensors for Material Modeling Source: https://github.com/applied-material-modeling/neml2/blob/main/python/examples/statistical.md Creates multi-dimensional PyTorch tensors for time, temperature, and loading conditions. These tensors are reshaped to facilitate batch processing in material models. ```python time = torch.zeros((ntime, nrate, ntemperature), device=device) loading = torch.zeros((ntime, nrate, ntemperature, 6), device=device) temperature = torch.zeros((ntime, nrate, ntemperature), device=device) for i, rate in enumerate(rates): time[:, i] = torch.linspace(0, max_strain / rate, ntime, device=device)[:, None] loading[..., 0] = torch.linspace(0, max_strain, ntime, device=device)[:, None, None] for i, T in enumerate(temperatures): temperature[:, :, i] = T time = time.reshape((ntime, -1, 1)) temperature = temperature.reshape((ntime, -1, 1)) loading = loading.reshape((ntime, -1, 6)) ``` -------------------------------- ### Iterate and Retrieve Model Parameters Source: https://github.com/applied-material-modeling/neml2/blob/main/doc/content/tutorials/models/model_parameters/main.md Demonstrates how to iterate through all available model parameters or retrieve a specific parameter by name using the NEML2 API. ```cpp for (auto const& [name, param] : model.parameters()) { std::cout << name << ": " << param << std::endl; } // Retrieve specific parameter auto K = model.get_parameter("K"); ``` ```python for name, param in model.parameters.items(): print(f"{name}: {param}") # Retrieve specific parameter K = model.get_parameter("K") # Or via attribute access K = model.K ```