Esempio n. 1
0
// 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;
}
Esempio n. 2
0
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;
}