From 2fbc6d4c5d0b72ef9a31bfb67c98c56d3063a0bb Mon Sep 17 00:00:00 2001 From: iwia06 <christoph.pflaum@fau.de> Date: Fri, 22 Jan 2021 12:12:17 +0100 Subject: [PATCH] performance Optimierung --- program/main.cc | 17 ++- program/program.pro | 2 +- program/source/extemp/variable.cc | 18 +++ program/source/extemp/variable.h | 131 ++++++++++++++++- program/source/extemp/variable_cc.h | 161 +++++++++++++++++++++ program/source/interpol/interpolCellVar.cc | 45 ++++++ program/source/interpol/interpolCellVar.h | 31 +++- 7 files changed, 399 insertions(+), 6 deletions(-) diff --git a/program/main.cc b/program/main.cc index 6e43d53..2ac9d1f 100644 --- a/program/main.cc +++ b/program/main.cc @@ -98,12 +98,25 @@ int main(int argc, char** argv) u = Cos(X*M_PI)*Cos(Y*M_PI)*Cos(Z*M_PI); + /* Interpolate_from_cell_to_point<Stencil_constant_z> interpolGrid(iteration); + interpolGrid.init(&blockgrid); + interpolGrid.doInterpolation(&u_cell,&interpol); +*/ - interpolGrid.init(&blockgrid); + FastInterpolate_from_cell_to_point interpolGrid; + interpolGrid.init(&blockgrid); + interpolGrid.doInterpolation(&u_cell,&interpol); - interpolGrid.doInterpolation(&u_cell,&interpol); + + std::ofstream DATEIA; + DATEIA.open("interpol.vtk"); + interpol.Print_VTK(DATEIA); + DATEIA.close(); + +// cout << " Maximum: " << Maximum(interpol) << " Minimum: " << Minimum(interpol) << endl; + cout << " Maximum : " << L_infty(u) << endl; cout << " Error : " << L_infty(interpol-u) << endl; diff --git a/program/program.pro b/program/program.pro index ca587ad..dd6241a 100644 --- a/program/program.pro +++ b/program/program.pro @@ -17,7 +17,7 @@ unix: MOC_DIR = MOC_FILES # getting pathes: -include(../config.pri) +include(../configMy.pri) INCLUDEPATH += $${UGBLOCKS_PATH} diff --git a/program/source/extemp/variable.cc b/program/source/extemp/variable.cc index 22395c2..1af0d3b 100644 --- a/program/source/extemp/variable.cc +++ b/program/source/extemp/variable.cc @@ -60,6 +60,24 @@ void Variable< std::complex<double> >::Update_back(int id_hex) const { my_rank, comm); } +template <> +void Variable<double>::AddUpFromHex(int id_hex) const { + AddUp_back_fromHex<double>(id_hex, blockgrid, + data_hexahedra, data_quadrangles, + data_edges, data_points, + my_rank, comm); +} + +template <> +void Variable< std::complex<double> >::AddUpFromHex(int id_hex) const { + AddUp_back_fromHex< std::complex<double> >(id_hex, blockgrid, + data_hexahedra, data_quadrangles, + data_edges, data_points, + my_rank, comm); +} + + + template <> template <> void Variable<double>::Update<hexahedronEl>(int id_hex) const{ diff --git a/program/source/extemp/variable.h b/program/source/extemp/variable.h index 1c58fe0..fea62d1 100644 --- a/program/source/extemp/variable.h +++ b/program/source/extemp/variable.h @@ -306,13 +306,21 @@ class Variable : public Expr<Variable< DTyp > >, public Object_based_on_ug { inline DTyp Give_data ( params_in, D3vector &posVector ) const ; void UpdateHexahedra(); ///> Updated alle Randdaten in allen Hexahedra - void UpdateHexahedraBack(); + void UpdateHexahedraBack(); /// todo update nur falls notwendig template <elementTyp TYP_EL> void Update ( int id ) const; void Update_back(int id) const; ///> fuer interpolation slice 2D -> 3D + + void AddUpFromHex(); ///> fuer Interpolation cell -> point + void AddUpFromHex(int id) const; ///> fuer Interpolation cell -> point + void SetAllZero(); ///> fuer Interpolation cell -> point + void AddFromOne(); ///> fuer Interpolation cell -> point + template <class Zell> + void AddFromZell(Zell& ZellVar); ///> fuer Interpolation cell -> point + inline DTyp Give_data_quadrangle_middle ( int id, int i, int j, int Nx ) const; inline DTyp Give_data_quadrangle_interior ( int id, int i, int j, int Nx ) const; @@ -430,6 +438,15 @@ void Variable<DTyp>::UpdateHexahedraBack() { } } +template <class DTyp> +void Variable<DTyp>::AddUpFromHex() { + for(int id_hex=0;id_hex<ug->Give_number_hexahedra();++id_hex) { + AddUpFromHex(id_hex); + } +} + + + template <class DTyp> int Variable<DTyp>::checkThreshold ( double threshold, int kz ) { int id_hex = 1; @@ -1494,11 +1511,123 @@ void Variable<DTyp>::operator= ( const Expr<A>& a ) { } +template <class DTyp> +void Variable<DTyp>::SetAllZero() { + int Nx, Ny, Nz; + + bool useOpenMP_here = UGBlocks::useOpenMP; + + // hexahedra + for(int id = 0;id < ug->Give_number_hexahedra();++id ) { + if ( ug->Give_hexahedron ( id )->my_object ( my_rank ) ) { + Nx = blockgrid->Give_Nx_hexahedron ( id ); + Ny = blockgrid->Give_Ny_hexahedron ( id ); + Nz = blockgrid->Give_Nz_hexahedron ( id ); + + #pragma omp parallel for num_threads(UGBlocks::numThreadsToTake) if(useOpenMP_here) + for(int k = 0;k <= Nz;++k ) { + for(int j = 0;j <= Ny;++j ) + for(int i = 0;i <= Nx;++i ) + data_hexahedra[id][i+ ( Nx+1 ) * ( j+ ( Ny+1 ) *k ) ] = 0.0; + } + } + } + + // quadrangles + for ( int id = 0;id < ug->Give_number_quadrangles();++id ) { + + if ( ug->Give_quadrangle ( id )->my_object ( my_rank ) ) { + Nx = blockgrid->Give_Nx_quadrangle ( id ); + Ny = blockgrid->Give_Ny_quadrangle ( id ); + + // #pragma omp parallel for private(i) num_threads(UGBlocks::numThreadsToTake) if(useOpenMP_here) + for(int j = 0;j <= Ny;++j ) + for (int i = 0;i <= Nx;++i ) { + data_quadrangles[id][i+ ( Nx+1 ) *j] = 0.0; + } + } + } + + // edges + for ( int id = 0;id < ug->Give_number_edges();++id ) { + if ( ug->Give_edge ( id )->my_object ( my_rank ) ) { + Nx = blockgrid->Give_Nx_edge ( id ); + + for(int i = 0;i <= Nx;++i ) + data_edges[id][i] = 0.0; + } + } + + // points + for(int id = 0;id < ug->Give_number_points();++id ) { + if(ug->Give_point ( id )->my_object ( my_rank ) ) { + data_points[id][0] = 0.0; + } + } +} +template <class DTyp> +template <class Zell> +void Variable<DTyp>::AddFromZell(Zell& ZellVar) { + int Nx, Ny, Nz; + + // hexahedra + for(int id = 0;id < ug->Give_number_hexahedra();++id ) { + if(ug->Give_hexahedron ( id )->my_object ( my_rank ) ) { + Nx = blockgrid->Give_Nx_hexahedron ( id ); + Ny = blockgrid->Give_Ny_hexahedron ( id ); + Nz = blockgrid->Give_Nz_hexahedron ( id ); + + for(int k = 0;k < Nz;++k ) { + for(int j = 0;j < Ny;++j ) + for(int i = 0;i < Nx;++i ) { + DTyp value = ZellVar.Give_cell_hexahedra(id,Ind_loc_matrix_hexahedra(i,j,k),i,j,k,Nx,Ny); + data_hexahedra[id][i + (Nx+1) * (j + (Ny+1)*k ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j + (Ny+1)*k ) ] += value; + data_hexahedra[id][i + (Nx+1) * (j+1 + (Ny+1)*k ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j+1 + (Ny+1)*k ) ] += value; + data_hexahedra[id][i + (Nx+1) * (j + (Ny+1)*(k+1) ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j + (Ny+1)*(k+1) ) ] += value; + data_hexahedra[id][i + (Nx+1) * (j+1 + (Ny+1)*(k+1) ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j+1 + (Ny+1)*(k+1) ) ] += value; + } + } + } + } +} +template <class DTyp> +void Variable<DTyp>::AddFromOne() { + int Nx, Ny, Nz; + + // hexahedra + for(int id = 0;id < ug->Give_number_hexahedra();++id ) { + if(ug->Give_hexahedron ( id )->my_object ( my_rank ) ) { + Nx = blockgrid->Give_Nx_hexahedron ( id ); + Ny = blockgrid->Give_Ny_hexahedron ( id ); + Nz = blockgrid->Give_Nz_hexahedron ( id ); + + + for(int k = 0;k < Nz;++k ) { + for(int j = 0;j < Ny;++j ) + for(int i = 0;i < Nx;++i ) { + DTyp value = 1.0; + data_hexahedra[id][i + (Nx+1) * (j + (Ny+1)*k ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j + (Ny+1)*k ) ] += value; + data_hexahedra[id][i + (Nx+1) * (j+1 + (Ny+1)*k ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j+1 + (Ny+1)*k ) ] += value; + data_hexahedra[id][i + (Nx+1) * (j + (Ny+1)*(k+1) ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j + (Ny+1)*(k+1) ) ] += value; + data_hexahedra[id][i + (Nx+1) * (j+1 + (Ny+1)*(k+1) ) ] += value; + data_hexahedra[id][i+1 + (Nx+1) * (j+1 + (Ny+1)*(k+1) ) ] += value; + } + } + } + } +} ///////////////////////////////////////////////////////////////////////// // 5. Nconst , ... funtions for copy of data diff --git a/program/source/extemp/variable_cc.h b/program/source/extemp/variable_cc.h index 87c68dc..7b30420 100644 --- a/program/source/extemp/variable_cc.h +++ b/program/source/extemp/variable_cc.h @@ -1083,6 +1083,167 @@ assert( rank_rec == 0); +template <class DTyp> +void AddUp_back_fromHex(int id_hex, Blockgrid* blockgrid, DTyp** data_hexahedra, + DTyp** data_quadrangles, DTyp** data_edges, DTyp** data_points, + int my_rank, MPI_Comm comm ) { + int i,j; + int id_quad, id_edge, id_point; + int Ni,Nj,Nconst; + int Nxedge; + int Nxquad,Nyquad; + int Nxhex,Nyhex,Nzhex; + int id_SW, id_SE, id_NW, idsp; + int id_W, id_E; + dir3D_sons c_SW ( ( dir3D_sons ) 0 ), c_SE ( ( dir3D_sons ) 0 ), c_NW ( ( dir3D_sons ) 0 ); + dir3D_sons c_W ( ( dir3D_sons ) 0 ), c_E ( ( dir3D_sons ) 0 ); + dir3D c_x, c_y; + Unstructured_grid* ug = blockgrid->Give_unstructured_grid(); + + int rank_send, rank_rec; // for parallel + + Nxhex = blockgrid->Give_Nx_hexahedron ( id_hex ); + Nyhex = blockgrid->Give_Ny_hexahedron ( id_hex ); + Nzhex = blockgrid->Give_Nz_hexahedron ( id_hex ); + + rank_rec = ug->Give_hexahedron ( id_hex )->Give_rank(); // for parallel + +// keine MPI Paralleliserung!!!!!!!!!!!!!! +assert( rank_rec == 0); + + // quadrangles + for(int fc=0; fc<6; ++fc ) { + id_quad = ug->Give_hexahedron ( id_hex )->Give_id_quadrangle ( ( dir3D ) fc ); + rank_send = ug->Give_quadrangle ( id_quad )->Give_rank(); // for parallel + if(rank_send==my_rank || rank_rec==my_rank ) { // for parallel + Nxquad = blockgrid->Give_Nx_quadrangle ( id_quad ); + Nyquad = blockgrid->Give_Ny_quadrangle ( id_quad ); + + // a) coordinate points of quadrangle + id_SW = ug->Give_quadrangle ( id_quad )->Give_id_corner ( SWdir2D ); + id_SE = ug->Give_quadrangle ( id_quad )->Give_id_corner ( SEdir2D ); + id_NW = ug->Give_quadrangle ( id_quad )->Give_id_corner ( NWdir2D ); + + // b) Find corresponding points in hexahedron + for(int c=0; c<8; ++c ) { + idsp = ug->Give_hexahedron ( id_hex )->Give_id_corner ( ( dir3D_sons ) c ); + if ( idsp==id_SW ) c_SW = ( dir3D_sons ) c; + else if ( idsp==id_SE ) c_SE = ( dir3D_sons ) c; + else if ( idsp==id_NW ) c_NW = ( dir3D_sons ) c; + } + + c_x = direction_from_to ( c_SW,c_SE ); + c_y = direction_from_to ( c_SW,c_NW ); + + // x - direction + Nconst = Give_Nconst ( ( dir3D ) c_x, Nxhex, Nyhex, Nzhex ); + Ni = Give_Ni ( ( dir3D ) c_x, Nxhex, Nyhex, Nzhex ); + + // y - direction + Nconst = Give_Nconst ( ( dir3D ) c_y, Nxhex, Nyhex, Nzhex ) + Nconst; + Nj = Give_Ni ( ( dir3D ) c_y, Nxhex, Nyhex, Nzhex ); + + // empty - direction + Nconst = Give_Nconst ( opposite3D ( ( dir3D ) fc ), + Nxhex, Nyhex, Nzhex ) + Nconst; + if(rank_send == rank_rec ) { // for parallel + for(j=1; j<Nyquad; ++j ) + for(i=1;i<Nxquad; ++i ) { + // vorwaerts: + // data_hexahedra[id_hex][i*Ni+j*Nj+Nconst] = + // data_quadrangles[id_quad][i+ ( Nxquad+1 ) *j]; + data_quadrangles[id_quad][i+ ( Nxquad+1 ) *j] += + data_hexahedra[id_hex][i*Ni+j*Nj+Nconst]; + } + } + else { + assert(false); + } + } + } + + // edges + for ( int ed=0; ed<12; ++ed ) { + id_edge = ug->Give_hexahedron ( id_hex )->Give_id_edge ( ( Edges_cell ) ed ); + rank_send = ug->Give_edge ( id_edge )->Give_rank(); // for parallel + if ( rank_send==my_rank || rank_rec==my_rank ) { // for parallel + Nxedge = blockgrid->Give_Nx_edge ( id_edge ); + + // a) coordinate points of edge + id_W = ug->Give_edge ( id_edge )->Give_id_corner_W(); + id_E = ug->Give_edge ( id_edge )->Give_id_corner_E(); + + // b) Find corresponding points in hexahedron + for ( int c=0; c<8; ++c ) { + idsp = ug->Give_hexahedron ( id_hex )->Give_id_corner ( ( dir3D_sons ) c ); + if ( idsp==id_W ) c_W = ( dir3D_sons ) c; + else if ( idsp==id_E ) c_E = ( dir3D_sons ) c; + } + + c_x = direction_from_to ( c_W,c_E ); + + // x - direction + Nconst = Give_Nconst ( ( dir3D ) c_x, Nxhex, Nyhex, Nzhex ); + Ni = Give_Ni ( ( dir3D ) c_x, Nxhex, Nyhex, Nzhex ); + + // A. empty - direction + Nconst = Give_Nconst ( opposite3D ( OrthoA ( ( Edges_cell ) ed ) ), + Nxhex, Nyhex, Nzhex ) + Nconst; + + // B. empty - direction + Nconst = Give_Nconst ( opposite3D ( OrthoB ( ( Edges_cell ) ed ) ), + Nxhex, Nyhex, Nzhex ) + Nconst; + + if(rank_send == rank_rec ) { // for parallel + for(i=1; i<Nxedge; ++i ) { + // vorwaerts + //data_hexahedra[id_hex][i*Ni+Nconst] = data_edges[id_edge][i]; + data_edges[id_edge][i] += data_hexahedra[id_hex][i*Ni+Nconst]; + } + } + else { + assert(false); + } + } + } + + // points + for ( int c=0; c<8; ++c ) { + id_point = ug->Give_hexahedron ( id_hex )->Give_id_corner ( ( dir3D_sons ) c ); + rank_send = ug->Give_point ( id_point )->Give_rank(); // for parallel + if ( rank_send==my_rank || rank_rec==my_rank ) { // for parallel + + // x- direction + Nconst = Give_Nconst ( opposite3D ( xCoord ( ( dir3D_sons ) c ) ), + Nxhex, Nyhex, Nzhex ); + + // y- direction + Nconst = Give_Nconst ( opposite3D ( yCoord ( ( dir3D_sons ) c ) ), + Nxhex, Nyhex, Nzhex ) + Nconst; + + // z- direction + Nconst = Give_Nconst ( opposite3D ( zCoord ( ( dir3D_sons ) c ) ), + Nxhex, Nyhex, Nzhex ) + Nconst; + + if(rank_send == rank_rec ) // for parallel + // vorwaerts + //data_hexahedra[id_hex][Nconst] = data_points[id_point][0]; + { + data_points[id_point][0] += data_hexahedra[id_hex][Nconst]; + } + else { + assert(false); + } + } + } +} + + + + + +////////////////////////////////////////////////////////////////////////////// + diff --git a/program/source/interpol/interpolCellVar.cc b/program/source/interpol/interpolCellVar.cc index 702cd42..fa703e5 100644 --- a/program/source/interpol/interpolCellVar.cc +++ b/program/source/interpol/interpolCellVar.cc @@ -26,6 +26,50 @@ using namespace ::_COLSAMM_; #include "assert.h" +FastInterpolate_from_cell_to_point::FastInterpolate_from_cell_to_point() { + weight = NULL; +} + +void FastInterpolate_from_cell_to_point::deleteData() { + if(weight!=NULL) delete weight; + weight = NULL; +} + +void FastInterpolate_from_cell_to_point::init(Blockgrid* blockgrid) { + deleteData(); + weight = new Variable<double>(*blockgrid); + weight->SetAllZero(); + weight->AddFromOne(); + weight->AddUpFromHex(); + weight->UpdateHexahedra(); + +/* + std::ofstream DATEIA; + + DATEIA.open("weight.vtk"); + weight->Print_VTK(DATEIA); + DATEIA.close(); + + cout << " Maximum: " << Maximum(*weight) << " Minimum: " << Minimum(*weight) << endl; + */ +} + +void FastInterpolate_from_cell_to_point::doInterpolation(Cell_variable<double>* varCell, Variable<double>* varPoint) { + assert(weight!=NULL); + varPoint->SetAllZero(); + varPoint->AddFromZell(*varCell); + varPoint->AddUpFromHex(); + + (*varPoint) = (*varPoint) / (*weight); + varPoint->UpdateHexahedra(); + + + +} + + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// template<> @@ -68,3 +112,4 @@ void Interpolate_from_cell_to_point<Stencil_constant_z>::init(Blockgrid* blockgr } } + diff --git a/program/source/interpol/interpolCellVar.h b/program/source/interpol/interpolCellVar.h index 7348969..9682ddd 100644 --- a/program/source/interpol/interpolCellVar.h +++ b/program/source/interpol/interpolCellVar.h @@ -48,6 +48,27 @@ #define INTERPOLCELLVAR_H +/** \addtogroup InterpolationOperators **/ +/* @{ */ +/** + * Interpolation from Cell_variable to Variable <br> + * FAST VERSION <br> + * Sometimes this version is a little bit less accurate than Interpolate_from_cell_to_point in case of smooth functions <br> + * But in case of a non smooth function, this version is more appropriate +**/ +class FastInterpolate_from_cell_to_point { + public: + FastInterpolate_from_cell_to_point(); + + void init(Blockgrid* blockgrid_); + void deleteData(); + void doInterpolation(Cell_variable<double>* varCell, Variable<double>* varPoint); + + ~FastInterpolate_from_cell_to_point() { deleteData(); } +private: + Variable<double>* weight; +}; + @@ -56,8 +77,11 @@ /** - * interpolation by Gauss-Seidel from Cell_variable to Variable - * template might be Stencil_constant_z + * Interpolation by Gauss-Seidel from Cell_variable to Variable <br> + * template might be Stencil_constant_z <br> + * SLOW VERSION <br> + * Sometimes this version is more accurate than FastInterpolate_from_cell_to_point <br> + * An example showed an increase of factor 3 of accuracy in case of a smooth function **/ template<class StenTyp> class Interpolate_from_cell_to_point { @@ -81,6 +105,8 @@ private: int numberGSinterations; }; +/* @} */ + template<class StenTyp> void Interpolate_from_cell_to_point<StenTyp>::doInterpolation(Cell_variable<double>* varCell, Variable<double>* varPoint) { @@ -125,4 +151,5 @@ void Interpolate_from_cell_to_point<StenTyp>::deleteData() { } } + #endif // INTERPOLCELLVAR_H -- GitLab