.. Copyright 2022 NWChemEx-Project
..
.. Licensed under the Apache License, Version 2.0 (the "License");
.. you may not use this file except in compliance with the License.
.. You may obtain a copy of the License at
..
.. http://www.apache.org/licenses/LICENSE-2.0
..
.. Unless required by applicable law or agreed to in writing, software
.. distributed under the License is distributed on an "AS IS" BASIS,
.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
.. See the License for the specific language governing permissions and
.. limitations under the License.

.. _module_designing:

******************
Designing a Module
******************

The previous pages covered how to actually code up a module. They did not
provide any guidance on how to design your module.

Additional Inputs
=================

The property type APIs are necessarily general and rigid. This can pose
difficulties when your module needs additional input. PluginPlay provides you
with two options for obtaining the extra input your module needs:

#. Define a module-specific input parameter
#. Call a submodule

Module-Specific Input
---------------------

Many algorithms have algorithmic parameters associated with them such as
thresholds, tolerances, maximum number of iterations, **etc.**. Generally
speaking it is best to expose these parameters to the user and not hardcode
them. These parameters are typically not exposed through the property type and
thus can not be set by the caller as positional arguments. At the same time it
is usually the end-user, not the calling function, which wants to manipulate
these parameters, **e.g.** it is the end-user which has decided that a
particularly tight energy convergence criteria is needed not the function which
is requesting the energy. For these types of parameters it makes sense to make
them module-specific inputs.

In our ``ScreenedCoulombsLaw`` example (TODO: Add link) we used a threshold to
determine when point charges should be screened out. This threshold is really an
algorithmic detail. Once it has been set (either to the default value or by the
end-user) it generally won't be touched again. The other option, having this
threshold be set by a submodule doesn't really make a whole lot of sense because
there really isn't an algorithm that can compute it (typically the default value
is determined by extensive benchmarking which establishes what value produces a
tolerable error; while that process could be encapsulated in a module, once
it's been done you might as well just use the value).

Call a Submodule
----------------

Module-specific inputs are primarily for algorithmic parameters. Submodules are
used primarily to establish data dependencies among computed properties. For
example in our ``ClassicalForce`` tutorial (TODO: add link) we used a submodule
to establish that when we compute the force on the particle it will depend on
the electric field (which in general must also be computed).  We did this by
calling a submodule that satisfied the ``ElectricField`` property type. By using
a submodule instead of a hard-coded call our ``ClassicalForce`` module works
with both the ``CoulombsLaw`` and ``ScreenedCoulombsLaw`` submodules (as well as
any other modules users choose to write which satisfy the ``ElectricField``
property type).

Using a module-specific input, for the electric field, in the ``ClassicalForce``
module doesn't make a lot of sense because: the value of the electric field is
system dependent (needs to be computed for every system) and the end-user
typically doesn't have the value sitting around (unless they've already called
a module satisfying the ``ElectricField`` property type).
