diff --git a/.github/workflows/openmdao_test_workflow.yml b/.github/workflows/openmdao_test_workflow.yml index c3aa2c0c26..e8e7bf6943 100644 --- a/.github/workflows/openmdao_test_workflow.yml +++ b/.github/workflows/openmdao_test_workflow.yml @@ -75,8 +75,8 @@ jobs: # test oldest supported versions - NAME: Ubuntu Oldest OS: ubuntu-latest - PY: '3.7' - NUMPY: '1.21' + PY: '3.8' + NUMPY: '1.22' SCIPY: '1.7' OPENMPI: '4.0' MPI4PY: '3.0' diff --git a/README.md b/README.md index c0ca185674..026965c1b1 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ generator. You can install everything needed for development by running: ## OpenMDAO Versions -**OpenMDAO 3.x.y** represents the current, supported version. It requires Python 3.7 +**OpenMDAO 3.x.y** represents the current, supported version. It requires Python 3.8 or later and is maintained [here][4]. To upgrade to the latest release, run: pip install --upgrade openmdao diff --git a/openmdao/core/component.py b/openmdao/core/component.py index 12f88bc3d6..bdb223c7cc 100644 --- a/openmdao/core/component.py +++ b/openmdao/core/component.py @@ -201,10 +201,6 @@ def _setup_procs(self, pathname, comm, mode, prob_meta): self._has_distrib_vars = self._has_distrib_outputs = False for meta in self._static_var_rel2meta.values(): - # variable isn't distributed if we're only running on 1 proc - if nprocs == 1 and 'distributed' in meta and meta['distributed']: - meta['distributed'] = False - # reset shape if any dynamic shape parameters are set in case this is a resetup # NOTE: this is necessary because we allow variables to be added in __init__. if 'shape_by_conn' in meta and (meta['shape_by_conn'] or diff --git a/openmdao/core/problem.py b/openmdao/core/problem.py index 942a0dd299..1d5fdb0fe5 100644 --- a/openmdao/core/problem.py +++ b/openmdao/core/problem.py @@ -936,19 +936,6 @@ def setup(self, check=False, logger=None, mode='auto', force_alloc_complex=False model = self.model comm = self.comm - if sys.version_info.minor < 8: - sv = sys.version_info - msg = f'OpenMDAO support for Python version {sv.major}.{sv.minor} will end soon.' - try: - from IPython import get_ipython - ip = get_ipython() - if ip is None or ip.config is None or 'IPKernelApp' not in ip.config: - warn_deprecation(msg) - except ImportError: - warn_deprecation(msg) - except AttributeError: - warn_deprecation(msg) - if not isinstance(self.model, Group): raise TypeError("The model for this Problem is of type " f"'{self.model.__class__.__name__}'. " @@ -1214,11 +1201,12 @@ def check_partials(self, out_stream=_DEFAULT_OUT_STREAM, includes=None, excludes excludes = [excludes] if isinstance(excludes, str) else excludes comps = [] - under_CI = env_truthy('OPENMDAO_CHECK_ALL_PARTIALS') + + # OPENMDAO_CHECK_ALL_PARTIALS overrides _no_check_partials (used for testing) + force_check_partials = env_truthy('OPENMDAO_CHECK_ALL_PARTIALS') for comp in model.system_iter(typ=Component, include_self=True): - # if we're under CI, do all of the partials, ignoring _no_check_partials - if comp._no_check_partials and not under_CI: + if comp._no_check_partials and not force_check_partials: continue # skip any Component with no outputs @@ -1405,7 +1393,7 @@ def check_partials(self, out_stream=_DEFAULT_OUT_STREAM, includes=None, excludes # Matrix Vector Product self._metadata['checking'] = True try: - comp._apply_linear(None, mode) + comp.run_apply_linear(mode) finally: self._metadata['checking'] = False diff --git a/openmdao/core/system.py b/openmdao/core/system.py index fbc3a3f4b9..0edfefcd87 100644 --- a/openmdao/core/system.py +++ b/openmdao/core/system.py @@ -2128,13 +2128,28 @@ def _setup_driver_units(self, abs2meta=None): "were specified." raise RuntimeError(msg.format(self.msginfo, name, var_units, units)) - factor, offset = unit_conversion(var_units, units) - base_adder, base_scaler = determine_adder_scaler(None, None, - meta['adder'], - meta['scaler']) - - meta['total_adder'] = offset + base_adder / factor - meta['total_scaler'] = base_scaler * factor + # Derivation of the total scaler and total adder for design variables: + # Given based design variable value y + # First we apply the desired unit conversion + # y_in_desired_units = unit_scaler * (y + unit_adder) + # Then we apply the user-declared scaling + # y_opt = declared_scaler * (y_in_desired_units + declared_adder) + # Thus + # y_opt = declared_scaler * (unit_scaler * (y + unit_adder) + declared_adder) + # And collecting terms + # y_opt = [declared_scaler * unit_scaler] + # * (y + unit_adder + declared_adder/unit_scaler) + # So the total_scaler and total_adder for the optimizer are: + # total_scaler = declared_scaler * unit_scaler + # total_adder = unit_adder + declared_adder / unit_scaler + + unit_scaler, unit_adder = unit_conversion(var_units, units) + declared_adder, declared_scaler = determine_adder_scaler(None, None, + meta['adder'], + meta['scaler']) + + meta['total_adder'] = unit_adder + declared_adder / unit_scaler + meta['total_scaler'] = declared_scaler * unit_scaler if meta['total_scaler'] is not None: has_scaling = True @@ -2172,13 +2187,12 @@ def _setup_driver_units(self, abs2meta=None): raise RuntimeError(msg.format(self.msginfo, type_dict[meta['type']], name, src_units, units)) - factor, offset = unit_conversion(src_units, units) - base_adder, base_scaler = determine_adder_scaler(None, None, - meta['adder'], - meta['scaler']) + unit_scaler, unit_adder = unit_conversion(src_units, units) + declared_adder, declared_scaler =\ + determine_adder_scaler(None, None, meta['adder'], meta['scaler']) - meta['total_scaler'] = base_scaler * factor - meta['total_adder'] = offset + base_adder / factor + meta['total_scaler'] = declared_scaler * unit_scaler + meta['total_adder'] = unit_adder + declared_adder / unit_scaler if meta['total_scaler'] is not None: has_scaling = True diff --git a/openmdao/core/tests/test_check_partials.py b/openmdao/core/tests/test_check_partials.py index 98cb6efc4b..1406e37e3e 100644 --- a/openmdao/core/tests/test_check_partials.py +++ b/openmdao/core/tests/test_check_partials.py @@ -1983,17 +1983,14 @@ def create_problem(force_alloc_complex=False): prob.setup(force_alloc_complex=force_alloc_complex) return prob, parab - expected_check_partials_error = f"Problem .*: Checking partials with respect " \ - "to variable '{var}' in component " \ - "'{comp.pathname}' using the same " \ - "method and options as are used to compute the " \ - "component's derivatives " \ - "will not provide any relevant information on the " \ - "accuracy\.\n" \ + expected_check_partials_error = "Problem {prob._name}: Checking partials " \ + "with respect to variable '{var}' in component '{comp.pathname}' using the " \ + "same method and options as are used to compute the component's derivatives " \ + "will not provide any relevant information on the accuracy.\n" \ "To correct this, change the options to do the \n" \ "check_partials using either:\n" \ - " - arguments to Problem\.check_partials. \n" \ - " - arguments to Component\.set_check_partial_options" + " - arguments to Problem.check_partials. \n" \ + " - arguments to Component.set_check_partial_options" # Scenario 1: # Compute partials: exact @@ -2008,9 +2005,10 @@ def create_problem(force_alloc_complex=False): # Expected result: Error prob, parab = create_problem() parab.declare_partials(of='*', wrt='*', method='fd') - expected_error_msg = expected_check_partials_error.format(var='x', comp=self.parab) - with self.assertRaisesRegex(OMInvalidCheckDerivativesOptionsWarning, expected_error_msg): + with self.assertRaises(OMInvalidCheckDerivativesOptionsWarning) as cm: prob.check_partials(method='fd') + self.assertEqual(str(cm.exception), + expected_check_partials_error.format(prob=prob, var='x', comp=parab)) # Scenario 3: # Compute partials: fd, with default options @@ -2052,9 +2050,10 @@ def create_problem(force_alloc_complex=False): # Expected result: Error since using fd to check fd. All options the same prob, parab = create_problem() parab.declare_partials(of='*', wrt='*', method='fd') - expected_error_msg = expected_check_partials_error.format(var='x', comp=parab) - with self.assertRaisesRegex(OMInvalidCheckDerivativesOptionsWarning, expected_error_msg): + with self.assertRaises(OMInvalidCheckDerivativesOptionsWarning) as cm: prob.check_partials(method='cs') + self.assertEqual(str(cm.exception), + expected_check_partials_error.format(prob=prob, var='x', comp=parab)) # Scenario 7: # Compute partials: fd, with default options @@ -2074,9 +2073,10 @@ def create_problem(force_alloc_complex=False): prob, parab = create_problem() parab.declare_partials(of='*', wrt='*', method='fd') parab.set_check_partial_options('*') - expected_error_msg = expected_check_partials_error.format(var='x', comp=parab) - with self.assertRaisesRegex(OMInvalidCheckDerivativesOptionsWarning, expected_error_msg): + with self.assertRaises(OMInvalidCheckDerivativesOptionsWarning) as cm: prob.check_partials() + self.assertEqual(str(cm.exception), + expected_check_partials_error.format(prob=prob, var='x', comp=parab)) # Scenario 9: # Compute partials: fd, with default options @@ -2132,9 +2132,10 @@ def create_problem(force_alloc_complex=False): prob, parab = create_problem(force_alloc_complex=True) parab.declare_partials(of='*', wrt='*', method='cs') parab.set_check_partial_options('*', method='cs') - expected_error_msg = expected_check_partials_error.format(var='x', comp=parab) - with self.assertRaisesRegex(OMInvalidCheckDerivativesOptionsWarning, expected_error_msg): + with self.assertRaises(OMInvalidCheckDerivativesOptionsWarning) as cm: prob.check_partials() + self.assertEqual(str(cm.exception), + expected_check_partials_error.format(prob=prob, var='x', comp=parab)) # Scenario 15: # Compute partials: cs, with default options @@ -2148,12 +2149,11 @@ def create_problem(force_alloc_complex=False): prob.check_partials() # Now do similar checks for check_totals when approximations are used - expected_check_totals_error_msg = "Problem .*: Checking totals using the same " \ - "method and options as are used to compute the " \ - "totals will not provide any relevant information on the " \ - "accuracy\.\n" \ + expected_check_totals_error_msg = "Problem {prob._name}: Checking totals using the " \ + "same method and options as are used to compute the totals will not provide " \ + "any relevant information on the accuracy.\n" \ "To correct this, change the options to do the " \ - "check_totals or on the call to approx_totals for the model\." + "check_totals or on the call to approx_totals for the model." # Scenario 16: # Compute totals: no approx on totals @@ -2172,9 +2172,10 @@ def create_problem(force_alloc_complex=False): prob.model.approx_totals() prob.setup() prob.run_model() - with self.assertRaisesRegex(OMInvalidCheckDerivativesOptionsWarning, - expected_check_totals_error_msg) : + with self.assertRaises(OMInvalidCheckDerivativesOptionsWarning) as cm: prob.check_totals() + self.assertEqual(str(cm.exception), + expected_check_totals_error_msg.format(prob=prob)) # Scenario 18: # Compute totals: approx on totals using defaults @@ -2225,9 +2226,10 @@ def create_problem(force_alloc_complex=False): prob.model.approx_totals(method='cs') prob.setup() prob.run_model() - with self.assertRaisesRegex(OMInvalidCheckDerivativesOptionsWarning, - expected_check_totals_error_msg): + with self.assertRaises(OMInvalidCheckDerivativesOptionsWarning) as cm: prob.check_totals(method='cs') + self.assertEqual(str(cm.exception), + expected_check_totals_error_msg.format(prob=prob)) # Scenario 22: # Compute totals: fd, the default diff --git a/openmdao/core/tests/test_distribcomp.py b/openmdao/core/tests/test_distribcomp.py index a4fb53c686..32eb423c24 100644 --- a/openmdao/core/tests/test_distribcomp.py +++ b/openmdao/core/tests/test_distribcomp.py @@ -1091,6 +1091,55 @@ def compute(self, inputs, outputs): assert_near_equal(p.get_val('C1.y', get_remote=False), 6. if p.model.C1.comm.rank == 0 else 14.) +@unittest.skipUnless(MPI and PETScVector, "MPI and PETSc are required.") +class TestDistribCheckMPI(unittest.TestCase): + N_PROCS = 2 + + def test_distrib_conn_check(self): + class Serial2Distributed(om.ExplicitComponent): + def setup(self): + self.add_input("serial_in", shape=3) + + if self.comm.rank == 0: + self.add_output("dist_out", shape=3, distributed=True) + else: + self.add_output("dist_out", shape=0, distributed=True) + + def compute(self, inputs, outputs): + if self.comm.rank == 0: + outputs["dist_out"] = inputs["serial_in"] + + class DistributedSum(om.ExplicitComponent): + def setup(self): + self.add_output("sum", shape=1) + + def compute(self, inputs, outputs): + outputs["sum"] = self.comm.bcast(sum(inputs["dist_in"]), root=0) + + class SumGroup(om.Group): + def setup(self): + self.add_subsystem("s2d", Serial2Distributed(), promotes_inputs=[("serial_in", "in")]) + self.add_subsystem("sum", DistributedSum(), promotes_outputs=["sum"]) + self.sum.add_input("dist_in", shape_by_conn=True, distributed=True) + self.connect("s2d.dist_out", "sum.dist_in") + + prob = om.Problem() + model = prob.model + + model.add_subsystem("ivc", om.IndepVarComp("x", [0.0, 1.0, 2.0, 3.0, 4.0, 5.0])) + parallel = model.add_subsystem('parallel', om.ParallelGroup()) + parallel.add_subsystem('sum1', SumGroup()) + parallel.add_subsystem('sum2', SumGroup()) + + model.connect("ivc.x", "parallel.sum1.in", src_indices=om.slicer[:3]) + model.connect("ivc.x", "parallel.sum2.in", src_indices=om.slicer[3:]) + + prob.setup() + prob.run_model() + + assert_near_equal(prob.get_val("parallel.sum1.sum", get_remote=True), 3.0) + assert_near_equal(prob.get_val("parallel.sum2.sum", get_remote=True), 12.0) + if __name__ == '__main__': from openmdao.utils.mpi import mpirun_tests mpirun_tests() diff --git a/openmdao/core/tests/test_scaling.py b/openmdao/core/tests/test_scaling.py index e0135a664c..1ea57751f7 100644 --- a/openmdao/core/tests/test_scaling.py +++ b/openmdao/core/tests/test_scaling.py @@ -10,7 +10,8 @@ from openmdao.test_suite.components.expl_comp_array import TestExplCompArrayDense from openmdao.test_suite.components.impl_comp_array import TestImplCompArrayDense -from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import force_check_partials +from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials from openmdao.test_suite.components.unit_conv import SrcComp, TgtCompF @@ -1434,5 +1435,160 @@ def test_iimplicit(self): assert_near_equal(totals[of, wrt]['abs error'][0], 0.0, 1e-7) +class TestResidualScaling(unittest.TestCase): + + def test_residual_scaling(self): + # When the residuals of an implicit component are scaled (for example + # using the res_ref argument to add_output), the partial derivatives + # computed through the matrix-free API should be modified to account + # for this scaling as they are through the standard API. + + # In this test case, an apply_linear method has been added to the + # Node component in the circuit analysis example and it's residuals + # have been scaled by a factor of 1000 (using res_ref=1e-3). + + class Resistor(om.ExplicitComponent): + """Computes current across a resistor using Ohm's law.""" + + def initialize(self): + self.options.declare("R", default=1.0, desc="Resistance in Ohms") + + def setup(self): + self.add_input("V_in", units="V") + self.add_input("V_out", units="V") + self.add_output("I", units="A") + + # partial derivs are constant, so we can assign their values in setup + R = self.options["R"] + self.declare_partials("I", "V_in", val=1 / R) + self.declare_partials("I", "V_out", val=-1 / R) + + def compute(self, inputs, outputs): + deltaV = inputs["V_in"] - inputs["V_out"] + outputs["I"] = deltaV / self.options["R"] + + class Diode(om.ExplicitComponent): + """Computes current across a diode using the Shockley diode equation.""" + + def initialize(self): + self.options.declare("Is", default=1e-15, desc="Saturation current in Amps") + self.options.declare("Vt", default=0.025875, desc="Thermal voltage in Volts") + + def setup(self): + self.add_input("V_in", units="V") + self.add_input("V_out", units="V") + self.add_output("I", units="A") + + # non-linear component, so we'll declare the partials here but compute them in compute_partials + self.declare_partials("I", "V_in") + self.declare_partials("I", "V_out") + + def compute(self, inputs, outputs): + deltaV = inputs["V_in"] - inputs["V_out"] + Is = self.options["Is"] + Vt = self.options["Vt"] + outputs["I"] = Is * (np.exp(deltaV / Vt) - 1) + + def compute_partials(self, inputs, J): + deltaV = inputs["V_in"] - inputs["V_out"] + Is = self.options["Is"] + Vt = self.options["Vt"] + I = Is * np.exp(deltaV / Vt) + + J["I", "V_in"] = I / Vt + J["I", "V_out"] = -I / Vt + + class Node(om.ImplicitComponent): + """Computes voltage residual across a node based on incoming and outgoing current.""" + + def initialize(self): + self.options.declare("n_in", default=1, types=int, desc="number of connections with + assumed in") + self.options.declare("n_out", default=1, types=int, desc="number of current connections + assumed out") + + def setup(self): + self.add_output("V", val=5.0, units="V", res_ref=1e-3) + + for i in range(self.options["n_in"]): + i_name = "I_in:{}".format(i) + self.add_input(i_name, units="A") + + for i in range(self.options["n_out"]): + i_name = "I_out:{}".format(i) + self.add_input(i_name, units="A") + + # note: we don't declare any partials wrt `V` here, + # because the residual doesn't directly depend on it + + def apply_nonlinear(self, inputs, outputs, residuals): + residuals["V"] = 0.0 + for i_conn in range(self.options["n_in"]): + residuals["V"] += inputs["I_in:{}".format(i_conn)] + for i_conn in range(self.options["n_out"]): + residuals["V"] -= inputs["I_out:{}".format(i_conn)] + + def apply_linear(self, inputs, outputs, d_inputs, d_outputs, d_residuals, mode): + if mode == "fwd": + for i_conn in range(self.options["n_in"]): + d_residuals["V"] += d_inputs["I_in:{}".format(i_conn)] + for i_conn in range(self.options["n_out"]): + d_residuals["V"] -= d_inputs["I_out:{}".format(i_conn)] + + if mode == "rev": + for i_conn in range(self.options["n_in"]): + d_inputs["I_in:{}".format(i_conn)] += d_residuals["V"] + for i_conn in range(self.options["n_out"]): + d_inputs["I_out:{}".format(i_conn)] -= d_residuals["V"] + + class Circuit(om.Group): + + def setup(self): + self.add_subsystem("n1", Node(n_in=1, n_out=2), promotes_inputs=[("I_in:0", "I_in")]) + self.add_subsystem("n2", Node()) # leaving defaults + + self.add_subsystem("R1", Resistor(R=100.0), promotes_inputs=[("V_out", "Vg")]) + self.add_subsystem("R2", Resistor(R=10000.0)) + self.add_subsystem("D1", Diode(), promotes_inputs=[("V_out", "Vg")]) + + self.connect("n1.V", ["R1.V_in", "R2.V_in"]) + self.connect("R1.I", "n1.I_out:0") + self.connect("R2.I", "n1.I_out:1") + + self.connect("n2.V", ["R2.V_out", "D1.V_in"]) + self.connect("R2.I", "n2.I_in:0") + self.connect("D1.I", "n2.I_out:0") + + self.nonlinear_solver = om.NewtonSolver() + self.linear_solver = om.ScipyKrylov() + + self.nonlinear_solver.options["iprint"] = -1 + self.nonlinear_solver.options["maxiter"] = 10 + self.nonlinear_solver.options["solve_subsystems"] = True + self.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() + self.nonlinear_solver.linesearch.options["maxiter"] = 10 + self.nonlinear_solver.linesearch.options["iprint"] = -1 + + p = om.Problem() + model = p.model + + model.add_subsystem("circuit", Circuit()) + + p.setup(force_alloc_complex=True) + + p.set_val("circuit.I_in", 0.1) + p.set_val("circuit.Vg", 0.0) + + # set some initial guesses + p.set_val("circuit.n1.V", 10.0) + p.set_val("circuit.n2.V", 1e-3) + + p.run_model() + + # sanity check: should sum to .1 Amps + assert_near_equal(p["circuit.R1.I"] + p["circuit.D1.I"], .1) + + partials = force_check_partials(p, method='cs', step=1e-200, compact_print=True, out_stream=None) + assert_check_partials(partials) + + if __name__ == '__main__': unittest.main() diff --git a/openmdao/docs/build_source_docs.py b/openmdao/docs/build_source_docs.py index 95564b8d35..114b84d7d9 100644 --- a/openmdao/docs/build_source_docs.py +++ b/openmdao/docs/build_source_docs.py @@ -124,7 +124,7 @@ def build_src_docs(top, src_dir, project_name='openmdao'): # specifically don't use os.path.join here. Even windows wants the # stuff in the file to have fwd slashes. title = f"[{package}]" - link = f"(packages/{package}.md)\n" + link = f"(packages/{package}.ipynb)\n" index_data += f"- {title}{link}" # make subpkg directory (e.g. _srcdocs/packages/core) for ref sheets @@ -143,7 +143,7 @@ def build_src_docs(top, src_dir, project_name='openmdao'): # specifically don't use os.path.join here. Even windows wants the # stuff in the file to have fwd slashes. title = f"[{sub_package}]" - link = f"({package}/{sub_package}.md)\n" + link = f"({package}/{sub_package}.ipynb)\n" package_data += f"- {title}{link}" # creates and writes out one reference sheet (e.g. core/component.ipynb) diff --git a/openmdao/docs/openmdao_book/_toc.yml b/openmdao/docs/openmdao_book/_toc.yml index a7a44e8a9e..f88947b111 100644 --- a/openmdao/docs/openmdao_book/_toc.yml +++ b/openmdao/docs/openmdao_book/_toc.yml @@ -72,9 +72,7 @@ parts: - file: other_useful_docs/building_a_tool/building_a_tool.md sections: - file: other_useful_docs/building_a_tool/repository_structure - - file: other_useful_docs/building_a_tool/github_pages - file: other_useful_docs/building_a_tool/release_process - - file: other_useful_docs/building_a_tool/travis - file: other_useful_docs/auto_ivc_api_translation - file: other_useful_docs/api_translation - file: other_useful_docs/environment_vars diff --git a/openmdao/docs/openmdao_book/advanced_user_guide/advanced_user_guide.ipynb b/openmdao/docs/openmdao_book/advanced_user_guide/advanced_user_guide.ipynb new file mode 100644 index 0000000000..40e0f995f4 --- /dev/null +++ b/openmdao/docs/openmdao_book/advanced_user_guide/advanced_user_guide.ipynb @@ -0,0 +1,63 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c6e0d73b-d3f4-4787-9f15-f8084f6695c8", + "metadata": {}, + "source": [ + "# Advanced User Guide\n", + "\n", + "These tutorials cover more advanced topics. This guide assumes that you have read the [Basic User Guide](../basic_user_guide/basic_user_guide.ipynb), and it builds from those basics to cover more complex topics that will let you get the most out of the framework. Within each section, the tutorials are designed to be read in order, but each section is self-contained enough that you can choose to read only the sections that are useful to you.\n", + "\n", + "\n", + "## Models with Implicit Components\n", + "\n", + "- [Building Models with Solvers and Implicit Components](models_implicit_components/models_with_solvers_implicit.ipynb)\n", + "- [Using BalanceComp to Create Implicit Relationships in Groups](models_implicit_components/implicit_with_balancecomp.ipynb)\n", + "\n", + "## Working with Analytic Derivatives\n", + "\n", + "- [Defining Partial Derivatives on Explicit Components](analytic_derivatives/partial_derivs_explicit.ipynb)\n", + "- [Defining Partial Derivatives on Implicit Components](analytic_derivatives/partial_derivs_implicit.ipynb)\n", + "- [Computing Total Derivatives of Coupled Models](analytic_derivatives/derivs_of_coupled_systems.ipynb)\n", + "\n", + "## Recoding and Reading Data\n", + "\n", + "- [Advanced Recording Example](recording/advanced_case_recording.ipynb)\n", + "\n", + "## Using OpenMDAO as a Part of a Larger Process\n", + "- [Cannonball Example with Euler Integration and an External Optimizer](example/euler_integration_example.ipynb)\n", + "\n", + "## Details about Complex Step\n", + "- [Using Complex Step to Compute Derivatives](complex_step.ipynb)\n", + "\n", + "## Using AnalysisError\n", + "- [Using AnalysisError to avoid a region in the solution space](analysis_errors/analysis_error.ipynb)\n", + "\n", + "## Computing Partial Derivatives using JAX\n", + "- [Computing Partial Derivatives of Explicit Components Using JAX](jax_derivatives/partial_derivs_explicit.ipynb)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/openmdao/docs/openmdao_book/advanced_user_guide/advanced_user_guide.md b/openmdao/docs/openmdao_book/advanced_user_guide/advanced_user_guide.md deleted file mode 100644 index 021fac796d..0000000000 --- a/openmdao/docs/openmdao_book/advanced_user_guide/advanced_user_guide.md +++ /dev/null @@ -1,35 +0,0 @@ -# Advanced User Guide - -These tutorials cover more advanced topics. This guide assumes that you have read the [Basic User Guide](../basic_user_guide/basic_user_guide.md), and it builds from those basics to cover more complex topics that will let you get the most out of the framework. Within each section, the tutorials are designed to be read in order, but each section is self-contained enough that you can choose to read only the sections that are useful to you. - - -## Models with Implicit Components - -- [Building Models with Solvers and Implicit Components](models_implicit_components/models_with_solvers_implicit.ipynb) -- [Using BalanceComp to Create Implicit Relationships in Groups](models_implicit_components/implicit_with_balancecomp.ipynb) - -## Working with Analytic Derivatives - -- [Defining Partial Derivatives on Explicit Components](analytic_derivatives/partial_derivs_explicit.ipynb) -- [Defining Partial Derivatives on Implicit Components](analytic_derivatives/partial_derivs_implicit.ipynb) -- [Computing Total Derivatives of Coupled Models](analytic_derivatives/derivs_of_coupled_systems.ipynb) - -## Recoding and Reading Data - -- [Advanced Recording Example](recording/advanced_case_recording.ipynb) - -## Using OpenMDAO as a Part of a Larger Process -- [Cannonball Example with Euler Integration and an External Optimizer](example/euler_integration_example.ipynb) - -## Details about Complex Step -- [Using Complex Step to Compute Derivatives](complex_step.ipynb) - -## Using AnalysisError -- [Using AnalysisError to avoid a region in the solution space](analysis_errors/analysis_error.ipynb) - -## Computing Partial Derivatives using JAX -- [Computing Partial Derivatives of Explicit Components Using JAX](jax_derivatives/partial_derivs_explicit.ipynb) - -```python - -``` diff --git a/openmdao/docs/openmdao_book/advanced_user_guide/models_implicit_components/models_with_solvers_implicit.ipynb b/openmdao/docs/openmdao_book/advanced_user_guide/models_implicit_components/models_with_solvers_implicit.ipynb index 16058f1d6d..fe0cd44d7c 100644 --- a/openmdao/docs/openmdao_book/advanced_user_guide/models_implicit_components/models_with_solvers_implicit.ipynb +++ b/openmdao/docs/openmdao_book/advanced_user_guide/models_implicit_components/models_with_solvers_implicit.ipynb @@ -115,7 +115,7 @@ "metadata": {}, "source": [ "```{important}\n", - "Since we've provided default values for the options, they won't be required arguments when instantiating `Resistor` or `Diode`. Check out the [Features](../../features/features.md) section for more details on how to use [component options] (../../features/core_features/working_with_components/options.ipynb).\n", + "Since we've provided default values for the options, they won't be required arguments when instantiating `Resistor` or `Diode`. Check out the [Features](../../features/features.ipynb) section for more details on how to use [component options] (../../features/core_features/working_with_components/options.ipynb).\n", "```" ] }, @@ -193,7 +193,7 @@ "metadata": {}, "source": [ "## Building the Circuit Group and Solving It with NewtonSolver\n", - "We can combine the `Resistor`, `Diode`, and `Node` into the circuit pictured above using a [Group](../../features/core_features/working_with_groups/main.md). Adding components and connecting their variables is the same as what you've seen before in the [Sellar - Two Discipline](../../basic_user_guide/multidisciplinary_optimization/sellar.ipynb) tutorial. What is new here is the additional use of the nonlinear [NewtonSolver](../../features/building_blocks/solvers/newton.ipynb) and linear [DirectSolver](../../features/building_blocks/solvers/direct_solver.ipynb) to converge the system.\n", + "We can combine the `Resistor`, `Diode`, and `Node` into the circuit pictured above using a [Group](../../features/core_features/working_with_groups/main.ipynb). Adding components and connecting their variables is the same as what you've seen before in the [Sellar - Two Discipline](../../basic_user_guide/multidisciplinary_optimization/sellar.ipynb) tutorial. What is new here is the additional use of the nonlinear [NewtonSolver](../../features/building_blocks/solvers/newton.ipynb) and linear [DirectSolver](../../features/building_blocks/solvers/direct_solver.ipynb) to converge the system.\n", "\n", "In previous tutorials, we used a gradient-free [NonlinearBlockGaussSeidel](../../features/building_blocks/solvers/nonlinear_block_gs.ipynb) solver, but that won't work here. Just above, we discussed that the `Node` class does not, and in fact can not, define its own `solve_nonlinear` method. Hence, there would be no calculations for the GaussSeidel solver to iterate on.\n", "Instead we use the Newton solver at the `Circuit` level, which uses Jacobian information to compute group level updates for all the variables simultaneously. The Newton solver's use of that Jacobian information is why we need to declare a linear solver in this case.\n", diff --git a/openmdao/docs/openmdao_book/features/core_features/adding_desvars_cons_objs/adding_design_variables.ipynb b/openmdao/docs/openmdao_book/features/core_features/adding_desvars_cons_objs/adding_design_variables.ipynb index 0e45982500..c91f87ae21 100644 --- a/openmdao/docs/openmdao_book/features/core_features/adding_desvars_cons_objs/adding_design_variables.ipynb +++ b/openmdao/docs/openmdao_book/features/core_features/adding_desvars_cons_objs/adding_design_variables.ipynb @@ -208,6 +208,56 @@ "assert_near_equal(obj['y2'][0], 40.555555555555586)\n", "assert_near_equal(con['y1'][0], 21.111111111111143)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# How the optimizer sees scaled variables\n", + "\n", + "As stated above, when dealing with both a unit conversion and user-defined scaling for design variables (or constraints or objectives), the quantity is first converted to the specified units and then scaled according to the users `ref|ref0|scaler|adder` specification. \n", + "\n", + "This means that any scaling specification should be done in the specified units.\n", + "\n", + "The following derivation of the \"total_scaler\" and the \"total_adder\" applies to both driver design variables and responses.\n", + "\n", + "Given some design variable quantity `y`, we first convert it to the driver's units. OpenMDAO's unit system determines the scale factor (`unit_scaler`) and offset (`unit_adder`) that convert `y` from it's units within the model to its units from the driver's perspective. These are the units specified in the call to `add_design_var` (or `add_constraint` or `add_objective`).\n", + "\n", + "```\n", + "y_in_desired_units = unit_scaler * (y + unit_adder)\n", + "```\n", + "\n", + "Then we apply the user-declared scaling\n", + "\n", + "```\n", + "y_opt = declared_scaler * (y_in_desired_units + declared_adder)\n", + "```\n", + "\n", + "Thus the optimizer sees the quantity as:\n", + "\n", + "```\n", + "y_opt = declared_scaler * (unit_scaler * (y + unit_adder) + declared_adder)\n", + "```\n", + "\n", + "If we gather the scaler and adder terms we have\n", + "\n", + "```\n", + "y_opt = [declared_scaler * unit_scaler] * (y + unit_adder + declared_adder / unit_scaler)\n", + "```\n", + "\n", + "And therefore the \"total_scaler\" and \"total_adder\" are:\n", + "\n", + "```\n", + "total_scaler = declared_scaler * unit_scaler\n", + "\n", + "total_adder = unit_adder + declared_adder / unit_scaler\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] } ], "metadata": { @@ -227,7 +277,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.11.4" }, "orphan": true }, diff --git a/openmdao/docs/openmdao_book/features/experimental/plugins.ipynb b/openmdao/docs/openmdao_book/features/experimental/plugins.ipynb index d60aa3c82a..db71065b6a 100644 --- a/openmdao/docs/openmdao_book/features/experimental/plugins.ipynb +++ b/openmdao/docs/openmdao_book/features/experimental/plugins.ipynb @@ -5,8 +5,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - ":orphan:\n", - "\n", "# Working with Plugins\n", "\n", "The OpenMDAO plugin infrastructure provides a way for you to discover and use code that can extend the functionality of OpenMDAO.\n", diff --git a/openmdao/docs/openmdao_book/features/features.ipynb b/openmdao/docs/openmdao_book/features/features.ipynb index 4d94167563..736d738a69 100644 --- a/openmdao/docs/openmdao_book/features/features.ipynb +++ b/openmdao/docs/openmdao_book/features/features.ipynb @@ -77,7 +77,7 @@ "\n", "- [Determining Variable Shapes at Runtime](experimental/dyn_shapes.ipynb)\n", "- [Simultaneous Coloring of Approximated Derivatives](experimental/approx_coloring.ipynb)\n", - "- [Working with Plugins](experimental/plugins.md)\n" + "- [Working with Plugins](experimental/plugins.ipynb)\n" ] } ], diff --git a/openmdao/docs/openmdao_book/main.ipynb b/openmdao/docs/openmdao_book/main.ipynb new file mode 100644 index 0000000000..ddd14a7cb3 --- /dev/null +++ b/openmdao/docs/openmdao_book/main.ipynb @@ -0,0 +1,84 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bd581f79-0054-4ae7-910f-90bb924b80e5", + "metadata": {}, + "source": [ + "# Welcome to OpenMDAO\n", + "\n", + "OpenMDAO is an open-source high-performance computing platform for\n", + "systems analysis and multidisciplinary optimization, written in Python.\n", + "It enables you to decompose your models, making them easier to build and\n", + "maintain, while still solving them in a tightly coupled manner with\n", + "efficient parallel numerical methods.\n", + "\n", + "The OpenMDAO project is primarily focused on supporting gradient-based\n", + "optimization with analytic derivatives to allow you to explore large\n", + "design spaces with hundreds or thousands of design variables, but the\n", + "framework also has a number of parallel computing features that can\n", + "work with gradient-free optimization, mixed-integer nonlinear\n", + "programming, and traditional design space exploration.\n", + "\n", + "If you are using OpenMDAO, please [cite](other/citing.ipynb) us!\n", + "\n", + "## User Guide\n", + "\n", + "These are a collection of tutorial problems that teach you important concepts and techniques for using OpenMDAO.\n", + "For new users, you should work through all material in **Getting Started** and **Basic User Guide**.\n", + "That represents the minimum set of information you need to understand to be able to work with OpenMDAO models.\n", + "\n", + "You will also find tutorials in the **Advanced User Guide** to be very helpful as you grow more familiar with OpenMDAO,\n", + "but you don't need to read these right away.\n", + "They explain important secondary concepts that you will run into when working with more complex OpenMDAO models.\n", + "\n", + "- [Getting Started](getting_started/getting_started.ipynb)\n", + "- [Basic User Guide](basic_user_guide/basic_user_guide.ipynb)\n", + "- [Advanced User Guide](advanced_user_guide/advanced_user_guide.ipynb)\n", + "\n", + "\n", + "## Reference Guide\n", + "\n", + "These docs are intended to be used by as a reference by users looking for explanation of a particular feature in detail or\n", + "documentation of the arguments/options/settings for a specific method, Component, Driver, or Solver.\n", + "\n", + "- [Features](features/features.ipynb)\n", + "- [Examples](examples/examples.ipynb)\n", + "- [Theory Manual](theory_manual/theory_manual.ipynb)\n", + "\n", + "\n", + "## Other Useful Docs\n", + "\n", + "- [Command Line Tools](other_useful_docs/om_command.ipynb)\n", + "- [How to Cite OpenMDAO](other/citing.ipynb)\n", + "- [Building a Tool on Top of OpenMDAO](other_useful_docs/building_a_tool/building_a_tool.ipynb)\n", + "- [Conversion Guide for the Auto-IVC (IndepVarComp) Feature](other_useful_docs/auto_ivc_api_translation.ipynb)\n", + "- [Upgrading from OpenMDAO 2.10 to OpenMDAO 3](other_useful_docs/api_translation.ipynb)\n", + "- [File Wrapping](other_useful_docs/file_wrap.ipynb)\n", + "- [Source Docs](_srcdocs/index.ipynb)\n", + "- [Developer Docs (if you’re going to contribute code)](other_useful_docs/developer_docs/developer_docs.ipynb)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/openmdao/docs/openmdao_book/main.md b/openmdao/docs/openmdao_book/main.md deleted file mode 100644 index b4159c75d4..0000000000 --- a/openmdao/docs/openmdao_book/main.md +++ /dev/null @@ -1,52 +0,0 @@ -# Welcome to OpenMDAO - -OpenMDAO is an open-source high-performance computing platform for -systems analysis and multidisciplinary optimization, written in Python. -It enables you to decompose your models, making them easier to build and -maintain, while still solving them in a tightly coupled manner with -efficient parallel numerical methods. - -The OpenMDAO project is primarily focused on supporting gradient-based -optimization with analytic derivatives to allow you to explore large -design spaces with hundreds or thousands of design variables, but the -framework also has a number of parallel computing features that can -work with gradient-free optimization, mixed-integer nonlinear -programming, and traditional design space exploration. - -If you are using OpenMDAO, please [cite](other/citing.ipynb) us! - -## User Guide - -These are a collection of tutorial problems that teach you important concepts and techniques for using OpenMDAO. -For new users, you should work through all material in **Getting Started** and **Basic User Guide**. -That represents the minimum set of information you need to understand to be able to work with OpenMDAO models. - -You will also find tutorials in the **Advanced User Guide** to be very helpful as you grow more familiar with OpenMDAO, -but you don't need to read these right away. -They explain important secondary concepts that you will run into when working with more complex OpenMDAO models. - -- [Getting Started](getting_started/getting_started.md) -- [Basic User Guide](basic_user_guide/basic_user_guide.md) -- [Advanced User Guide](advanced_user_guide/advanced_user_guide.md) - - -## Reference Guide - -These docs are intended to be used by as a reference by users looking for explanation of a particular feature in detail or -documentation of the arguments/options/settings for a specific method, Component, Driver, or Solver. - -- [Features](features/features.md) -- [Examples](examples/examples.md) -- [Theory Manual](theory_manual/theory_manual.md) - - -## Other Useful Docs - -- [Command Line Tools](other_useful_docs/om_command.ipynb) -- [How to Cite OpenMDAO](other/citing.ipynb) -- [Building a Tool on Top of OpenMDAO](other_useful_docs/building_a_tool/building_a_tool.md) -- [Conversion Guide for the Auto-IVC (IndepVarComp) Feature](other_useful_docs/auto_ivc_api_translation.ipynb) -- [Upgrading from OpenMDAO 2.10 to OpenMDAO 3](other_useful_docs/api_translation.ipynb) -- [File Wrapping](other_useful_docs/file_wrap.ipynb) -- [Source Docs](_srcdocs/index.md) -- [Developer Docs (if you’re going to contribute code)](other_useful_docs/developer_docs/developer_docs.md) diff --git a/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/building_a_tool.ipynb b/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/building_a_tool.ipynb new file mode 100644 index 0000000000..92c550209d --- /dev/null +++ b/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/building_a_tool.ipynb @@ -0,0 +1,41 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6900e30d-8361-430b-b20a-b7f0e78bc4ba", + "metadata": {}, + "source": [ + "# Building a Tool on Top of OpenMDAO\n", + "\n", + "There are several things to take into account when setting up a repository that depends on\n", + "OpenMDAO. Repository structure, writing project documentation with Sphinx, getting project\n", + "documentation transferred to github-pages, setting up continuous integration on Travis CI, and\n", + "releasing software are the topics covered.\n", + "\n", + "- [Repository Structure](repository_structure.ipynb)\n", + "- [Release Your Project on pypi](release_process.ipynb)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/building_a_tool.md b/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/building_a_tool.md deleted file mode 100644 index 3a1e89a583..0000000000 --- a/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/building_a_tool.md +++ /dev/null @@ -1,11 +0,0 @@ -# Building a Tool on Top of OpenMDAO - -There are several things to take into account when setting up a repository that depends on -OpenMDAO. Repository structure, writing project documentation with Sphinx, getting project -documentation transferred to github-pages, setting up continuous integration on Travis CI, and -releasing software are the topics covered. - -- [Repository Structure](repository_structure.ipynb) -- [Hosting Documentation on github-pages](github_pages.ipynb) -- [Setting Up Travis CI for Your Project](travis.ipynb) -- [Release Your Project on pypi](release_process.ipynb) diff --git a/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/github_pages.ipynb b/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/github_pages.ipynb deleted file mode 100644 index edff997116..0000000000 --- a/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/github_pages.ipynb +++ /dev/null @@ -1,54 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-input", - "active-ipynb", - "remove-output" - ] - }, - "outputs": [], - "source": [ - "try:\n", - " from openmdao.utils.notebook_utils import notebook_mode\n", - "except ImportError:\n", - " !python -m pip install openmdao[notebooks]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Coming Soon\n", - "", - "\n", - "Switching away from Github pages. Update coming soon " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.1" - }, - "orphan": true - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/travis.ipynb b/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/travis.ipynb deleted file mode 100644 index e2fa383b0e..0000000000 --- a/openmdao/docs/openmdao_book/other_useful_docs/building_a_tool/travis.ipynb +++ /dev/null @@ -1,54 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-input", - "active-ipynb", - "remove-output" - ] - }, - "outputs": [], - "source": [ - "try:\n", - " from openmdao.utils.notebook_utils import notebook_mode\n", - "except ImportError:\n", - " !python -m pip install openmdao[notebooks]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Coming Soon\n", - "", - "\n", - "Switching to Github Actions. Update coming soon" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.1" - }, - "orphan": true - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/openmdao/docs/openmdao_book/theory_manual/advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.ipynb b/openmdao/docs/openmdao_book/theory_manual/advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.ipynb new file mode 100644 index 0000000000..41c155d099 --- /dev/null +++ b/openmdao/docs/openmdao_book/theory_manual/advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.ipynb @@ -0,0 +1,38 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8a8b2441-3b0b-461f-9ee7-f5fd9678b558", + "metadata": {}, + "source": [ + "# Advanced Linear Solver Algorithms for Special Cases\n", + "\n", + "There are certain cases where it is possible to further improve linear solver performance via the application of specialized algorithms. In some cases, the application of these algorithms can have an impact on whether you choose the forward or reverse mode for derivative solves. This section details the types of structures within a model that are necessary in order to benefit from these algorithms.\n", + "\n", + "- [Solving for Derivatives of Multiple Separable Constraints Using a Single Linear Solve](separable.ipynb)\n", + "- [Parallelizing Derivative Solves of Multipoint Models At a Small Memory Cost](fan_out.ipynb)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/openmdao/docs/openmdao_book/theory_manual/advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.md b/openmdao/docs/openmdao_book/theory_manual/advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.md deleted file mode 100644 index e5c43f7e7b..0000000000 --- a/openmdao/docs/openmdao_book/theory_manual/advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.md +++ /dev/null @@ -1,6 +0,0 @@ -# Advanced Linear Solver Algorithms for Special Cases - -There are certain cases where it is possible to further improve linear solver performance via the application of specialized algorithms. In some cases, the application of these algorithms can have an impact on whether you choose the forward or reverse mode for derivative solves. This section details the types of structures within a model that are necessary in order to benefit from these algorithms. - -- [Solving for Derivatives of Multiple Separable Constraints Using a Single Linear Solve](separable.ipynb) -- [Parallelizing Derivative Solves of Multipoint Models At a Small Memory Cost](fan_out.ipynb) diff --git a/openmdao/docs/openmdao_book/theory_manual/class_structure.ipynb b/openmdao/docs/openmdao_book/theory_manual/class_structure.ipynb index 6efbcea054..460664ecde 100644 --- a/openmdao/docs/openmdao_book/theory_manual/class_structure.ipynb +++ b/openmdao/docs/openmdao_book/theory_manual/class_structure.ipynb @@ -24,9 +24,9 @@ "source": [ "# OpenMDAO Class Structure\n", "\n", - "In the [Basic User Guide](../basic_user_guide/basic_user_guide.md), you have seen how to define a problem composed of\n", + "In the [Basic User Guide](../basic_user_guide/basic_user_guide.ipynb), you have seen how to define a problem composed of\n", "a model and a driver. You saw how a model can be built from components of different types and how\n", - "a driver is used to perform an optimization. Then in the [Advanced User Guide](../advanced_user_guide/advanced_user_guide.md),\n", + "a driver is used to perform an optimization. Then in the [Advanced User Guide](../advanced_user_guide/advanced_user_guide.ipynb),\n", "you learned about solvers and methods for computing derivatives.\n", "\n", "The following diagram shows the relationship between these various object types (classes) and the\n", @@ -77,13 +77,13 @@ "The `Driver` class defines algorithms that iteratively call the model. There are different types\n", "of drivers, for example one driver might implement an optimization algorithm while another would execute\n", "a design of experiments (DOE). The driver types that are included with OpenMDAO are described in\n", - "[Drivers](../features/building_blocks/drivers/index.md)." + "[Drivers](../features/building_blocks/drivers/index.ipynb)." ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -97,7 +97,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.1" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/openmdao/docs/openmdao_book/theory_manual/setup_linear_solvers.ipynb b/openmdao/docs/openmdao_book/theory_manual/setup_linear_solvers.ipynb index 9423c78950..f9069431df 100644 --- a/openmdao/docs/openmdao_book/theory_manual/setup_linear_solvers.ipynb +++ b/openmdao/docs/openmdao_book/theory_manual/setup_linear_solvers.ipynb @@ -42,7 +42,7 @@ "The resulting linear system can be solved using a block-forward or block-backward substitution algorithm.\n", "Alternatively you could view the solution algorithm as a single iteration of a block Gauss-Seidel algorithm.\n", "In OpenMDAO, the single-pass block Gauss-Seidel algorithm is implemented via the [LinearRunOnce](../features/building_blocks/solvers/linear_runonce.ipynb) solver.\n", - "This is the default solver used by OpenMDAO on all [Groups](../features/core_features/working_with_groups/main.md).\n", + "This is the default solver used by OpenMDAO on all [Groups](../features/core_features/working_with_groups/main.ipynb).\n", "\n", "![uncoupled_fwd](images/matrix_figs/uncoupled_fwd.png)\n", "\n", @@ -322,7 +322,7 @@ "\n", "## A Very Simple Example\n", "\n", - "Consider, as an example, the [Sellar Problem](../basic_user_guide/multidisciplinary_optimization/sellar.ipynb) from the [Multidisciplinary Optimization User Guide](../basic_user_guide/basic_user_guide.md).\n", + "Consider, as an example, the [Sellar Problem](../basic_user_guide/multidisciplinary_optimization/sellar.ipynb) from the [Multidisciplinary Optimization User Guide](../basic_user_guide/basic_user_guide.ipynb).\n", "In that problem, coupling is created by a cyclic connection between the `d1` and `d2` components.\n", "You can see that coupling clearly in the n2 diagram below, because there are off-diagonal terms both above and below the diagonal inside the `cycle` group." ] diff --git a/openmdao/docs/openmdao_book/theory_manual/theory_manual.ipynb b/openmdao/docs/openmdao_book/theory_manual/theory_manual.ipynb new file mode 100644 index 0000000000..51669f81cb --- /dev/null +++ b/openmdao/docs/openmdao_book/theory_manual/theory_manual.ipynb @@ -0,0 +1,50 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f32b0019-3ef6-4462-9cf5-e1490f7143e8", + "metadata": {}, + "source": [ + "# Theory Manual\n", + "\n", + "The Theory Manual exists to explain some of the underlying concepts behind OpenMDAO in more detail. It is not intended to show you how to use any specific features of OpenMDAO, but rather to understand why you might choose to use a feature. It provides information in a more theoretical and mathematical manner to help users gain a deeper understanding of how the framework operates.\n", + "\n", + "\n", + "- [OpenMDAO Class Structure](class_structure.ipynb)\n", + "- [Understanding How Variables Work](implicit_transformation_of_vars.ipynb)\n", + "- [The System Setup Stack: Understanding When to Use setup and configure](setup_stack.ipynb)\n", + "- [OpenMDAO Solvers](solver_api.ipynb)\n", + "- [Scaling Variables in OpenMDAO](scaling.ipynb)\n", + "- [Determining How Many Times a System was Executed](iter_count.ipynb)\n", + "- [Using OpenMDAO with MPI](mpi.ipynb)\n", + "\n", + "## Total Derivatives Theory\n", + "\n", + "- [How Total Derivatives are Computed](total_derivs_theory.ipynb)\n", + "- [Setting Up a Model for Efficient Linear Solves](setup_linear_solvers.ipynb)\n", + "- [Advanced Linear Solver Algorithms for Special Cases](advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.ipynb)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/openmdao/docs/openmdao_book/theory_manual/theory_manual.md b/openmdao/docs/openmdao_book/theory_manual/theory_manual.md deleted file mode 100644 index 3f31a13350..0000000000 --- a/openmdao/docs/openmdao_book/theory_manual/theory_manual.md +++ /dev/null @@ -1,18 +0,0 @@ -# Theory Manual - -The Theory Manual exists to explain some of the underlying concepts behind OpenMDAO in more detail. It is not intended to show you how to use any specific features of OpenMDAO, but rather to understand why you might choose to use a feature. It provides information in a more theoretical and mathematical manner to help users gain a deeper understanding of how the framework operates. - - -- [OpenMDAO Class Structure](class_structure.ipynb) -- [Understanding How Variables Work](implicit_transformation_of_vars.ipynb) -- [The System Setup Stack: Understanding When to Use setup and configure](setup_stack.ipynb) -- [OpenMDAO Solvers](solver_api.ipynb) -- [Scaling Variables in OpenMDAO](scaling.ipynb) -- [Determining How Many Times a System was Executed](iter_count.ipynb) -- [Using OpenMDAO with MPI](mpi.ipynb) - -## Total Derivatives Theory - -- [How Total Derivatives are Computed](total_derivs_theory.ipynb) -- [Setting Up a Model for Efficient Linear Solves](setup_linear_solvers.ipynb) -- [Advanced Linear Solver Algorithms for Special Cases](advanced_linear_solvers_special_cases/advanced_linear_solvers_special_cases.md) diff --git a/openmdao/docs/upload_doc_version.py b/openmdao/docs/upload_doc_version.py index abfe402871..5b1635aa38 100644 --- a/openmdao/docs/upload_doc_version.py +++ b/openmdao/docs/upload_doc_version.py @@ -1,6 +1,7 @@ import sys import subprocess from packaging.version import Version +from warnings import warn def get_tag_info(): @@ -17,7 +18,8 @@ def get_tag_info(): version_tags = cmd_out.split() if not version_tags: - raise Exception('No tags found in repository') + warn('No tags found in repository') + return None, None # use sort to put the versions list in order from lowest to highest version_tags.sort(key=Version) @@ -58,7 +60,7 @@ def get_doc_version(): current_commit = get_commit_info() - if current_commit == release_commit: + if release_tag is not None and current_commit == release_commit: return release_tag, 1 else: return current_commit, 0 diff --git a/openmdao/test_suite/tests/test_warnings.py b/openmdao/test_suite/tests/test_warnings.py index e2d7d58d7d..c2f6ab14da 100644 --- a/openmdao/test_suite/tests/test_warnings.py +++ b/openmdao/test_suite/tests/test_warnings.py @@ -143,7 +143,6 @@ def compute(self, inputs, outputs): with warnings.catch_warnings(): warnings.filterwarnings('error', category=om.OpenMDAOWarning) - warnings.filterwarnings("ignore", r'.*OpenMDAO support for Python version .* will end soon.*') with self.assertRaises(Exception) as e: p.setup() diff --git a/openmdao/utils/om.py b/openmdao/utils/om.py index 3d8b0f029b..ba7a034a61 100644 --- a/openmdao/utils/om.py +++ b/openmdao/utils/om.py @@ -5,10 +5,7 @@ import sys import os import argparse -if sys.version_info.minor > 7: - import importlib.metadata as ilmd -else: - ilmd = None +import importlib.metadata as ilmd import re from openmdao import __version__ as version @@ -660,7 +657,7 @@ def openmdao_cmd(): if hasattr(options, 'executor'): options.executor(options, user_args) - elif options.dependency_versions is True and ilmd is not None: + elif options.dependency_versions is True: dep_versions = {} _get_deps(dep_versions, 'openmdao') diff --git a/openmdao/utils/tests/test_units.py b/openmdao/utils/tests/test_units.py index 7e6f4a40fa..690919ab34 100644 --- a/openmdao/utils/tests/test_units.py +++ b/openmdao/utils/tests/test_units.py @@ -324,7 +324,6 @@ def test_connect_unitless_to_none(self): with warnings.catch_warnings(): warnings.simplefilter("error") - warnings.filterwarnings("ignore", r'.*OpenMDAO support for Python version .* will end soon.*') p.setup() p.run_model() @@ -341,7 +340,6 @@ def test_promote_unitless_and_none(self): with warnings.catch_warnings(): warnings.simplefilter("error") - warnings.filterwarnings("ignore", r'.*OpenMDAO support for Python version .* will end soon.*') p.setup() p.run_model() @@ -359,7 +357,6 @@ def test_promote_unitless_ivc_to_exec_comp(self): with warnings.catch_warnings(): warnings.simplefilter("error") - warnings.filterwarnings("ignore", r'.*OpenMDAO support for Python version .* will end soon.*') p.setup() p.run_model() diff --git a/setup.py b/setup.py index a9f5b6292b..61445c71d5 100644 --- a/setup.py +++ b/setup.py @@ -26,8 +26,8 @@ 'pyDOE3' ], 'jax': [ - 'jax>=0.4.0; python_version>="3.8"', - 'jaxlib>=0.4.0; python_version>="3.8"' + 'jax>=0.4.0', + 'jaxlib>=0.4.0' ], 'notebooks': [ 'notebook', @@ -74,7 +74,7 @@ 'Operating System :: Microsoft :: Windows', 'Topic :: Scientific/Engineering', 'Programming Language :: Python', - 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', ], keywords='optimization multidisciplinary multi-disciplinary analysis', @@ -185,7 +185,7 @@ ], 'openmdao': ['*/tests/*.py', '*/*/tests/*.py', '*/*/*/tests/*.py'] }, - python_requires=">=3.7", + python_requires=">=3.8", install_requires=[ 'networkx>=2.0', 'numpy',