Exemplo n.º 1
0
// #################################################################
// Ductの計算領域のセルIDを設定する
void IP_Duct::setup(int* bcd, Control* R, REAL_TYPE* G_org, const int NoMedium, const MediumList* mat, float* cut, int* bid)
{
  int mid_fluid=1;        /// 流体
  int mid_solid=2;        /// 固体
  int mid_driver=3;       /// ドライバ部
  int mid_driver_face=4;  /// ドライバ流出面
  REAL_TYPE x, y, z, dh, r, len;
  REAL_TYPE ox, oy, oz, Lx, Ly, Lz;
  
  // ローカルにコピー
  int ix = size[0];
  int jx = size[1];
  int kx = size[2];
  int gd = guide;
  
  // 隣接ランクのIDを取得 nID[6]
  const int* nID = paraMngr->GetNeighborRankID();
  
  ox = origin[0];
  oy = origin[1];
  oz = origin[2];
  Lx = region[0];
  Ly = region[1];
  Lz = region[2];
  dh = deltaX;
  r  = driver.diameter/R->RefLength * 0.5;
  len= driver.length/R->RefLength;
  
  // Initialize
#pragma omp parallel for firstprivate(ix, jx, kx, gd, mid_solid) schedule(static)
  for (int k=1; k<=kx; k++) {
    for (int j=1; j<=jx; j++) {
      for (int i=1; i<=ix; i++) {
        size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
        bcd[m] = 0;
      }
    }
  }
  
  // Inner
  if (driver.shape == id_rectangular ) { // 矩形管の場合は内部は全て流体
#pragma omp parallel for firstprivate(ix, jx, kx, gd, mid_fluid) \
schedule(static)
    for (int k=1; k<=kx; k++) {
      for (int j=1; j<=jx; j++) {
        for (int i=1; i<=ix; i++) {
          size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
          bcd[m] = 0;
        }
      }
    }
  }
  else { // 円管の場合,半径以下のセルを流体にする(ノードにかかわらず)
    switch (driver.direction) {
      case X_minus:
      case X_plus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
              y = oy + 0.5*dh + dh*(j-1);
              z = oz + 0.5*dh + dh*(k-1);
              if ( (y-r)*(y-r)+(z-r)*(z-r) <= r*r ) bcd[m] |= mid_fluid;
            }
          }
        }
        break;
        
      case Y_minus:
      case Y_plus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
              x = ox + 0.5*dh + dh*(i-1);
              z = oz + 0.5*dh + dh*(k-1);
              if ( (x-r)*(x-r)+(z-r)*(z-r) <= r*r ) bcd[m] |= mid_fluid;
            }
          }
        }
        break;
        
      case Z_minus:
      case Z_plus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
              x = ox + 0.5*dh + dh*(i-1);
              y = oy + 0.5*dh + dh*(j-1);
              if ( (x-r)*(x-r)+(y-r)*(y-r) <= r*r ) bcd[m] |= mid_fluid;
            }
          }
        }
        break;
    }   
  }
  
  // ドライバ部分
  if ( driver.length > 0.0 ) {
    
    switch (driver.direction) {
      case X_minus:
        if ( nID[driver.direction] < 0 ) {
          for (int k=1; k<=kx; k++) {
            for (int j=1; j<=jx; j++) {
              for (int i=1; i<=ix; i++) {
                size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
                x = ox + 0.5*dh + dh*(i-1);
                y = oy + 0.5*dh + dh*(j-1);
                z = oz + 0.5*dh + dh*(k-1);
                if ( x < ox+len ) {
                  if ( driver.shape == id_circular ) {
                    if ( (y-r)*(y-r)+(z-r)*(z-r) <= r*r ) bcd[m] |= mid_driver; // 半径以内をドライバIDにする
                  }
                  else {
                    bcd[m] |= mid_driver;
                  }
                }
              }
            }
          }
        }        
        break;
        
      case X_plus:
        if ( nID[driver.direction] < 0 ) {
          for (int k=1; k<=kx; k++) {
            for (int j=1; j<=jx; j++) {
              for (int i=1; i<=ix; i++) {
                size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
                x = ox + 0.5*dh + dh*(i-1);
                y = oy + 0.5*dh + dh*(j-1);
                z = oz + 0.5*dh + dh*(k-1);
                if ( x > ox+Lx-len ) {
                  if ( driver.shape == id_circular ) {
                    if ( (y-r)*(y-r)+(z-r)*(z-r) <= r*r ) bcd[m] |= mid_driver;
                  }
                  else {
                    bcd[m] |= mid_driver;
                  }
                }                
              }
            }
          }
        }
        break;
        
      case Y_minus:
        if ( nID[driver.direction] < 0 ) {
          for (int k=1; k<=kx; k++) {
            for (int j=1; j<=jx; j++) {
              for (int i=1; i<=ix; i++) {
                size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
                x = ox + 0.5*dh + dh*(i-1);
                y = oy + 0.5*dh + dh*(j-1);
                z = oz + 0.5*dh + dh*(k-1);
                if ( y < oy+len ) {
                  if ( driver.shape == id_circular ) {
                    if ( (x-r)*(x-r)+(z-r)*(z-r) <= r*r ) bcd[m] |= mid_driver;
                  }
                  else {
                    bcd[m] |= mid_driver;
                  }
                }
              }
            }
          }
        }        
        break;
        
      case Y_plus:
        if ( nID[driver.direction] < 0 ) {
          for (int k=1; k<=kx; k++) {
            for (int j=1; j<=jx; j++) {
              for (int i=1; i<=ix; i++) {
                size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
                x = ox + 0.5*dh + dh*(i-1);
                y = oy + 0.5*dh + dh*(j-1);
                z = oz + 0.5*dh + dh*(k-1);
                if ( y > oy+Ly-len ) {
                  if ( driver.shape == id_circular ) {
                    if ( (x-r)*(x-r)+(z-r)*(z-r) <= r*r ) bcd[m] |= mid_driver;
                  }
                  else {
                    bcd[m] |= mid_driver;
                  }
                }
              }
            }
          }
        }
        break;
        
      case Z_minus:
        if ( nID[driver.direction] < 0 ) {
          for (int k=1; k<=kx; k++) {
            for (int j=1; j<=jx; j++) {
              for (int i=1; i<=ix; i++) {
                size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
                x = ox + 0.5*dh + dh*(i-1);
                y = oy + 0.5*dh + dh*(j-1);
                z = oz + 0.5*dh + dh*(k-1);
                if ( z < oz+len ) {
                  if ( driver.shape == id_circular ) {
                    if ( (x-r)*(x-r)+(y-r)*(y-r) <= r*r ) bcd[m] |= mid_driver;
                  }
                  else {
                    bcd[m] |= mid_driver;
                  }
                }
              }
            }
          }
        }
        break;
        
      case Z_plus:
        if ( nID[driver.direction] < 0 ) {
          for (int k=1; k<=kx; k++) {
            for (int j=1; j<=jx; j++) {
              for (int i=1; i<=ix; i++) {
                size_t m = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
                x = ox + 0.5*dh + dh*(i-1);
                y = oy + 0.5*dh + dh*(j-1);
                z = oz + 0.5*dh + dh*(k-1);
                if ( z > oz+Lz-len ) {
                  if ( driver.shape == id_circular ) {
                    if ( (x-r)*(x-r)+(y-r)*(y-r) <= r*r ) bcd[m] |= mid_driver;
                  }
                  else {
                    bcd[m] |= mid_driver;
                  }
                }
              }
            }
          }
        }
        break;
    }    
  }
  
  // ドライバの下流面にIDを設定
  if ( driver.length > 0.0 ) {
    
    switch (driver.direction) 
    {
      case X_minus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i,   j, k, ix, jx, kx, gd);
              size_t m1= _F_IDX_S3D(i+1, j, k, ix, jx, kx, gd);
              if ( (DECODE_CMP( bcd[m] )  == mid_driver) && (DECODE_CMP( bcd[m1] ) == mid_fluid) )
              {
                bcd[m] |= mid_driver_face;
              }
            }
          }
        }        
        break;
        
      case X_plus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i,   j, k, ix, jx, kx, gd);
              size_t m1= _F_IDX_S3D(i-1, j, k, ix, jx, kx, gd);
              if ( (DECODE_CMP( bcd[m] ) == mid_driver) && (DECODE_CMP( bcd[m1] )  == mid_fluid) ) 
              {
                bcd[m] |= mid_driver_face;
              }
            }
          }
        }
        break;
        
      case Y_minus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i, j,   k, ix, jx, kx, gd);
              size_t m1= _F_IDX_S3D(i, j+1, k, ix, jx, kx, gd);
              if ( (DECODE_CMP( bcd[m] ) == mid_driver) && (DECODE_CMP( bcd[m1] )  == mid_fluid) ) 
              {
                bcd[m] |= mid_driver_face;
              }
            }
          }
        }        
        break;
        
      case Y_plus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i, j,   k, ix, jx, kx, gd);
              size_t m1= _F_IDX_S3D(i, j-1, k, ix, jx, kx, gd);
              if ( (DECODE_CMP( bcd[m] ) == mid_driver) && (DECODE_CMP( bcd[m1] )  == mid_fluid) ) 
              {
                bcd[m] |= mid_driver_face;
              }
            }
          }
        }
        break;
        
      case Z_minus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i, j, k,   ix, jx, kx, gd);
              size_t m1= _F_IDX_S3D(i, j, k+1, ix, jx, kx, gd);
              if ( (DECODE_CMP( bcd[m] ) == mid_driver) && (DECODE_CMP( bcd[m1] )  == mid_fluid) ) 
              {
                bcd[m] |= mid_driver_face;
              }
            }
          }
        }
        break;
        
      case Z_plus:
        for (int k=1; k<=kx; k++) {
          for (int j=1; j<=jx; j++) {
            for (int i=1; i<=ix; i++) {
              size_t m = _F_IDX_S3D(i, j, k,   ix, jx, kx, gd);
              size_t m1= _F_IDX_S3D(i, j, k-1, ix, jx, kx, gd);
              if ( (DECODE_CMP( bcd[m] ) == mid_driver) && (DECODE_CMP( bcd[m1] )  == mid_fluid) ) 
              {
                bcd[m] |= mid_driver_face;
              }
            }
          }
        }
        break;
    }    
  }
  
}
Exemplo n.º 2
0
// #################################################################
// Cell IDをbvxで出力する
int IO_BASE::writeCellID(const int out_gc)
{
  if (IO_Voxel != voxel_BVX) return 0;
  
  unsigned bitWidth = 5;
  int rank = paraMngr->GetMyRankID(procGrp);
  
  int ix = size[0];
  int jx = size[1];
  int kx = size[2];
  int gc = out_gc;
  int gd = guide;
  
  size_t nx = (ix+2*gc) * (jx+2*gc) * (kx+2*gc);
  
  // unsignd char
  u8 *buf = new u8[nx];
  
  // start indexの値 下位5bitの値のみ
  u8 val = DECODE_CMP(d_bcd[ _F_IDX_S3D(1-gc, 1-gc, 1-gc, ix, jx, kx, gd) ]);
  int c=0;
  
#pragma omp parallel for firstprivate(ix, jx, kx, gc, gd, val) schedule(static) reduction(+:c)
  for (int k=1-gc; k<=kx+gc; k++) {
    for (int j=1-gc; j<=jx+gc; j++) {
      for (int i=1-gc; i<=ix+gc; i++) {
        size_t m0 = _F_IDX_S3D(i, j, k, ix, jx, kx, gd);
        size_t m1 = _F_IDX_S3D(i, j, k, ix, jx, kx, gc);
        u8 tmp = DECODE_CMP(d_bcd[m0]);
        buf[m1] = tmp;
        if ( tmp == val ) c++;
      }
    }
  }
  
  bool ret = false;
  int ret_val=0;
  
  // サブドメイン内が全て同じ値の時(c==nx)には、CellID配列を書き出さずに戻り値はval
  if ( c != nx )
  {
    ret = BVX_IO::Save_Block_CellID(size, gc, bitWidth, rank, OutDirPath, buf, BVXcomp);
    if ( !ret )
    {
      stamped_printf("\tError : when saving CellID\n");
      Exit(0);
    }
    ret_val = -1;
  }
  else
  {
    ret_val = (int)val;
  }
  

  if (buf)
  {
    delete [] buf;
    buf = NULL;
  }

  return ret_val;
}
Exemplo n.º 3
0
// #################################################################
// モデルIDをsphフォーマット(float)で出力する
void Intrinsic::writeSPH(const int *bcd, const Control* R)
{
  int ix, jx, kx;
  float ox, oy, oz, dx, dy, dz;
  char fname[64];
  
  if ( paraMngr->IsParallel() )
  {
    sprintf( fname, "model_%06d.sph", paraMngr->GetMyRankID(procGrp) );
  }
  else
  {
    sprintf( fname, "model.sph" );
  }
  
  ofstream ofs(fname, ios::out | ios::binary);
  
  if (!ofs)
  {
    cout << "\tCan't open " << fname << " file" << endl;
    Exit(0);
  }
  
  int imax = size[0];
  int jmax = size[1];
  int kmax = size[2];
  int gd = guide;
  
  ix = imax+2;  // +2 means guide cell
  jx = jmax+2;
  kx = kmax+2;
  
  size_t nx = (size_t)(ix*jx*kx);
  
  dx = (float)pitch[0]*RefL;
  dy = (float)pitch[1]*RefL;
  dz = (float)pitch[2]*RefL;
  
  ox = (float)origin[0]*RefL - dx; // 片側1層分をシフト
  oy = (float)origin[1]*RefL - dy;
  oz = (float)origin[2]*RefL - dz;
  
  float *q = new float[nx];
  
  #pragma omp parallel for firstprivate(imax, jmax, kmax, ix, jx, gd) schedule(static)
  for (int k=0; k<=(kmax+1); k++) {
    for (int j=0; j<=(jmax+1); j++) {
      for (int i=0; i<=(imax+1); i++) {
        size_t l = (size_t)(ix*jx*k + ix*j + i);
        size_t m = _F_IDX_S3D(i, j, k, imax, jmax, kmax, gd);
        q[l] = (float)DECODE_CMP(bcd[m]);
      }
    }
  }
  
  // data property
  int dType  = 1; // float
  int svType = 1; // scalar
  int pad = sizeof(int)*2;
  ofs.write( (char*)&pad, sizeof(int) );
  ofs.write( (char*)&svType, sizeof(int) );
  ofs.write( (char*)&dType,  sizeof(int) );
  ofs.write( (char*)&pad, sizeof(int) );
  
  // voxel size
  pad = sizeof(int)*3;
  ofs.write( (char*)&pad, sizeof(int) );
  ofs.write( (char*)&ix, sizeof(int) );
  ofs.write( (char*)&jx, sizeof(int) );
  ofs.write( (char*)&kx, sizeof(int) );
  ofs.write( (char*)&pad, sizeof(int) );
  
  // original point of domain
  pad = sizeof(float)*3;
  ofs.write( (char*)&pad, sizeof(int) );
  ofs.write( (char*)&ox, sizeof(float) );
  ofs.write( (char*)&oy, sizeof(float) );
  ofs.write( (char*)&oz, sizeof(float) );
  ofs.write( (char*)&pad, sizeof(int) );
  
  // pitch of voxel
  ofs.write( (char*)&pad, sizeof(int) );
  ofs.write( (char*)&dx, sizeof(float) );
  ofs.write( (char*)&dy, sizeof(float) );
  ofs.write( (char*)&dz, sizeof(float) );
  ofs.write( (char*)&pad, sizeof(int) );
  
  // time stamp
  int stp = 0;
  float tm = 0.0;
  pad = sizeof(int)+sizeof(float);
  ofs.write( (char*)&pad, sizeof(int) );
  ofs.write( (char*)&stp, sizeof(int) );
  ofs.write( (char*)&tm, sizeof(float) );
  ofs.write( (char*)&pad, sizeof(int) );
  
  // medium ID
  pad = nx * sizeof(float);
  ofs.write( (char*)&pad, sizeof(int) );
  ofs.write( (char*)q,   pad );
  ofs.write( (char*)&pad, sizeof(int) );
  
  ofs.close();
  
  if (q) { delete [] q; q=NULL; }
}
Exemplo n.º 4
0
// #################################################################
// 例題のモデルをsvxフォーマットで出力する(ID)
bool IO_BASE::writeSVX(const int* array, const bool flag)
{
  //if ( IO_Voxel != voxel_SVX ) return false;
  
  int   sz, ix, jx, kx;
  size_t m, l;
  float ox, oy, oz, dx, dy, dz;
  
  char svx_fname[512];
  
  if ( paraMngr->IsParallel() ) {
    sprintf( svx_fname, "example_%06d.svx", paraMngr->GetMyRankID(procGrp) );
  } else {
    sprintf( svx_fname, "example.svx" );
  }
  ofstream ofs(svx_fname, ios::out | ios::binary);
  if (!ofs) {
    cout << "\tCan't open " << svx_fname << " file" << endl;
    Exit(0);
  }
  
  int imax = size[0];
  int jmax = size[1];
  int kmax = size[2];
  int gd = guide;
  
  ix = imax+2;  // +2 means guide cell for IP model
  jx = jmax+2;
  kx = kmax+2;
  
  size_t nx = (size_t)(ix*jx*kx);
  
  dx = (float)pitch[0]*C->RefLength;
  dy = (float)pitch[1]*C->RefLength;
  dz = (float)pitch[2]*C->RefLength;
  ox = (float)origin[0]*C->RefLength - dx; // 片側1層分をシフト
  oy = (float)origin[1]*C->RefLength - dy;
  oz = (float)origin[2]*C->RefLength - dz;
  
  //stamped_printf("example out org(%e %e %e) dimensional\n", ox, oy, oz);
  
  int   *q = new int[nx];
  
  if ( !flag ) // d_bcd
  {
#pragma omp parallel for firstprivate(imax, jmax, kmax, gd, ix, jx) schedule(static)
    for (int k=0; k<=(kmax+1); k++) {
      for (int j=0; j<=(jmax+1); j++) {
        for (int i=0; i<=(imax+1); i++) {
          size_t l = (size_t)(ix*jx*k + ix*j + i);
          size_t m = _F_IDX_S3D(i, j, k, imax, jmax, kmax, gd);
          q[l] = DECODE_CMP(array[m]);
        }
      }
    }
  }
  else // d_mid
  {
#pragma omp parallel for firstprivate(imax, jmax, kmax, gd, ix, jx) schedule(static)
    for (int k=0; k<=(kmax+1); k++) {
      for (int j=0; j<=(jmax+1); j++) {
        for (int i=0; i<=(imax+1); i++) {
          size_t l = (size_t)(ix*jx*k + ix*j + i);
          size_t m = _F_IDX_S3D(i, j, k, imax, jmax, kmax, gd);
          q[l] = array[m];
        }
      }
    }
  }
  

  
  // voxel size
  sz = sizeof(int)*3;
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)&ix, sizeof(int) );
  ofs.write( (char*)&jx, sizeof(int) );
  ofs.write( (char*)&kx, sizeof(int) );
  ofs.write( (char*)&sz, sizeof(int) );
  
  // original point of domain
  sz = sizeof(float)*3;
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)&ox, sizeof(float) );
  ofs.write( (char*)&oy, sizeof(float) );
  ofs.write( (char*)&oz, sizeof(float) );
  ofs.write( (char*)&sz, sizeof(int) );
  
  // pitch of voxel
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)&dx, sizeof(float) );
  ofs.write( (char*)&dy, sizeof(float) );
  ofs.write( (char*)&dz, sizeof(float) );
  ofs.write( (char*)&sz, sizeof(int) );
  
  // type of stored data
  sz = sizeof(int)*1;
  int dtype = 0;
  dtype |= ( 0x1<<2 );  // medium ID
  ofs.write( (char*)&sz,  sizeof(int) );
  ofs.write( (char*)&dtype, sizeof(int) );
  ofs.write( (char*)&sz,  sizeof(int) );
  
  // medium ID
  sz = nx * sizeof(int);
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)q,   sz );
  ofs.write( (char*)&sz, sizeof(int) );
  
  ofs.close();
  
  if (q) { delete [] q; q=NULL; }
  
  return true;
}
Exemplo n.º 5
0
// #################################################################
// 例題のモデルをsvxフォーマットで出力する(ID)
void Intrinsic::writeSVX(const int* bcd, Control* R)
{
  
  int   sz, ix, jx, kx;
  size_t m, l;
  float ox, oy, oz, dx, dy, dz;
  
  char svx_fname[512];
  
  if ( paraMngr->IsParallel() ) {
    sprintf( svx_fname, "example_%06d.svx", paraMngr->GetMyRankID(procGrp) );
  } else {
    sprintf( svx_fname, "example.svx" );
  }
  ofstream ofs(svx_fname, ios::out | ios::binary);
  if (!ofs) {
    cout << "\tCan't open " << svx_fname << " file" << endl;
    Exit(0);
  }
  
  int imax = size[0];
  int jmax = size[1];
  int kmax = size[2];
  int gd = guide;
  
  ix = imax+2;  // +2 means guide cell for IP model
  jx = jmax+2;
  kx = kmax+2;
  
  size_t nx = (size_t)(ix*jx*kx);
  
  dx = (float)pitch[0]*RefL;
  dy = (float)pitch[1]*RefL;
  dz = (float)pitch[2]*RefL;
  ox = (float)origin[0]*RefL - dx; // 片側1層分をシフト
  oy = (float)origin[1]*RefL - dy;
  oz = (float)origin[2]*RefL - dz;
  
  //stamped_printf("example out org(%e %e %e) dimensional\n", ox, oy, oz);
  
  int   *q = new int[nx];
  
  for (int k=0; k<=(kmax+1); k++) {
    for (int j=0; j<=(jmax+1); j++) {
      for (int i=0; i<=(imax+1); i++) {
        l = (size_t)(ix*jx*k + ix*j + i);
        m = _F_IDX_S3D(i, j, k, imax, jmax, kmax, gd);
        q[l] = DECODE_CMP(bcd[m]);
      }
    }
  }
  
  // voxel size
  sz = sizeof(int)*3;
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)&ix, sizeof(int) );
  ofs.write( (char*)&jx, sizeof(int) );
  ofs.write( (char*)&kx, sizeof(int) );
  ofs.write( (char*)&sz, sizeof(int) );
  
  // original point of domain
  sz = sizeof(float)*3;
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)&ox, sizeof(float) );
  ofs.write( (char*)&oy, sizeof(float) );
  ofs.write( (char*)&oz, sizeof(float) );
  ofs.write( (char*)&sz, sizeof(int) );
  
  // pitch of voxel
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)&dx, sizeof(float) );
  ofs.write( (char*)&dy, sizeof(float) );
  ofs.write( (char*)&dz, sizeof(float) );
  ofs.write( (char*)&sz, sizeof(int) );
  
  // type of stored data
  sz = sizeof(int)*1;
  int dtype = 0;
  dtype |= ( 0x1<<2 );  // medium ID
  ofs.write( (char*)&sz,  sizeof(int) );
  ofs.write( (char*)&dtype, sizeof(int) );
  ofs.write( (char*)&sz,  sizeof(int) );
  
  // medium ID
  sz = nx * sizeof(int);
  ofs.write( (char*)&sz, sizeof(int) );
  ofs.write( (char*)q,   sz );
  ofs.write( (char*)&sz, sizeof(int) );
  
  ofs.close();
  
  if (q) { delete [] q; q=NULL; }
}