int main(int argc, char** argv) { MPI::Init(argc, argv); MPI::Comm& comm = MPI::COMM_WORLD; int myrank = comm.Get_rank(); Config conf; if (myrank == 0) { if (argc != 2) { std::cout << "usage: " << argv[0] << " configfile" << std::endl; comm.Abort(EX_USAGE); } std::cout << "# of MPI processes = " << comm.Get_size() << std::endl; #ifdef _OPENMP std::cout << "# of OpenMP threads = " << omp_get_max_threads() << std::endl; #endif std::cout << std::endl << "Configuration file: " << argv[1] << std::endl; } conf.load(argv[1]); if (myrank == 0) conf.print(); RootGrid* rootGrid = new RootGrid(1, 1, 1); Divider* divider; if (conf.treeType == "flat") { divider = new FlatDivider(rootGrid, conf.maxLevel); } else if (conf.treeType == "simple") { divider = new SimpleDivider(rootGrid, conf.minLevel, conf.maxLevel); } else { exit(EX_READ_CONFIG); } BCMOctree::Ordering ordering; if (conf.ordering == "Z") { ordering = BCMOctree::Z; } else if (conf.ordering == "Hilbert") { ordering = BCMOctree::HILBERT; } else if (conf.ordering == "random") { ordering = BCMOctree::RANDOM; } else { exit(EX_READ_CONFIG); } BCMOctree* tree = new BCMOctree(rootGrid, divider, ordering); int numLeafNode = tree->getNumLeafNode(); std::vector<Node*>& leafNodeArray = tree->getLeafNodeArray(); Partition* partition = new Partition(comm.Get_size(), numLeafNode); if (myrank == 0) { std::cout << std::endl << "Partitioning" << std::endl; partition->print(); } // ブロック内のセル数 Vec3i size(conf.size, conf.size, conf.size); BoundaryConditionSetter* boundaryConditionSetter = new BoundaryConditionSetter(&conf); BlockFactory* blockFactory = new BlockFactory(tree, partition, boundaryConditionSetter, size); BlockManager& blockManager = BlockManager::getInstance(); for (int id = partition->getStart(myrank); id < partition->getEnd(myrank); id++) { Node* node = leafNodeArray[id]; Block* block = blockFactory->makeBlock(node); blockManager.registerBlock(block); } blockManager.endRegisterBlock(); blockManager.printBlockLayoutInfo(); delete tree; delete partition; delete boundaryConditionSetter; std::vector<double> boundaryValue(1); boundaryValue[0] = 0.0; Solver solver(conf, boundaryValue); Timing::start(INIT); solver.initialize(); Timing::stop(INIT); Timing::start(RUN); solver.run(); Timing::stop(RUN); solver.checkResult(conf.verbose); if (myrank == 0) { std::cout << std::endl << "Timings" << std::endl; Timing::print(INIT, " Solver::initialize "); Timing::print(RUN, " Solver::run "); #ifdef TIMING Timing::print(SOR, " SOR in block "); Timing::print(VCUPDATE, " VCUpdate + BC "); Timing::print(BC, " BC "); #endif } MPI::Finalize(); return EX_SUCCESS; }
void RBEC::stepForward() { int i, j, k, l; int n_dof = fem_space.n_dof(); int n_total_dof = 2 * n_dof; mat_RBEC.reinit(sp_RBEC); mat_rere.reinit(sp_rere); mat_reim.reinit(sp_reim); mat_imre.reinit(sp_imre); mat_imim.reinit(sp_imim); Vector<double> phi(n_total_dof); FEMFunction <double, DIM> phi_star(fem_space); Vector<double> rhs(n_total_dof); Potential V(gamma_x, gamma_y); /// 准备一个遍历全部单元的迭代器. FEMSpace<double, DIM>::ElementIterator the_element = fem_space.beginElement(); FEMSpace<double, DIM>::ElementIterator end_element = fem_space.endElement(); /// 循环遍历全部单元, 只是为了统计每一行的非零元个数. for (; the_element != end_element; ++the_element) { /// 当前单元信息. double volume = the_element->templateElement().volume(); const QuadratureInfo<DIM>& quad_info = the_element->findQuadratureInfo(6); std::vector<double> jacobian = the_element->local_to_global_jacobian(quad_info.quadraturePoint()); int n_quadrature_point = quad_info.n_quadraturePoint(); std::vector<AFEPack::Point<DIM> > q_point = the_element->local_to_global(quad_info.quadraturePoint()); /// 单元信息. std::vector<std::vector<std::vector<double> > > basis_gradient = the_element->basis_function_gradient(q_point); std::vector<std::vector<double> > basis_value = the_element->basis_function_value(q_point); std::vector<double> phi_re_value = phi_re.value(q_point, *the_element); std::vector<double> phi_im_value = phi_im.value(q_point, *the_element); const std::vector<int>& element_dof = the_element->dof(); int n_element_dof = the_element->n_dof(); /// 实际拼装. for (l = 0; l < n_quadrature_point; ++l) { double Jxw = quad_info.weight(l) * jacobian[l] * volume; for (j = 0; j < n_element_dof; ++j) { for (k = 0; k < n_element_dof; ++k) { double cont = Jxw * ((1 / dt) * basis_value[j][l] * basis_value[k][l] + 0.5 * innerProduct(basis_gradient[j][l], basis_gradient[k][l]) + V.value(q_point[l]) * basis_value[j][l] * basis_value[k][l] + beta * (phi_re_value[l] * phi_re_value[l] + phi_im_value[l] * phi_im_value[l]) * basis_value[j][l] * basis_value[k][l]); mat_RBEC.add(element_dof[j], element_dof[k], cont); mat_RBEC.add(element_dof[j] + n_dof, element_dof[k] + n_dof, cont); } rhs(element_dof[j]) += Jxw * phi_re_value[l] * basis_value[j][l] / dt; rhs(element_dof[j] + n_dof) += Jxw * phi_im_value[l] * basis_value[j][l] / dt; } } } FEMFunction<double, DIM> _phi_re(phi_re); FEMFunction<double, DIM> _phi_im(phi_im); boundaryValue(phi, rhs, mat_RBEC); // AMGSolver solver(mat_RBEC); // solver.solve(phi, rhs); dealii::SolverControl solver_control(4000, 1e-15); SolverGMRES<Vector<double> >::AdditionalData para(500, false, true); SolverGMRES<Vector<double> > gmres(solver_control, para); gmres.solve(mat_RBEC, phi, rhs, PreconditionIdentity()); for (int i = 0; i < n_dof; ++i) { phi_re(i) = phi(i); phi_im(i) = phi(n_dof + i); } for (int i = 0; i < n_dof; ++i) phi_star(i) = sqrt(phi_re(i) * phi_re(i) + phi_im(i) * phi_im(i)); double L2Phi = Functional::L2Norm(phi_re, 6); std::cout << "L2 norm = " << L2Phi << std::endl; for (int i = 0; i < n_dof; ++i) { phi_re(i) /= L2Phi; phi_im(i) /= L2Phi; } double e = energy(phi_re, phi_im, 6); std::cout << "Energy = " << e << std::endl; t += dt; };