

import numpy as np

from openmdao.core.implicitcomponent import ImplicitComponent


class {class_name}(ImplicitComponent):
    """
    <class description here>

    Attributes
    ----------
    ...
    """

    def __init__(self, **kwargs):
        """
        Intialize this component.

        Parameters
        ----------
        **kwargs : dict of keyword arguments
            Keyword arguments that will be mapped into the Component options.
        """
        super().__init__(**kwargs)
        # set attributes here...

    def initialize(self):
        """
        Declare options.
        """
        # self.options.declare('myopt', default=1, types=int, desc='My option.')
        pass

    def setup(self):
        """
        Add inputs and outputs and declare partials.
        """
        # self.add_input(name='foo', shape=None, units=None)
        # self.add_output(name='bar', shape=None, units=None)

        # self.declare_partials(of='bar', wrt='foo', rows=None, cols=None, val=None)
        pass

    def apply_nonlinear(self, inputs, outputs, residuals):
        """
        <describe apply_nonlinear here>

        Parameters
        ----------
        inputs : Vector
            unscaled, dimensional input variables read via inputs[key]
        outputs : Vector
            unscaled, dimensional output variables read via outputs[key]
        residuals : Vector
            unscaled, dimensional residuals written to via residuals[key]
        """
        # residuals['bar'] = 1
        pass

    def solve_nonlinear(self, inputs, outputs):
        """
        <describe solve_nonlinear here>

        Parameters
        ----------
        inputs : Vector
            unscaled, dimensional input variables read via inputs[key]
        outputs : Vector
            unscaled, dimensional output variables read via outputs[key]
        """
        # outputs['bar'] = inputs['foo']
        pass

    def linearize(self, inputs, outputs, partials):
        """
        Compute the non-constant partial derivatives.

        Parameters
        ----------
        inputs : Vector
            unscaled, dimensional input variables read via inputs[key]
        outputs : Vector
            unscaled, dimensional output variables read via outputs[key]
        partials : partial Jacobian
            sub-jac components written to partials[output_name, input_name]
        """
        # partials['bar', 'foo'] = inputs['foo']
        pass

    def apply_linear(self, inputs, outputs, d_inputs, d_outputs, d_residuals, mode):
        r"""
        Compute jac-vector product. The model is assumed to be in an unscaled state.

        If mode is:
            'fwd': (d_inputs, d_outputs) \|-> d_residuals

            'rev': d_residuals \|-> (d_inputs, d_outputs)

        Parameters
        ----------
        inputs : Vector
            unscaled, dimensional input variables read via inputs[key]
        outputs : Vector
            unscaled, dimensional output variables read via outputs[key]
        d_inputs : Vector
            see inputs; product must be computed only if var_name in d_inputs
        d_outputs : Vector
            see outputs; product must be computed only if var_name in d_outputs
        d_residuals : Vector
            see outputs
        mode : str
            either 'fwd' or 'rev'
        """
        pass

    def solve_linear(self, d_outputs, d_residuals, mode):
        """
        <describe solve_linear here>

        Parameters
        ----------
        d_outputs : Vector
            unscaled, dimensional quantities read via d_outputs[key]
        d_residuals : Vector
            unscaled, dimensional quantities read via d_residuals[key]
        mode : str
            either 'fwd' or 'rev'

        If mode is:
            'fwd': d_outputs -> d_residuals

            'rev': d_residuals -> d_outputs

        """
        pass
