Esempio n. 1
0
/**
 * Execute application
 * @param argc number of arguments
 * @param argv list of character strings
 */
void gridpack::hello_world::HWApp::execute(int argc, char** argv)
{
  // load input file
  gridpack::parallel::Communicator world;
  boost::shared_ptr<HWNetwork> network(new HWNetwork(world));

  // read configuration file
  std::string filename = "10x10.raw";

  // Read in external PTI file with network configuration
  gridpack::parser::PTI23_parser<HWNetwork> parser(network);
  parser.parse(filename.c_str());

  // partition network
  network->partition();

  // create factory
  gridpack::hello_world::HWFactory factory(network);
  factory.load();

  // Create serial IO object to export data from buses
  gridpack::serial_io::SerialBusIO<HWNetwork> busIO(128,network);
  busIO.header("\nMessage from buses\n");
  busIO.write();


  // Create serial IO object to export data from branches
  gridpack::serial_io::SerialBranchIO<HWNetwork> branchIO(128,network);
  branchIO.header("\nMessage from branches\n");
  branchIO.write();
}
Esempio n. 2
0
/**
 * Execute application
 */
void gridpack::dynamic_simulation::DSApp::execute(int argc, char** argv)
{
  gridpack::utility::CoarseTimer *timer =
    gridpack::utility::CoarseTimer::instance();
  int t_total = timer->createCategory("Total Application");
  timer->start(t_total);
  gridpack::parallel::Communicator world;
  boost::shared_ptr<DSNetwork> network(new DSNetwork(world));

  int t_setup = timer->createCategory("Read in Data");
  timer->start(t_setup);
  // read configuration file
  gridpack::utility::Configuration *config = gridpack::utility::Configuration::configuration();
  if (argc >= 2 && argv[1] != NULL) {
    char inputfile[256];
    sprintf(inputfile,"%s",argv[1]);
    config->open(inputfile,world);
  } else {
    config->open("input.xml",world);
  }
  gridpack::utility::Configuration::CursorPtr cursor;
  cursor = config->getCursor("Configuration.Dynamic_simulation");
  std::string filename = cursor->get("networkConfiguration",
      "No network configuration specified");
  double sim_time = cursor->get("simulationTime",0.0);
  if (sim_time == 0.0) {
    // TODO: some kind of error
  }
  double time_step = cursor->get("timeStep",0.0);
  if (time_step == 0.0) {
    // TODO: some kind of error
  }

  // Read in information about fault events and store them in internal data
  // structure
  cursor = config->getCursor("Configuration.Dynamic_simulation.faultEvents");
  gridpack::utility::Configuration::ChildCursors events;
  if (cursor) cursor->children(events);
  std::vector<gridpack::dynamic_simulation::DSBranch::Event>
     faults = setFaultEvents(events); 

  // load input file
  gridpack::parser::PTI23_parser<DSNetwork> parser(network);
  parser.parse(filename.c_str());
  cursor = config->getCursor("Configuration.Dynamic_simulation");
  filename = cursor->get("generatorParameters","");
  timer->stop(t_setup);

  int t_part = timer->createCategory("Partition Network");
  timer->start(t_part);
  // partition network
  network->partition();
  timer->stop(t_part);
  if (filename.size() > 0) parser.externalParse(filename.c_str());

  // Create serial IO object to export data from buses or branches
  gridpack::serial_io::SerialBusIO<DSNetwork> busIO(2048, network);
  gridpack::serial_io::SerialBranchIO<DSNetwork> branchIO(128, network);
  char ioBuf[128];

  int t_config = timer->createCategory("Configure Network");
  timer->start(t_config);
  // create factory
  gridpack::dynamic_simulation::DSFactory factory(network);
  factory.load();

  // set network components using factory
  factory.setComponents();
  timer->stop(t_config);

  // set YBus components so that you can create Y matrix  
  factory.setYBus();

  if (!factory.checkGen()) {
    busIO.header("Missing generators on at least one processor\n");
    return;
  }

  int t_matset = timer->createCategory("Matrix Setup");
  timer->start(t_matset);
  factory.setMode(YBUS);
  gridpack::mapper::FullMatrixMap<DSNetwork> ybusMap(network);
  timer->stop(t_matset);

  int t_trans = timer->createCategory("Matrix Transpose");
  // Construct matrix Y_a using extracted xd and ra from gen data, 
  // and construct its diagonal matrix diagY_a
  timer->start(t_matset);
  factory.setMode(YA);
  gridpack::mapper::FullMatrixMap<DSNetwork> yaMap(network);
  boost::shared_ptr<gridpack::math::Matrix> diagY_a = yaMap.mapToMatrix();
  ///busIO.header("\n=== diagY_a: ============\n");
  ///diagY_a->print(); 
  // Convert diagY_a from sparse matrix to dense matrix Y_a so that SuperLU_DIST can solve
  gridpack::math::MatrixStorageType denseType = gridpack::math::Dense;
  boost::shared_ptr<gridpack::math::Matrix> Y_a(gridpack::math::storageType(*diagY_a, denseType));
  timer->stop(t_matset);

  // Construct matrix Ymod: Ymod = diagY_a * permTrans
  int t_matmul = timer->createCategory("Matrix Multiply");
  // Form matrix Y_b: Y_b(1:ngen, jg) = -Ymod, where jg represents the 
  // corresponding index sets of buses that the generators are connected to. 
  // Then construct Y_b's transposed matrix Y_c: Y_c = Y_b'
  // This two steps can be done by using a P matrix to get Y_c directly.
  timer->start(t_matset);
  factory.setMode(YC);
  gridpack::mapper::FullMatrixMap<DSNetwork> cMap(network);
  boost::shared_ptr<gridpack::math::Matrix> Y_cDense = cMap.mapToMatrix(true);

  factory.setMode(YB);
  gridpack::mapper::FullMatrixMap<DSNetwork> bMap(network);
  boost::shared_ptr<gridpack::math::Matrix> Y_b = bMap.mapToMatrix();
  timer->stop(t_matset);
  ///busIO.header("\n=== Y_b: ============\n");
  ///Y_b->print();
  
  timer->start(t_matset);
  factory.setMode(updateYbus);
  boost::shared_ptr<gridpack::math::Matrix> prefy11ybus = ybusMap.mapToMatrix();
  timer->stop(t_matset);
  ///branchIO.header("\n=== prefy11ybus: ============\n");
  ///prefy11ybus->print();

  // Solve linear equations of ybus * X = Y_c
  //gridpack::math::LinearSolver solver1(*prefy11ybus);
  //solver1.configure(cursor);
  int t_solve = timer->createCategory("Solve Linear Equation");
  timer->start(t_solve);
  gridpack::math::LinearMatrixSolver solver1(*prefy11ybus);
  boost::shared_ptr<gridpack::math::Matrix> prefy11X(solver1.solve(*Y_cDense));
  timer->stop(t_solve);
  ///branchIO.header("\n=== prefy11X: ============\n");
  ///prefy11X->print(); 
  
  //-----------------------------------------------------------------------
  // Compute prefy11
  //-----------------------------------------------------------------------
  // Form reduced admittance matrix prefy11: prefy11 = Y_b * X
  timer->start(t_matmul);
  boost::shared_ptr<gridpack::math::Matrix> prefy11(multiply(*Y_b, *prefy11X)); 
  timer->stop(t_matmul);
  // Update prefy11: prefy11 = Y_a + prefy11
  prefy11->add(*Y_a);
  ///branchIO.header("\n=== Reduced Ybus: prefy11: ============\n");
  ///prefy11->print();

  //-----------------------------------------------------------------------
  // Compute fy11
  // Update ybus values at fault stage
  //-----------------------------------------------------------------------
  // Read the switch info from faults Event from input.xml
  int sw2_2 = faults[0].from_idx - 1;
  int sw3_2 = faults[0].to_idx - 1;

  boost::shared_ptr<gridpack::math::Matrix> fy11ybus(prefy11ybus->clone());
  ///branchIO.header("\n=== fy11ybus(original): ============\n");
  ///fy11ybus->print();
  gridpack::ComplexType x(0.0, -1e7);
  timer->start(t_matset);
  factory.setEvent(faults[0]);
  factory.setMode(onFY);
  ybusMap.overwriteMatrix(fy11ybus);
  timer->stop(t_matset);
  ///branchIO.header("\n=== fy11ybus: ============\n");
  ///fy11ybus->print();

  // Solve linear equations of fy11ybus * X = Y_c
  timer->start(t_solve);
  gridpack::math::LinearMatrixSolver solver2(*fy11ybus);
  boost::shared_ptr<gridpack::math::Matrix> fy11X(solver2.solve(*Y_cDense)); 
  timer->stop(t_solve);
  ///branchIO.header("\n=== fy11X: ============\n");
  ///fy11X->print();
  
  // Form reduced admittance matrix fy11: fy11 = Y_b * X
  timer->start(t_matmul);
  boost::shared_ptr<gridpack::math::Matrix> fy11(multiply(*Y_b, *fy11X)); 
  timer->stop(t_matmul);
  // Update fy11: fy11 = Y_a + fy11
  fy11->add(*Y_a);
  ///branchIO.header("\n=== Reduced Ybus: fy11: ============\n");
  ///fy11->print();

  //-----------------------------------------------------------------------
  // Compute posfy11
  // Update ybus values at clear fault stage
  //-----------------------------------------------------------------------
  // Get the updating factor for posfy11 stage ybus
  timer->start(t_matset);
  boost::shared_ptr<gridpack::math::Matrix> posfy11ybus(prefy11ybus->clone());
  timer->stop(t_matset);
  ///branchIO.header("\n=== posfy11ybus (original): ============\n");
  ///posfy11ybus->print();
  timer->start(t_matset);
  factory.setMode(posFY);
  ybusMap.incrementMatrix(posfy11ybus);
  timer->stop(t_matset);
  ///branchIO.header("\n=== posfy11ybus: ============\n");
  ///posfy11ybus->print();
    
  // Solve linear equations of posfy11ybus * X = Y_c
  timer->start(t_solve);
  gridpack::math::LinearMatrixSolver solver3(*posfy11ybus);
  boost::shared_ptr<gridpack::math::Matrix> posfy11X(solver3.solve(*Y_cDense)); 
  timer->stop(t_solve);
  ///branchIO.header("\n=== posfy11X: ============\n");
  ///posfy11X->print();
  
  // Form reduced admittance matrix posfy11: posfy11 = Y_b * X
  timer->start(t_matmul);
  boost::shared_ptr<gridpack::math::Matrix> posfy11(multiply(*Y_b, *posfy11X)); 
  timer->stop(t_matmul);
  // Update posfy11: posfy11 = Y_a + posfy11
  posfy11->add(*Y_a);
  ///branchIO.header("\n=== Reduced Ybus: posfy11: ============\n");
  ///posfy11->print();

  //-----------------------------------------------------------------------
  // Integration implementation (Modified Euler Method)
  //-----------------------------------------------------------------------
 
  factory.setDSParams();
  factory.setMode(Eprime0);
  gridpack::mapper::BusVectorMap<DSNetwork> Emap(network);
  boost::shared_ptr<gridpack::math::Vector> eprime_s0 = Emap.mapToVector();
  boost::shared_ptr<gridpack::math::Vector> eprime_s1(eprime_s0->clone());
  boost::shared_ptr<gridpack::math::Vector> curr(eprime_s0->clone());

  timer->start(t_trans);
  boost::shared_ptr<gridpack::math::Matrix> trans_prefy11(transpose(*prefy11));
  boost::shared_ptr<gridpack::math::Matrix> trans_fy11(transpose(*fy11));
  boost::shared_ptr<gridpack::math::Matrix> trans_posfy11(transpose(*posfy11));
  timer->stop(t_trans);

  // Simulation related variables
  int simu_k;
  int t_step[20];
  double t_width[20];
  int flagF;
  int S_Steps;
  int last_S_Steps;
  int steps3, steps2, steps1;
  double h_sol1, h_sol2;
  int flagF1, flagF2;
  int I_Steps;

  const double sysFreq = 60.0;
  double pi = 4.0*atan(1.0);
  const double basrad = 2.0 * pi * sysFreq;
  gridpack::ComplexType jay(0.0, 1.0);

  // switch info is set up here 
  int nswtch = 4;
  static double sw1[4];
  static double sw7[4];
  sw1[0] = 0.0;
  sw1[1] = faults[0].start;
  sw1[2] = faults[0].end;
  sw1[3] = sim_time;
  sw7[0] = time_step;
  sw7[1] = faults[0].step;
  sw7[2] = time_step;
  sw7[3] = time_step;
  simu_k = 0; 
  for (int i = 0; i < nswtch-1; i++) {
    t_step[i] = (int) ((sw1[i+1] -sw1[i]) / sw7[i]);   
    t_width[i] = (sw1[i+1] - sw1[i]) / t_step[i];
    simu_k += t_step[i];
  }
  simu_k++;

  steps3 = t_step[0] + t_step[1] + t_step[2] - 1;
  steps2 = t_step[0] + t_step[1] - 1;
  steps1 = t_step[0] - 1;
  h_sol1 = t_width[0];
  h_sol2 = h_sol1;
  flagF1 = 0; 
  flagF2 = 0; 
  S_Steps = 1; 
  last_S_Steps = -1;

  for (I_Steps = 0; I_Steps < simu_k+1; I_Steps++) {
    if (I_Steps < steps1) {
      S_Steps = I_Steps;
      flagF1 = 0;
      flagF2 = 0;
    } else if (I_Steps == steps1) { 
      S_Steps = I_Steps;
      flagF1 = 0;
      flagF2 = 1;
    } else if (I_Steps == steps1+1) {
      S_Steps = I_Steps;
      flagF1 = 1;
      flagF2 = 1;
    } else if ((I_Steps>steps1+1) && (I_Steps<steps2+1)) {
      S_Steps = I_Steps - 1;
      flagF1 = 1;
      flagF2 = 1;
    } else if (I_Steps==steps2+1) {
      S_Steps = I_Steps - 1;
      flagF1 = 1;
      flagF2 = 2;
    } else if (I_Steps==steps2+2) {
      S_Steps = I_Steps - 1;
      flagF1 = 2;
      flagF2 = 2;
    } else if (I_Steps>steps2+2) {
      S_Steps = I_Steps - 2;
      flagF1 = 2;
      flagF2 = 2;
    }

    if (I_Steps !=0 && last_S_Steps != S_Steps) {
      factory.initDSStep(false);
    } else {
      factory.initDSStep(true);
    }
    factory.setMode(Eprime0);
    Emap.mapToVector(eprime_s0);
     
    // ---------- CALL i_simu_innerloop(k,S_Steps,flagF1): ----------
    int t_trnsmul = timer->createCategory("Transpose Multiply");
    timer->start(t_trnsmul);
    if (flagF1 == 0) {
      curr.reset(multiply(*trans_prefy11, *eprime_s0)); //MatMultTranspose(prefy11, eprime_s0, curr);
      //transposeMultiply(*prefy11,*eprime_s0,*curr);
    } else if (flagF1 == 1) {
      curr.reset(multiply(*trans_fy11, *eprime_s0)); //MatMultTranspose(fy11, eprime_s0, curr);
      //transposeMultiply(*fy11,*eprime_s0,*curr);
    } else if (flagF1 == 2) {
      curr.reset(multiply(*trans_posfy11, *eprime_s0)); //MatMultTranspose(posfy11, eprime_s0, curr);
      //transposeMultiply(*posfy11,*eprime_s0,*curr);
    } 
    timer->stop(t_trnsmul);
    
    factory.setMode(Current);
    Emap.mapToBus(curr);
    factory.predDSStep(h_sol1);
    factory.setMode(Eprime1);
    Emap.mapToVector(eprime_s1);

    // ---------- CALL i_simu_innerloop2(k,S_Steps+1,flagF2): ----------
    timer->start(t_trnsmul);
    if (flagF2 == 0) {
      curr.reset(multiply(*trans_prefy11, *eprime_s1)); //MatMultTranspose(prefy11, eprime_s1, curr);
      //transposeMultiply(*prefy11,*eprime_s1,*curr);
    } else if (flagF2 == 1) {
      curr.reset(multiply(*trans_fy11, *eprime_s1)); //MatMultTranspose(fy11, eprime_s1, curr);
      //transposeMultiply(*fy11,*eprime_s1,*curr);
    } else if (flagF2 == 2) {
      curr.reset(multiply(*trans_posfy11, *eprime_s1)); //MatMultTranspose(posfy11, eprime_s1, curr);
      //transposeMultiply(*posfy11,*eprime_s1,*curr);
    }
    timer->stop(t_trnsmul);

    factory.setMode(Current);
    Emap.mapToBus(curr);
    factory.corrDSStep(h_sol2);

    // Print to screen
    if (last_S_Steps != S_Steps) {
      //sprintf(ioBuf, "\n========================S_Steps = %d=========================\n", S_Steps);
      //busIO.header(ioBuf);
      //mac_ang_s0->print();  
      //mac_spd_s0->print();  
      //pmech->print();
      //pelect->print();
      //sprintf(ioBuf, "========================End of S_Steps = %d=========================\n\n", S_Steps);
      //busIO.header(ioBuf);
    }
    if (I_Steps == simu_k) {
      sprintf(ioBuf, "\n========================S_Steps = %d=========================\n",
          S_Steps+1);
      busIO.header(ioBuf);
      sprintf(ioBuf, "\n         Bus ID     Generator ID"
          "    mac_ang         mac_spd         mech            elect\n\n");
      busIO.header(ioBuf);
      //mac_ang_s1->print();  
      //mac_spd_s1->print();  
      //pmech->print();
      //pelect->print();
      busIO.write();
      sprintf(ioBuf, "\n========================End of S_Steps = %d=========================\n\n",
          S_Steps+1);
      busIO.header(ioBuf);
    } // End of Print to screen 
    
    last_S_Steps = S_Steps;
  }
  timer->stop(t_total);
  timer->dump();
}
Esempio n. 3
0
// -------------------------------------------------------------
// PFApp2::execute
// -------------------------------------------------------------
void
PFApp2::execute(int argc, char** argv)
{
  parallel::Communicator world;
  boost::shared_ptr<PFNetwork> network(new PFNetwork(world));

  // read configuration file
  utility::Configuration *config = 
    utility::Configuration::configuration();
  if (argc >= 2 && argv[1] != NULL) {
    char inputfile[256];
    sprintf(inputfile,"%s",argv[1]);
    config->open(inputfile,world);
  } else {
    config->open("input.xml",world);
  }
  utility::Configuration::CursorPtr cursor;
  cursor = config->getCursor("Configuration.Powerflow");
  std::string filename;
  int filetype = 23;
  if (!cursor->get("networkConfiguration",&filename)) {
    if (!cursor->get("networkConfiguration_v33",&filename)) {
      printf("No network configuration file specified\n");
      return;
    } else {
      filetype = 33;
    }
  }

  // load input file
  utility::CoarseTimer *timer =
    utility::CoarseTimer::instance();
  int t_pti = timer->createCategory("PTI Parser");
  timer->start(t_pti);
  if (filetype == 23) {
    parser::PTI23_parser<PFNetwork> parser(network);
    parser.parse(filename.c_str());
  } else {
    parser::PTI33_parser<PFNetwork> parser(network);
    parser.parse(filename.c_str());
  }
  timer->stop(t_pti);

  // partition network
  int t_part = timer->createCategory("Partition");
  timer->start(t_part);
  network->partition();
  timer->stop(t_part);

  // create factory
  PFFactory factory(network);
  int t_fload = timer->createCategory("Factory Load");
  timer->start(t_fload);
  factory.load();
  timer->stop(t_fload);

  // set network components using factory
  int t_fset = timer->createCategory("Factory Set Components");
  timer->start(t_fset);
  factory.setComponents();
  timer->stop(t_fset);

  // Set up bus data exchange buffers. Need to decide what data needs to be
  // exchanged
  int t_fex = timer->createCategory("Factory Set Exchange");
  timer->start(t_fex);
  factory.setExchange();
  timer->stop(t_fex);

  // Create bus data exchange
  int t_setupdt = timer->createCategory("Set Bus Update");
  timer->start(t_setupdt);
  network->initBusUpdate();
  timer->stop(t_setupdt);

  // set YBus components so that you can create Y matrix
  factory.setYBus();

  // make Sbus components to create S vector
  factory.setSBus();

  // Solve the problem

  bool useNewton(false);
  useNewton = cursor->get("UseNewton", useNewton);

  int t_lsolv = timer->createCategory("Solver");

  timer->start(t_lsolv);

  PFSolverHelper helper(factory, network);
  math::NonlinearSolver::JacobianBuilder jbuildf = boost::ref(helper);
  math::NonlinearSolver::FunctionBuilder fbuildf = boost::ref(helper);

  boost::scoped_ptr<math::NonlinearSolver> solver;
  if (useNewton) {
    math::NewtonRaphsonSolver *tmpsolver = 
      new math::NewtonRaphsonSolver(*(helper.J), jbuildf, fbuildf);
    tmpsolver->tolerance(1.0e-08);
    tmpsolver->maximumIterations(50);
    solver.reset(tmpsolver);
  } else {
    solver.reset(new math::NonlinearSolver(*(helper.J), jbuildf, fbuildf));
  }

  try {
    solver->configure(cursor);
    solver->solve(*helper.X);
    helper.update(*helper.X);
  } catch (const Exception& e) {
    std::cerr << e.what() << std::endl;
  }

  timer->stop(t_lsolv);

  // Report the results

  serial_io::SerialBusIO<PFNetwork> busIO(128,network);
  serial_io::SerialBranchIO<PFNetwork> branchIO(128,network);

  branchIO.header("\n   Branch Power Flow\n");
  branchIO.header("\n        Bus 1       Bus 2            P"
                  "                    Q\n");
  branchIO.write();


  busIO.header("\n   Bus Voltages and Phase Angles\n");
  busIO.header("\n   Bus Number      Phase Angle      Voltage Magnitude\n");
  busIO.write();

  timer->dump();
}
Esempio n. 4
0
void run (const int &me, const int &nprocs)
{
  // Create network
  gridpack::parallel::Communicator world;
  boost::shared_ptr<TestNetwork> network(new TestNetwork(world));

  // Factor processors into a processor grid
  int ipx, ipy, pdx, pdy;
  factor_grid(nprocs, XDIM, YDIM, &pdx, &pdy);
  if (me == 0) {
    printf("\nProcessor configuration is %d X %d\n",pdx,pdy);
  }
  ipx = me%pdx;
  ipy = (me-ipx)/pdx;

  int ixmin, ixmax, iymin, iymax; // bounds of locally owned nodes
  int iaxmin, iaxmax, iaymin, iaymax; // bounds of locally held nodes
  ixmin = static_cast<int>((static_cast<double>(ipx*XDIM))/(static_cast<double>(pdx)));
  ixmax = static_cast<int>((static_cast<double>((ipx+1)*XDIM))/(static_cast<double>(pdx)))-1;
  iymin = static_cast<int>((static_cast<double>(ipy*YDIM))/(static_cast<double>(pdy)));
  iymax = static_cast<int>((static_cast<double>((ipy+1)*YDIM))/(static_cast<double>(pdy)))-1;

  iaxmin = ixmin - 1;
  if (ixmin == 0) iaxmin = 0;
  iaxmax = ixmax + 1;
  if (ixmax == XDIM - 1) iaxmax = XDIM - 1;

  iaymin = iymin - 1;
  if (iymin == 0) iaymin = 0;
  iaymax = iymax + 1;
  if (iymax == YDIM - 1) iaymax = YDIM - 1;

  // Add buses to network
  int ncnt, n, ix, iy, nx, ny, i, j;
  ncnt = 0;
  nx = iaxmax - iaxmin + 1;
  ny = iaymax - iaymin + 1;
  for (j=0; j<ny; j++) {
    iy = j + iaymin;
    for (i=0; i<nx; i++) {
      ix = i + iaxmin;
      n = iy*XDIM + ix;
      n = 2*n;  // Provide original index that is not equal to global index 
      network->addBus(n);
      // Set active flag for network buses
      if (ix >= ixmin && ix <= ixmax && iy >= iymin && iy <= iymax) {
        network->setActiveBus(ncnt, true);
      } else {
        network->setActiveBus(ncnt, false);
      }
      n = n/2;
      network->setGlobalBusIndex(ncnt, n);
      if (ix == 0 && iy == 0) {
        network->setReferenceBus(ncnt);
      }
      ncnt++;
    }
  }

  // Add branches to network. Start with branches connecting buses in the
  // i-direction
  int n1, n2, lx, ly;
  ncnt = 0;
  nx = iaxmax - iaxmin;
  ny = iymax - iymin + 1;
  for (j=0; j<ny; j++) {
    iy = j + iymin;
    for (i=0; i<nx; i++) {
      ix = i + iaxmin;
      n1 = iy*XDIM+ix;
      n1 = 2*n1;
      n2 = iy*XDIM+ix+1;
      n2 = 2*n2;
      network->addBranch(n1, n2);
      n1 = n1/2;
      n2 = n2/2;
      network->setGlobalBusIndex1(ncnt, n1);
      network->setGlobalBusIndex2(ncnt, n2);
      n = iy*(XDIM-1) + ix;
      network->setGlobalBranchIndex(ncnt,n);
      // Figure out local indices of buses
      lx = ix - iaxmin;
      ly = iy - iaymin;
      n1 = ly*(iaxmax-iaxmin+1) + lx;
      n2 = ly*(iaxmax-iaxmin+1) + lx + 1;
      network->setLocalBusIndex1(ncnt,n1);
      network->setLocalBusIndex2(ncnt,n2);
      // Determine which branches are locally held. Use the rule that if bus 1
      // is local, then branch belongs to this processor
      if (ix >= ixmin && ix <= ixmax && iy >= iymin && iy <= iymax) {
        network->setActiveBranch(ncnt, true);
      } else {
        network->setActiveBranch(ncnt, false);
      }
      ncnt++;
    }
  }
  // Add branches connecting buses in the j-direction
  nx = ixmax - ixmin + 1;
  ny = iaymax - iaymin;
  for (j=0; j<ny; j++) {
    iy = j + iaymin;
    for (i=0; i<nx; i++) {
      ix = i + ixmin;
      n1 = iy*XDIM+ix;
      n1 = 2*n1;
      n2 = (iy+1)*XDIM+ix;
      n2 = 2*n2;
      network->addBranch(n1, n2);
      n1 = n1/2;
      n2 = n2/2;
      network->setGlobalBusIndex1(ncnt, n1);
      network->setGlobalBusIndex2(ncnt, n2);
      n = iy*XDIM + ix + (XDIM-1)*YDIM;
      network->setGlobalBranchIndex(ncnt,n);
      // Figure out local indices of buses
      lx = ix - iaxmin;
      ly = iy - iaymin;
      n1 = ly*(iaxmax-iaxmin+1) + lx;
      n2 = (ly+1)*(iaxmax-iaxmin+1) + lx;
      network->setLocalBusIndex1(ncnt,n1);
      network->setLocalBusIndex2(ncnt,n2);
      // Determine which branches are locally held. Use the rule that if bus 1
      // is local, then branch belongs to this processor
      if (ix >= ixmin && ix <= ixmax && iy >= iymin && iy <= iymax) {
        network->setActiveBranch(ncnt, true);
      } else {
        network->setActiveBranch(ncnt, false);
      }
      ncnt++;
    }
  }

  // Set up some remaining properties of network and network components so that
  // matrix-vector interface is ready to go
  gridpack::factory::BaseFactory<TestNetwork> factory(network);
  factory.setComponents();

  // Create serial bus IO object
  gridpack::serial_io::SerialBusIO<TestNetwork> busIO(128,network);
  busIO.header("\n  Bus Properties\n");
  busIO.header("\n       Original   Global\n");
  busIO.write();

  // Create serial branch IO object
  gridpack::serial_io::SerialBranchIO<TestNetwork> branchIO(128,network);
  branchIO.header("\n  Branch Properties\n");
  branchIO.header("\n         Original1  Original2  Global1 Global2\n");
  branchIO.write();
}