Beispiel #1
0
// Traj_AmberNetcdf::info()
void Traj_AmberNetcdf::Info() {
  mprintf("is a NetCDF AMBER trajectory");
  if (readAccess_ && !HasCoords()) mprintf(" (no coordinates)");
  if (CoordInfo().HasVel()) mprintf(" containing velocities");
  if (CoordInfo().HasTemp()) mprintf(" with replica temperatures");
  if (remd_dimension_ > 0) mprintf(", with %i dimensions", remd_dimension_);
}
Beispiel #2
0
/** Set up trajectory for write. Calculate the length of each cooordinate
  * frame. Set the title and titleSize. Calculate the full output file
  * size, necessary only for seeking when MPI writing. Allocate memory for
  * the frame buffer. 
  */
int Traj_AmberCoord::setupTrajout(FileName const& fname, Topology* trajParm,
                                  CoordinateInfo const& cInfoIn, 
                                  int NframesToWrite, bool append)
{
  // Set Temperature Write
  // FIXME: Check for temperatures in input frames and when appending.
  SetCoordInfo( cInfoIn );
  if (outputTemp_) {
    headerSize_ = REMD_HEADER_SIZE;
    if (!CoordInfo().HasTemp())
      mprintf("Warning: No temperature information in input frames.\n");
  }
  if (!append) {
    // Write the title if not appending
    if (file_.SetupWrite( fname, debug_ )) return 1;
    std::string title = Title();
    if (title.empty()) {
      // Set up default title
      title.assign("Cpptraj Generated trajectory");
      title.resize(80,' ');
      SetTitle( title );
    } else {
      // Check title length
      if (title.size() > 80) {
        mprintf("Warning: Amber traj title for %s too long: truncating.\n[%s]\n",
                file_.Filename().base(), title.c_str());
        title.resize(80);
      }
    }
    if (file_.OpenFile()) return 1;
    file_.Printf("%-s\n", title.c_str());
  } else {
    // Just set up for append
    if (file_.SetupAppend( fname, debug_ )) return 1;
    if (file_.OpenFile()) return 1;
  }
  // Allocate buffer. Will not buffer REMD header or need to seek.
  // NOTE: This is done here since SetupFrameBuffer allocates based
  //       on write mode, which is not known until now.
  natom3_ = trajParm->Natom() * 3;
  file_.SetupFrameBuffer( natom3_, 8, 10 );
  // If box coords are present, allocate extra space for them
  switch (CoordInfo().TrajBox().Type()) {
    case Box::NOBOX   : numBoxCoords_ = 0; break;
    case Box::ORTHO   :
    case Box::TRUNCOCT: numBoxCoords_ = 3; break;
    default           : numBoxCoords_ = 6;
  }
  file_.ResizeBuffer( numBoxCoords_ );
 
  if (debug_>0) 
    rprintf("(%s): Each frame has %lu bytes.\n", file_.Filename().base(), file_.FrameSize());
  
  return 0;
}
Beispiel #3
0
int Traj_GmxTrX::setupTrajout(FileName const& fname, Topology* trajParm,
                              CoordinateInfo const& cInfoIn,
                              int NframesToWrite, bool append)
{
    if (!append) {
        SetCoordInfo( cInfoIn );
        natoms_ = trajParm->Natom();
        natom3_ = natoms_ * 3;
        // Default to little endian, precision 4, TRR
        format_ = TRR;
        isBigEndian_ = false;
        precision_ = 4;
        // Set up title
        if (Title().empty())
            SetTitle("Cpptraj generated TRR file.");
        // Set size defaults, box, velocity etc
        ir_size_ = 0;
        e_size_ = 0;
        if (CoordInfo().HasBox())
            box_size_ = precision_ * 9;
        else
            box_size_ = 0;
        vir_size_ = 0;
        pres_size_ = 0;
        top_size_ = 0;
        sym_size_ = 0;
        x_size_ = natom3_ * precision_;
        if (CoordInfo().HasVel())
            v_size_ = natom3_ * precision_;
        else
            v_size_ = 0;
        f_size_ = 0;
        step_ = 0;
        nre_ = 0;
        dt_ = 0.0;
        lambda_ = 0.0;
        // Allocate temp space for coords/velo
        AllocateCoords();
        if (file_.SetupWrite( fname, debug_)) return 1;
        if (file_.OpenFile()) return 1;
    } else {
        int nframes = setupTrajin( fname, trajParm );
        if ( format_ == TRJ ) {
            mprinterr("Error: Only writes to TRR files supported.\n");
            return 1;
        }
        if ( nframes == TRAJIN_ERR ) return 1;
        mprintf("\tAppending to TRR file starting at frame %i\n", nframes);
        // Re-open for appending
        if (file_.SetupAppend( fname, debug_ )) return 1;
        if (file_.OpenFile()) return 1;
    }
    return 0;
}
Beispiel #4
0
/** Create Netcdf file specified by filename and set up dimension and
  * variable IDs. 
  */
