.. 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).