cdm/src/main/java/ucar/nc2/ft/fmrc/FmrcDataset.java
@Override
    public Array reallyRead(Variable mainv, Section section, CancelTask cancelTask) throws IOException, InvalidRangeException {
      FmrcInvLite.Gridset.Grid gridLite = (FmrcInvLite.Gridset.Grid) mainv.getSPobject();

      // read the original type - if its been promoted to a new type, the conversion happens after this read
      DataType dtype = (mainv instanceof VariableDS) ? ((VariableDS) mainv).getOriginalDataType() : mainv.getDataType();

      Array allData = Array.factory(dtype, section.getShape());
      int destPos = 0;

      // assumes the first two dimensions are runtime and time: LOOK: ensemble ??
      List<Range> ranges = section.getRanges();
      Range runRange = ranges.get(0);
      Range timeRange = ranges.get(1);
      List<Range> innerSection = ranges.subList(2, ranges.size());

      // keep track of open file - must be local variable for thread safety
      HashMap<String, NetcdfDataset> openFilesRead = new HashMap<>();
      try {

        // iterate over the desired runs
        for (int runIdx : runRange) {
          //Date runDate = vstate.runTimes.get(runIdx);

          // iterate over the desired forecast times
          for (int timeIdx : timeRange) {
            Array result = null;

            // find the inventory for this grid, runtime, and hour
            TimeInventory.Instance timeInv = gridLite.getInstance(runIdx, timeIdx);
            if (timeInv != null) {
              if (debugRead) System.out.printf("HIT %d %d ", runIdx, timeIdx);
              result = read(timeInv, gridLite.name, innerSection, openFilesRead); // may return null
              result = MAMath.convert(result, dtype); // just in case it need to be converted
            }

            // missing data
            if (result == null) {
              int[] shape = new Section(innerSection).getShape();
              result = ((VariableDS) mainv).getMissingDataArray(shape); // fill with missing values
              if (debugRead) System.out.printf("MISS %d %d ", runIdx, timeIdx);
            }

            if (debugRead)
              System.out.printf("%d %d reallyRead %s %d bytes start at %d total size is %d%n",
                      runIdx, timeIdx, mainv.getFullName(), result.getSize(), destPos, allData.getSize());

            Array.arraycopy(result, 0, allData, destPos, (int) result.getSize());
            destPos += result.getSize();
          }
        }
        return allData;

      } finally {
        // close any files used during this operation
        closeAll(openFilesRead);
      }
    }
@Override
    public Array reallyRead(Variable mainv, Section section, CancelTask cancelTask) throws IOException, InvalidRangeException {
      FmrcInvLite.Gridset.Grid gridLite = (FmrcInvLite.Gridset.Grid) mainv.getSPobject();

      // read the original type - if its been promoted to a new type, the conversion happens after this read
      DataType dtype = (mainv instanceof VariableDS) ? ((VariableDS) mainv).getOriginalDataType() : mainv.getDataType();

      Array allData = Array.factory(dtype, section.getShape());
      int destPos = 0;

      // assumes the first two dimensions are runtime and time: LOOK: ensemble ??
      List<Range> ranges = section.getRanges();
      Range runRange = ranges.get(0);
      Range timeRange = ranges.get(1);
      List<Range> innerSection = ranges.subList(2, ranges.size());

      // keep track of open file - must be local variable for thread safety
      HashMap<String, NetcdfDataset> openFilesRead = new HashMap<>();
      try {

        // iterate over the desired runs
        for (int runIdx : runRange) {
          //Date runDate = vstate.runTimes.get(runIdx);

          // iterate over the desired forecast times
          for (int timeIdx : timeRange) {
            Array result = null;

            // find the inventory for this grid, runtime, and hour
            TimeInventory.Instance timeInv = gridLite.getInstance(runIdx, timeIdx);
            if (timeInv != null) {
              if (debugRead) System.out.printf("HIT %d %d ", runIdx, timeIdx);
              result = read(timeInv, gridLite.name, innerSection, openFilesRead); // may return null
              result = MAMath.convert(result, dtype); // just in case it need to be converted
            }

            // missing data
            if (result == null) {
              int[] shape = new Section(innerSection).getShape();
              result = ((VariableDS) mainv).getMissingDataArray(shape); // fill with missing values
              if (debugRead) System.out.printf("MISS %d %d ", runIdx, timeIdx);
            }

            if (debugRead)
              System.out.printf("%d %d reallyRead %s %d bytes start at %d total size is %d%n",
                      runIdx, timeIdx, mainv.getFullName(), result.getSize(), destPos, allData.getSize());

            Array.arraycopy(result, 0, allData, destPos, (int) result.getSize());
            destPos += result.getSize();
          }
        }
        return allData;

      } finally {
        // close any files used during this operation
        closeAll(openFilesRead);
      }
    }
here is where agg variables get read