int Traj_AmberNetcdf::setupTrajout(FileName const& fname, Topology* trajParm,
                                   CoordinateInfo const& cInfoIn, 
                                   int NframesToWrite, bool append)
{
  readAccess_ = false;
  if (!append) {
    CoordinateInfo cInfo = cInfoIn;
    // Deal with output options
    // For backwards compatibility always write temperature if remdtraj is true.
    if (outputTemp_ && !cInfo.HasTemp()) cInfo.SetTemperature(true);
    // Explicitly write velocity - initial frames may not have velocity info.
    if (outputVel_ && !cInfo.HasVel()) cInfo.SetVelocity(true);
    if (outputFrc_ && !cInfo.HasForce()) cInfo.SetForce(true);
    SetCoordInfo( cInfo );
    filename_ = fname;
    // Set up title
    if (Title().empty())
      SetTitle("Cpptraj Generated trajectory");
    // Create NetCDF file.
    if (NC_create( filename_.Full(), NC_AMBERTRAJ, trajParm->Natom(), CoordInfo(), Title() ))
      return 1;
    if (debug_>1) NetcdfDebug();
    // Close Netcdf file. It will be reopened write.
    NC_close();
    // Allocate memory
    if (Coord_!=0) delete[] Coord_;
    Coord_ = new float[ Ncatom3() ];
  } else { // NOTE: File existence is checked for in Trajout
    // Call setupTrajin to set input parameters. This will also allocate
    // memory for coords.
    if (setupTrajin(fname, trajParm) == TRAJIN_ERR) return 1;
    // Check output options.
    if (outputTemp_ && !CoordInfo().HasTemp())
      mprintf("Warning: Cannot append temperature data to NetCDF file '%s'; no temperature dimension.\n",
              filename_.base());
    if (outputVel_ && !CoordInfo().HasVel())
      mprintf("Warning: Cannot append velocity data to NetCDF file '%s'; no velocity dimension.\n",
              filename_.base());
    if (outputFrc_ && !CoordInfo().HasForce())
      mprintf("Warning: Cannot append force data to NetCDF file '%s'; no force dimension.\n",
              filename_.base());
    if (debug_ > 0)
      mprintf("\tNetCDF: Appending %s starting at frame %i\n", filename_.base(), Ncframe()); 
  }
  // Open file
  if ( NC_openWrite( filename_.Full() ) != 0 ) {
    mprinterr("Error: Opening Netcdf file %s for Write.\n", filename_.base());
    return 1;
  }
  return 0;
}
Beispiel #5
0
int Traj_Gro::readFrame(int fnum, Frame& frm) {
    if (fnum < currentSet_) {
        file_.CloseFile();
        file_.OpenFileRead( fname_ );
        currentSet_ = 0;
    }
    // Position file
    const char* ptr;
    for (int set = currentSet_; set != fnum; set++) {
        ptr = file_.Line(); // Title
        ptr = file_.Line(); // Natoms
        for (int i = 0; i != linesToRead_; i++)
            ptr = file_.Line(); // Atom (and possibly box)
        if (ptr == 0) return 1;
    }
    // Read current frame
    ptr = file_.Line(); // Title
    if (ptr == 0) return 1;
    if (CoordInfo().HasTime())
        frm.SetTime( GetTimeValue(ptr) );
    ptr = file_.Line(); // Natoms TODO check?
    double* Xptr = frm.xAddress();
    if (CoordInfo().HasVel()) {
        double* Vptr = frm.vAddress();
        for (int i = 0; i != natom_; i++, Xptr += 3, Vptr += 3) {
            ptr = file_.Line(); // Atom
            sscanf(ptr, "%*5c%*5c%*5c%*5c%lf %lf %lf %lf %lf %lf",
                   Xptr, Xptr+1, Xptr+2, Vptr, Vptr+1, Vptr+2);
            for (int n = 0; n != 3; n++) {
                Xptr[n] *= 10.0;
                Vptr[n] *= 10.0;
            }
        }
    } else {
        for (int i = 0; i != natom_; i++, Xptr += 3) {
            ptr = file_.Line(); // Atom
            sscanf(ptr, "%*5c%*5c%*5c%*5c%lf %lf %lf", Xptr, Xptr+1, Xptr+2);
            for (int n = 0; n != 3; n++)
                Xptr[n] *= 10.0;
        }
    }
    // Box read
    if (CoordInfo().HasBox()) {
        ptr = file_.Line();
        frm.SetBox( GetBox(ptr) );
    }

    ++currentSet_;
    return 0;
}
Beispiel #6
0
// Traj_AmberRestart::readVelocity()
int Traj_AmberRestart::readVelocity(int set, Frame& frameIn) {
  if (CoordInfo().HasVel()) {
    std::copy(VEL_.begin(), VEL_.end(), frameIn.vAddress());
    return 0;
  }
  return 1;
}
Beispiel #7
0
// Traj_NcEnsemble::Info()
void Traj_NcEnsemble::Info() {
  mprintf("is a NetCDF Ensemble AMBER trajectory");
  if (readAccess_) {
    mprintf(" with %s", CoordInfo().InfoString().c_str());
    if (useVelAsCoords_) mprintf(" (using velocities as coordinates)");
    if (useFrcAsCoords_) mprintf(" (using forces as coordinates)");
    if (remd_dimension_ > 0) mprintf(", %i replica dimensions", remd_dimension_);
  } 
}
Beispiel #8
0
// Traj_AmberCoord::Info()
void Traj_AmberCoord::Info() {
  if (CoordInfo().HasTemp()) 
    mprintf("is an AMBER REMD trajectory");
  else
    mprintf("is an AMBER trajectory");
  if (highPrecision_) mprintf(" (high precision)");
  if (writeType_ == VEL) mprintf(" (MDVEL)");
  else if (writeType_ == FRC) mprintf(" (MDFRC)");
}
Beispiel #9
0
/** Allocate a character buffer based on number of coords and whether 
  * velocities/box info is present.
  */
int Traj_AmberRestart::setupTrajout(FileName const& fname, Topology* trajParm,
                                    CoordinateInfo const& cInfoIn, 
                                    int NframesToWrite, bool append)
{
  if (append) {
    mprinterr("Error: Append not supported for Amber Restart.\n");
    return 1;
  }
  CoordinateInfo cInfo = cInfoIn;
  if (!cInfo.HasTemp() && outputTemp_) cInfo.SetTemperature(true);
  // If temperature requested write time as well or format will break.
  if (cInfo.HasTemp()) {
    outputTime_ = true;
    if (!cInfo.HasTime() && time0_ < 0.0) time0_ = 1.0;
  }
  if (cInfo.HasVel() && !outputVel_) cInfo.SetVelocity(false);
  if (outputTime_) {
    if (!cInfo.HasTime() && time0_ >= 0) cInfo.SetTime(true);
  } else
    cInfo.SetTime(false);
  SetCoordInfo( cInfo );
  if (file_.SetupWrite( fname, debug_ )) return 1;
  readAccess_ = false;
  // Set trajectory info
  natom3_ = trajParm->Natom() * 3;
  // Calculate the length of coordinate frame in bytes
  file_.SetupFrameBuffer( natom3_, 12, 6 ); 
  // Dont know ahead of time if velocities will be used, allocate space
  // just in case. Velocity will not be written if V input is null.
  file_.ResizeBuffer( natom3_ );
  // If box coords are present, allocate extra space for them
  if (CoordInfo().HasBox()) {
    numBoxCoords_ = 6;
    file_.ResizeBuffer( numBoxCoords_ );
  }
  // If number of frames to write == 1 set singleWrite so we dont append
  // frame # to filename.
  if (NframesToWrite==1) singleWrite_ = true;
  // Set up title
  std::string outTitle = Title();
  if (outTitle.empty()) {
    outTitle.assign("Cpptraj Generated Restart");
    outTitle.resize(80, ' ');
  } else {
    if ( outTitle.size() > 80) {
      mprintf("Warning: Amber restart title for %s too long: truncating.\n[%s]\n",
              file_.Filename().base(), outTitle.c_str());
      outTitle.resize(80);
    }
  }
  SetTitle( outTitle );

  return 0;
}
Beispiel #10
0
/** Write coords in Frame to file in amber restart format. */
int Traj_AmberRestart::writeFrame(int set, Frame const& frameOut) {
  // If just writing 1 frame dont modify output filename
  if (singleWrite_) {
    if (file_.OpenFile()) return 1;
  } else {
    if (file_.OpenWriteNumbered( set + 1 ) ) return 1;
  }

  // Write out title
  file_.Printf("%-s\n", Title().c_str());
  // Write out atoms
  file_.Printf("%5i", frameOut.Natom());
  // Write out restart time
  if (CoordInfo().HasTime()) {
    if (time0_>=0)
      restartTime_ = (time0_ + (double)set) * dt_;
    else
      restartTime_ = frameOut.Time();
    file_.Printf("%15.7lE",restartTime_);
  }
  // Write out temperature
  if (CoordInfo().HasTemp())
    file_.Printf("%15.7lE",frameOut.Temperature());
  file_.Printf("\n");

  // Write coords to buffer
  file_.BufferBegin();
  file_.DoubleToBuffer(frameOut.xAddress(), natom3_, "%12.7f");
  // Write velocity to buffer. Check V since velocity not known ahead of time
  if (CoordInfo().HasVel() && frameOut.HasVelocity())
    file_.DoubleToBuffer(frameOut.vAddress(), natom3_, "%12.7f");
  // Write box to buffer
  if (numBoxCoords_!=0)
    file_.DoubleToBuffer(frameOut.bAddress(), numBoxCoords_, "%12.7f");

  if (file_.WriteFrame()) return 1;

  file_.CloseFile();

  return 0;
}
Beispiel #11
0
/** Copy buffered coords/velocities/box to input frame. */
int Traj_AmberRestart::readFrame(int set, Frame& frameIn) {
  // Set frame temp
  if (CoordInfo().HasTemp())
    frameIn.SetTemperature( restartTemp_ );
  // Set frame time
  if (CoordInfo().HasTime())
    frameIn.SetTime( restartTime_ );
  // Get coords from buffer
  std::copy(CRD_.begin(), CRD_.end(), frameIn.xAddress());
  // Get velocity from buffer if present
  if (CoordInfo().HasVel()) {
    if (frameIn.HasVelocity()) {
      if (useVelAsCoords_)
        std::copy(VEL_.begin(), VEL_.end(), frameIn.xAddress());
      else
        std::copy(VEL_.begin(), VEL_.end(), frameIn.vAddress());
    }
  }
  // Get box from buffer if present
  if (numBoxCoords_!=0) 
    std::copy(boxInfo_.boxPtr(), boxInfo_.boxPtr()+6, frameIn.bAddress());
  return 0;
}
Beispiel #12
0
void Traj_GmxTrX::AllocateCoords() {
    // Allocate temp space for coords/velo
    if (farray_ != 0) {
        delete[] farray_;
        farray_ = 0;
    }
    if (darray_ != 0) {
        delete[] darray_;
        darray_ = 0;
    }
    size_t arraySize = (size_t)natom3_;
    if (CoordInfo().HasVel()) arraySize *= 2;
    if (precision_ == sizeof(float))
        farray_ = new float[ arraySize ];
    else
        darray_ = new double[ arraySize ];
}
Beispiel #13
0
// Traj_AmberRestart::Info()
void Traj_AmberRestart::Info() {
  mprintf("is an AMBER restart file");
  if (readAccess_) {
    // If read access we know for sure whether there are velocities.
    if (CoordInfo().HasVel())
      mprintf(" with velocity info");
    else
      mprintf(", no velocities");
    if (useVelAsCoords_) mprintf(" (using velocities as coords)");
  } else {
    // If write, not sure yet whether velocities will be written since
    // it also depends on if the frame has velocity info, so only state
    // if novelocity was specified.
    if (!outputVel_) mprintf(", no velocities");
    if (!outputTime_) mprintf(", no time");
  }
}
Beispiel #14
0
// Traj_NcEnsemble::setupTrajout()
int Traj_NcEnsemble::setupTrajout(FileName const& fname, Topology* trajParm,
                                  CoordinateInfo const& cInfoIn,
                                  int NframesToWrite, bool append)
{
  int err = 0;
# ifdef MPI
  if (NoPnetcdf()) return 1;
# endif
  readAccess_ = false;
  if (!append) {
    CoordinateInfo cInfo = cInfoIn;
    // TODO: File output modifications
    SetCoordInfo( cInfo );
#   ifdef MPI
    ensembleStart_ = Parallel::World().Rank();
    ensembleEnd_ = Parallel::World().Rank() + 1;
#   else
    ensembleStart_ = 0;
    ensembleEnd_ = cInfo.EnsembleSize();;
#   endif
    filename_ = fname;
    // Set up title
    if (Title().empty())
      SetTitle("Cpptraj Generated trajectory");
#   ifdef MPI
    if (Parallel::World().Master()) { // Only master creates file.
#   endif
      // Create NetCDF file.
      err = NC_create(filename_.Full(), NC_AMBERENSEMBLE, trajParm->Natom(), CoordInfo(),
                      Title(), debug_);
      // Close Netcdf file. It will be reopened write. FIXME should NC_create leave it closed?
      NC_close();
#   ifdef MPI
    }
    Parallel::World().MasterBcast(&err, 1, MPI_INT);
#   endif
    if (err != 0) return 1;
#   ifdef MPI
    // Synchronize netcdf info on non-master threads
    Sync(Parallel::World());
    // DEBUG: Print info for all ranks
    DebugVIDs();
#   endif
    // Allocate memory
    if (Coord_!=0) delete[] Coord_;
    Coord_ = new float[ Ncatom3() ];
  } else { // NOTE: File existence is checked for in Trajout
    // Call setupTrajin to set input parameters. This will also allocate
    // memory for coords.
    if (setupTrajin(fname, trajParm) == TRAJIN_ERR) return 1;
    if (debug_ > 0)
      mprintf("\tNetCDF: Appending %s starting at frame %i\n", filename_.base(), Ncframe());
  }
  // Open file
# ifdef HAS_PNETCDF
  err = ncmpi_open(MPI_COMM_WORLD, filename_.full(), NC_WRITE, MPI_INFO_NULL, &ncid_);
  // TODO: Graceful error handling
# else
  err = NC_openWrite( filename_.Full() );
# endif  
  if ( err != 0 ) {
    mprinterr("Error: Opening Netcdf file %s for Write.\n", filename_.base());
    return 1;
  }

  return 0;
}
Beispiel #15
0
void Traj_Gro::Info() {
    mprintf("is a GRO file");
    if (CoordInfo().HasTime()) mprintf(", with time");
    if (CoordInfo().HasVel()) mprintf(", with velocities");
    if (CoordInfo().HasBox()) mprintf(", with box info");
}
Beispiel #16
0
// Traj_NcEnsemble::writeArray()
int Traj_NcEnsemble::writeArray(int set, FramePtrArray const& Farray) {
# ifdef HAS_PNETCDF
  MPI_Offset pstart_[4];
  MPI_Offset pcount_[4];
# define start_ pstart_
# define count_ pcount_
# endif
  start_[0] = ncframe_; // Frame
  start_[2] = 0;        // Atoms
  start_[3] = 0;        // XYZ
  count_[0] = 1; // Frame
  count_[1] = 1; // Ensemble
  count_[3] = 3; // XYZ
  for (int member = ensembleStart_; member != ensembleEnd_; member++) {
    //rprintf("DEBUG: Writing set %i, member %i\n", set+1, member); 
#   ifdef MPI
    Frame* frm = Farray[0];
#   else
    Frame* frm = Farray[member];
#   endif
    start_[1] = member;   // Ensemble
    count_[2] = Ncatom(); // Atoms
    // Write Coords
    //WriteIndices(); // DEBUG
    DoubleToFloat(Coord_, frm->xAddress());
#   ifdef HAS_PNETCDF
    if (ncmpi_put_vara_float_all(ncid_, coordVID_, start_, count_, Coord_))
#   else
    if (checkNCerr(nc_put_vara_float(ncid_, coordVID_, start_, count_, Coord_)))
#   endif
    {
      mprinterr("Error: Netcdf Writing coords frame %i\n", set+1);
      return 1;
    }
    // Write velocity.
    if (CoordInfo().HasVel() && frm->HasVelocity()) { // TODO: Determine V beforehand
      DoubleToFloat(Coord_, frm->vAddress());
#     ifdef HAS_PNETCDF
      if (ncmpi_put_vara_float_all(ncid_, velocityVID_, start_, count_, Coord_))
#     else
      if (checkNCerr(nc_put_vara_float(ncid_, velocityVID_, start_, count_, Coord_)) )
#     endif
      {
        mprinterr("Error: Netcdf writing velocity frame %i\n", set+1);
        return 1;
      }
    }
    // Write box
    if (cellLengthVID_ != -1) {
      count_[2] = 3;
#     ifdef HAS_PNETCDF
      if (ncmpi_put_vara_double_all(ncid_,cellLengthVID_,start_,count_,frm->bAddress()))
#     else
      if (checkNCerr(nc_put_vara_double(ncid_,cellLengthVID_,start_,count_,frm->bAddress())) )
#     endif
      {
        mprinterr("Error: Writing cell lengths frame %i.\n", set+1);
        return 1;
      }
#     ifdef HAS_PNETCDF
      if (ncmpi_put_vara_double_all(ncid_,cellAngleVID_,start_,count_,frm->bAddress()+3))
#     else
      if (checkNCerr(nc_put_vara_double(ncid_,cellAngleVID_,start_,count_,frm->bAddress()+3)))
#     endif
      {
        mprinterr("Error: Writing cell angles frame %i.\n", set+1);
        return 1;
      }
    }
    // Write temperature
    if (TempVID_!=-1) {
#     ifdef HAS_PNETCDF
      if (ncmpi_put_vara_double_all(ncid_,TempVID_,start_,count_,frm->tAddress()))
#     else
      if (checkNCerr(nc_put_vara_double(ncid_,TempVID_,start_,count_,frm->tAddress())))
#     endif
      {
        mprinterr("Error: Writing temperature frame %i.\n", set+1);
        return 1;
      }
    }
    // Write indices
    if (indicesVID_ != -1) {
      count_[2] = remd_dimension_;
#     ifdef HAS_PNETCDF
      if (ncmpi_put_vara_int_all(ncid_,indicesVID_,start_,count_,frm->iAddress()))
#     else
      if (checkNCerr(nc_put_vara_int(ncid_,indicesVID_,start_,count_,frm->iAddress())))
#     endif
      {
        mprinterr("Error: Writing indices frame %i.\n", set+1);
        return 1;
      }
    }
  }
# ifdef HAS_PNETCDF
  //ncmpi_sync(ncid_);
# else
  nc_sync(ncid_); // Necessary after every write??
# endif
  ++ncframe_;
# ifdef HAS_PNETCDF
  // DEBUG
# undef start_
# undef count_
# endif
  return 0;
}
Beispiel #17
0
// Traj_AmberNetcdf::writeFrame() 
int Traj_AmberNetcdf::writeFrame(int set, Frame const& frameOut) {
  DoubleToFloat(Coord_, frameOut.xAddress());

  // Write coords
  start_[0] = ncframe_;
  start_[1] = 0;
  start_[2] = 0;
  count_[0] = 1;
  count_[1] = Ncatom();
  count_[2] = 3;
  if (checkNCerr(nc_put_vara_float(ncid_,coordVID_,start_,count_,Coord_)) ) {
    mprinterr("Error: Netcdf Writing coords frame %i\n", set+1);
    return 1;
  }

  // Write velocity. FIXME: Should check in setup
  if (CoordInfo().HasVel() && frameOut.HasVelocity()) {
    DoubleToFloat(Coord_, frameOut.vAddress());
    if (checkNCerr(nc_put_vara_float(ncid_, velocityVID_, start_, count_, Coord_)) ) {
      mprinterr("Error: Netcdf writing velocity frame %i\n", set+1);
      return 1;
    }
  }

  // Write box
  if (cellLengthVID_ != -1) {
    count_[1] = 3;
    count_[2] = 0;
    if (checkNCerr(nc_put_vara_double(ncid_,cellLengthVID_,start_,count_,frameOut.bAddress())) ) {
      mprinterr("Error: Writing cell lengths frame %i.\n", set+1);
      return 1;
    }
    if (checkNCerr(nc_put_vara_double(ncid_,cellAngleVID_,start_,count_, frameOut.bAddress()+3)) ) {
      mprinterr("Error: Writing cell angles frame %i.\n", set+1);
      return 1;
    }
  }

  // Write temperature
  if (TempVID_!=-1) {
    if ( checkNCerr( nc_put_vara_double(ncid_,TempVID_,start_,count_,frameOut.tAddress())) ) {
      mprinterr("Error: Writing temperature frame %i.\n", set+1);
      return 1;
    }
  }

  // Write time
  if (timeVID_ != -1) {
    float tVal = (float)frameOut.Time();
    if ( checkNCerr( nc_put_vara_float(ncid_,timeVID_,start_,count_,&tVal)) ) {
      mprinterr("Error: Writing time frame %i.\n", set+1);
      return 1;
    }
  }
    
  // Write indices
  if (indicesVID_ != -1) {
    count_[1] = remd_dimension_;
    if ( checkNCerr(nc_put_vara_int(ncid_,indicesVID_,start_,count_,frameOut.iAddress())) ) {
      mprinterr("Error: Writing indices frame %i.\n", set+1);
      return 1;
    }
  }

  nc_sync(ncid_); // Necessary after every write??

  ++ncframe_;

  return 0;
}