Task: Clarified multiple forces with the same global parameter (openmm/openmm#3769)

org: openmm
repo: openmm
pr_number: 3769
issue_title: Clarified multiple forces with the same global parameter
issue_body: Fixes #3768.  I added documentation to clarify this case, and also made the Context throw an exception if two forces define global parameters with the same name but different default values.
resolved_issues: number: 3768
title: Implicit value substitution when two  `CustomExternalForce` have global parameters with the same name
body: # general description
I found that if two custom external forces have global parameters with the same name, the value of the latter one would be substitue by the first one. Also, when I tried to get the parameter value through `getGlobalParameterDefualtValue` it will not print the 'substituted' value but the original value setted by me. (I know that naming two global parameter with the same name is probably not best practice, but this behaviour makes it difficult to debug). I recommand either emphasizing this behaviour in the documentation or throwing errors when two global parameters have the same name.

# version info
```python
print(openmm.__version__)
```
7.7

# procedures to reproduce
```python
import openmm as mm
from openmm import app
from openmm import unit
mass = 40 * unit.amu
system = mm.System()
system.addParticle(mass)

external1 = mm.CustomExternalForce("k*x")
external1.addGlobalParameter("k", 1*unit.kilojoule_per_mole/unit.nanometer)
external1.addParticle(0, [])

external2 = mm.CustomExternalForce("k*y")
external2.addGlobalParameter("k", 2*unit.kilojoule_per_mole/unit.nanometer)
external2.addParticle(0, [])
system.addForce(external1)
system.addForce(external2)
```

When I query through the force object, the paramter values are correct
```python
for i in range(system.getNumForces()):
    f = system.getForce(i)
    print(f" name of the force: {f.getName()}")
    print(f" energy function of the force: {f.getEnergyFunction()}")
    for j in range(f.getNumGlobalParameters()):
        print(f"{f.getGlobalParameterName(j)}: {f.getGlobalParameterDefaultValue(j)}")

for i, f in enumerate(system.getForces()):
    f.setForceGroup(i)
```
name of the force: CustomExternalForce
energy function of the force: k*x
k: 1.0
name of the force: CustomExternalForce
energy function of the force: k*y
k: 2.0

But when i initialize and calculate the potential energy, it's wrong
```python
topology = app.Topology()
element = app.Element.getBySymbol('Ar')
chain = topology.addChain('A')
residue = topology.addResidue('OSC', chain)
topology.addAtom('Ar', element, residue)
integrator = mm.VerletIntegrator(2*unit.femtosecond)
simulation = app.Simulation(topology, system, integrator)
simulation.context.setPositions(np.array([[1, 2, 0]])*unit.nanometer)
for i, f in enumerate(system.getForces()):
    state = simulation.context.getState(getEnergy=True, groups={i})
    print(f.getName(), state.getPotentialEnergy())
```
CustomExternalForce 1.0 kJ/mol
CustomExternalForce 2.0 kJ/mol
Where the second customexternalforce should have 2*2=4kJ/mol as potential energy

## IMPORTANT INSTRUCTIONS

1. If you edit a python file, you MUST run 'make PythonInstall' inside the build directory
2. If you edit a c++ file, you MUST run 'make -j4 && make install" inside the build directory

Reference solution:
fix_patch: diff --git a/docs-source/usersguide/theory/03_custom_forces.rst b/docs-source/usersguide/theory/03_custom_forces.rst
index 17fbfdddc8..201bf9e5d9 100644
--- a/docs-source/usersguide/theory/03_custom_forces.rst
+++ b/docs-source/usersguide/theory/03_custom_forces.rst
@@ -465,6 +465,13 @@ example, if a :class:`CustomNonbondedForce` uses a long range correction, changi
 a global parameter may require the correction coefficient to be recalculated,
 which is expensive.
 
+It is possible for multiple forces to depend on the same global parameter.  To do this,
+simply have each force specify a parameter with the same name.  This can be useful
+in certain cases.  For example, in an alchemical simulation, you might have a
+parameter that interpolates between two endpoints corresponding to different molecules.
+Changing the one parameter would simultaneously modify multiple bonded and nonbonded
+forces.
+
 The other type of parameter is ones that record many values, one for each element
 of the force, such as per-particle or per-bond parameters.  These values are stored
 directly in the force object itself, and hence are part of the system definition.
diff --git a/openmmapi/src/ContextImpl.cpp b/openmmapi/src/ContextImpl.cpp
index e86b9241f6..77f3453706 100644
--- a/openmmapi/src/ContextImpl.cpp
+++ b/openmmapi/src/ContextImpl.cpp
@@ -188,6 +188,9 @@ void ContextImpl::initialize() {
     for (size_t i = 0; i < forceImpls.size(); ++i) {
         forceImpls[i]->initialize(*this);
         map<string, double> forceParameters = forceImpls[i]->getDefaultParameters();
+        for (auto param : forceParameters)
+            if (parameters.find(param.first) != parameters.end() && parameters[param.first] != forceParameters[param.first])
+                throw OpenMMException("Two Forces define different default values for the parameter '"+param.first+"'");
         parameters.insert(forceParameters.begin(), forceParameters.end());
     }
     integrator.initialize(*this);