Repository: yt-project/yt

Issue:
Parallel Projection Plot Error with Dark Matter only SPH Simulation
<!--To help us understand and resolve your issue, please fill out the form to
the best of your ability.-->
<!--You can feel free to delete the sections that do not apply.-->

### Bug report

**Bug summary**

When creating a projection plot in parallel with a dark matter only gadget snapshot, the non-root processors do not recognize the ('deposit', 'Halo_density') field, and so the script crashes. I was running on two processors for simplicity. The bug occurs in my own gadget snapshot, but I was able to reproduce it with the agora_1e11.00400 dataset from yt-project.org/data. I am using yt version 3.4-dev.  

**Code for reproduction**

```python
import yt

yt.enable_parallelism()

ds = yt.load('agora_1e11.00400/agora_1e11.00400')

prj = yt.ProjectionPlot(ds, fields=('deposit', 'DarkMatter_density'), axis='z')
prj.save()
```

**Actual outcome**

```
yt : [INFO     ] 2017-07-08 19:12:35,060 Global parallel computation enabled: 0 / 2
yt : [INFO     ] 2017-07-08 19:12:35,060 Global parallel computation enabled: 1 / 2
P000 yt : [INFO     ] 2017-07-08 19:12:35,097 Parameters: current_time              = 1.0
P000 yt : [INFO     ] 2017-07-08 19:12:35,097 Parameters: domain_dimensions         = [2 2 2]
P000 yt : [INFO     ] 2017-07-08 19:12:35,098 Parameters: domain_left_edge          = None
P000 yt : [INFO     ] 2017-07-08 19:12:35,098 Parameters: domain_right_edge         = None
P000 yt : [INFO     ] 2017-07-08 19:12:35,098 Parameters: cosmological_simulation   = 0.0
P000 yt : [INFO     ] 2017-07-08 19:12:35,476 Allocating for 1.055e+07 particles (index particle type 'all')
P001 yt : [INFO     ] 2017-07-08 19:12:36,696 Adding 1.055e+07 particles
P000 yt : [INFO     ] 2017-07-08 19:12:36,703 Adding 1.055e+07 particles
P000 yt : [INFO     ] 2017-07-08 19:12:38,501 Identified 8.036e+05 octs
  File "/home/polaris/practice_code/yt_parallel_practice/parallel_plot.py", line 34, in <module>
P000 yt : [INFO     ] 2017-07-08 19:12:49,266 Projection completed
    prj = yt.ProjectionPlot(ds, fields=('deposit', 'DarkMatter_density'), axis='z')
  File "/home/polaris/Research/yt_rockstar/yt/visualization/plot_window.py", line 1521, in __init__
    max_level=max_level)
  File "/home/polaris/Research/yt_rockstar/yt/data_objects/construction_data_containers.py", line 264, in __init__
    self.get_data(field)
  File "/home/polaris/Research/yt_rockstar/yt/data_objects/construction_data_containers.py", line 383, in get_data
    input_units = self._projected_units[field]
P001 yt : [ERROR    ] 2017-07-08 19:12:49,267 KeyError: ('deposit', 'DarkMatter_density')
P001 yt : [ERROR    ] 2017-07-08 19:12:49,267 Error occured on rank 1.
--------------------------------------------------------------------------
MPI_ABORT was invoked on rank 1 in communicator MPI_COMM_WORLD
with errorcode 1.

NOTE: invoking MPI_ABORT causes Open MPI to kill all MPI processes.
You may or may not see output from other processes, depending on
exactly when Open MPI kills them.
--------------------------------------------------------------------------
```

**Expected outcome**

A basic projection plot should be created. It works when run in serial (i.e. without invoking mpirun).

**Version Information**
<!--Please specify your platform and versions of the relevant libraries you are
using:-->
  * Operating System: Ubuntu 16.04
  * Python Version: 2.7.12
  * yt version: 3.4-dev
  * Other Libraries (if applicable): 

<!--Please tell us how you installed yt and python e.g., from source,
pip, conda. If you installed from conda, please specify which channel you used
if not the default-->
yt was install from source.




Discussion:
I can reproduce. Thanks for the report! I will try to look at this at the sprints at SciPy next week. If you or someone else gets a chance to debug and get a fix together in the mean time, feel free to take a shot at a fix.

For now I think you're going to need to run your scripts on one processor. On the off chance you have lots of data files instead of one really big one, you can use `yt.parallel_objects` to iterate over the data files in parallel, but with each CPU only processing one dataset at a time.

Resolving patch:
diff --git a/yt/data_objects/construction_data_containers.py b/yt/data_objects/construction_data_containers.py
--- a/yt/data_objects/construction_data_containers.py
+++ b/yt/data_objects/construction_data_containers.py
@@ -342,6 +342,10 @@ def get_data(self, fields = None):
                     self._initialize_projected_units(fields, chunk)
                     _units_initialized = True
                 self._handle_chunk(chunk, fields, tree)
+        # if there's less than nprocs chunks, units won't be initialized
+        # on all processors, so sync with _projected_units on rank 0
+        projected_units = self.comm.mpi_bcast(self._projected_units)
+        self._projected_units = projected_units
         # Note that this will briefly double RAM usage
         if self.method == "mip":
             merge_style = -1


Test patch: