// Compute // void compute(const Options& option){ // MPI // int nProcs; int myProc; MPIOStream cout(0, std::cout); MPI_Comm_size(MPI_COMM_WORLD,&nProcs); MPI_Comm_rank(MPI_COMM_WORLD,&myProc); // Get parameters // // Wavenumber double f = atof(option.getValue("-f")[1].c_str()); Omega0 = 2 * Pi * f; double k = Omega0 / C0; // FEM orders const int orderVol = atoi(option.getValue("-ov")[1].c_str()); const int orderSur = atoi(option.getValue("-ob")[1].c_str()); // OSRC double ck = 0; int NPade = 4; Complex keps = k + Complex(0, k * ck); // Get Domains // cout << "Reading domain... " << endl << flush; Mesh msh(option.getValue("-msh")[1]); GroupOfElement air(msh.getFromPhysical(1007, myProc + 1)); GroupOfElement rod(msh.getFromPhysical(1008, myProc + 1)); GroupOfElement src(msh.getFromPhysical(1009, myProc + 1)); GroupOfElement infinity(msh.getFromPhysical(1010, myProc + 1)); GroupOfElement ddmBoundary(msh.getFromPhysical(40000 + myProc + 1)); // Full domain vector<const GroupOfElement*> domain(5); domain[0] = &air; domain[1] = &rod; domain[2] = &src; domain[3] = &infinity; domain[4] = &ddmBoundary; // Dirichlet boundary container vector<const GroupOfElement*> dirichlet(1); dirichlet[0] = &src; // DDM boundary container vector<const GroupOfElement*> ddmBoundaryDomain(1); ddmBoundaryDomain[0] = &ddmBoundary; // Function space // FunctionSpaceVector fs( domain, orderVol); FunctionSpaceVector fG(ddmBoundaryDomain, orderSur); vector<const FunctionSpaceVector*> OsrcPhi(NPade, NULL); vector<const FunctionSpaceScalar*> OsrcRho(NPade, NULL); FunctionSpaceVector OsrcR(ddmBoundaryDomain, orderVol); for(int j = 0; j < NPade; j++){ OsrcPhi[j] = new FunctionSpaceVector(ddmBoundaryDomain, orderVol); if(orderVol == 0) OsrcRho[j] = new FunctionSpaceScalar(ddmBoundaryDomain, 1); else OsrcRho[j] = new FunctionSpaceScalar(ddmBoundaryDomain, orderVol); } // Formulations // cout << "FEM terms... " << endl << flush; // Waves FormulationSteadyWave<Complex> waveAir(air, fs, k); FormulationSteadyWave<Complex> waveRod(rod, fs, k, nuRRod, epsRRod, sVol); FormulationSilverMuller radiation(infinity, fs, k); // Ddm context map<Dof, Complex> ddmG; map<Dof, Complex> rhsG; FormulationHelper::initDofMap(fG, ddmBoundary, ddmG); FormulationHelper::initDofMap(fG, ddmBoundary, rhsG); DDMContextOSRCVector context(ddmBoundary, dirichlet, fs, fG, OsrcPhi, OsrcRho, OsrcR, k, keps, NPade, Pi / 2); context.setDDMDofs(ddmG); // Ddm FormulationOSRCVector ddm(context); FormulationUpdateOSRCVector upDdm(context); // Dummy FormulationDummy<Complex> dummy; // Container FormulationContainer<Complex> allFem; allFem.addFormulation(waveAir); allFem.addFormulation(waveRod); allFem.addFormulation(radiation); // Solve non-homogenous problem // cout << "Solving non homogenous problem" << endl << flush; System<Complex>* nonHomogenous = new System<Complex>; nonHomogenous->addFormulation(allFem); nonHomogenous->addFormulation(ddm); SystemHelper<Complex>::dirichlet(*nonHomogenous, fs, src, fSrc); nonHomogenous->assemble(); nonHomogenous->solve(); // Solve non-homogenous DDM problem // cout << "Computing right hand side" << endl << flush; context.setSystem(*nonHomogenous); upDdm.update(); // update volume solution (at DDM border) System<Complex>* nonHomogenousDDM = new System<Complex>; nonHomogenousDDM->addFormulation(upDdm); nonHomogenousDDM->assemble(); nonHomogenousDDM->solve(); nonHomogenousDDM->getSolution(rhsG, 0); // Clear Systems // delete nonHomogenous; delete nonHomogenousDDM; // DDM Solver // cout << "Solving DDM problem" << endl << flush; SolverDDM* solver = new SolverDDM(allFem, dummy, context, ddm, upDdm, rhsG); // Solve int maxIt = 1000; solver->setMaximumIteration(maxIt); solver->setRestart(maxIt); // No restart! cout << " ! Warning: no restart ! " << endl; solver->solve(); // Get Solution solver->getSolution(ddmG); context.setDDMDofs(ddmG); // Clear DDM delete solver; // Full Problem // cout << "Solving full problem" << endl << flush; ddm.update(); System<Complex> full; full.addFormulation(allFem); full.addFormulation(ddm); SystemHelper<Complex>::dirichlet(full, fs, src, fSrc); full.assemble(); full.solve(); // Draw Solution // try{ option.getValue("-nopos"); } catch(...){ cout << "Writing full problem" << endl << flush; FEMSolution<Complex> feSol; full.getSolution(feSol, fs, domain); feSol.setSaveMesh(false); feSol.setBinaryFormat(true); feSol.setParition(myProc + 1); feSol.write("boubouchon"); } // Give peak virtual memory // double myVmPeak = getPeakMemory(); double* alVmPeak = new double[nProcs]; MPI_Allgather(&myVmPeak,1,MPI_DOUBLE, alVmPeak,1,MPI_DOUBLE, MPI_COMM_WORLD); cout << "Peak VM:" << endl << flush; for(int i = 0; i < nProcs; i++) cout << " ** Process " << i << ": " << alVmPeak[i] << " MB" << endl << flush; // Give max peak VMem accross all processes // int maxIdx = 0; for(int i = 1; i < nProcs; i++) if(alVmPeak[maxIdx] < alVmPeak[i]) maxIdx = i; cout << "Maximum Peak VM accross MPI processes:" << endl << " ** Process " << maxIdx << ": " << alVmPeak[maxIdx] << " MB" << endl << flush; // Give systems sizes // int mySize = full.getSize(); int* alSize = new int[nProcs]; MPI_Allgather(&mySize, 1, MPI_INT, alSize, 1, MPI_INT, MPI_COMM_WORLD); cout << "Volume system size:" << endl << flush; for(int i = 0; i < nProcs; i++) cout << " ** Process " << i << ": " << alSize[i] << " unknowns" << endl << flush; // Clear // for(int j = 0; j < NPade; j++){ delete OsrcPhi[j]; delete OsrcRho[j]; } delete[] alVmPeak; delete[] alSize; }
void compute(const Options& option){ // MPI std::cout // MPIOStream cout(0, std::cout); int myProc; int nProcs; MPI_Comm_rank(MPI_COMM_WORLD, &myProc); MPI_Comm_size(MPI_COMM_WORLD, &nProcs); // Get PML Data // cout << "Reading PML... " << endl << flush; PML::read(option.getValue("-pml")[1]); // Get Domains // cout << "Reading domain... " << endl << flush; Mesh msh(option.getValue("-msh")[1]); GroupOfElement* Air; GroupOfElement* PMLx; GroupOfElement* PMLxy; GroupOfElement* PMLy; GroupOfElement* Mirror; GroupOfElement* Frame; GroupOfElement* LineOY; GroupOfElement* OutPML; if(nProcs != 1){ Air = new GroupOfElement(msh.getFromPhysical(4000, myProc + 1)); PMLx = new GroupOfElement(msh.getFromPhysical(1000, myProc + 1)); PMLxy = new GroupOfElement(msh.getFromPhysical(2000, myProc + 1)); PMLy = new GroupOfElement(msh.getFromPhysical(3000, myProc + 1)); Mirror = new GroupOfElement(msh.getFromPhysical( 103, myProc + 1)); Frame = new GroupOfElement(msh.getFromPhysical( 105, myProc + 1)); LineOY = new GroupOfElement(msh.getFromPhysical( 101, myProc + 1)); OutPML = new GroupOfElement(msh.getFromPhysical( 104, myProc + 1)); } else{ Air = new GroupOfElement(msh.getFromPhysical(4000)); PMLx = new GroupOfElement(msh.getFromPhysical(1000)); PMLxy = new GroupOfElement(msh.getFromPhysical(2000)); PMLy = new GroupOfElement(msh.getFromPhysical(3000)); Mirror = new GroupOfElement(msh.getFromPhysical( 103)); Frame = new GroupOfElement(msh.getFromPhysical( 105)); LineOY = new GroupOfElement(msh.getFromPhysical( 101)); OutPML = new GroupOfElement(msh.getFromPhysical( 104)); } // Full Domain vector<const GroupOfElement*> All_domains(8); All_domains[0] = Air; All_domains[1] = PMLx; All_domains[2] = PMLxy; All_domains[3] = PMLy; All_domains[4] = Mirror; All_domains[5] = Frame; All_domains[6] = LineOY; All_domains[7] = OutPML; // FunctionSpace // cout << "FunctionSpace... " << endl << flush; const size_t order = atoi(option.getValue("-o")[1].c_str()); FunctionSpaceVector fs(All_domains, order); // Formulations // // Volume cout << "Formulations... " << endl << flush; Formulation<Complex>* stifAir; Formulation<Complex>* stifXY; Formulation<Complex>* stifX; Formulation<Complex>* stifY; Formulation<Complex>* massAir; Formulation<Complex>* massXY; Formulation<Complex>* massX; Formulation<Complex>* massY; /* stifAir = new FStif(*Air, fs, fs, Material::Air::Nu); stifXY = new FStif(*PMLxy, fs, fs, Material::XY::Nu); stifX = new FStif(*PMLx, fs, fs, Material::X::Nu); stifY = new FStif(*PMLy, fs, fs, Material::Y::Nu); massAir = new FMass(*Air, fs, fs, Material::Air::Epsilon); massXY = new FMass(*PMLxy, fs, fs, Material::XY::Epsilon); massX = new FMass(*PMLx, fs, fs, Material::X::Epsilon); massY = new FMass(*PMLy, fs, fs, Material::Y::Epsilon); */ stifAir = new FStif(*Air, fs, fs,Material::Air::OverMuEps); stifXY = new FStif(*PMLxy, fs, fs, Material::XY::OverMuEps); stifX = new FStif(*PMLx, fs, fs, Material::X::OverMuEps); stifY = new FStif(*PMLy, fs, fs, Material::Y::OverMuEps); massAir = new FMass(*Air, fs, fs); massXY = new FMass(*PMLxy, fs, fs); massX = new FMass(*PMLx, fs, fs); massY = new FMass(*PMLy, fs, fs); // Impedance boundary condition Formulation<Complex>* impedance = new FMass(*Frame, fs, fs, fImpedance); // System // cout << "System... " << endl << flush; SystemEigen sys; sys.addFormulation(*stifAir); sys.addFormulation(*stifXY); sys.addFormulation(*stifX); sys.addFormulation(*stifY); sys.addFormulationB(*massAir); sys.addFormulationB(*massXY); sys.addFormulationB(*massX); sys.addFormulationB(*massY); sys.addFormulationB(*impedance); // Dirichlet // cout << "Dirichlet... " << endl << flush; SystemHelper<Complex>::dirichlet(sys, fs, *Mirror, fZero); //SystemHelper<Complex>::dirichlet(sys, fs, *Frame , fZero); SystemHelper<Complex>::dirichlet(sys, fs, *LineOY, fZero); SystemHelper<Complex>::dirichlet(sys, fs, *OutPML, fZero); // Assemble // cout << "True assembling... " << endl << flush; sys.assemble(); // Free formulations // delete stifAir; delete stifXY; delete stifX; delete stifY; delete massAir; delete massXY; delete massX; delete massY; delete impedance; // Solve // // Set number of eigenvalue (if any, else default) try{ sys.setNumberOfEigenValues(atoi(option.getValue("-n")[1].c_str())); } catch(...){ } // Set shift (if any, else default) try{ const double shift = atof(option.getValue("-shift")[1].c_str()); sys.setWhichEigenpairs("target_magnitude"); sys.setTarget(Complex(shift, 0)); } catch(...){ } // Set tolerance (if any, else default) try{ sys.setTolerance(atof(option.getValue("-tol")[1].c_str())); } catch(...){ } // Set maximun iteration number (if any, else default) try{ sys.setMaxIteration(atoi(option.getValue("-maxit")[1].c_str())); } catch(...){ } // Do what you have to do ! //sys.setProblem("pos_gen_non_hermitian"); sys.setProblem("gen_non_hermitian"); cout << "Solving: " << sys.getSize() << "..." << endl << flush; sys.solve(); // Post-Pro // if(myProc == 0){ // Display cout << "Post Pro" << endl << flush; const size_t nEigenValue = sys.getNComputedSolution(); fullVector<Complex> eigenValue; sys.getEigenValues(eigenValue); cout << "Number of found Eigenvalues: " << nEigenValue << endl << endl << "Number\tEigen Value" << endl; for(size_t i = 0; i < nEigenValue; i++) cout << "#" << i + 1 << "\t" << std::scientific << eigenValue(i) << endl; // Dump on disk dump("harocheValues.txt", eigenValue); } // Draw try{ option.getValue("-nopos"); } catch(...){ FEMSolution<Complex> feSol; sys.getSolution(feSol, fs, All_domains); //feSol.setSaveMesh(false); feSol.setBinaryFormat(true); if(nProcs != 1) feSol.setParition(myProc + 1); feSol.write("harocheModes"); } // Game over! // delete Air; delete PMLx; delete PMLxy; delete PMLy; delete Mirror; delete Frame; delete LineOY; delete OutPML; // Give peak virtual memory // cout << "Process " << myProc << " peak VM: " << getPeakMemory() << endl; }