src/expde/grid/parallel.cc

Go to the documentation of this file.
00001 //    expde: expression templates for partial differential equations.
00002 //    Copyright (C) 2001  Christoph Pflaum
00003 //    This program is free software; you can redistribute it and/or modify
00004 //    it under the terms of the GNU General Public License as published byn 2 of the License, or
00005 //    (at your option) any later version.
00006 //
00007 //    This program is distributed in the hope that it will be useful,
00008 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 //    GNU General Public License for more details.
00011 //
00012 //                 SEE  Notice1.doc made by 
00013 //                 LAWRENCE LIVERMORE NATIONAL LABORATORY
00014 //
00015 
00016 // ------------------------------------------------------------
00017 // parallel.cc
00018 //
00019 // ------------------------------------------------------------
00020 
00021 #define DEBUG false
00022 
00023 // Include level 0:
00024 #ifdef COMP_GNUOLD
00025  #include <iostream.h>
00026  #include <fstream.h>
00027  #include <time.h>
00028  #include <math.h>
00029 #else
00030  #include <iostream>
00031  #include <fstream>
00032  #include <ctime>
00033  #include <cmath>
00034 #endif 
00035 
00036 
00037 // Include level 0:
00038 #include "../parser.h"
00039 
00040 // Include level 1:
00041 #include "../paramete.h"
00042 #include "../abbrevi.h"
00043 #include "../math_lib/math_lib.h"
00044 
00045 // Include level 2:
00046 #include "../basic/basic.h"
00047 
00048 // Include level 3:
00049 #include "../domain/domain.h"
00050 
00051 // Include level 5:
00052 #include "gpar.h"
00053 #include "parallel.h"
00054 
00055 int MY_RANK;
00056 
00057 Parallel_Info::~Parallel_Info() {
00058   for(int d=0;d<26;++d) {
00059     delete buffer_send[d];
00060     delete buffer_receive[d];
00061   }
00062   delete buffer_send_info;
00063   delete buffer_receive_info;
00064 
00065  //Loeschen des hashtables proc:
00066   int i_iter;
00067   Point_hashtable_proc* poi;
00068   for(i_iter=0;i_iter<hashtable_proc_leng;++i_iter) {
00069     poi=hashtable_proc_start[i_iter];
00070     delete poi;
00071   }
00072   delete hashtable_proc_start;
00073 
00074   Point_hashtable_proc_corner* poic;
00075   for(i_iter=0;i_iter<hashtable_proc_corner_leng;++i_iter) {
00076     poic=hashtable_proc_corner_start[i_iter];
00077     delete poic;
00078   }
00079   delete hashtable_proc_corner_start;
00080 }
00081 
00082 Parallel_Info::Parallel_Info(All_Domains* dom, MPI_Comm com) : 
00083   domain(dom), comm(com) {
00084   // -1.Step: refine_level is set in Grid_base::Grid_base
00085   // 0.Step: buffer initialization
00086   for(int d=0;d<26;++d) {
00087     length_send[d]    = 2;
00088     length_receive[d] = 2;
00089     buffer_send[d]    = new double[2];
00090     buffer_receive[d] = new double[2];
00091   }
00092   length_send_info = 2;
00093   length_receive_info = 2;
00094   buffer_send_info    = new int[2];
00095   buffer_receive_info = new int[2];
00096 
00097   // 1.step: MPI infos
00098   MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
00099   MPI_Comm_size(MPI_COMM_WORLD, &p);
00100 
00101   // 2.step: initialize haschtable
00102   Initialize_hash_proc(2*p);
00103   Initialize_hash_proc_corner(2*p);
00104 
00105   MY_RANK=my_rank;
00106 }
00107 
00108 // constructor for testing how many processors are used
00109 // no grid is generated
00110 //------------
00111 Parallel_Info::Parallel_Info(int n_max, All_Domains* dom,
00112                              int pp, Grid_gen_parameters& gpara) : 
00113   domain(dom) {
00114   //-1.Step: things usually done in Grid_base::Grid_base
00115     // for parallel:
00116   refine_level = gpara.Give_r_parallel();
00117 
00118   // calc offset
00119   double offset_square;
00120   double h_offset;
00121   offset_square = gpara.Give_offset_square();
00122   h_offset = offset_square * dom->GiveH() / Zweipotenz(n_max);
00123 
00124   // set bounding_box parameters
00125   A_bounding = dom->GiveA() + D3vector(-h_offset, -h_offset, -h_offset);
00126   H_bounding = dom->GiveH()+2.0*h_offset;
00127   H_bounding = gpara.Give_stretch_square() * H_bounding;
00128   max_level = n_max;
00129 
00130   // move A_bounding if necessary
00131   if(gpara.Is_there_grid_point()) {
00132     make_grid_with_grid_point(gpara.Give_grid_point(),
00133                               H_bounding / Zweipotenz(max_level));
00134   }
00135 
00136   // 0.Step: buffer initialization
00137   for(int d=0;d<26;++d) {
00138     length_send[d]    = 2;
00139     length_receive[d] = 2;
00140     buffer_send[d]    = new double[2];
00141     buffer_receive[d] = new double[2];
00142   }
00143   length_send_info = 2;
00144   length_receive_info = 2;
00145   buffer_send_info    = new int[2];
00146   buffer_receive_info = new int[2];
00147 
00148   // 1.step: MPI infos
00149   my_rank=0;
00150   p = pp;
00151 
00152   // 2.step: initialize haschtable
00153   Initialize_hash_proc(2*p);
00154   Initialize_hash_proc_corner(2*p);
00155 
00156   MY_RANK=my_rank;
00157 
00158   // 3.step: Generate_processes();
00159   Generate_processes();
00160 }
00161 
00162 Parallel_Info::Parallel_Info(double h_finest_level,  All_Domains* dom,
00163                              int pp, Grid_gen_parameters& gpara) : 
00164   domain(dom) {
00165   double h_offset, offset_square;
00166   int i;
00167 
00168   // for parallel:
00169   refine_level = gpara.Give_r_parallel();
00170 
00171   // calc max_level
00172   offset_square = gpara.Give_offset_square();
00173   h_offset = offset_square * h_finest_level;
00174 
00175   A_bounding = dom->GiveA() + D3vector(-h_offset, -h_offset, -h_offset);
00176   H_bounding = dom->GiveH()+2.0*h_offset;
00177   H_bounding = gpara.Give_stretch_square() * H_bounding;
00178 
00179 
00180   if(h_finest_level > H_bounding / 4.0) 
00181     cout << " Coose large meshsize h_finest_level!! " << endl;
00182 
00183   if(gpara.Is_there_grid_point()) {
00184     make_grid_with_grid_point(gpara.Give_grid_point(),h_finest_level);
00185   }
00186 
00187   for(i=2;(i<Max_number_levels) && 
00188         (H_bounding > ((double)(Zweipotenz(i)) * h_finest_level));i++) { };
00189 
00190   max_level = i;
00191   H_bounding = Zweipotenz(max_level) * h_finest_level;
00192 
00193   //-1.Step: things usually done in Grid_base::Grid_base
00194 
00195 
00196   // move A_bounding if necessary
00197   if(gpara.Is_there_grid_point()) {
00198     make_grid_with_grid_point(gpara.Give_grid_point(),
00199                               H_bounding / Zweipotenz(max_level));
00200   }
00201 
00202   // 0.Step: buffer initialization
00203   for(int d=0;d<26;++d) {
00204     length_send[d]    = 2;
00205     length_receive[d] = 2;
00206     buffer_send[d]    = new double[2];
00207     buffer_receive[d] = new double[2];
00208   }
00209   length_send_info = 2;
00210   length_receive_info = 2;
00211   buffer_send_info    = new int[2];
00212   buffer_receive_info = new int[2];
00213 
00214   // 1.step: MPI infos
00215   my_rank=0;
00216   p = pp;
00217 
00218   // 2.step: initialize haschtable
00219   Initialize_hash_proc(2*p);
00220   Initialize_hash_proc_corner(2*p);
00221 
00222   MY_RANK=my_rank;
00223 
00224   // 3.step: Generate_processes();
00225   Generate_processes();
00226 }
00227 
00228 void Parallel_Info::process_info() {
00229   cout << " Information about processes: " << endl;
00230   cout << " Number of processes: " << give_number_of_processes() << endl;
00231   cout << " Number of active processes: " 
00232        << give_number_of_active_processes() << endl;
00233 #ifdef PERIODIC
00234   cout << " Periodic BC in z selected " << endl;
00235 #endif
00236   if(parallel_version == false)  {
00237     cout << " This is the serial version! " << endl;
00238   }
00239 }
00240 
00241 Index3D Parallel_Info::Give_level_index_of(int rang, int level) {
00242   if(level > n_parallel)
00243     level = n_parallel;
00244   iterate_hash_proc {
00245     if(point_proc->num_proc == rang)
00246       if(point_proc->Give_Index().Tiefe()==level)
00247         return point_proc->Give_Index();
00248   }
00249 
00250   // neu periodisch
00251   return Index3D(3,3,3);
00252 }
00253 
00254 /*
00255 int Parallel_Info::Give_coarsest_level_of(int rang, int level) {
00256   iterate_hash_proc {
00257     if(point_proc->num_proc == rang)
00258       if(point_proc->Give_Index().Tiefe()==level)
00259         return point_proc->Give_Index();
00260   }
00261 
00262   // neu periodisch
00263   return Index3D(3,3,3);
00264 }
00265 */
00266 
00267 void Parallel_Info::Generate_processes() {
00268   Partitioning* pointer_parti;
00269   Partitioning* pointer_parti_old;
00270   rough_domain *pointer_rough_domain;
00271   int opt_I,     opt_J,     opt_K,     n_nec,     n_interior;
00272   int opt_I_old, opt_J_old, opt_K_old, n_nec_old, n_interior_old;
00273   int i;
00274 
00275   // 3.step: find minimal value for p_level: p_level_min
00276   // result is: p_level=0,1,2,3,...
00277   for(p_level=0;Zweipotenz(p_level*3)<=p;++p_level) {};
00278   --p_level;
00279 
00280 
00281 
00282   // 4.step: Partitioning
00283   pointer_parti = NULL;
00284   pointer_parti_old = NULL;
00285   for(n_nec=p-1;n_nec<p && p_level<max_level;++p_level) {
00286     // a) construct rough domain
00287     pointer_rough_domain = new rough_domain(p_level,refine_level,domain,
00288                                             A_bounding,H_bounding);
00289     n_interior_old       = n_interior;
00290     n_interior           = pointer_rough_domain->Give_n_interior();
00291 
00292 
00293     // b) save old partitioning and make new one
00294     n_nec_old = n_nec;
00295     opt_I_old = opt_I; opt_J_old = opt_J; opt_K_old = opt_K;
00296     if(pointer_parti_old!=NULL) delete(pointer_parti_old);
00297     pointer_parti_old = pointer_parti;    
00298     pointer_parti = new Partitioning(p_level);
00299     // c) calc number of necessary processes
00300     n_nec =
00301       pointer_rough_domain->Calc_optimal_partitioning(p,opt_I,opt_J,opt_K,
00302                                                       pointer_parti);
00303 
00304     delete(pointer_rough_domain);
00305 
00306     if(DEBUG) {
00307       MPI_Barrier(MPI_COMM_WORLD);
00308       if(my_rank==0) {
00309         
00310         cout << " Iteration: " 
00311              << " p_level: " << p_level
00312              << " max_level: " << max_level
00313              << " n_nec: " << n_nec << endl;
00314         cout << " partitioning: " << endl;
00315         pointer_parti->Print();
00316         
00317       }
00318     MPI_Barrier(MPI_COMM_WORLD);
00319     }
00320 
00321   }
00322   // take actual partitioning
00323   if(n_nec==p) {
00324     if(pointer_parti_old!=NULL) delete(pointer_parti_old);
00325     p_level=p_level-1;
00326   }
00327   // take old partitioning
00328   else {
00329     delete(pointer_parti);
00330     pointer_parti = pointer_parti_old;
00331     n_nec = n_nec_old;
00332     opt_I = opt_I_old; opt_J = opt_J_old; opt_K = opt_K_old;
00333     n_interior = n_interior_old;
00334     p_level=p_level-2;
00335   }
00336   if(MY_RANK==0) if(p_level>=max_level-2)
00337     cout << "\n Choose large value for n_level! \n" << endl;
00338 
00339 
00340   if(n_nec > p)
00341     cout << " Not implemented: Error in Parallel_Info::Generate_processes() "
00342          << endl;
00343 
00344   // 5. step: Set bounding box and ...
00345   n_parallel=p_level+2;
00346 
00347    // periodic
00348   // work
00349   if(domain->Is_periodic()) {
00350   // if(false) {
00351     n_parallel=p_level+1;
00352 
00353   }
00354   else {
00355     n_parallel=p_level+2;
00356 
00357     max_level =  max_level+1;
00358     A_bounding = A_bounding -
00359       H_bounding/(double)n_interior 
00360       * D3vector((double)opt_I,(double)opt_J,(double)opt_K);
00361     H_bounding = H_bounding*2.0;
00362   }
00363 
00364   if(MY_RANK==0) if(n_parallel>max_level-2)
00365     cout << "\n Error : Choose a finer grid or less processors! \n" << endl;
00366 
00367 if(DEBUG) {  
00368     cout << " opt_I " << opt_I << endl;
00369     cout << " opt_J " << opt_J << endl;
00370     cout << " opt_K " << opt_K << endl;
00371 
00372     if(MY_RANK==0) 
00373       cout << "   take p_level: " <<  p_level 
00374            << " max_level:    "   << max_level
00375            << " p_level:      "   << p_level
00376            << " n_parallel:    "  << n_parallel << endl;
00377 }
00378 
00379   if(domain->Is_periodic()) {
00380     // periodic
00381     Ixl = Index1D(0);
00382     Iyl = Index1D(0);
00383     Izl = Index1D(0);
00384 
00385     Ixr = Index1D(1);
00386     Iyr = Index1D(1);
00387     Izr = Index1D(1);
00388   }
00389   else {
00390     Ixl = Index1D(0);
00391     Iyl = Index1D(0);
00392     Izl = Index1D(0);
00393     // Berchnung des tree-index (Index1) aus kartesischen index (opt_I)
00394     for(i=0;i<opt_I;++i) Ixl = Ixl.next(Rd,p_level+refine_level+1);
00395     for(i=0;i<opt_J;++i) Iyl = Iyl.next(Rd,p_level+refine_level+1);
00396     for(i=0;i<opt_K;++i) Izl = Izl.next(Rd,p_level+refine_level+1);
00397     
00398     
00399     Ixr = Ixr.next(Rd,1);
00400     Iyr = Iyr.next(Rd,1);
00401     Izr = Izr.next(Rd,1);
00402     for(i=0;i<opt_I;++i) Ixr = Ixr.next(Rd,p_level+refine_level+1);
00403     for(i=0;i<opt_J;++i) Iyr = Iyr.next(Rd,p_level+refine_level+1);
00404     for(i=0;i<opt_K;++i) Izr = Izr.next(Rd,p_level+refine_level+1);
00405   }
00406 
00407   pxl = Ixl.coordinate();   pyl = Iyl.coordinate();   pzl = Izl.coordinate();
00408   pxr = Ixr.coordinate();   pyr = Iyr.coordinate();   pzr = Izr.coordinate();
00409 
00410   // 6.step: search cells on level max_level_parallel
00411   Index3D ind(2,2,2);
00412 
00413   if(n_parallel==1) {
00414     Add_proc_cell(ind);
00415   }
00416   else {
00417     Recursion_study_cells(ind, pointer_parti);
00418   } 
00419 
00420 if(DEBUG) {
00421   MPI_Barrier(MPI_COMM_WORLD);
00422   if(my_rank==0) {
00423     cout << " partitioning: " << endl;
00424     pointer_parti->Print();
00425   }
00426   MPI_Barrier(MPI_COMM_WORLD);
00427 }
00428 
00429   // 7.step: stop if number of processes is too small
00430   if(p < hashtable_proc_occ) {
00431     cout << " Number of processes is too small! "
00432          << p << ", active: "
00433          << hashtable_proc_occ << endl;
00434     return;
00435   }
00436 
00437   // 8.step: my_index
00438   i=0;
00439   iterate_hash_proc {
00440     if(point_proc!=NULL) {
00441       point_proc->num_proc = i; 
00442       if(i==my_rank) my_index = point_proc->Give_Index();
00443       ++i;
00444     }
00445   }
00446 
00447   // 9.   Step: Calc coarse processors
00448   // 9.1. Step: set number of active processors
00449   number_of_active_procs = hashtable_proc_occ;
00450   // 9.2. Step: calc coarse processors
00451   //            and coarser index and level
00452   Calc_coarse_processors();
00453 
00454   // 10.Step:    Set rank3D and edges und faces of my_index
00455   // 10.1. Step: Set Rank for 6 main direction
00456   Set_rank_3D();
00457 
00458   // 10.2. Step: Set Rank for special direction
00459   if(I_am_active()) {
00460     for(i=0;i<6;++i) {
00461       coarse_faces[i]      = my_index.surface((dir_3D)i);
00462       info_coarse_faces[i] = give_next_rank_destination((dir_3D)i,
00463                                                         n_parallel-1) >= 0;
00464     }
00465     for(i=0;i<12;++i) {
00466       coarse_edges[i]      = my_index.edge((Edges_cell)i);
00467       info_coarse_edges[i] = give_next_rank_destination((Edges_cell)i) >= 0;
00468     }
00469     for(i=0;i<8;++i) {
00470       coarse_corners[i]      = my_index.neighbour((dir_sons)i);
00471       info_coarse_corners[i] = give_next_rank_destination((dir_sons)i) >= 0;
00472       info_coarse_corners[i] = true;
00473     }
00474   }
00475 
00476   /*
00477   cout << " my_rank: " << my_rank
00478        << " T: " << info_coarse_faces[Tdir]
00479        << " D: " << info_coarse_faces[Ddir]
00480        << " W: " << info_coarse_faces[Wdir]
00481        << " E: " << info_coarse_faces[Edir]
00482        << " N: " << info_coarse_faces[Ndir]
00483        << " S: " << info_coarse_faces[Sdir] << endl;
00484   */
00485 
00486 if(DEBUG) {
00487  MPI_Barrier(MPI_COMM_WORLD);
00488  cout.precision(4);
00489   cout << " my_rank: " << my_rank
00490        << " my old bounding_box: " 
00491        << " xl: " << pxl << " yl: " << pyl << " zl: " << pzl
00492        << " xr: " << pxr << " yr: " << pyr << " zr: " << pzr
00493        << endl;
00494  cout.precision(8);
00495  MPI_Barrier(MPI_COMM_WORLD);
00496 }
00497 
00498   // 11.Step: Delete
00499   delete(pointer_parti);
00500   //  cout << " \n My index: ";  my_index.coordinate().Print(); cout << endl;
00501 
00502 
00503 
00504 
00505 
00506 if(DEBUG) {
00507   // Processor hashtable
00508   MPI_Barrier(MPI_COMM_WORLD);
00509   if(my_rank==0) {
00510     cout << " procs von 0: " << endl; 
00511     iterate_hash_proc {
00512       cout << " processor "
00513            << " x: " << point_proc->Give_Index().I_x().coordinate()
00514            << " y: " << point_proc->Give_Index().I_y().coordinate()
00515            << " z: " << point_proc->Give_Index().I_z().coordinate()
00516            << endl;
00517     }
00518   }
00519 
00520   MPI_Barrier(MPI_COMM_WORLD);
00521   D3vector cooo;
00522   if(my_rank==0) {
00523     cout << " Physical Informations: " << endl;
00524     A_bounding.Print();
00525     cout << " \n " 
00526          << H_bounding
00527          << endl;
00528 
00529     cout << " procs von 0 physical: " << endl; 
00530 
00531     iterate_hash_proc {
00532       cooo = coord_in_domain(point_proc->Give_Index());
00533       cout << " processor "
00534            << " x: " << cooo.x
00535            << " y: " << cooo.y
00536            << " z: " << cooo.z
00537            << endl;
00538     }
00539   }
00540 
00541   MPI_Barrier(MPI_COMM_WORLD);
00542   cout << " my_rank:  " << my_rank
00543        << " x: " << my_index.I_x().coordinate()
00544        << " y: " << my_index.I_y().coordinate()
00545        << " z: " << my_index.I_z().coordinate()
00546        << " \n " 
00547        << " x: " << my_index.I_x().get()
00548        << " y: " << my_index.I_y().get()
00549        << " z: " << my_index.I_z().get()
00550        << endl;
00551   MPI_Barrier(MPI_COMM_WORLD);
00552 }
00553 
00554 
00555 
00556 
00557 }
00558 
00559 
00560 void Parallel_Info::Generate_seriel_process() {
00561   int i;
00562 
00563   // 1. step: Set bounding box and ...
00564   pxl = 0.0;   pyl = 0.0;   pzl = 0.0;
00565   pxr = 1.0;   pyr = 1.0;   pzr = 1.0;
00566 
00567   // 2.step: my_index, my_rank
00568   Index3D ind(2,2,2);
00569   my_index = ind;
00570 
00571   my_rank=0;
00572   n_parallel = 0;
00573   my_coarsest_level = 0;
00574 
00575   // 9.Step:  Set edges und faces of my_index
00576   for(i=0;i<6;++i) {
00577     coarse_faces[i]      = my_index.surface((dir_3D)i);
00578     info_coarse_faces[i] = give_next_rank_destination((dir_3D)i,
00579                                                       n_parallel-1) >= 0;
00580   }
00581   for(i=0;i<12;++i) {
00582     coarse_edges[i]      = my_index.edge((Edges_cell)i);
00583     info_coarse_edges[i] = give_next_rank_destination((Edges_cell)i) >= 0;
00584   }
00585   for(i=0;i<8;++i) {
00586     coarse_corners[i]      = my_index.neighbour((dir_sons)i);
00587     info_coarse_corners[i] = give_next_rank_destination((dir_sons)i) >= 0;
00588     info_coarse_corners[i] = true;
00589   }
00590 }
00591 
00592 void Parallel_Info::make_grid_with_grid_point(D3vector gp, double fms) {
00593   double new_q;
00594   D3vector move_v;
00595   if(A_bounding.x >= gp.x ||
00596      A_bounding.y >= gp.y ||
00597      A_bounding.z >= gp.z ||
00598      A_bounding.x+H_bounding <= gp.x ||
00599      A_bounding.y+H_bounding <= gp.y ||
00600      A_bounding.z+H_bounding <= gp.z)  {
00601     cout << " \n Error: Grid point is too far away from domain! \n" << endl;
00602   }
00603   else {
00604     for(new_q=gp.x;A_bounding.x<new_q;new_q=new_q-fms) {};
00605     move_v.x = A_bounding.x-new_q;
00606 
00607     for(new_q=gp.y;A_bounding.y<new_q;new_q=new_q-fms) {};
00608     move_v.y = A_bounding.y-new_q;
00609 
00610     for(new_q=gp.z;A_bounding.z<new_q;new_q=new_q-fms) {};
00611     move_v.z = A_bounding.z-new_q;
00612 
00613     H_bounding = H_bounding + L_infty(move_v);
00614     A_bounding = A_bounding - move_v;
00615   }
00616 }
00617 
00618 bool Parallel_Info::contained_in_old_bounding_box(Index3D I) const {
00619   if(I.I_x()==Ixl || I.I_x()==Ixr || 
00620      I.I_y()==Iyl || I.I_y()==Iyr || 
00621      I.I_z()==Izl || I.I_z()==Izr) return false;
00622   double s;
00623   s = I.I_x().coordinate();
00624   if(s<pxl || s>pxr) return false;
00625   s = I.I_y().coordinate();
00626   if(s<pyl || s>pyr) return false;
00627   s = I.I_z().coordinate();
00628   if(s<pzl || s>pzr) return false;
00629   return true;
00630 }
00631 
00632 
00633 // local and old bounding
00634 bool Parallel_Info::contained_in_boxes(Index3D I) const {  
00635   int i;
00636   // weg falls periodic
00637 #ifndef PERIODIC
00638    if(contained_in_old_bounding_box(I)) {
00639 #endif
00640   
00641     if(my_index<=I) return true;
00642     for(i=0;i<6;++i) {
00643       if(coarse_faces[i]>>I) {
00644         if(info_coarse_faces[i]==false) return false;
00645         else if(coarse_faces[i]<=I)     return true;
00646       }
00647     }
00648     for(i=0;i<12;++i) {
00649       if(coarse_edges[i]>>I) {
00650         if(info_coarse_edges[i]==false) return false;
00651         else if(coarse_edges[i]<=I)     return true;
00652       }
00653     }
00654     for(i=0;i<8;++i) {
00655       if(coarse_corners[i]==I) {
00656         if(info_coarse_corners[i]==false) return false;
00657       }
00658     }
00659 
00660 
00661     return true;
00662 #ifndef PERIODIC
00663    }
00664    return false;
00665 #endif
00666 }
00667 
00668 
00669 
00670 int Parallel_Info::give_next_rank_source(Edges_cell ed) { // -1 if not exists
00671   int t;
00672   Index3D next, sp;
00673   
00674   ed = opposite3D(ed);
00675 
00676   t = my_index.Tiefe();
00677   sp = my_index.next(ed,t);
00678 
00679 #ifndef PERIODIC
00680   if(sp.I_x()==Index1D(0) || sp.I_y()==Index1D(0) || sp.I_z()==Index1D(0) ||
00681      sp.I_x()==Index1D(1) || sp.I_y()==Index1D(1) || sp.I_z()==Index1D(1)) 
00682      return -1;
00683 #endif
00684 
00685   next = sp.next(ed,t);
00686 
00687   iterate_hash_proc {
00688     if(point_proc!=NULL)
00689       if(point_proc->Give_Index() == next) {
00690         if(point_proc->num_proc == my_rank) return -1;
00691         return point_proc->num_proc; 
00692       }
00693   }
00694   return -1;
00695 };
00696 
00697 int Parallel_Info::give_next_rank_destination(Edges_cell ed) { 
00698                                               // -1 if not exists
00699   int t;
00700   Index3D next, sp;
00701 
00702   t = my_index.Tiefe();
00703   sp = my_index.next(ed,t);
00704 #ifndef PERIODIC
00705   if(sp.I_x()==Index1D(0) || sp.I_y()==Index1D(0) || sp.I_z()==Index1D(0) ||
00706      sp.I_x()==Index1D(1) || sp.I_y()==Index1D(1) || sp.I_z()==Index1D(1)) 
00707      return -1;
00708 #endif
00709 
00710   next = sp.next(ed,t);
00711 
00712   iterate_hash_proc {
00713     if(point_proc!=NULL)
00714       if(point_proc->Give_Index() == next) {
00715         if(point_proc->num_proc == my_rank) return -1;
00716         return point_proc->num_proc; 
00717       }
00718   }
00719   return -1;
00720 };
00721 
00722 
00723 int Parallel_Info::give_next_rank_destination(dir_sons d) { 
00724                                               // -1 if not exists
00725   int t;
00726   Index3D next, sp;
00727 
00728   t = my_index.Tiefe();
00729   sp = my_index.next(d,t);
00730 
00731 #ifndef PERIODIC
00732   if(sp.I_x()==Index1D(0) || sp.I_y()==Index1D(0) || sp.I_z()==Index1D(0) ||
00733      sp.I_x()==Index1D(1) || sp.I_y()==Index1D(1) || sp.I_z()==Index1D(1)) 
00734     return -1;
00735 #endif
00736 
00737   next = sp.next(d,t);
00738 
00739   iterate_hash_proc {
00740     if(point_proc!=NULL)
00741       if(point_proc->Give_Index() == next) {
00742         if(point_proc->num_proc == my_rank) return -1;
00743         return point_proc->num_proc; 
00744       }
00745   }
00746   return -1;
00747 };
00748 
00749 int Parallel_Info::give_next_rank_source(dir_sons d) { 
00750                                               // -1 if not exists
00751   int t;
00752   Index3D next, sp;
00753   dir_sons dd;
00754 
00755   dd = d;
00756   d = opposite3D(dd);
00757 
00758   t = my_index.Tiefe();
00759   sp = my_index.next(d,t);
00760 
00761 #ifndef PERIODIC
00762     if(sp.I_x()==Index1D(0) || sp.I_y()==Index1D(0) || sp.I_z()==Index1D(0) ||
00763     sp.I_x()==Index1D(1) || sp.I_y()==Index1D(1) || sp.I_z()==Index1D(1)) 
00764     return -1;
00765 #endif
00766 
00767   next = sp.next(d,t);
00768 
00769   iterate_hash_proc {
00770     if(point_proc!=NULL)
00771     if(point_proc->Give_Index() == next) {
00772         if(point_proc->num_proc == my_rank) return -1;
00773         return point_proc->num_proc; 
00774       }
00775   }
00776   return -1;
00777 };
00778 
00779 /*
00780 void Parallel_Info::Set_coarser_index_and_level() {
00781   int lev;
00782   Index3D origin;
00783   // a) coarsest possible level
00784   origin = my_index.neighbour(WSDd);
00785   my_coarsest_level = origin.Tiefe();
00786   if(my_coarsest_level < 1)
00787     my_coarsest_level = 1;
00788 
00789   // b) my index on coarser levels
00790   my_level_index = new Index3D[n_parallel];
00791   // - set for too coarser levels
00792   for(lev=0;lev<=my_coarsest_level;++lev) {
00793     my_level_index[lev] = my_index;
00794   }
00795   // - calculate rest coarse levels
00796   for(lev=my_coarsest_level+1;lev<n_parallel;++lev) {
00797     my_level_index[lev] = origin.next_ENT(lev);
00798   }
00799 }
00800 */
00801 
00802 Index3D Parallel_Info::Give_next_on_level(int d,          // 0 <= d < 26
00803                                           Index3D me) {
00804   int t;
00805   Index3D nextS;
00806 
00807   t = me.Tiefe();
00808     
00809   if(d<6) {
00810     nextS = me.next((dir_3D)d,t);
00811     nextS = nextS.next((dir_3D)d,t);
00812   }
00813   else if(d<18) {
00814     nextS = me.next((Edges_cell)(d-6),t);
00815     nextS = nextS.next((Edges_cell)(d-6),t);
00816   }
00817   else {
00818     nextS = me.next((dir_sons)(d-18),t);
00819     nextS = nextS.next((dir_sons)(d-18),t);
00820   }
00821   return nextS;
00822 }
00823 
00824 void Parallel_Info::Calc_coarse_processors() {
00825   Index3D next, nnext;
00826   int i, l, rrr;
00827   bool found;
00828   Point_hashtable_proc* ppp;
00829 
00830   dir_sons priority[8];
00831   priority[0] = ENTd;  
00832   priority[1] = ENDd;   priority[2] = ESTd;   priority[3] = WNTd;
00833   priority[4] = ESDd;   priority[5] = WNDd;   priority[6] = WSTd;
00834   priority[7] = WSDd;
00835 
00836   min_level = 1;
00837 
00838   // new
00839   // 1. Calc all coarse interior processors
00840   Index3D ind(2,2,2);
00841   Recursion_calc_coarse_processors(ind);
00842 
00843   // 2. Calc corners of processors
00844   iterate_hash_proc {
00845     ind = point_proc->Give_Index();
00846     l = ind.Tiefe();
00847     for(i=0;i<8;++i)
00848       Add_proc_corner(ind.neighbour((dir_sons)i),l-1);
00849   }
00850 
00851   for(l=n_parallel;l>=min_level+1;--l) {
00852     // 3 set: used_on_coarser_grid=false
00853     iterate_hash_proc {
00854       point_proc->used_on_coarser_grid=false;
00855     }
00856 
00857     // 4. study proc corner, which exists also on coarser level
00858     /*
00859 
00860      idea of priority concept
00861 
00862      *---*---*
00863      | | | | |
00864      |---|---|
00865      | |2|1| |
00866      *---I---*
00867      | |4|3| |
00868      |---|---|
00869      | | | | |
00870      *---*---*
00871 
00872      */
00873 
00874 
00875     iterate_hash_proc_corner { 
00876       ind = point_proc_corner->ind;
00877 
00878       if(ind.Tiefe()<l-1 &&
00879          point_proc_corner->maximal_level>=l-1) {
00880         found=false;
00881 
00882         for(i=0;i<8 && found==false;++i) {
00883           next = ind.next(priority[i],l);
00884           if(Exists_proc(next)) {
00885             found = true;
00886 
00887             // work on fine proc
00888             ppp = hashtable_proc_point(next);
00889             ppp->used_on_coarser_grid=true;
00890             rrr = ppp->num_proc;
00891 
00892             // work on coarse proc
00893             next = ind.next(ENTd,l-1);
00894             if(Exists_proc(next)==false) {
00895               Add_proc_cell(next); // add  processor
00896               ppp = hashtable_proc_point(next);
00897               ppp->interior_processor = false; // make it exterior
00898             }
00899             else 
00900               ppp = hashtable_proc_point(next);
00901             ppp->num_proc = rrr;
00902 
00903             // work on proc corner
00904             point_proc_corner->num_proc = rrr;
00905           }
00906         }
00907       }
00908     }
00909 
00910     // 5. study proc corner, which exists only on this level
00911     iterate_hash_proc_corner { 
00912       ind = point_proc_corner->ind;
00913       if(ind.Tiefe()==l-1 &&
00914          point_proc_corner->maximal_level>=l-1) {
00915         found=false;
00916         for(i=0;i<8 && found==false;++i) {
00917           next = ind.next(priority[i],l);
00918           if(Exists_proc(next)) {
00919             found = true;
00920 
00921             // work on fine proc
00922             ppp = hashtable_proc_point(next);
00923             rrr = ppp->num_proc;
00924 
00925             // work on proc corner
00926             point_proc_corner->num_proc = rrr;
00927           }
00928         }
00929         if(developer_version) {
00930           if(found==false)
00931             cout << " error in Calc_coarse_processors(). 5. " << endl;
00932         }
00933       }
00934     }
00935 
00936     /*
00937 
00938       find out which of the fine proc 1,2,3,4
00939       are not used
00940 
00941      *---*
00942      |3 4|
00943      | I |
00944      |1 2|
00945      *---*
00946 
00947      */    
00948 
00949 
00950     // 6. study coarser procs
00951     iterate_hash_proc {
00952       ind = point_proc->Give_Index();
00953       if(ind.Tiefe()==l-1) {
00954         if(point_proc->num_proc <0) {
00955           // it is necessary to look for an unused processor 
00956           found=false;
00957           for(i=0;i<8 && found==false;++i) {
00958             next = ind.son((dir_sons)i); // zuerst WSDd
00959             if(Exists_proc(next)) {
00960               ppp = hashtable_proc_point(next);
00961               if(ppp->used_on_coarser_grid==false) {
00962                 // found one
00963                 found=true;
00964                 point_proc->num_proc = ppp->num_proc;
00965               }
00966             }
00967           }
00968           if(found==false) {
00969             cout << " \n \n rise minimal level to: "
00970                  << l-1 << endl;
00971             if(min_level<l-1)
00972               min_level = l-1;
00973           }
00974         }
00975       }
00976     }
00977   }
00978 
00979 
00980 
00981   // 7. Calc my_level_index and my_coarsest_level
00982   if(I_am_active()) {
00983     int level;
00984     my_level_index = new Index3D[n_parallel];
00985     my_coarsest_level = n_parallel-1;
00986     for(level=n_parallel-1;level>min_level;level--) {
00987       my_level_index[level] = my_index.son(ENTd); // this means empty
00988       iterate_hash_proc {
00989         if(point_proc!=NULL)
00990           if(point_proc->Give_Index().Tiefe() == level &&
00991              point_proc->num_proc==my_rank) {
00992             my_level_index[level] = point_proc->Give_Index();
00993             my_coarsest_level = level-1;
00994           }
00995       }
00996     }
00997     if(my_coarsest_level<1)
00998       my_coarsest_level=1;
00999   }
01000 
01001 
01002   //  Print_processors();
01003 }
01004 
01005 
01006 void Parallel_Info::Recursion_calc_coarse_processors(Index3D I) {
01007   int level, i;
01008   bool no_sons;
01009 
01010   level = I.Tiefe();
01011   
01012   if(level<n_parallel-1) {
01013     // recursion
01014     for(i=0;i<8;++i) 
01015       Recursion_calc_coarse_processors(I.son((dir_sons)i));
01016   }
01017   // calc number of processor for this coarse cell
01018   no_sons = true;
01019   for(i=0;i<8;++i)
01020     if(exists_process(I.son((dir_sons)i))) no_sons = false;
01021   if(no_sons == false) {
01022     //  if(I.Tiefe()>1)
01023     Add_proc_cell(I); // add interior processor
01024   }
01025 }
01026 
01027 Index3D Parallel_Info::Give_my_level_index(int level) {
01028   if(level>=n_parallel) return my_index;
01029   return my_level_index[level];
01030 }
01031 
01032 void Parallel_Info::Print_processors() { 
01033   if(my_rank==0) {
01034     for(int l=n_parallel;l>=1;--l) {
01035       cout << " Processors on level: " << l << endl;
01036       iterate_hash_proc {
01037         if(point_proc->Give_Index().Tiefe() == l) {
01038           point_proc->Give_Index().coordinate().Print();
01039           cout << " rank: " << point_proc->num_proc << endl;
01040         }
01041       }
01042     }
01043   }
01044 }
01045 
01046 void Parallel_Info::Set_rank_3D() { 
01047   Index3D next, sp;
01048   bool stop;
01049   int d, num_pp;
01050   int lev;
01051 
01052   if(I_am_active()) {
01053     // 1. Part: faces
01054     //  **************
01055     // a) next processor for level >= n_parallel-1
01056     // rank on finest level
01057     for(d=0;d<6;++d) {
01058       stop=false;
01059       sp = my_index.next((dir_3D)d,my_index.Tiefe());
01060 
01061 #ifndef PERIODIC
01062       if(sp.I_q(Main_direction((dir_3D)d))==OneDpart((dir_3D)d)) {
01063         next_rank_destination[d]        = -1;
01064         next_rank_source[opposite3D((dir_3D)d)] = -1;
01065         stop = true;
01066       }
01067 #endif
01068       next = sp.next((dir_3D)d,my_index.Tiefe());
01069       
01070       if(stop==false) {
01071         iterate_hash_proc {
01072           if(point_proc!=NULL)
01073             if(point_proc->Give_Index() == next) {
01074               // processor found
01075               next_rank_destination[d]        = point_proc->num_proc;
01076               next_rank_source[opposite3D((dir_3D)d)] = point_proc->num_proc;
01077               stop = true;
01078             }
01079         }
01080       }
01081       if(stop==false) {
01082         // no processor found
01083         next_rank_destination[d]=-1;
01084         next_rank_source[opposite3D((dir_3D)d)]=-1;
01085       }
01086     }
01087     
01088     // b) next processor for level < n_parallel-1
01089     for(d=0;d<6;++d) {
01090       next_rank_source_coarse[d]      = new int[n_parallel-1];
01091       next_rank_destination_coarse[d] = new int[n_parallel-1];
01092     }
01093     // rank on coarser level
01094     // - set -1 for too coarser levels
01095     for(d=0;d<6;++d) for(lev=0;lev<my_coarsest_level;++lev) {
01096       next_rank_source_coarse[d][lev] = -1;
01097       next_rank_destination_coarse[d][lev] = -1;
01098     }
01099     // - calculate rest coarse levels
01100     for(d=0;d<6;++d) for(lev=my_coarsest_level;lev<n_parallel-1;++lev) {
01101       sp = my_level_index[lev+1].next((dir_3D)d,lev+1);
01102       // periodisch weg
01103 #ifndef PERIODIC
01104       if(sp.I_q(Main_direction((dir_3D)d))==OneDpart((dir_3D)d)) {
01105         next_rank_destination_coarse[d][lev]                = -1;
01106         next_rank_source_coarse[opposite3D((dir_3D)d)][lev] = -1;
01107       }
01108       else
01109 #endif
01110         {
01111           next = sp.next((dir_3D)d,lev+1);
01112           num_pp = Give_proc_number(next);
01113           next_rank_destination_coarse[d][lev]                = num_pp;
01114           next_rank_source_coarse[opposite3D((dir_3D)d)][lev] = num_pp;
01115         }
01116     }
01117     
01118     // 2. Part: edges
01119     // **************
01120     // a) next processor for level >= n_parallel-1
01121     // rank on finest level
01122     for(d=0;d<12;++d) {
01123       next_rank_source_edges[d] =
01124         give_next_rank_source((Edges_cell)d);
01125       next_rank_destination_edges[d] =
01126         give_next_rank_destination((Edges_cell)d);
01127     }
01128 
01129     // b) next processor for level < n_parallel-1
01130     for(d=0;d<12;++d) {
01131       next_rank_source_coarse_edges[d]      = new int[n_parallel-1];
01132       next_rank_destination_coarse_edges[d] = new int[n_parallel-1];
01133     }
01134     // rank on coarser level
01135     // - set -1 for too coarser levels
01136     for(d=0;d<12;++d) for(lev=0;lev<my_coarsest_level;++lev) {
01137       next_rank_source_coarse_edges[d][lev] = -1;
01138       next_rank_destination_coarse_edges[d][lev] = -1;
01139     }
01140     // - calculate rest coarse levels
01141     for(d=0;d<12;++d) for(lev=my_coarsest_level;lev<n_parallel-1;++lev) {
01142       sp = my_level_index[lev+1].next((Edges_cell)d,lev+1);
01143       next = sp.next((Edges_cell)d,lev+1);
01144 
01145       num_pp = Give_proc_number(next);
01146       next_rank_destination_coarse_edges[d][lev]                = num_pp;
01147       next_rank_source_coarse_edges[opposite3D((Edges_cell)d)][lev] = num_pp;
01148     }
01149     
01150 
01151     // 2. Part: corners
01152     // **************
01153     // a) next processor for level >= n_parallel-1
01154     // rank on finest level
01155     for(d=0;d<8;++d) {
01156       next_rank_source_corners[d] =
01157         give_next_rank_source((dir_sons)d);
01158       next_rank_destination_corners[d] =
01159         give_next_rank_destination((dir_sons)d);
01160     }
01161 
01162     // b) next processor for level < n_parallel-1
01163     for(d=0;d<8;++d) {
01164       next_rank_source_coarse_corners[d]      = new int[n_parallel-1];
01165       next_rank_destination_coarse_corners[d] = new int[n_parallel-1];
01166     }
01167     // rank on coarser level
01168     // - set -1 for too coarser levels
01169     for(d=0;d<8;++d) for(lev=0;lev<my_coarsest_level;++lev) {
01170       next_rank_source_coarse_corners[d][lev] = -1;
01171       next_rank_destination_coarse_corners[d][lev] = -1;
01172     }
01173     // - calculate rest coarse levels
01174     for(d=0;d<8;++d) for(lev=my_coarsest_level;lev<n_parallel-1;++lev) {
01175       sp = my_level_index[lev+1].next((dir_sons)d,lev+1);
01176       next = sp.next((dir_sons)d,lev+1);
01177       num_pp = Give_proc_number(next);
01178       next_rank_destination_coarse_corners[d][lev] 
01179         = num_pp;
01180       next_rank_source_coarse_corners[opposite3D((dir_sons)d)][lev]
01181         = num_pp;
01182     }
01183 
01184 
01185 
01186 
01187     /*
01188 
01189 
01190 iterate_hash_proc {
01191   if(point_proc->Give_Index().Tiefe() == n_parallel) {
01192     cout << " rank: " << point_proc->num_proc << " , and: ";
01193     point_proc->Give_Index().coordinate().Print();
01194     cout << endl;
01195   }
01196 }
01197 
01198 
01199   cout << " n_parallel: " << n_parallel
01200        << " my_coarsest_level: " << my_coarsest_level
01201        << " my_rank: " <<  my_rank
01202        << " \n source_corners[WST]: " 
01203        << next_rank_source_coarse_corners[WSTd][lev]
01204        << " des_corners[WST]: " 
01205        << next_rank_destination_coarse_corners[WSTd]
01206        << " source_corners[END]: "
01207        << next_rank_source_coarse_corners[ENDd]
01208        << " des_corners[END]: " 
01209        << next_rank_destination_coarse_corners[ENDd]
01210        << endl;
01211     */
01212 
01213 
01214     
01215 
01216 
01217   }
01218 };
01219 
01220 int* Parallel_Info::Give_buffer_send_info(int l) {
01221   if(length_send_info<l) {
01222     delete(buffer_send_info);
01223     buffer_send_info = new int[l];
01224   }
01225   return buffer_send_info;
01226 }
01227 
01228 int* Parallel_Info::Give_buffer_receive_info(int l) {
01229   if(length_receive_info<l) {
01230     delete(buffer_receive_info);
01231     buffer_receive_info = new int[l];
01232   }
01233   return buffer_receive_info;
01234 }
01235 
01236 
01237 double* Parallel_Info::Give_buffer_send(int d, int l) {
01238   if(length_send[d]<l) {
01239     delete(buffer_send[d]);
01240     buffer_send[d] = new double[l];
01241   }
01242   return buffer_send[d];
01243 }
01244 
01245 double* Parallel_Info::Give_buffer_receive(int d, int l) {
01246   if(length_receive[d]<l) {
01247     delete(buffer_receive[d]);
01248     buffer_receive[d] = new double[l];
01249   }
01250   return buffer_receive[d];
01251 }
01252 
01253   
01254 
01255 void Parallel_Info::Recursion_study_cells(Index3D I, Partitioning* parti) {
01256   int i;
01257   Index3D I_neigh;
01258 
01259   if(I.Tiefe() < n_parallel) {  // level too small-> recursion
01260     for(i=0;i<8;++i)
01261       Recursion_study_cells(I.son((dir_sons)i),parti);
01262   }
01263   else {                              // level we look for
01264     // look to neighbours
01265     if(parti->Is_this_a_proc(I)) {
01266       Add_proc_cell(I);
01267     }
01268   }
01269 };
01270 
01271 int Parallel_Info::Give_proc_number(Index3D I) {
01272   Point_hashtable_proc* ppp;
01273   ppp = hashtable_proc_point(I);
01274   if(ppp==NULL) return -1;
01275   return ppp->num_proc;
01276 }
01277 
01278 bool Parallel_Info::Exists_proc(Index3D I) {
01279   Point_hashtable_proc* ppp;
01280   ppp = hashtable_proc_point(I);
01281   if(ppp==NULL) return false;
01282   return true;
01283 }
01284 
01285 int Parallel_Info::Give_proc_corner_number(Index3D I) {
01286   Point_hashtable_proc_corner* ppp;
01287   ppp = hashtable_proc_corner_point(I);
01288   if(ppp==NULL) return -1;
01289   return ppp->num_proc;
01290 }
01291 
01292 bool Parallel_Info::Exists_proc_corner(Index3D I) {
01293   Point_hashtable_proc_corner* ppp;
01294   ppp = hashtable_proc_corner_point(I);
01295   if(ppp==NULL) return false;
01296   return true;
01297 }
01298 
01299 void Parallel_Info::Add_proc_cell(Index3D I) {
01300   static Point_hashtable_proc* point;
01301   point = hashtable_proc_start
01302     [hashtable_proc_function(I.ind_x.index,I.ind_y.index,I.ind_z.index,
01303                          hashtable_proc_leng)];
01304   if(point==NULL) {
01305     hashtable_proc_occ++;
01306     point = new Point_hashtable_proc(I);
01307     hashtable_proc_start[hashtable_proc_function(I.ind_x.index,I.ind_y.index,
01308                                                  I.ind_z.index,
01309                                                  hashtable_proc_leng)] = point;
01310   }
01311   else {
01312     while(point->next!=NULL && point->ind!=I) point = point->next;
01313     if(point->ind!=I) {
01314       hashtable_proc_occ++;
01315       point->next = new Point_hashtable_proc(I);
01316     }
01317   }
01318 }
01319 
01320 void Parallel_Info::Add_proc_corner(Index3D I, int l) {
01321   Point_hashtable_proc_corner* point;
01322   Point_hashtable_proc_corner* pp;
01323   point = hashtable_proc_corner_start
01324     [hashtable_proc_corner_function(I.ind_x.index,I.ind_y.index,I.ind_z.index,
01325                          hashtable_proc_corner_leng)];
01326   if(point==NULL) {
01327     hashtable_proc_corner_occ++;
01328     point = new Point_hashtable_proc_corner(I);
01329     hashtable_proc_corner_start[hashtable_proc_corner_function(I.ind_x.index,
01330                                                         I.ind_y.index,
01331                                                         I.ind_z.index,
01332                                       hashtable_proc_corner_leng)] = point;
01333     pp = point;
01334   }
01335   else {
01336     while(point->next!=NULL && point->ind!=I) point = point->next;
01337     if(point->ind!=I) {
01338       hashtable_proc_corner_occ++;
01339       point->next = new Point_hashtable_proc_corner(I);
01340       pp = point->next;
01341     }
01342     else 
01343       pp = point;
01344   }
01345   if(pp->maximal_level<l)
01346     pp->maximal_level=l;
01347 }
01348 
01349 // Elementares fuer hashtable_proc
01350 // ----------------------------
01351 void Parallel_Info::Initialize_hash_proc(int lenght) {
01352   int i;
01353   hashtable_proc_leng = Find_next_prime(lenght);
01354   hashtable_proc_start = new Point_hashtable_proc*[hashtable_proc_leng];
01355   for(i=0;i<hashtable_proc_leng;++i)
01356     hashtable_proc_start[i] = NULL;
01357   hashtable_proc_occ=0;
01358 }
01359 
01360 void Parallel_Info::Initialize_hash_proc_corner(int lenght) {
01361   int i;
01362   hashtable_proc_corner_leng = Find_next_prime(lenght);
01363   hashtable_proc_corner_start = 
01364     new Point_hashtable_proc_corner*[hashtable_proc_corner_leng];
01365   for(i=0;i<hashtable_proc_corner_leng;++i)
01366     hashtable_proc_corner_start[i] = NULL;
01367   hashtable_proc_corner_occ=0;
01368 }
01369 
01370 
01371 //  rough domain
01372 // ---------------------------------
01373 inline void rough_domain::set(int i, int j, int k) {
01374   start[i+l*j+ll*k] = true;
01375 }
01376 
01377 rough_domain::rough_domain(int P_level, int Refine_level, All_Domains* dom,
01378                            D3vector A_bounding, double H_bounding) :
01379   p_level(P_level), refine_level(Refine_level) {
01380   int i,j,k;
01381   D3vector A;
01382   double h;  
01383   bool nothing;
01384 
01385   // periodic
01386   is_periodic = dom->Is_periodic();
01387 
01388   // alloce storage
01389   n_interior = Zweipotenz(p_level+refine_level);
01390   n_side     = Zweipotenz(refine_level);
01391   l  = n_interior;
01392   ll = l*l;
01393 
01394   start = new bool[l*l*l];
01395   for(i=0;i<l*l*l;++i) start[i]=false;
01396 
01397   // set entries of rough_domain
01398   A = A_bounding;
01399   h = H_bounding / (double)n_interior;
01400 
01401   nothing=true;
01402   for(i=1;i<n_interior;++i) 
01403     for(j=1;j<n_interior;++j) 
01404       for(k=1;k<n_interior;++k) {
01405         if(dom->point_in_domain(D3vector(h*i,h*j,h*k)+A)) {
01406           nothing=false;
01407           set(i-1,j  ,k);         set(i,j  ,k);
01408           set(i-1,j-1,k);         set(i,j-1,k);
01409 
01410           set(i-1,j  ,k-1);       set(i,j  ,k-1);
01411           set(i-1,j-1,k-1);       set(i,j-1,k-1);
01412         }
01413       }
01414 
01415   if(nothing) {
01416     for(i=0;i<n_interior;++i)
01417       for(j=0;j<n_interior;++j)
01418         for(k=0;k<n_interior;++k)
01419           start[i+l*j+ll*k] =true;
01420   }
01421 
01422   /*
01423   cout << " \n Matrix: ";
01424   for(i=0;i<=n_interior;++i) {
01425     cout << " \n next:";
01426     for(j=0;j<=n_interior;++j) {
01427       cout << endl;
01428       for(k=0;k<=n_interior;++k) {
01429         cout << start[i+l*j+ll*k] << ", ";
01430       }
01431     }
01432   }
01433   cout << " \n : n_interior: " << n_interior
01434        << " \n : n_side: "     << n_side       << endl;
01435   */
01436 };
01437 
01438 rough_domain::~rough_domain() {
01439   delete(start);
01440 }
01441 
01442 bool rough_domain::In_domain(int i, int j, int k) {
01443   if(developer_version) {
01444     if(i<1-n_side          || j<1-n_side          || k<1-n_side          ||
01445        i>n_interior+n_side || j>n_interior+n_side || k>n_interior+n_side) {
01446       cout << " \n error in rough_domain::In_domain!!"  
01447            << " i: " << i << " j: " << j << " k: " << k << endl;
01448     }
01449   }
01450   if(j<0          || i<0          || k<0   || 
01451      i>=n_interior || j>=n_interior || k>=n_interior) {
01452     return false;
01453   }
01454   return start[i+l*j+ll*k];
01455 };
01456 
01457 
01458 /*
01459 int rough_domain::p_necessary(int I, int J, int K, int p) {
01460   int i,j,k,n_nec;
01461   int iS,jS,kS;
01462   int ii,jj,kk;
01463   bool intersec;
01464 
01465   n_nec=0;
01466   for(i=0;i<=n_interior/n_side;++i) 
01467     for(j=0;j<=n_interior/n_side;++j)  
01468       for(k=0;k<=n_interior/n_side;++k) {
01469         iS=-I+i*n_side;
01470         jS=-J+j*n_side;
01471         kS=-K+k*n_side;
01472 
01473         intersec=false;
01474         for(ii=0;ii<=n_side && intersec==false;++ii) 
01475           for(jj=0;jj<=n_side && intersec==false;++jj) 
01476             for(kk=0;kk<=n_side && intersec==false;++kk) {
01477               if(In_domain(iS+ii,jS+jj,kS+kk)) {
01478                 intersec=true;
01479               }
01480             }
01481 
01482         if(intersec==true) {
01483           ++n_nec;
01484         }
01485         if(n_nec>p) return n_nec;
01486       }
01487   return n_nec;
01488 };
01489 */
01490 
01491 quality rough_domain::calc_quality(int I, int J, int K, int p) {
01492   int i,j,k,n_nec;
01493   int iS,jS,kS;
01494   int ii,jj,kk;
01495   int num_inter_sec, minimal_inter_sec, maximal_inter_sec;
01496   bool intersec;
01497 
01498   minimal_inter_sec = (n_side+1)*(n_side+1)*(n_side+1);
01499   maximal_inter_sec = 0;
01500   n_nec=0;
01501   for(i=0;i<=n_interior/n_side;++i) 
01502     for(j=0;j<=n_interior/n_side;++j)  
01503       for(k=0;k<=n_interior/n_side;++k) {
01504         iS=-I+i*n_side;
01505         jS=-J+j*n_side;
01506         kS=-K+k*n_side;
01507 
01508         num_inter_sec = 0;
01509         intersec      = false;
01510         for(ii=0;ii<n_side;++ii) 
01511           for(jj=0;jj<n_side;++jj) 
01512             for(kk=0;kk<n_side;++kk) {
01513               if(In_domain(iS+ii,jS+jj,kS+kk)) {
01514                 intersec=true;
01515                 //      if(Full_in_domain(iS+ii,jS+jj,kS+kk))
01516                   ++num_inter_sec;
01517               }
01518             }
01519         if(intersec) {
01520           ++n_nec;
01521           if(num_inter_sec<minimal_inter_sec)
01522             minimal_inter_sec=num_inter_sec;
01523           if(num_inter_sec>maximal_inter_sec)
01524             maximal_inter_sec=num_inter_sec;
01525         }
01526         if(n_nec>p) return quality();
01527       }
01528 
01529   // cout << " intersec: " << minimal_inter_sec << endl;
01530 
01531   return quality(n_nec,minimal_inter_sec,maximal_inter_sec); // yes quality 
01532   // return quality(n_nec,0);  // no quality 
01533 };
01534 
01535 void rough_domain::Set_partitioning(int I, int J, int K, Partitioning* parti) {
01536   int i,j,k;
01537   int iS,jS,kS;
01538   int ii,jj,kk;
01539   bool intersec;
01540 
01541   /*
01542   cout << " \n : n_interior: " << n_interior
01543        << " \n : n_side: "     << n_side       << endl;
01544   */
01545 
01546   for(i=0;i<=n_interior/n_side;++i) 
01547     for(j=0;j<=n_interior/n_side;++j)  
01548       for(k=0;k<=n_interior/n_side;++k) {
01549         iS=-I+i*n_side;
01550         jS=-J+j*n_side;
01551         kS=-K+k*n_side;
01552 
01553         intersec=false;
01554         for(ii=0;ii<n_side && intersec==false;++ii) 
01555           for(jj=0;jj<n_side && intersec==false;++jj) 
01556             for(kk=0;kk<n_side && intersec==false;++kk) {
01557               if(In_domain(iS+ii,jS+jj,kS+kk)) {
01558                 intersec=true;
01559               }
01560             }
01561 
01562         if(intersec==true) {
01563           parti->Put_proc(i,j,k);
01564         }
01565       }
01566 };
01567 
01568 
01569 int rough_domain::Calc_optimal_partitioning(int p,
01570                                             int& opt_I,int& opt_J,int& opt_K,
01571                                             Partitioning* parti) {
01572   int I,J,K;
01573 
01574   quality q_new, q_opt;
01575 
01576 
01577   if(is_periodic) {
01578   // if(false) {
01579     I = 0; J = 0; K = 0;
01580     opt_I=0; opt_J=0; opt_K=0;
01581 
01582     q_new=calc_quality(opt_I,opt_J,opt_K,p);
01583     if(q_opt<q_new) {
01584       q_opt=q_new;
01585       opt_I=I; opt_J=J; opt_K=K;
01586     }
01587   }
01588   else {
01589     for(I=0;I<n_side;++I) for(J=0;J<n_side;++J) for(K=0;K<n_side;++K) {
01590       q_new=calc_quality(I,J,K,p);
01591       if(q_opt<q_new) {
01592         q_opt=q_new;
01593         opt_I=I; opt_J=J; opt_K=K;
01594       }
01595     }
01596   }
01597 
01598   Set_partitioning(opt_I,opt_J,opt_K,parti);
01599   if(q_opt.positive_quality()) return q_opt.Give_p_nec();
01600   else                         return p+1;
01601 }
01602 
01603 
01604 
01605 //  Partitioning
01606 // ---------------------------------
01607 Partitioning::Partitioning(int level) {
01608   int i,j,k;
01609   
01610   size    = Zweipotenz(level+1);
01611 
01612   start = new bool[size*size*size];
01613 
01614   // set false of Partitioning
01615   for(i=0;i<size;++i) 
01616     for(j=0;j<size;++j) 
01617       for(k=0;k<size;++k) {
01618         start[i+size*j+size*size*k] = false;
01619       }
01620 };
01621 
01622 Partitioning::~Partitioning() {
01623   delete(start);
01624 }
01625 
01626 void Partitioning::Put_proc(int i, int j, int k) {
01627   if(developer_version) {
01628     if(i>=size || j>=size || k>=size) {
01629       cout << " Error in Partitioning::Put_proc at: "
01630            << i << ", "  << j << ", "  << k << ", "  << size << endl;
01631     }
01632   }
01633   start[i+size*j+size*size*k]=true;
01634 }
01635 
01636 bool Partitioning::Is_this_a_proc(Index3D Ind) {
01637   Index3D I;
01638   int t;
01639   t = Ind.Tiefe()-1;
01640 
01641   /*  
01642   if(developer_version) {
01643     if((size-1)*2!=Zweipotenz(t))
01644       cout << " Error in Partitioning::Is_this_a_proc " << endl;
01645   }
01646   */
01647 
01648   // periodic
01649   I = Ind.neighbour_non_periodic(WSDd);
01650   return
01651     start[I.I_x().cart_index(t)+
01652          size*I.I_y().cart_index(t)+
01653          size*size*I.I_z().cart_index(t)];
01654 }
01655 
01656 void Partitioning::Print() {
01657   int i,j,k;
01658  
01659   cout << " Partitioning: " << endl;
01660   for(i=0;i<size;++i) {
01661     cout << " \n new z-level: " << endl;
01662     for(j=0;j<size;++j) {
01663       cout << endl;
01664       for(k=0;k<size;++k) {
01665         cout << start[i+size*j+size*size*k] << ", ";
01666       }
01667     }
01668   }
01669   cout << endl;
01670 }

Generated on Mon Jan 16 13:23:41 2006 for IPPL by  doxygen 1.4.6