From 7c25e7bacba2dfafcdb5a92dccf91c0707906afd Mon Sep 17 00:00:00 2001 From: Bret Naylor Date: Thu, 20 Jul 2023 15:00:59 -0400 Subject: [PATCH 1/3] added poem 91 --- POEM_091.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 POEM_091.md diff --git a/POEM_091.md b/POEM_091.md new file mode 100644 index 00000000..133755bd --- /dev/null +++ b/POEM_091.md @@ -0,0 +1,81 @@ +POEM ID: 091 +Title: Eliminate combined jacobian-based and matrix free capability in components. +authors: @naylor-b +Competing POEMs: +Related POEMs: +Associated implementation PR: + +Status: + +- [x] Active +- [ ] Requesting decision +- [ ] Accepted +- [ ] Rejected +- [ ] Integrated + + +## Motivation + +Our current implementation allows a component to perform matrix free operations (`compute_jacvec_product` or `apply_linear`) and in addition compute sub-jacobians using `compute_partials` or `linearize`. This makes it difficult to declare partials for that component in a way that results in the best performance. OpenMDAO has a new relevance graph (or will have shortly after this POEM is submitted) that considers dependencies between individual inputs and outputs of the same component based on which partials are declared within that component, i.e., if no partial is declared for output y with respect to input x, then in the graph, y does not depend on x. + +In order to take advantage of this new relevance graph, all components must accurately declare which of their partials are +nonzero. In the case of a matrix free component, the current implementation will allocate space to contain the corresponding +sub-jacobian for every declared partial. Some variables in a matrix free component are likely quite large, resulting in +allocation of a very large sub-jacobian. OpenMDAO currently warns the user when this happens, which discourages the author of +a matrix free component from declaring any partials. But if the matrix free component doesn't declare any partials, how can +the new relevance graph accurately reflect any internal sparsity within that component? + + +## Proposed solution + +We propose that OpenMDAO will no longer allow a single component to compute both matrix free and jacobian based derivatives. +All components with either be 100% matrix free or 100% jacobian based. + +This means that a matrix free component can declare partials to inform the framework about its internal sparsity without +unnecessarily allocating memory for sub-jacobians. + +In order to maintain backward compatability, a matrix free component that declares no partials will be treated as if it +declared dense partials, i.e., all outputs depend on all inputs. However, if a matrix free component declares *any* partials, +then any that are not declared are assumed to be zero. + + +## Example + +In the example below, the matrix free component has an output 'y1' that depends only on input 'x1' and an output +'y2' that depends only on input 'x2'. Declaring the partials only for 'y1' wrt 'x1' and 'y2' wrt 'x2' tells the +framework that the 'y1' wrt 'x2' and 'y2' wrt 'x1' partials are zero and those connections can be left out of the +relevance graph. + + +``` +class MatFreeComp(om.ExplicitComponent): + + def setup(self): + self.add_input("x1", val=1.0) + self.add_input("x2", val=1.0) + self.add_output("y1", val=1.0) + self.add_output("y2", val=1.0) + + self.declare_partials('y1', 'x1') + self.declare_partials('y2', 'x2') + + def compute(self, inputs, outputs): + outputs['y1'] = 2.0 * inputs['x1'] + outputs['y2'] = 3.0 * inputs['x2'] + + def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode): + if mode == 'fwd': + if 'y1' in d_outputs: + if 'x1' in d_inputs: + d_outputs['y1'] += 2.0 * d_inputs['x1'] + if 'y2' in d_outputs: + if 'x2' in d_inputs: + d_outputs['y2'] += 3.0 * d_inputs['x2'] + else: # rev + if 'y1' in d_outputs: + if 'x1' in d_inputs: + d_inputs['x1'] += 2.0 * d_outputs['y1'] + if 'y2' in d_outputs: + if 'x2' in d_inputs: + d_inputs['x2'] += 3.0 * d_outputs['y2'] +``` \ No newline at end of file From a97b58ae70b6242908b68680e6136580f0ec39ae Mon Sep 17 00:00:00 2001 From: Bret Naylor Date: Wed, 23 Aug 2023 13:52:06 -0400 Subject: [PATCH 2/3] small fixes --- POEM_091.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/POEM_091.md b/POEM_091.md index 133755bd..9076e802 100644 --- a/POEM_091.md +++ b/POEM_091.md @@ -16,7 +16,8 @@ Status: ## Motivation -Our current implementation allows a component to perform matrix free operations (`compute_jacvec_product` or `apply_linear`) and in addition compute sub-jacobians using `compute_partials` or `linearize`. This makes it difficult to declare partials for that component in a way that results in the best performance. OpenMDAO has a new relevance graph (or will have shortly after this POEM is submitted) that considers dependencies between individual inputs and outputs of the same component based on which partials are declared within that component, i.e., if no partial is declared for output y with respect to input x, then in the graph, y does not depend on x. +Our current implementation allows a component to perform matrix free operations (`compute_jacvec_product` or `apply_linear`) and in addition compute sub-jacobians using `compute_partials` or `linearize`. This makes it difficult to declare partials for that component in a way that results in the best performance. OpenMDAO has a new relevance graph +that considers dependencies between individual inputs and outputs of the same component based on which partials are declared within that component, i.e., if no partial is declared for output y with respect to input x, then in the graph, y does not depend on x. In order to take advantage of this new relevance graph, all components must accurately declare which of their partials are nonzero. In the case of a matrix free component, the current implementation will allocate space to contain the corresponding @@ -29,10 +30,10 @@ the new relevance graph accurately reflect any internal sparsity within that com ## Proposed solution We propose that OpenMDAO will no longer allow a single component to compute both matrix free and jacobian based derivatives. -All components with either be 100% matrix free or 100% jacobian based. +All components will be either 100% matrix free or 100% jacobian based. This means that a matrix free component can declare partials to inform the framework about its internal sparsity without -unnecessarily allocating memory for sub-jacobians. +allocating any memory for sub-jacobians. In order to maintain backward compatability, a matrix free component that declares no partials will be treated as if it declared dense partials, i.e., all outputs depend on all inputs. However, if a matrix free component declares *any* partials, From 78477d7307d9c534a5a89379ee2c23ce3cc34cde Mon Sep 17 00:00:00 2001 From: Bret Naylor Date: Mon, 28 Aug 2023 16:49:49 -0400 Subject: [PATCH 3/3] updated wording to clarify that restrictions apply only to individual components --- POEM_091.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/POEM_091.md b/POEM_091.md index 9076e802..e77ca800 100644 --- a/POEM_091.md +++ b/POEM_091.md @@ -1,5 +1,5 @@ POEM ID: 091 -Title: Eliminate combined jacobian-based and matrix free capability in components. +Title: Eliminate combined jacobian-based and matrix free capability in a single component. authors: @naylor-b Competing POEMs: Related POEMs: @@ -30,7 +30,8 @@ the new relevance graph accurately reflect any internal sparsity within that com ## Proposed solution We propose that OpenMDAO will no longer allow a single component to compute both matrix free and jacobian based derivatives. -All components will be either 100% matrix free or 100% jacobian based. +Each component will be either matrix free or jacobian based, but not both. Note that matrix free components and jacobian +based components may still be freely mixed within the same model. This means that a matrix free component can declare partials to inform the framework about its internal sparsity without allocating any memory for sub-jacobians.