Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing MPError class in favor of baseclasses Error. #12

Merged
merged 9 commits into from
Jan 7, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions doc/reference.rst → doc/API.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
.. _multipoint_API:

API Reference
=============
API
===

.. currentmodule:: multipoint.multiPointSparse

.. autoclass:: multipoint.multiPointSparse
.. autoclass:: multiPointSparse
:members:

2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@
extensions.extend(["numpydoc"])

# mock import for autodoc
autodoc_mock_imports = ["numpy", "mpi4py"]
autodoc_mock_imports = ["numpy", "mpi4py", "baseclasses"]
10 changes: 4 additions & 6 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,18 @@
multiPoint
==========

Contents:

``multiPointSparse`` is a helper module for doing multipoint
optimizations. The documentaion ``multiPoint`` is given below.
optimizations. The documentation ``multiPoint`` is given below.

To install, first clone the repo, then go into the root directory and type::
To install, first clone the repository, then go into the root directory and type::

pip install .

For stability we recommend cloning or checking out a tagged release.


.. toctree::
:maxdepth: 2

tutorial
reference
examples
Copy link
Contributor

@marcomangano marcomangano Jan 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you are missing the examples.rst file that calls the ex1.py script via literalinclude. The examples are not showing up in the docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to commit that one. Should be there now.

API
24 changes: 12 additions & 12 deletions doc/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The goal of ``MultiPoint`` is to facilitate optimization problems that
contain may different computations, all occurring in parallel, each of
which may be parallel. ``MultiPoint`` effectively hides the required
MPI communication from the user which results in more readable, more
robust and easier to understand optimization scripts.
robust and easier to understand optimization scripts.

For our simple example, lets assume we have two parallel codes, ``A``
and ``B`` that we want to run at the same time for an
Expand All @@ -19,9 +19,9 @@ one copy of code ``B``. The analysis path would look like::
Objective
Functions
/------------\ Funcs
/---| Code A |--->----\ User supplied objcon
/---| Code A |--->----\ User supplied objcon
| \------------/ | /---------------\
Optimizer | /------------\ Funcs | Combine | Combine funcs | Return to
Optimizer | /------------\ Funcs | Combine | Combine funcs | Return to
----->---- +---| Code A |--->--- +------>--------+ to get final |----->------
Input | \------------/ | all funcs | obj/con | optimizer
| /------------\ Funcs | \---------------/
Expand All @@ -34,7 +34,7 @@ processors, the second copy of code ``A`` requires 2 processors and
the copy of code ``B`` requires 4 processors. For this case, we would
require ``3 + 2 + 4 = 9`` total processors. Scripts using
``MultiPointSparse`` must be called with precisely the correct
number of processors.
number of processors.

>>> from mpi4py import MPI
>>> from multipoint import multiPointSparse
Expand All @@ -60,19 +60,19 @@ At this point, you should have the following if you executed the code with 9 pro

The input to each of the Objective Functions is the (unmodified) dictionary of
optimization variables from pyOptSparse. Each code is then required to
use the optimization variables as it requires.
use the optimization variables as it requires.

The output from each of Objective functions ``funcs`` is a Python
dictionary of computed values. **For computed values that are
different for each member in a processorSet or between processorSets
it is necessary to use unique keys**. It is therefore necessary for
the user to use an appropriate name mangling scheme.
the user to use an appropriate name mangling scheme.

In the example above we have two copies of Code A. In typical usage,
these two instances will produce the same *number* and *type* of
quantities but at different operating conditions or other similar
variation. Since we need these quantities for either the optimization
objective or constraints, these values must be given a unique name.
objective or constraints, these values must be given a unique name.

A simple name-mangling scheme is to simply use the ``ptID`` variable that
is returned from the call to `createCommunicators`::
Expand All @@ -91,7 +91,7 @@ A similar thing can be done for ``B``::

A ``processorSet`` is characterized by a single "objective" and
"sensitivity" function. For each ``processorSet`` we must supply Python
functions for the objective and sensitivity evaluation.
functions for the objective and sensitivity evaluation.

>>> MP.setProcSetObjFunc('codeA', objA)
>>> MP.setProcSetObjFunc('codeB', objB)
Expand All @@ -115,7 +115,7 @@ process is given below::
all funcs | | output to pyOptSparse
------->------ + input /--------\ output |------------->----
\-------->--+ objcon | ----------/
keys \--------/ keys
keys \--------/ keys

``multiPointSparse`` analyzes the optimization object and determine if
any of the required constraint keys are already present in all funcs,
Expand All @@ -139,14 +139,14 @@ There all three values contribute to the objective, while ``A_0`` and
``pass-though keys``.

Generally speaking, the computations in objcon should be simple and
not overally computationally intensive. The sensitivity of the ``output
not overly computationally intensive. The sensitivity of the ``output
keys`` with respect to the ``input keys`` is computed automatically by
``multiPointSparse`` using the complex step method.

.. warning::
Pass-through keys **cannot** be used in objcon.
Pass-through keys **cannot** be used in objcon.

.. warning::
.. warning::
Computations in objcon must be able to use complex
number. Generally this will mean if numpy arrays are used, the
``dtype=complex`` keyword argument is used.
Expand Down
58 changes: 58 additions & 0 deletions examples/ex1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
This example demonstrates how to add processor sets and perform operations
on a specific group of processors within a set.

To run locally do: ``mpirun -np 10 --oversubscribe python ex1.py``.
"""
# rst init (begin)
# ==============================================================================
# Import modules
# ==============================================================================
from mpi4py import MPI
from multipoint import multiPointSparse

# rst init (end)
# ==============================================================================
# Processor allocation
# ==============================================================================
# Instantiate the multipoint object
MP = multiPointSparse(MPI.COMM_WORLD)

# Add all processor sets and create the communicators
MP.addProcessorSet("codeA", 3, [3, 2, 1])
MP.addProcessorSet("codeB", 1, 4)
comm, setComm, setFlags, groupFlags, ptID = MP.createCommunicators()

# Extract setName on a given processor for convenience
setName = MP.getSetName()

# Create all directories for all groups in all sets
ptDirs = MP.createDirectories("./output")

# For information, print out all values on all processors
print(
f"setName={setName}, comm.rank={comm.rank}, comm.size={comm.size}, setComm.rank={setComm.rank}, setComm.size={setComm.size}, setFlags={setFlags}, groupFlags={groupFlags}, ptID={ptID}"
)
# rst alloc (end)
# ==============================================================================
# Problem setup
# ==============================================================================
# To perform operations on all processors in a set we can use the setFlags
if setFlags["codeA"]: # Alternatively, setName == "codeA" could be used here
# ...
# To access a particular group within the set can be done using the ptID
# Here we access only the processors in the first group
if 0 == ptID:
print(f"setName={setName} comm.rank={comm.rank} ptID={ptID}")

# To access all groups (but still a specific one) we simply loop over the size of the set
for i in range(setComm.size):
if i == ptID:
print(f"setName={setName} comm.rank={comm.rank} ptID={ptID} i={i}")

# Similarly, for the other processor set
if setFlags["codeB"]:
for i in range(setComm.size):
if i == ptID:
print(f"setName={setName} comm.rank={comm.rank} ptID={ptID} i={i}")
# rst problem (end)
2 changes: 1 addition & 1 deletion multipoint/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "1.3.0"
__version__ = "1.3.1"


from .multiPointSparse import multiPointSparse
Expand Down
Loading