diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8ada99197..a61ac27a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,13 +51,30 @@ jobs: - name: Setup uv uses: astral-sh/setup-uv@v7 + - name: MSVC developer environment (Windows) + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + + - name: sccache (Windows) + if: runner.os == 'Windows' + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Enable sccache + Ninja for the editable build (Windows) + if: runner.os == 'Windows' + run: | + # scikit-build-core honors CMAKE_ARGS; the compiler-launcher property + # only works with the Ninja generator (ignored by Visual Studio), so + # the MSVC dev env + ninja (installed below) are required for sccache. + "SCCACHE_GHA_ENABLED=true" | Out-File $env:GITHUB_ENV -Append + "CMAKE_ARGS=-DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache" | Out-File $env:GITHUB_ENV -Append + - name: Editable install run: | uv venv # --no-build-isolation so the backend in the venv is the one that # actually builds the editable wheel (and so later direct cmake # rebuilds share its build tree). - uv pip install scikit-build-core pybind11 numpy + uv pip install scikit-build-core pybind11 numpy ninja uv pip install -e .[dev] --no-build-isolation - name: Vendor conda BLAS/LAPACK runtime next to the extension (Windows) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e97c47760..d8bbe2866 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,21 @@ jobs: environment-file: ${{ matrix.environment-file }} channels: conda-forge,set3mah + - name: MSVC developer environment (Windows) + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + + - name: sccache (Windows) + if: runner.os == 'Windows' + uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Enable sccache + Ninja for all Windows builds + if: runner.os == 'Windows' + run: | + pip install ninja + "SCCACHE_GHA_ENABLED=true" | Out-File $env:GITHUB_ENV -Append + "CMAKE_ARGS=-DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache" | Out-File $env:GITHUB_ENV -Append + - name: Prepare conda environment (Unix) if: runner.os != 'Windows' run: | @@ -71,11 +86,13 @@ jobs: - name: Build (Windows) if: runner.os == 'Windows' run: | - cmake -S . -B build ` + cmake -S . -B build -G Ninja ` -DCMAKE_BUILD_TYPE=Release ` + -DCMAKE_C_COMPILER_LAUNCHER=sccache ` + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ` -DCMAKE_INSTALL_PREFIX="$env:CONDA_PREFIX/Library" ` -Wno-dev - cmake --build build --config Release + cmake --build build - name: Tests (Unix) if: runner.os != 'Windows' diff --git a/src/Continuum_mechanics/Micromechanics/multiphase.cpp b/src/Continuum_mechanics/Micromechanics/multiphase.cpp index 16812c15b..eac117c6d 100755 --- a/src/Continuum_mechanics/Micromechanics/multiphase.cpp +++ b/src/Continuum_mechanics/Micromechanics/multiphase.cpp @@ -86,8 +86,15 @@ void umat_multi(phase_characteristics &phase, const mat &DR, const double &Time, //Initialization if (start) { - + for (int i=0; itangent_mode = simcoon::tangent_continuum; //Run the appropriate constitutive model select_umat_M(phase.sub_phases[i], DR, Time, DTime, ndi, nshr, start, solver_type, tnew_dt); } diff --git a/src/Simulation/Phase/state_variables.cpp b/src/Simulation/Phase/state_variables.cpp index fe24df486..5bed06a94 100755 --- a/src/Simulation/Phase/state_variables.cpp +++ b/src/Simulation/Phase/state_variables.cpp @@ -214,6 +214,7 @@ state_variables::~state_variables() state_variables& state_variables::operator = (const state_variables& sv) //---------------------------------------------------------------------- { + tangent_mode = sv.tangent_mode; Etot = sv.Etot; DEtot = sv.DEtot; etot = sv.etot; @@ -527,6 +528,11 @@ state_variables& state_variables::rotate_l2g(const state_variables& sv, const do state_variables& state_variables::rotate_g2l(const state_variables& sv, const double &psi, const double &theta, const double &phi) //---------------------------------------------------------------------- { + // Configuration travels with the g->l transfer: the solver sets + // tangent_mode on the GLOBAL sv, the kernels read the LOCAL one — without + // this copy the solver's tangent_mode parameter is dead (kernels always + // run the compile-time default). + tangent_mode = sv.tangent_mode; Etot = sv.Etot; DEtot = sv.DEtot; etot = sv.etot; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c146ddcee..e87a581d4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,7 @@ set(TEST_SRCS test/Umats/HYPER/THYPER.cpp test/Umats/LOG_int/TLOG_int.cpp test/Umats/MIMTN/TMIMTN.cpp + test/Umats/MIMTP/TMIMTP.cpp test/Umats/MIPLN/TMIPLN.cpp test/Umats/UMEXT/TUMEXT.cpp ) diff --git a/test/Umats/MIMTP/TMIMTP.cpp b/test/Umats/MIMTP/TMIMTP.cpp new file mode 100644 index 000000000..e2333deb7 --- /dev/null +++ b/test/Umats/MIMTP/TMIMTP.cpp @@ -0,0 +1,99 @@ +/* This file is part of simcoon. + +simcoon is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcoon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcoon. If not, see . + +*/ + +///@file TMIMTP.cpp +///@brief Mori-Tanaka homogenization with a PLASTIC (modular MODUL) matrix. +/// +/// Guards what the all-elastic MIMTN fixture cannot: elastic Lt is +/// tangent-mode invariant, so MIMTN is blind to the tangent family used by +/// the localization. Here the matrix is a MODUL phase (Von Mises + Voce) +/// loaded well past yield, so the strain concentration tensors are built +/// from an evolving elastoplastic Lt. The recorded reference encodes the +/// CONTINUUM-tangent localization (sub-phases pinned to tangent_continuum +/// in umat_multi, per the incremental Mori-Tanaka formulation) — a change +/// of phase tangent family, a broken tangent_mode propagation, or a modular +/// regression inside the micromechanics all shift the strain partition and +/// fail the comparison. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace arma; +using namespace simcoon; + +TEST(TMIMTP, MIMTN_plastic_modular_matrix_solver) +{ + string path_data = "data"; + string path_results = "results"; + string outputfile = "results_job.txt"; + string pathfile = "path.txt"; + string materialfile = "material.dat"; + string sol_essentials = "solver_essentials.inp"; + string sol_control = "solver_control.inp"; + + string umat_name; + unsigned int nprops = 0; + unsigned int nstatev = 0; + vec props; + + double psi_rve = 0.; + double theta_rve = 0.; + double phi_rve = 0.; + + int solver_type = 0; + int corate_type = 0; + double div_tnew_dt_solver = 0.; + double mul_tnew_dt_solver = 0.; + int miniter_solver = 0; + int maxiter_solver = 0; + int inforce_solver = 0; + double precision_solver = 0.; + double lambda_solver = 0.; + + ASSERT_NO_THROW(solver_essentials(solver_type, corate_type, path_data, sol_essentials)) << "Failed to read solver essentials - check if file exists"; + ASSERT_NO_THROW(solver_control(div_tnew_dt_solver, mul_tnew_dt_solver, miniter_solver, maxiter_solver, inforce_solver, precision_solver, lambda_solver, path_data, sol_control)) << "Failed to read solver control - check if file exists"; + + ASSERT_NO_THROW(read_matprops(umat_name, nprops, props, nstatev, psi_rve, theta_rve, phi_rve, path_data, materialfile)) << "Failed to read material properties - check if file exists"; + solver(umat_name, props, nstatev, psi_rve, theta_rve, phi_rve, solver_type, corate_type, div_tnew_dt_solver, mul_tnew_dt_solver, miniter_solver, maxiter_solver, inforce_solver, precision_solver, lambda_solver, path_data, path_results, pathfile, outputfile); + + string path_comparison = "comparison/results_job_global-0.txt"; + string path_outputfile = path_results + "/" + "results_job_global-0.txt"; + + mat C; + C.load(path_comparison); + mat R; + R.load(path_outputfile); + + ASSERT_EQ(C.n_rows, R.n_rows); + ASSERT_EQ(C.n_cols, R.n_cols); + for (unsigned int i=0; i