-
Notifications
You must be signed in to change notification settings - Fork 7
PhasorDynamics simulations with sparse Jacobians #312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
cf71e3b
Functional PhasorDynamics simulations with sparse Jacobians.
nkoukpaizan e49d7b3
Cleaner Enzyme sparse wrapper implementation.
nkoukpaizan d70afce
Replace int-int maps with vector of integers for residual/variable in…
nkoukpaizan d0763c9
Make use of INVALID_INDEX constant.
nkoukpaizan 0429a10
Suppress warnings.
nkoukpaizan ffe01f5
Apply pre-commmit fixes
nkoukpaizan 02410e0
More intuitive PhasorDynamics example test names.
nkoukpaizan 1d30817
Add sstream include to VariableMonitor.
nkoukpaizan 59eba69
Missing LINK_LIBRARIES for Logger.
nkoukpaizan f470a32
Hide initial Jacobian evaluation workaround in SystemModel a todo ite…
nkoukpaizan 2963163
Apply pre-commmit fixes
nkoukpaizan 30da7cc
CMake guard for Enzyme -O0 -enzyme-auto-sparsity=1 bug.
nkoukpaizan 6732dc3
Misc documentation of Enzyme utilities.
nkoukpaizan 77080fe
Fix warning.
nkoukpaizan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| /** | ||
| * @file DfDwb.hpp | ||
| * @author Nicholson Koukpaizan (koukpaizannk@ornl.gov) | ||
| * | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <GridKit/AutomaticDifferentiation/Enzyme/EnzymeDefinitions.hpp> | ||
| #include <GridKit/AutomaticDifferentiation/Enzyme/LowerSparseStorage.hpp> | ||
| #include <GridKit/AutomaticDifferentiation/Enzyme/ModelWrappers.hpp> | ||
| #include <GridKit/LinearAlgebra/SparseMatrix/COO_Matrix.hpp> | ||
| #include <GridKit/ScalarTraits.hpp> | ||
|
|
||
| namespace GridKit | ||
| { | ||
| namespace Enzyme | ||
| { | ||
| namespace Sparse | ||
| { | ||
| /** | ||
| * @brief Enzyme automatic differentiation Jacobian evaluator : df/dwb | ||
| * | ||
| * @tparam ModelT - model type | ||
| * @tparam MemberFunctions - member function parameter key | ||
| * @tparam ScalarT - scalar data type | ||
| * @tparam IdxT - matrix index data type | ||
| */ | ||
| template <typename ModelT, MemberFunctions function, class ScalarT, typename IdxT> | ||
| struct DfDwb | ||
| { | ||
| using RealT = typename GridKit::ScalarTraits<ScalarT>::RealT; | ||
| using MatrixT = GridKit::LinearAlgebra::COO_Matrix<RealT, IdxT>; | ||
|
|
||
| /** | ||
| * @param[in] model - Pointer to the model to be differentiated | ||
| * @param[in] n_res - Number of residual functions | ||
| * @param[in] n_var - Number of independent variables | ||
| * @param[in] res_indices - Global residual indices | ||
| * @param[in] var_indices - Global variable indices | ||
| * @param[in] y - Internal variables | ||
| * @param[in] yp - Internal variable derivatives | ||
| * @param[in] wb - Bus variables | ||
| * @param[in,out] jac - Jacobian | ||
| */ | ||
| static void eval(ModelT* model, | ||
| size_t n_res, | ||
| size_t n_var, | ||
| const std::vector<IdxT>& res_indices, | ||
| const std::vector<IdxT>& var_indices, | ||
| ScalarT* y, | ||
| ScalarT* yp, | ||
| ScalarT* wb, | ||
| MatrixT& jac) | ||
| { | ||
| if (n_res > 0 && n_var > 0) | ||
| { | ||
| std::vector<Triple<ScalarT>> triplets; //< @todo: Update once sparse storage format changes | ||
| std::vector<ScalarT> elementary_v(n_var); | ||
| for (size_t var_i = 0; var_i < n_var; ++var_i) | ||
| { | ||
| // Sparse storage. @see LowerSparseStorage.hpp | ||
| ScalarT* output = __enzyme_todense<ScalarT*>((void*) ident_load<ScalarT>, (void*) ident_store<ScalarT>, var_i); | ||
| ScalarT* d_output = __enzyme_todense<ScalarT*>((void*) sparse_load<ScalarT>, (void*) sparse_store<ScalarT>, var_i, &triplets); | ||
|
|
||
| // Elementary vector for Jacobian-vector product | ||
| std::ranges::fill(elementary_v, 0.0); | ||
| elementary_v[var_i] = 1.0; | ||
|
|
||
| // Core automatic differentiaation intrinsic that will be replaced by a derivative | ||
| __enzyme_fwddiff<void>((void*) ModelWrapper<ModelT, function, ScalarT>::eval, | ||
| enzyme_const, | ||
pelesh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| model, | ||
| enzyme_const, | ||
| y, | ||
| enzyme_const, | ||
| yp, | ||
| enzyme_dup, | ||
| wb, | ||
| output, | ||
| enzyme_dupnoneed, | ||
| elementary_v.data(), | ||
| d_output); | ||
| } | ||
|
|
||
| // Store result | ||
| std::vector<IdxT> ctemp{}; | ||
| std::vector<IdxT> rtemp{}; | ||
| std::vector<ScalarT> valtemp{}; | ||
| for (auto& tup : triplets) | ||
| { | ||
| rtemp.push_back(res_indices[static_cast<size_t>(tup.row)]); | ||
| ctemp.push_back(var_indices[static_cast<size_t>(tup.col)]); | ||
| valtemp.push_back(tup.val); | ||
| } | ||
| jac.setValues(rtemp, ctemp, valtemp); //< @todo: Update once sparse storage format changes | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @param[in] model - Pointer to the model to be differentiated | ||
| * @param[in] n_res - Number of residual functions | ||
| * @param[in] n_var - Number of independent variables | ||
| * @param[in] res_indices - Global residual indices | ||
| * @param[in] var_indices - Global variable indices | ||
| * @param[in] y - Internal variables | ||
| * @param[in] yp - Internal variable derivatives | ||
| * @param[in] wb - Bus variables | ||
| * @param[in] ws - Signal variables | ||
| * @param[in,out] jac - Jacobian | ||
| */ | ||
| static void eval(ModelT* model, | ||
| size_t n_res, | ||
| size_t n_var, | ||
| const std::vector<IdxT>& res_indices, | ||
| const std::vector<IdxT>& var_indices, | ||
| ScalarT* y, | ||
| ScalarT* yp, | ||
| ScalarT* wb, | ||
| ScalarT* ws, | ||
| MatrixT& jac) | ||
| { | ||
| if (n_res > 0 && n_var > 0) | ||
| { | ||
| std::vector<Triple<ScalarT>> triplets; //< @todo: Update once sparse storage format changes | ||
| std::vector<ScalarT> elementary_v(n_var); | ||
| for (size_t var_i = 0; var_i < n_var; ++var_i) | ||
| { | ||
| // Sparse storage. @see LowerSparseStorage.hpp | ||
| ScalarT* output = __enzyme_todense<ScalarT*>((void*) ident_load<ScalarT>, (void*) ident_store<ScalarT>, var_i); | ||
| ScalarT* d_output = __enzyme_todense<ScalarT*>((void*) sparse_load<ScalarT>, (void*) sparse_store<ScalarT>, var_i, &triplets); | ||
|
|
||
pelesh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Elementary vector for Jacobian-vector product | ||
| std::ranges::fill(elementary_v, 0.0); | ||
| elementary_v[var_i] = 1.0; | ||
|
|
||
| // Core automatic differentiaation intrinsic that will be replaced by a derivative | ||
| __enzyme_fwddiff<void>((void*) ModelWrapper<ModelT, function, ScalarT>::eval, | ||
| enzyme_const, | ||
| model, | ||
| enzyme_const, | ||
| y, | ||
| enzyme_const, | ||
| yp, | ||
| enzyme_dup, | ||
| wb, | ||
| output, | ||
| enzyme_const, | ||
| ws, | ||
| enzyme_dupnoneed, | ||
| elementary_v.data(), | ||
| d_output); | ||
| } | ||
|
|
||
| // Store result | ||
| std::vector<IdxT> ctemp{}; | ||
| std::vector<IdxT> rtemp{}; | ||
| std::vector<ScalarT> valtemp{}; | ||
| for (auto& tup : triplets) | ||
| { | ||
| rtemp.push_back(res_indices[static_cast<size_t>(tup.row)]); | ||
| ctemp.push_back(var_indices[static_cast<size_t>(tup.col)]); | ||
| valtemp.push_back(tup.val); | ||
| } | ||
| jac.setValues(rtemp, ctemp, valtemp); //< @todo: Update once sparse storage format changes | ||
| } | ||
| } | ||
| }; | ||
| } // namespace Sparse | ||
| } // namespace Enzyme | ||
| } // namespace GridKit | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| /** | ||
| * @file DfDws.hpp | ||
| * @author Nicholson Koukpaizan (koukpaizannk@ornl.gov) | ||
| * | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <GridKit/AutomaticDifferentiation/Enzyme/EnzymeDefinitions.hpp> | ||
| #include <GridKit/AutomaticDifferentiation/Enzyme/LowerSparseStorage.hpp> | ||
| #include <GridKit/AutomaticDifferentiation/Enzyme/ModelWrappers.hpp> | ||
| #include <GridKit/Constants.hpp> | ||
| #include <GridKit/LinearAlgebra/SparseMatrix/COO_Matrix.hpp> | ||
| #include <GridKit/ScalarTraits.hpp> | ||
|
|
||
| namespace GridKit | ||
| { | ||
| namespace Enzyme | ||
| { | ||
| namespace Sparse | ||
| { | ||
| /** | ||
| * @brief Enzyme automatic differentiation Jacobian evaluator: df/dws | ||
| * | ||
| * @tparam ModelT - model type | ||
pelesh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * @tparam MemberFunctions - member function parameter key | ||
| * @tparam ScalarT - scalar data type | ||
| * @tparam IdxT - matrix index data type | ||
| */ | ||
| template <typename ModelT, MemberFunctions function, class ScalarT, typename IdxT> | ||
| struct DfDws | ||
| { | ||
| using RealT = typename GridKit::ScalarTraits<ScalarT>::RealT; | ||
| using MatrixT = GridKit::LinearAlgebra::COO_Matrix<RealT, IdxT>; | ||
|
|
||
| /** | ||
| * @param[in] model - Pointer to the model to be differentiated | ||
| * @param[in] n_res - Number of residual functions | ||
| * @param[in] n_var - Number of independent variables | ||
| * @param[in] res_indices - Global residual indices | ||
| * @param[in] var_indices - Global variable indices | ||
| * @param[in] y - Internal variables | ||
| * @param[in] yp - Internal variable derivatives | ||
| * @param[in] wb - Bus variables | ||
| * @param[in] ws - Signal variables | ||
| * @param[in,out] jac - Jacobian | ||
| */ | ||
| static void eval(ModelT* model, | ||
| size_t n_res, | ||
| size_t n_var, | ||
| const std::vector<IdxT>& res_indices, | ||
| const std::vector<IdxT>& var_indices, | ||
| ScalarT* y, | ||
| ScalarT* yp, | ||
| ScalarT* wb, | ||
| ScalarT* ws, | ||
| MatrixT& jac) | ||
| { | ||
| if (n_res > 0 && n_var > 0) | ||
| { | ||
| std::vector<Triple<ScalarT>> triplets; //< @todo: Update once sparse storage format changes | ||
| std::vector<ScalarT> elementary_v(n_var); | ||
| for (size_t var_i = 0; var_i < n_var; ++var_i) | ||
| { | ||
| // Sparse storage. @see LowerSparseStorage.hpp | ||
| ScalarT* output = __enzyme_todense<ScalarT*>((void*) ident_load<ScalarT>, (void*) ident_store<ScalarT>, var_i); | ||
| ScalarT* d_output = __enzyme_todense<ScalarT*>((void*) sparse_load<ScalarT>, (void*) sparse_store<ScalarT>, var_i, &triplets); | ||
|
|
||
| // Elementary vector for Jacobian-vector product | ||
| std::ranges::fill(elementary_v, 0.0); | ||
| elementary_v[var_i] = 1.0; | ||
|
|
||
| // Core automatic differentiaation intrinsic that will be replaced by a derivative | ||
| __enzyme_fwddiff<void>((void*) ModelWrapper<ModelT, function, ScalarT>::eval, | ||
| enzyme_const, | ||
| model, | ||
| enzyme_const, | ||
| y, | ||
| enzyme_const, | ||
| yp, | ||
| enzyme_const, | ||
| wb, | ||
| enzyme_dup, | ||
| ws, | ||
| output, | ||
| enzyme_dupnoneed, | ||
| elementary_v.data(), | ||
| d_output); | ||
| } | ||
|
|
||
| // Store result | ||
| std::vector<IdxT> ctemp{}; | ||
| std::vector<IdxT> rtemp{}; | ||
| std::vector<ScalarT> valtemp{}; | ||
| for (auto& tup : triplets) | ||
| { | ||
| IdxT row = res_indices[static_cast<size_t>(tup.row)]; | ||
| IdxT col = var_indices[static_cast<size_t>(tup.col)]; | ||
| if (col != INVALID_INDEX<IdxT>) | ||
| { | ||
| rtemp.push_back(row); | ||
| ctemp.push_back(col); | ||
| valtemp.push_back(tup.val); | ||
| } | ||
| } | ||
| jac.setValues(rtemp, ctemp, valtemp); //< @todo: Update once sparse storage format changes | ||
| } | ||
| } | ||
| }; | ||
| } // namespace Sparse | ||
| } // namespace Enzyme | ||
| } // namespace GridKit | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.