grib/src/main/java/ucar/nc2/grib/collection/GribIosp.java
private void makeUniqueTimeCoordinate2D(NetcdfFile ncfile, Group g, CoordinateTime2D time2D) {
    CoordinateRuntime runtime = time2D.getRuntimeCoordinate();

    int countU = 0;
    for (int run = 0; run < time2D.getNruns(); run++) {
      CoordinateTimeAbstract timeCoord = time2D.getTimeCoordinate(run);
      countU += timeCoord.getSize();
    }
    int ntimes = countU;
    String tcName = time2D.getName();

    ncfile.addDimension(g, new Dimension(tcName, ntimes));
    Variable v = ncfile
        .addVariable(g, new Variable(ncfile, g, null, tcName, DataType.DOUBLE, tcName));
    String units = runtime.getUnit(); // + " since " + runtime.getFirstDate();
    v.addAttribute(new Attribute(CDM.UNITS, units));
    v.addAttribute(new Attribute(CF.STANDARD_NAME, CF.TIME));
    v.addAttribute(new Attribute(CDM.LONG_NAME, Grib.GRIB_VALID_TIME));
    v.addAttribute(new Attribute(CF.CALENDAR, Calendar.proleptic_gregorian.toString()));

    // the data is not generated until asked for to save space
    if (!time2D.isTimeInterval()) {
      v.setSPobject(new Time2Dinfo(Time2DinfoType.offU, time2D, null));
    } else {
      v.setSPobject(new Time2Dinfo(Time2DinfoType.intvU, time2D, null));
      // bounds for intervals
      String bounds_name = tcName + "_bounds";
      Variable bounds = ncfile.addVariable(g,
          new Variable(ncfile, g, null, bounds_name, DataType.DOUBLE, tcName + " 2"));
      v.addAttribute(new Attribute(CF.BOUNDS, bounds_name));
      bounds.addAttribute(new Attribute(CDM.UNITS, units));
      bounds.addAttribute(new Attribute(CDM.LONG_NAME, "bounds for " + tcName));
      bounds.setSPobject(new Time2Dinfo(Time2DinfoType.boundsU, time2D, null));
    }

    if (runtime.getNCoords() != 1) {
      // for this case we have to generate a separate reftime, because have to use the same dimension
      String refName = "ref" + tcName;
      if (g.findVariable(refName) == null) {
        Variable vref = ncfile
            .addVariable(g, new Variable(ncfile, g, null, refName, DataType.DOUBLE, tcName));
        vref.addAttribute(new Attribute(CF.STANDARD_NAME, CF.TIME_REFERENCE));
        vref.addAttribute(new Attribute(CDM.LONG_NAME, Grib.GRIB_RUNTIME));
        vref.addAttribute(new Attribute(CF.CALENDAR, Calendar.proleptic_gregorian.toString()));
        vref.addAttribute(new Attribute(CDM.UNITS, units));
        vref.setSPobject(new Time2Dinfo(Time2DinfoType.isUniqueRuntime, time2D, null));
      }
    }
  }
private void makeUniqueTimeCoordinate2D(NetcdfFile ncfile, Group g, CoordinateTime2D time2D) {
    CoordinateRuntime runtime = time2D.getRuntimeCoordinate();

    int countU = 0;
    for (int run = 0; run < time2D.getNruns(); run++) {
      CoordinateTimeAbstract timeCoord = time2D.getTimeCoordinate(run);
      countU += timeCoord.getSize();
    }
    int ntimes = countU;
    String tcName = time2D.getName();

    ncfile.addDimension(g, new Dimension(tcName, ntimes));
    Variable v = ncfile
        .addVariable(g, new Variable(ncfile, g, null, tcName, DataType.DOUBLE, tcName));
    String units = runtime.getUnit(); // + " since " + runtime.getFirstDate();
    v.addAttribute(new Attribute(CDM.UNITS, units));
    v.addAttribute(new Attribute(CF.STANDARD_NAME, CF.TIME));
    v.addAttribute(new Attribute(CDM.LONG_NAME, Grib.GRIB_VALID_TIME));
    v.addAttribute(new Attribute(CF.CALENDAR, Calendar.proleptic_gregorian.toString()));

    // the data is not generated until asked for to save space
    if (!time2D.isTimeInterval()) {
      v.setSPobject(new Time2Dinfo(Time2DinfoType.offU, time2D, null));
    } else {
      v.setSPobject(new Time2Dinfo(Time2DinfoType.intvU, time2D, null));
      // bounds for intervals
      String bounds_name = tcName + "_bounds";
      Variable bounds = ncfile.addVariable(g,
          new Variable(ncfile, g, null, bounds_name, DataType.DOUBLE, tcName + " 2"));
      v.addAttribute(new Attribute(CF.BOUNDS, bounds_name));
      bounds.addAttribute(new Attribute(CDM.UNITS, units));
      bounds.addAttribute(new Attribute(CDM.LONG_NAME, "bounds for " + tcName));
      bounds.setSPobject(new Time2Dinfo(Time2DinfoType.boundsU, time2D, null));
    }

    if (runtime.getNCoords() != 1) {
      // for this case we have to generate a separate reftime, because have to use the same dimension
      String refName = "ref" + tcName;
      if (g.findVariable(refName) == null) {
        Variable vref = ncfile
            .addVariable(g, new Variable(ncfile, g, null, refName, DataType.DOUBLE, tcName));
        vref.addAttribute(new Attribute(CF.STANDARD_NAME, CF.TIME_REFERENCE));
        vref.addAttribute(new Attribute(CDM.LONG_NAME, Grib.GRIB_RUNTIME));
        vref.addAttribute(new Attribute(CF.CALENDAR, Calendar.proleptic_gregorian.toString()));
        vref.addAttribute(new Attribute(CDM.UNITS, units));
        vref.setSPobject(new Time2Dinfo(Time2DinfoType.isUniqueRuntime, time2D, null));
      }
    }
  }
