/** * 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(); }
/** * 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(); }
// ------------------------------------------------------------- // 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(); }
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(); }