private void makeUniqueTimeCoordinate2D ( NetcdfFile ncfile , Group g , CoordinateTime2D time2D ) { CoordinateRuntime runtime = time2D . getRuntimeCoordinate ( ) ; int countU = 0 ; for ( int run = 0 ; run < time2D . getNruns ( ) ; run ++ ) { CoordinateTimeAbstract timeCoord = time2D . getTimeCoordinate ( run ) ; countU += timeCoord . getSize ( ) ; } int ntimes = countU ; String tcName = time2D . getName ( ) ; ncfile . addDimension ( g , new Dimension ( tcName , ntimes ) ) ; Variable v = ncfile . addVariable ( g , new Variable ( ncfile , g , null , tcName , DataType . DOUBLE , tcName ) ) ; String units = runtime . getUnit ( ) ; // + " since " + runtime.getFirstDate(); v . addAttribute ( new Attribute ( CDM . UNITS , units ) ) ; v . addAttribute ( new Attribute ( CF . STANDARD_NAME , CF . TIME ) ) ; v . addAttribute ( new Attribute ( CDM . LONG_NAME , Grib . GRIB_VALID_TIME ) ) ; v . addAttribute ( new Attribute ( CF . CALENDAR , Calendar . proleptic_gregorian . toString ( ) ) ) ; // the data is not generated until asked for to save space if ( ! time2D . isTimeInterval ( ) ) { v . setSPobject ( new Time2Dinfo ( Time2DinfoType . offU , time2D , null ) ) ; } else { v . setSPobject ( new Time2Dinfo ( Time2DinfoType . intvU , time2D , null ) ) ; // bounds for intervals String bounds_name = tcName + "_bounds" ; Variable bounds = ncfile . addVariable ( g , new Variable ( ncfile , g , null , bounds_name , DataType . DOUBLE , tcName + " 2" ) ) ; v . addAttribute ( new Attribute ( CF . BOUNDS , bounds_name ) ) ; bounds . addAttribute ( new Attribute ( CDM . UNITS , units ) ) ; bounds . addAttribute ( new Attribute ( CDM . LONG_NAME , "bounds for " + tcName ) ) ; bounds . setSPobject ( new Time2Dinfo ( Time2DinfoType . boundsU , time2D , null ) ) ; } if ( runtime . getNCoords ( ) != 1 ) { // for this case we have to generate a separate reftime, because have to use the same dimension String refName = "ref" + tcName ; if ( g . findVariable ( refName ) == null ) { Variable vref = ncfile . addVariable ( g , new Variable ( ncfile , g , null , refName , DataType . DOUBLE , tcName ) ) ; vref . addAttribute ( new Attribute ( CF . STANDARD_NAME , CF . TIME_REFERENCE ) ) ; vref . addAttribute ( new Attribute ( CDM . LONG_NAME , Grib . GRIB_RUNTIME ) ) ; vref . addAttribute ( new Attribute ( CF . CALENDAR , Calendar . proleptic_gregorian . toString ( ) ) ) ; vref . addAttribute ( new Attribute ( CDM . UNITS , units ) ) ; vref . setSPobject ( new Time2Dinfo ( Time2DinfoType . isUniqueRuntime , time2D , null ) ) ; } } }
time(nruns, ntimes) -> time(ntimes) with dependent reftime(ntime) coordinate
time ( nruns ntimes ) - > time ( ntimes ) with dependent reftime ( ntime ) coordinate