int main() { // initialize grid. params are read from input file GRID grid; // initialize a result object on grid Result result(&grid); // fill in Delta by initializing it to semi-circle InitDelta(DOStypes::SemiCircle, grid.get_N(), 0.2, 0.0, 0.01, 0.5, result.omega, result.Delta); result.mu = 0.1; result.n = 0.5; result.mu0 = 0.3; //make a copy Result r2(result); //r2.CopyFrom(&result); r2.mu = 0.2; r2.Delta[1000] = 7; result.PrintResult("Result.dat"); r2.PrintResult("Result.dat.c"); Result r3(&grid); // this way mu, n and mu0 are not read r3.ReadFromFile("Result.dat.c"); r3.n = 0.3; r3.PrintResult("Result.dat.cc"); return 0; }
void find_boundary_component_germs(GRID const& G, FACETSET & C, int& num_comps, int& num_facets) { typedef GRID grid_type; typedef grid_types<GRID> gt; typedef typename gt::Facet Facet; typedef typename gt::FacetIterator FacetIterator; typedef iscellinside_pred<grid_type> inside; typedef BoundaryComponentEdgeIterator2D<grid_type, inside> BCFacetIterator; partial_grid_function<Facet,bool> marked(G,false); num_comps = num_facets = 0; for(FacetIterator f = G.FirstFacet(); ! f.IsDone(); ++f) if( (! marked(*f)) && (G.IsOnBoundary(*f))) { C.push_back(*f); num_comps++; BCFacetIterator bf(*f,inside(G)); while(! bf.IsDone()) { num_facets++; marked[*bf] = true; ++bf; } } }
//##################################################################### // Constructor //##################################################################### template<class T,class RW> OPENGL_COMPONENT_THIN_SHELLS_DEBUGGING_3D<T,RW>:: OPENGL_COMPONENT_THIN_SHELLS_DEBUGGING_3D(const GRID<TV> &grid,const std::string& directory) :OPENGL_COMPONENT("Thin Shells Debugging"),grid(grid), invalid_color_map(OPENGL_COLOR::Red()), opengl_density_valid_mask(grid,density_valid_mask,&invalid_color_map,OPENGL_SCALAR_FIELD_3D<T,bool>::DRAW_POINTS), directory(directory),frame_loaded(-1),valid(false), draw_density_valid_mask(false),draw_node_neighbors_visible(false),draw_face_corners_visible(false) { is_animation=true; mac_grid=grid.Get_MAC_Grid();u_grid=grid.Get_X_Face_Grid();v_grid=grid.Get_Y_Face_Grid();w_grid=grid.Get_Z_Face_Grid(); }
int count_boundary_facets(GRID const& G) { typedef GRID grid_type; typedef grid_types<GRID> gt; typedef typename gt::FacetIterator FacetIterator; int nf = 0; for(FacetIterator f = G.FirstFacet(); ! f.IsDone(); ++f) if(G.IsOnBoundary(*f)) ++nf; return nf; }
/*! Initializes the grid for smoothing and fitmaps * * \param m Reference mesh * */ void initGrid(CMesh & m) { GRID* grid = new GRID(); vcg::tri::UpdateBounding<CMesh>::Box(m); vcg::tri::UpdateEdges<CMesh>::Set(m); grid->Set(m.face.begin(), m.face.end()); // grid->ShowStats(stdout); MyCollapse::grid() = grid; MyCollapseAdaptive::grid() = grid; }
void Compute_Cut_Geometries(const GRID<VECTOR<T,1> >& grid,const int num_ghost_cells,typename COLLISION_GEOMETRY_COLLECTION_POLICY<GRID<VECTOR<T,1> > >::GRID_BASED_COLLISION_GEOMETRY& collision_bodies_affecting_fluid,ARRAY<CUT_CELLS<T,1>*,VECTOR<int,1> >& cut_cells){ typedef VECTOR<T,1> TV; typedef VECTOR<int,1> TV_INT; for(typename GRID<TV>::CELL_ITERATOR iterator(grid,num_ghost_cells);iterator.Valid();iterator.Next()){ TV_INT index=iterator.Cell_Index();COLLISION_GEOMETRY_ID body_id; ARRAY<COLLISION_GEOMETRY_ID> collision_objects;collision_bodies_affecting_fluid.objects_in_cell.Get_Objects_For_Cell(index,collision_objects); if(!collision_objects.Size()) cut_cells(index)=0; else{ cut_cells(index) = new CUT_CELLS<T,1>();cut_cells(index)->dominant_element=0; RANGE<TV> cell_volume=iterator.Bounding_Box(); RAY<TV> l_to_r_ray(cell_volume.min_corner,cell_volume.max_corner-cell_volume.min_corner,true);l_to_r_ray.t_max=l_to_r_ray.direction.Normalize();l_to_r_ray.semi_infinite=false; RAY<TV> r_to_l_ray(cell_volume.max_corner,cell_volume.min_corner-cell_volume.max_corner,true);r_to_l_ray.t_max=r_to_l_ray.direction.Normalize();r_to_l_ray.semi_infinite=false; if(collision_bodies_affecting_fluid.Intersection_With_Any_Simplicial_Object(l_to_r_ray,body_id,&collision_objects)){ int poly_index=cut_cells(index)->geometry.Append(POLYGON<TV>(RANGE<TV>(cell_volume.min_corner, l_to_r_ray.Point(l_to_r_ray.t_max)))); TV centroid=ARRAYS_COMPUTATIONS::Average(cut_cells(index)->geometry(poly_index).X); cut_cells(index)->visibility.Resize(poly_index); if(!Is_Occluded_Cell_Center<T,1>(centroid,grid.Center(index),collision_bodies_affecting_fluid.objects_in_cell,collision_bodies_affecting_fluid.collision_geometry_collection,index)){ cut_cells(index)->dominant_element=poly_index; cut_cells(index)->visibility(poly_index).Append(index);} if(!cut_cells(index)->dominant_element) for(int node=1;!cut_cells(index)->dominant_element && node<=cut_cells(index)->geometry(poly_index).X.Size();++node) if(!Is_Occluded_Cell_Center<T,1>(cut_cells(index)->geometry(poly_index).X(node),grid.Center(index),collision_bodies_affecting_fluid.objects_in_cell,collision_bodies_affecting_fluid.collision_geometry_collection,index)){ cut_cells(index)->dominant_element=poly_index; cut_cells(index)->visibility(poly_index).Append(index);} TV_INT neighbor_cell_index=index-TV_INT::Axis_Vector(1); if(!Is_Occluded_Cell<T,1>(centroid,grid.Center(neighbor_cell_index),collision_bodies_affecting_fluid.objects_in_cell,collision_bodies_affecting_fluid.collision_geometry_collection,index,neighbor_cell_index)) cut_cells(index)->visibility(poly_index).Append(neighbor_cell_index);} if(collision_bodies_affecting_fluid.Intersection_With_Any_Simplicial_Object(r_to_l_ray,body_id,&collision_objects)){ int poly_index=cut_cells(index)->geometry.Append(POLYGON<TV>(RANGE<TV>(r_to_l_ray.Point(r_to_l_ray.t_max),cell_volume.max_corner))); TV centroid=ARRAYS_COMPUTATIONS::Average(cut_cells(index)->geometry(poly_index).X); cut_cells(index)->visibility.Resize(poly_index); if(!Is_Occluded_Cell_Center<T,1>(centroid,grid.Center(index),collision_bodies_affecting_fluid.objects_in_cell,collision_bodies_affecting_fluid.collision_geometry_collection,index)){ cut_cells(index)->dominant_element=poly_index; cut_cells(index)->visibility(poly_index).Append(index);} if(!cut_cells(index)->dominant_element) for(int node=1;!cut_cells(index)->dominant_element && node<=cut_cells(index)->geometry(poly_index).X.Size();++node) if(!Is_Occluded_Cell_Center<T,1>(cut_cells(index)->geometry(poly_index).X(node),grid.Center(index),collision_bodies_affecting_fluid.objects_in_cell,collision_bodies_affecting_fluid.collision_geometry_collection,index)){ cut_cells(index)->dominant_element=poly_index; cut_cells(index)->visibility(poly_index).Append(index);} TV_INT neighbor_cell_index=index+TV_INT::Axis_Vector(1); if(!Is_Occluded_Cell<T,1>(centroid,grid.Center(neighbor_cell_index),collision_bodies_affecting_fluid.objects_in_cell,collision_bodies_affecting_fluid.collision_geometry_collection,index,neighbor_cell_index)) cut_cells(index)->visibility(poly_index).Append(neighbor_cell_index);} if(!cut_cells(index)->geometry.Size()){delete cut_cells(index);cut_cells(index)=0;}}} }
bool isSphereInside(SPHERES& spheres, int index, GRID &grid) { float x = spheres.coords[index * 4]; float y = spheres.coords[index * 4 + 1]; float z = spheres.coords[index * 4 + 2]; float r = spheres.coords[index * 4 + 3]; double xl = grid.rminloc[0] - r; double yl = grid.rminloc[1] - r; double zl = grid.rminloc[2] - r; double xr = grid.rmaxloc[0] + r; double yr = grid.rmaxloc[1] + r; double zr = grid.rmaxloc[2] + r; fromCoordsToSpheresCoords(yl, spheres.rmin[1], spheres.rmax[1]); fromCoordsToSpheresCoords(zl, spheres.rmin[2], spheres.rmax[2]); fromCoordsToSpheresCoords(yr, spheres.rmin[1], spheres.rmax[1]); fromCoordsToSpheresCoords(zr, spheres.rmin[2], spheres.rmax[2]); bool chkX, chkY, chkZ; chkX = chkY = chkZ = true; if (grid.getDimensionality() >= 2) { if ((grid.rmaxloc[1] - grid.rminloc[1]) >= (spheres.rmax[1] - spheres.rmin[1])) chkY = true; else { if (yl <= yr) chkY = ((y >= yl) && (y <= yr)); else chkY = ((y >= yr) || (y <= yl)); } } if (grid.getDimensionality() == 3) { if ((grid.rmaxloc[2] - grid.rminloc[2]) >= (spheres.rmax[2] - spheres.rmin[2])) chkZ = true; else { if (zl <= zr) chkZ = ((z >= zl) && (z <= zr)); else chkZ = ((z >= zr) || (z <= zl)); } } return chkX && chkY && chkZ; }
//##################################################################### // Function Quadratic_Extrapolate //##################################################################### template<class TV,class T2> void EXTRAPOLATION_HIGHER_ORDER<TV,T2>:: Extrapolate_Face(const GRID<TV>& grid,const T_LEVELSET& phi,int ghost,ARRAY<T2,FACE_INDEX<TV::m> >& u,int iterations,int order,T distance) { for(int i=1;i<=TV::m;i++){ GRID<TV> node_grid(grid.Get_Axis_X_Face_Grid(i)); Extrapolate_Node(node_grid,phi,ghost,u.Component(i),iterations,order,distance);} }
LEVELSET<GRID<TV> >* createTriMeshAndLevelSet(const char* name) { string n = string(name); TRIANGULATED_SURFACE<float>* triangles = new TRIANGULATED_SURFACE<float>(); triangles->loadOBJ(name); triangles->Update_Bounding_Box_And_Gravity_Center(); RANGE<TV> range = triangles->bounding_box; range.min -= TV(0.2, 0.2, 0.2); range.max += TV(0.2, 0.2, 0.2); GRID<TV>* grid = new GRID<TV>(TV_INT(40,40,40), range); ARRAY<3,float>* phi = new ARRAY<3, float>(grid->Domain_Indices()); LEVELSET<GRID<TV> >* implicit_object = new LEVELSET<GRID<TV> >(*grid, *phi); SimLib::LEVELSET_MAKER<float> level_maker; ARRAY<3, int> closest_index; level_maker.Compute_Level_Set(*triangles, *grid, *phi, closest_index); ((LEVELSET<GRID<TV> >*)implicit_object)->Fast_Marching_Method(*triangles, closest_index); return implicit_object; }
//##################################################################### // Function Calculate_Blackbody_Spectrum //##################################################################### // radiance_spectrum is in units of Watts/(steradian*m^2)/m // input grid of wavelengths in nanometers template<class T> void BLACKBODY<T>:: Calculate_Radiance_Spectrum(const T temperature,const GRID<VECTOR<T,1> >& grid,ARRAY<T,VECTOR<int,1> >& radiance_spectrum) const { T constant_1=T(plancks_constant*sqr(speed_of_light)/2),constant_2=T(plancks_constant*speed_of_light/boltzmanns_constant); for(int i=1;i<=grid.counts.x;i++){ T lambda=grid.Axis_X(i,1); radiance_spectrum(i)=constant_1/(cube(lambda)*sqr(lambda)*(exp(constant_2/(lambda*temperature))-1));} }
//##################################################################### // Function Negative_Material //##################################################################### template<class TV> typename TV::SCALAR IMPLICIT_OBJECT_INTERSECTOR<TV>:: Negative_Material_In_Cell(const GRID<TV>& grid,const TV_INT& cell_index,const bool force_full_refinement) { // refinement step static TV_INT phi_indices[GRID<TV>::number_of_nodes_per_cell];grid.Nodes_In_Cell_From_Minimum_Corner_Node(cell_index,phi_indices); cell_particle_X.Resize(GRID<TV>::number_of_nodes_per_cell); for(int i=1;i<=GRID<TV>::number_of_nodes_per_cell;i++) cell_particle_X(i)=grid.Node(phi_indices[i-1]); cell_refinement_simplices.Remove_All();Refined_Object_Initialization_Helper(cell_refinement_simplices); int last_node=cell_particle_X.m; cell_phis.Resize(last_node); // compute phis for extant nodes T minimum_phi=FLT_MAX,maximum_phi=-FLT_MAX; for(int i=1;i<=last_node;i++){T& phi=cell_phis(i); phi=grid_nodal_phis(phi_indices[i-1]); if(phi<minimum_phi) minimum_phi=phi; if(phi>maximum_phi) maximum_phi=phi;} if(minimum_phi*maximum_phi>0 && min(abs(minimum_phi),abs(maximum_phi))>grid.Minimum_Edge_Length()) return minimum_phi<=0?full_cell_size:0; int unrefined_point_count=last_node; int last_parent_simplex=0,first_parent_simplex=1; for(int depth=0;depth<maximum_refinement_depth;depth++){ first_parent_simplex=last_parent_simplex+1; last_parent_simplex=cell_refinement_simplices.m; for(int s=last_parent_simplex;s>=first_parent_simplex;s--){ const T_ELEMENT simplex=cell_refinement_simplices(s); if(depth < minimum_refinement_depth || Refinement_Condition(cell_particle_X,cell_phis,simplex) || force_full_refinement){ last_parent_simplex--; cell_refinement_simplices.Remove_Index_Lazy(s); Refine_Simplex(*this,cell_refinement_simplices,cell_particle_X,simplex);}} cell_phis.Resize(cell_particle_X.m); // compute phis for extant nodes for(int i=last_node+1;i<=cell_phis.m;i++) cell_phis(i)=Phi(cell_particle_X(i)); last_node=cell_phis.m;} if(maximum_refinement_depth>0 && cell_phis.m==unrefined_point_count) return minimum_phi<=0?full_cell_size:0; // compute material T negative_material=0; for(int i=1;i<=cell_refinement_simplices.m;i++) negative_material+=T_SIMPLEX::Negative_Material(cell_particle_X,cell_phis,cell_refinement_simplices(i)); return clamp(negative_material,(T)0,full_cell_size); }
void manifold_checking_report(std::ostream& out, std::string const& grid_name, bool is_mf, GRID const& G, GF_F const& singular_facets, GF_V const& isolated_vertices, GF_V const& singular_interior_vertices, GF_V const& singular_boundary_vertices) { using namespace GrAL; typedef grid_types<GF_V> vgt; typedef grid_types<GF_F> fgt; out << "Grid \"" << grid_name << "\" is" << (is_mf ? " " : " NOT " ) << "a manifold grid.\n"; out << "|V|=" << G.NumOfVertices() << " |E|=" << G.NumOfEdges() << " |C|=" << G.NumOfCells() << std::endl; if(! is_mf) { if(singular_facets.size() > 0) { out << singular_facets.size() << " singular edges: "; for(typename fgt::EdgeIterator e = GrAL::begin_x(singular_facets); !e.IsDone(); ++e) out << "[" << (*e).v1() << "," << (*e).v2() << "] "; out << "\n"; } if(isolated_vertices.size() > 0) { out << isolated_vertices.size() << " isolated vertices: "; for(typename vgt::VertexIterator v = GrAL::begin_x(isolated_vertices); !v.IsDone(); ++v) out << v.handle() << ","; out << "\n"; } if(singular_interior_vertices.size() > 0) { out << singular_interior_vertices.size() << " singular interior vertices: "; for(typename vgt::VertexIterator v = GrAL::begin_x(singular_interior_vertices); !v.IsDone(); ++v) out << v.handle() << ","; out << "\n"; } if(singular_boundary_vertices.size() > 0) { out << singular_boundary_vertices.size() << " singular boundary vertices: "; for(typename vgt::VertexIterator v = GrAL::begin_x(singular_boundary_vertices); !v.IsDone(); ++v) out << v.handle() << ","; out << "\n"; } } }
void write_complex2d(GRID const& G, ::std::ostream& out, int offset, VCORR & G2Out_v, CCORR & G2Out_c) { typedef grid_types<GRID> gt; typedef typename gt::Vertex Vertex; typedef typename gt::Cell Cell; typedef typename gt::VertexIterator VertexIterator; typedef typename gt::CellIterator CellIterator; typedef typename gt::VertexOnCellIterator VertexOnCellIterator; out << G.NumOfVertices() << " " << G.NumOfCells() << "\n\n"; // if GRID is a subrange type, we cannot initialized grid-functions // directly with G, but must get hold of the underlying grid. // This solution is not optimal. There could be a c-t branch // with an additional grid-type parameter for grid-functions. typedef element_traits<Vertex> et; typedef typename et::grid_type base_grid_type; // possibly != GRID Vertex dummy(*(G.FirstVertex())); base_grid_type const& baseG(dummy.TheGrid()); grid_function<Vertex,int> VNum(baseG); int vnum = offset; for(VertexIterator v= G.FirstVertex(); ! v.IsDone(); ++v){ // out << Geo.coord(*v) << "\n"; VNum[*v] = vnum; G2Out_v[v.handle()] = vnum; vnum++; } out << "\n"; int cnum = offset; for(CellIterator c = GrAL::begin_x(G); !c.IsDone(); ++c){ out << (*c).NumOfVertices() << " "; G2Out_c[c.handle()] = cnum; ++cnum; for(VertexOnCellIterator vc = GrAL::begin_x(*c); ! vc.IsDone(); ++vc) out << VNum[*vc] << " "; out << "\n"; } }
int getSolution(int n, int m) { GRID g; VVV ava; VVB pos; MAP hash; g.resize(n); ava.resize(n); pos.resize(n); for (int i = 0; i < n; ++i) { ava[i].resize(m); g[i].resize(m); pos[i].resize(m); } int dots = 0; int count = 0; for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) { char c; cin >> g[i][j]; if (g[i][j] == '.') dots++; pos[i][j] = (g[i][j] == '.'); } for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) preProcess(g, i, j,ava); for (int i = 1; i <= dots; ++i) { int r = countQueen(g, i, 0, 0, ava, pos, hash); if (r == 0) break; count += r; count %= 1000000007; } return count; }
int main() { // Generate new map CA* reg = new CA(40,40); GRID map = reg->getMap(); // Print out the map char out = ' '; for (int x = 0; x < (int)map.size(); x++) { for (int y = 0; y < (int)map[x].size(); y++) { // map is full of bools, diff between them out = map[x][y] ? 'X' : ' '; std::cout << out; } std::cout << std::endl; } return 0; }
void write_complex2d(GRID const& G, GEOM const& Geo, ::std::ostream& out, int offset) { typedef grid_types<GRID> gt; typedef typename gt::Vertex Vertex; typedef typename gt::Cell Cell; typedef typename gt::VertexIterator VertexIterator; typedef typename gt::CellIterator CellIterator; typedef typename gt::VertexOnCellIterator VertexOnCellIterator; out << G.NumOfVertices() << " " << G.NumOfCells() << "\n\n"; // if GRID is a subrange type, we cannot initialized grid-functions // directly with G, but must get hold of the underlying grid. // This solution is not optimal. There could be a c-t branch // with an additional grid-type parameter for grid-functions. typedef element_traits<Vertex> et; typedef typename et::grid_type base_grid_type; // possibly != GRID Vertex dummy(*(G.FirstVertex())); ref_ptr<base_grid_type const> baseG(dummy.TheGrid()); grid_function<Vertex,int> VNum(* baseG); int vnum = offset; for(VertexIterator v= G.FirstVertex(); ! v.IsDone(); ++v){ out << std::setprecision(std::numeric_limits<double>::digits10) << Geo.coord(*v) << "\n"; VNum[*v] = vnum; vnum++; } out << "\n"; for(CellIterator c = G.FirstCell(); !c.IsDone(); ++c){ out << GrAL::size<Vertex>(*c) << " "; for(VertexOnCellIterator vc = GrAL::begin<Vertex>(*c); ! vc.IsDone(); ++vc) out << VNum[*vc] << " "; out << "\n"; } }
//##################################################################### // Function Quadratic_Extrapolate //##################################################################### template<class TV,class T2> void EXTRAPOLATION_HIGHER_ORDER<TV,T2>:: Extrapolate_Node(const GRID<TV>& grid,const T_LEVELSET& phi,int ghost,ARRAYS_ND_BASE<VECTOR<T2,TV::m> >& u,int iterations,int order,T distance) { PHYSBAM_ASSERT(order>=1 && order<=3); PHYSBAM_ASSERT(!grid.Is_MAC_Grid()); T dt=grid.dX.Max()/(TV::m+1); MAPPING m; ARRAY<TV> normal; ARRAY<VECTOR<STENCIL,TV::m> > stencil; Fill_Level(grid,phi,ghost,m,normal,stencil,order,distance); ARRAY<T2> du[3]; du[0].Resize(m.max_solve_index(2*order+1)); ARRAY<T2> tmp(m.max_solve_index(2*order+1)); for(int i=m.max_solve_index(1)+1;i<=m.max_solve_index(2*order+1);i++) du[0](i)=u(m.index_to_node(i)); for(int o=1;o<order;o++) Fill_un(m,grid.one_over_dX,normal,du[o-1],du[o],o,order); for(int i=0;i<order;i++) du[i](1)=FLT_MAX/100; // Sentinal values for ENO. tmp(1)=FLT_MAX/100; for(int o=order;o>0;o--) for(int i=1;i<=iterations;i++) Extrapolate_RK2(m,stencil,du[o-1],(o!=order?&du[o]:0),tmp,o,dt); for(int i=2;i<=m.max_solve_index(1);i++) u(m.index_to_node(i))=du[0](i); }
//##################################################################### // Function Compute_Level_Set //##################################################################### template<class T> void LEVELSET_MAKER_UNIFORM_2D<T>:: Compute_Level_Set(SEGMENTED_CURVE_2D<T>& curve,GRID<TV>& grid,int ghost_cells,ARRAY<T,TV_INT>& phi) { phi.Fill(FLT_MAX); T dx=grid.dX.Max(); ARRAY<bool,TV_INT> done(grid.Domain_Indices(ghost_cells+1)); for(int i=1;i<=curve.mesh.elements.m;i++){ SEGMENT_2D<T> segment(curve.particles.X(curve.mesh.elements(i).x),curve.particles.X(curve.mesh.elements(i).y)); RANGE<TV_INT> box(grid.Cell(segment.x1,3)); box.Enlarge_To_Include_Point(grid.Cell(segment.x2,3)); box=box.Intersect(box,grid.Domain_Indices(ghost_cells-1)); if(box.Empty()) continue; for(UNIFORM_ARRAY_ITERATOR<TV::m> it(box.Thickened(1));it.Valid();it.Next()){ TV X=grid.X(it.index); T dist=segment.Distance_From_Point_To_Segment(X); if(dist<abs(phi(it.index))+dx*1e-4 && dist<dx){ bool new_sign=TV::Dot_Product(X-segment.x1,segment.Normal())<0; if(abs(dist-abs(phi(it.index)))<dx*1e-4 && new_sign != (phi(it.index)<0)) new_sign=curve.Inside(grid.X(it.index)); if(abs(dist)<abs(phi(it.index))) phi(it.index)=dist; phi(it.index)=abs(phi(it.index))*(new_sign?-1:1); done(it.index)=true;}}} ARRAY<TV_INT> todo,next_todo; for(UNIFORM_GRID_ITERATOR_CELL<TV> it(grid);it.Valid();it.Next()) if(phi(it.index)!=FLT_MAX) todo.Append(it.index); for(int layer=1;todo.m;layer++){ while(todo.m){ TV_INT index=todo.Pop(); T next=sign(phi(index))*layer*dx; Compute_Level_Set_Helper(index+TV_INT(1,0),next,next_todo,phi); Compute_Level_Set_Helper(index-TV_INT(1,0),next,next_todo,phi); Compute_Level_Set_Helper(index+TV_INT(0,1),next,next_todo,phi); Compute_Level_Set_Helper(index-TV_INT(0,1),next,next_todo,phi);} todo.Exchange(next_todo);} /* for(UNIFORM_GRID_ITERATOR_CELL<TV> it(grid);it.Valid();it.Next()){ VECTOR<T,3> color=phi(it.index)>0?VECTOR<T,3>(0,1,0):VECTOR<T,3>(1,0,0); if(done(it.index)) color/=(T)3; Add_Debug_Particle(grid.X(it.index),color);}*/ PHYSBAM_DEBUG_WRITE_SUBSTEP("Compute Level Set",0,1); LEVELSET_2D<GRID<TV> > levelset(grid,phi); FAST_MARCHING_METHOD_UNIFORM<GRID<TV> > fmm(levelset,ghost_cells); fmm.Fast_Marching_Method(phi,done); }
//##################################################################### // Function Calculate //##################################################################### template<class T> void Calculate(SEGMENTED_CURVE_2D<T>& curve,const GRID<VECTOR<T,2> >& grid,ARRAY<T,VECTOR<int,2> >& phi,bool print_progress) { bool bounding_box_defined=curve.bounding_box!=0;if(!bounding_box_defined) curve.Update_Bounding_Box(); phi.Resize(1,grid.counts.x,1,grid.counts.y); T epsilon=(T)1e-8*grid.min_dX; int total_cells=grid.counts.x*grid.counts.y,cells_done=0,progress=-1; for(int i=1;i<=grid.counts.x;i++) for(int j=1;j<=grid.counts.y;j++){ phi(i,j)=curve.Calculate_Signed_Distance(grid.X(i,j),epsilon); if(print_progress){ cells_done++;int new_progress=(int)((T)100*cells_done/total_cells); if(new_progress > progress){ #ifndef COMPILE_WITHOUT_READ_WRITE_SUPPORT LOG::cout<<new_progress<<"% "<<std::flush; #endif progress=new_progress;}}} #ifndef COMPILE_WITHOUT_READ_WRITE_SUPPORT if(print_progress) LOG::cout<<std::endl; #endif if(!bounding_box_defined){delete curve.bounding_box;curve.bounding_box=0;} }
void EQS_KL2D::Execute( PROJECT* project, int steadyFlow ) { MODEL* model = project->M2D; GRID* rg = project->M2D->region; NODE** node = model->node; ELEM** elem = model->elem; int np = model->np; int ne = model->ne; int diverged_cg = 0; double theNorm = -1.0; double cm = project->KD.cm * project->KD.cd; model->Incinit(); // print information on actual iteration ----------------------------------------------- project->PrintTheCycle( 1 ); REPORT::rpt.PrintTime( 1 ); // set parameters according to time integration and relaxation ------------------------- double th = project->timeint.thetaTurb; double dt = project->timeint.incTime.Getsec(); if( fabs(th) < 1.0e-10 || fabs(dt) < 1.0e-10 ) { REPORT::rpt.Error( kParameterFault, "theta or timeInterval too small (EQS_KL2D::execute - 1)" ); } double thdt = 1.0 / dt / th; double dt_K; double relaxDt_KD = project->timeint.relaxTimeTurb.Getsec(); int relaxMethod = project->relaxMethod; if( steadyFlow ) { if( relaxMethod >= 3 ) // stationary flow time relaxed computation { dt_K = relaxDt_KD; relaxThdt_KD = 1.0 / dt_K; } else { dt_K = dt; relaxThdt_KD = 0.0; } for( int i=0; i<np; i++ ) node[i]->v.dKdt = 0.0; } else // instationary flow { if( relaxMethod >= 3 ) // instationary flow time relaxed computation { dt_K = relaxDt_KD; } else { dt_K = dt; } relaxThdt_KD = 1.0 / dt_K / th; // time prediction ------------------------------------------------------------------- for( int i=0; i<np; i++ ) { VARS* v = &(node[i]->v); /* VARS* vo = &(node[i]->vo); v->K = vo->K + vo->dKdt * dt; v->dKdt = (1.0 - 1.0/th)*vo->dKdt + thdt*(v->K - vo->K); */ v->dKdt = 0.0; } } if( model->Getinit() != modelInit ) { initStructure = true; modelInit = model->Getinit(); } // determine friction coefficients ----------------------------------------------------- model->DoFriction( project ); // set KD boundary conditions ---------------------------------------------------------- model->SetBoundKD( project ); // set up equation numbers ------------------------------------------------------------- project->fix[0] = BCON::kFixK; project->elemKind = ELEM::kRegion; SetEqno( model, 1, 0, 0, project->fix, project->elemKind ); double* B = (double*) MEMORY::memo.Array_eq( neq ); double* X = (double*) MEMORY::memo.Array_eq( neq ); if( !B || !X ) REPORT::rpt.Error( kMemoryFault, "can not allocate memory (EQS_KL2D::execute - 2)" ); // ------------------------------------------------------------------------------------- for( int it=0; it<project->actualCycit; it++ ) { double relax; int conv = true; // print information on actual iteration --------------------------------------------- if( it ) { project->PrintTheCycle( it+1 ); REPORT::rpt.PrintTime( 2 ); } // compute dissipation --------------------------------------------------------------- Dissipation( project ); // initialize Reynolds stresses and eddy viscosity ----------------------------------- rg->Turbulence( project ); // solve equations with frontal solving algorithm ------------------------------------ for( int i=0; i<neq; i++ ) X[i] = 0.0; diverged_cg = Solve( model, neq, B, X, project ); // statistics ------------------------------------------------------------------------ int noAbs, noPer; double maxAbs, maxPer, avAbs, avPer; REPORT::rpt.Message( 1, "\n\n %s\n\n %s\n\n", "(KLCycle) convergence parameters ...", " variable node average maximum" ); Update( model, &project->subdom, X, 0, kVarK, &maxAbs, &maxPer, &avAbs, &avPer, &noAbs, &noPer ); REPORT::rpt.Message( 1, " %1c %5d %12.5le %12.5le %s\n", 'K', noAbs, avAbs, maxAbs, " (abs)" ); REPORT::rpt.Message( 1, " %1c %5d %12.5lf %12.5lf %s\n\n", ' ', noPer, avPer, maxPer, " ( % )" ); if( fabs(maxAbs) > project->convKD ) conv = false; // determine relaxation parameter for NEWTON-RAPHSON --------------------------------- double minK = 0.0; double maxK = 0.0; switch( relaxMethod ) { case 2: theNorm = 0.0; maxK = 0.0; for( int i=0; i<np; i++ ) { int eqno; double dK = 0.0; eqno = GetEqno( node[i], 0 ); if( eqno >= 0 ) dK = fabs( X[eqno] ); theNorm += dK*dK; if( dK > maxK ) maxK = dK; } theNorm = sqrt( theNorm ); relax = project->maxDeltaKD / maxK; if( relax > 1.0 ) relax = 1.0; REPORT::rpt.Message( 1, "\n %s %12.4le\n %s %12.4le\n\n", " relaxation: norm =", theNorm, " relax =", relax ); break; case 3: case 4: REPORT::rpt.Message( 1, "\n %s %12.4le\n", "(KLCycle) relaxed time: dt_K =", dt_K ); if( dt_K < dt ) conv = false; theNorm = 0.0; maxK = 0.0; for( int i=0; i<np; i++ ) { int eqno; double dK = 0.0; eqno = GetEqno( node[i], 0 ); if( eqno >= 0 ) dK = fabs( X[eqno] ); theNorm += dK*dK; if( dK > maxK ) maxK = dK; } theNorm = sqrt( theNorm ); relax = project->maxDeltaKD / maxK; dt_K *= relax; if( dt_K > dt ) dt_K = dt; if( dt_K < relaxDt_KD ) dt_K = relaxDt_KD; if( steadyFlow ) relaxThdt_KD = 1.0 / dt_K; else relaxThdt_KD = 1.0 / dt_K / th; if( relax > 1.0 ) relax = 1.0; REPORT::rpt.Message( 1, "\n %s %12.4le\n %s %12.4le\n\n", " relaxation: norm =", theNorm, " relax =", relax ); break; default: relax = 1.0; theNorm = 0.0; for( int i=0; i<np; i++ ) { int eqno; double dK = 0.0; eqno = GetEqno( node[i], 0 ); if( eqno >= 0 ) dK = fabs( X[eqno] ); theNorm += dK*dK; } theNorm = sqrt( theNorm ); REPORT::rpt.Message( 1, "\n %s %12.4le\n %s %12.4le\n\n", " relaxation: norm =", theNorm, " relax =", relax ); break; } // update ---------------------------------------------------------------------------- for( int i=0; i<np; i++ ) { int n = GetEqno( node[i], 0 ); if( n >= 0 ) node[i]->v.K += relax * X[n]; } // check for range of values --------------------------------------------------------- int first = true; int jk = 0; for( int i=0; i<np; i++ ) { if( first ) { first = false; minK = maxK = node[i]->v.K; } else { if( node[i]->v.K < minK ) minK = node[i]->v.K; if( node[i]->v.K > maxK ) maxK = node[i]->v.K; } if( node[i]->v.K <= 0.0 ) { // node[i]->v.K = project->minK; node[i]->v.K = sqrt( node[i]->vt * node[i]->v.D / cm ); if( GetEqno(node[i],0) >= 0 ) jk++; } } if( jk ) { REPORT::rpt.Message( 1, " (KLCycle) %d %s\n\n", jk, "nodes with K out of range"); } REPORT::rpt.Message( 1, " (KLCycle) minimum of K: %le\n", minK ); REPORT::rpt.Message( 1, " maximum of K: %le\n", maxK ); // compute midside values (linear interpolation) ------------------------------------- for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; int ncn = el->Getncn(); int nnd = el->Getnnd(); for( int i=ncn; i<nnd; i++ ) { // get left and right corner node to midside node i int il, ir; double left, rght; el->GetQShape()->getCornerNodes( i, &il, &ir ); left = el->nd[il]->v.K; rght = el->nd[ir]->v.K; el->nd[i]->v.K = 0.5 * (left + rght); } } // compute time derivatives ---------------------------------------------------------- rg->ReportCuPe( dt, project->vk ); if( !steadyFlow ) { double iTheta; iTheta = 1.0 - 1.0 / project->timeint.thetaTurb; for( int i=0; i<np; i++ ) { if( isFS(node[i]->flag, NODE::kDry) || isFS(node[i]->flag, NODE::kMarsh) ) { node[i]->v.dKdt = 0.0; } else { double K, pK, pdKdt; VARS *v, *vo; v = &(node[i]->v); vo = &(node[i]->vo); K = v->K; pK = vo->K; pdKdt = vo->dKdt; // compute derivatives at actual time step node[i]->v.dKdt = iTheta*pdKdt + thdt*(K - pK); } } } if( conv ) break; } MEMORY::memo.Detach( B ); MEMORY::memo.Detach( X ); if( diverged_cg ) project->errLevel |= diverged_cg | kErr_no_conv_cg; }
void EQS_KL2D::Dissipation( PROJECT* project ) { double cm = project->KD.cm; double cd = project->KD.cd; MODEL* model = project->M2D; GRID* rg = model->region; // initialization ---------------------------------------------------------------------- for( int n=0; n<rg->Getnp(); n++ ) { NODE* nd = rg->Getnode(n); nd->v.D = 0.0; } double* ndarea = (double*) MEMORY::memo.Array_nd( rg->Getnp() ); for( int n=0; n<rg->Getnp(); n++ ) ndarea[n] = 0.0; // ------------------------------------------------------------------------------------- // loop on elements // ------------------------------------------------------------------------------------- for( int e=0; e<rg->Getne(); e++ ) { ELEM* el = rg->Getelem(e); if( !isFS(el->flag, ELEM::kDry) ) { TYPE* type = TYPE::Getid( el->type ); int nnd = el->Getnnd(); NODE** nd = el->nd; // --------------------------------------------------------------------------------- // compute coordinates relative to first node // --------------------------------------------------------------------------------- double xmin, xmax, ymin, ymax; double x[kMaxNodes2D], y[kMaxNodes2D]; xmin = xmax = x[0] = nd[0]->x; ymin = ymax = y[0] = nd[0]->y; for( int i=1; i<nnd; i++ ) { if( nd[i]->x < xmin ) xmin = nd[i]->x; if( nd[i]->x > xmax ) xmax = nd[i]->x; if( nd[i]->y < ymin ) ymin = nd[i]->y; if( nd[i]->y > ymax ) ymax = nd[i]->y; x[i] = nd[i]->x - x[0]; y[i] = nd[i]->y - y[0]; } x[0] = y[0] = 0.0; double lm = type->lm; // grid depending lm --------------------------------------------------------------- if( isFS(project->actualTurb, BCONSET::kVtLES) ) { lm *= sqrt( (xmax-xmin)*(ymax-ymin) ); } double area = el->area(); for( int i=0; i<nnd; i++ ) { double K = nd[i]->v.K; if( K <= 0.0 ) K = project->minK; double ls = lm / sqrt( sqrt(cm*cm*cm/cd) ); nd[i]->v.D += area * cd * sqrt(K*K*K) / ls; ndarea[nd[i]->Getno()] += area; } } } for( int n=0; n<rg->Getnp(); n++ ) { NODE* nd = rg->Getnode(n); if( ndarea[n] > 0.0 ) nd->v.D /= ndarea[n]; } MEMORY::memo.Detach( ndarea ); }
void PRECO_ILUT::Solve( PROJECT* project, EQS* eqs, double* B, double* X ) { int neq = crsi->m_neq; int neq_dn = crsi->m_neq_dn; int neq_up = crsi->m_neq_up; int* width = crsi->m_width; int** index = crsi->m_index; REALPR** ILU = crsi->m_A; //////////////////////////////////////////////////////////////////////////////////////// // 1. forward solve: manipulate vector B with lower part of matrix ILU // // 1.1 MPI: forward solve for interior subdomain nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 1.1\n" ); # endif for( int i=0; i<neq_up; i++ ) { X[i] = B[i]; for( int j=1; j<width[i]; j++ ) { int eq = index[i][j]; if( eq < i ) // L-matrix { X[i] += ILU[i][j] * X[eq]; } } } //////////////////////////////////////////////////////////////////////////////////////// // 1.2 MPI communication: // receive from subdomains with smaller pid (2 <- 1) // s < pid ==> upstream interface nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 1.2\n" ); # endif # ifdef _MPI_ if( project->subdom.npr > 1 ) { SUBDOM* subdom = &project->subdom; INFACE* inface = subdom->inface; MPI_Status status; int df = eqs->dfcn; for( int s=subdom->npr-1; s>=0; s-- ) { int np = inface[s].np; // number of interface nodes if( np > 0 && s < subdom->pid ) // upstream interface nodes { int cnt = 0; # ifdef _MPI_DBG { char text[200]; sprintf( text, " ### receiving from %d:", s+1 ); REPORT::rpt.Output( text ); } # endif MPI_Recv( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD, &status ); # ifdef _MPI_DBG { char text[200]; sprintf( text, " %d values\n", cnt ); REPORT::rpt.Output( text ); } # endif if( cnt ) { MPI_Recv( inface[s].recv, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD, &status ); cnt = 0; for( int n=0; n<np; n++ ) { NODE* nd = inface[s].node[n]; if( !isFS(nd->flag, NODE::kDry) ) // nothing received if node is dry... { SUB* sub = nd->sub; while( sub ) { if( sub->no == s ) break; sub = sub->next; } if( !sub->dry ) // ...or if the node is dry in { // any adjacent subdomain for( int e=0; e<df; e++ ) { int eqno = eqs->GetEqno( nd, e ); if( eqno >= 0 ) { X[eqno] = inface[s].recv[cnt]; cnt++; } } } } } } } } } //////////////////////////////////////////////////////////////////////////////////////// // 1.3 MPI: forward solve for upstream interface nodes // Note: X[i] is not initialized with B[i] since // this was performed in prior subdomain # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 1.3\n" ); # endif for( int i=neq_up; i<neq_dn; i++ ) { for( int j=1; j<width[i]; j++ ) { int eq = index[i][j]; if( eq < i ) { X[i] += ILU[i][j] * X[eq]; } } } //////////////////////////////////////////////////////////////////////////////////////// // 1.4 MPI: faktorisation of downstream interface nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 1.4\n" ); # endif for( int i=neq_dn; i<neq; i++ ) { X[i] = B[i]; for( int j=1; j<width[i]; j++ ) { int eq = index[i][j]; if( eq < neq_dn ) { X[i] += ILU[i][j] * X[eq]; } } } //////////////////////////////////////////////////////////////////////////////////////// // 1.5 MPI communication: // send to subdomains with larger pid (2 -> 3) // s > pid ==> downstream interface nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 1.5\n" ); # endif if( project->subdom.npr > 1 ) { SUBDOM* subdom = &project->subdom; INFACE* inface = subdom->inface; int df = eqs->dfcn; for( int s=0; s<subdom->npr; s++ ) { int np = inface[s].np; // number of interface nodes if( np > 0 && s > subdom->pid ) // downstream interface nodes { int cnt = 0; for( int n=0; n<np; n++ ) { NODE* nd = inface[s].node[n]; if( !isFS(nd->flag, NODE::kDry) ) // nothing to send if the node is dry... { SUB* sub = nd->sub; while( sub ) { if( sub->no == s ) break; sub = sub->next; } if( !sub->dry ) // ...or if the node is dry in { // any adjacent subdomain for( int e=0; e<df; e++ ) { int eqno = eqs->GetEqno( nd, e ); if( eqno >= 0 ) { inface[s].send[cnt] = X[eqno]; cnt++; } } } } } # ifdef _MPI_DBG { char text[200]; sprintf( text, " ### sending %d values to %d\n", cnt, s+1 ); REPORT::rpt.Output( text ); } # endif MPI_Send( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD ); if( cnt ) MPI_Send( inface[s].send, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD ); } } } # endif //////////////////////////////////////////////////////////////////////////////////////// # ifdef kDebug { FILE* dbg; char filename[80]; MODEL* model = project->M2D; GRID* region = model->region; if( project->subdom.npr == 1 ) sprintf( filename, "forwX.dbg" ); else sprintf( filename, "forwX_%02d.dbg", project->subdom.pid ); dbg = fopen( filename, "w" ); fprintf( dbg, "%d\n", region->Getnp() ); for( int n=0; n<region->Getnp(); n++ ) { NODE* nd = region->Getnode( n ); for( int e=0; e<eqs->dfcn; e++ ) { int eqno = eqs->GetEqno( nd, e ); fprintf( dbg, "%5d %1d ", nd->Getname(), e ); if( eqno >= 0 ) fprintf( dbg, "%14.6le\n", X[eqno] ); else fprintf( dbg, "%14.6le\n", 0.0 ); } } fclose( dbg ); } # endif # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) forward solve finished\n" ); # endif //////////////////////////////////////////////////////////////////////////////////////// // 2. solve for X with upper part of matrix ILU (backward substitution) // // 2.1 MPI communication: // receive from subdomains with larger pid (2 <- 3) // s > pid ==> downstream interface nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 2.1\n" ); # endif # ifdef _MPI_ if( project->subdom.npr > 1 ) { SUBDOM* subdom = &project->subdom; INFACE* inface = subdom->inface; MPI_Status status; int df = eqs->dfcn; for( int s=subdom->npr-1; s>=0; s-- ) { int np = inface[s].np; // number of interface nodes if( np > 0 && s > subdom->pid ) // downstream interface nodes { int cnt = 0; # ifdef _MPI_DBG { char text[200]; sprintf( text, " ### receiving from %d:", s+1 ); REPORT::rpt.Output( text ); } # endif MPI_Recv( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD, &status ); # ifdef _MPI_DBG { char text[200]; sprintf( text, " %d values\n", cnt ); REPORT::rpt.Output( text ); } # endif if( cnt ) { MPI_Recv( inface[s].recv, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD, &status ); cnt = 0; for( int n=0; n<np; n++ ) { NODE* nd = inface[s].node[n]; if( !isFS(nd->flag, NODE::kDry) ) // nothing received if node is dry... { SUB* sub = nd->sub; while( sub ) { if( sub->no == s ) break; sub = sub->next; } if( !sub->dry ) // ...or if the node is dry in { // any adjacent subdomain for( int e=0; e<df; e++ ) { int req = eqs->GetEqno( nd, e ); if( req >= 0 ) { X[req] = inface[s].recv[cnt]; cnt++; } } } } } } } } } //////////////////////////////////////////////////////////////////////////////////////// // 2.2 MPI: solve for upstream interface nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 2.2\n" ); # endif for( int i=neq_dn-1; i>=neq_up; i-- ) { for( int j=1; j<width[i]; j++ ) { int eq = index[i][j]; if( eq > i ) { X[i] -= ILU[i][j] * X[eq]; } } if( fabs(ILU[i][0]) < kZero ) REPORT::rpt.Error( kParameterFault, "division by zero - EQS::ILU_solver(1)" ); X[i] /= ILU[i][0]; } //////////////////////////////////////////////////////////////////////////////////////// // 2.3 MPI communication: // send to subdomains with smaller pid (2 -> 1) // s < pid ==> upstream interface nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 2.3\n" ); # endif if( project->subdom.npr > 1 ) { SUBDOM* subdom = &project->subdom; INFACE* inface = subdom->inface; int df = eqs->dfcn; for( int s=0; s<subdom->npr; s++ ) { int np = inface[s].np; // number of interface nodes if( np > 0 && s < subdom->pid ) // upstream interface nodes { int cnt = 0; for( int n=0; n<np; n++ ) { NODE* nd = inface[s].node[n]; if( !isFS(nd->flag, NODE::kDry) ) // nothing to send if node is dry... { SUB* sub = nd->sub; while( sub ) { if( sub->no == s ) break; sub = sub->next; } if( !sub->dry ) // ...or if the node is dry in { // any adjacent subdomain for( int e=0; e<df; e++ ) { int eqno = eqs->GetEqno( nd, e ); if( eqno >= 0 ) { inface[s].send[cnt] = X[eqno]; cnt++; } } } } } # ifdef _MPI_DBG { char text[200]; sprintf( text, " ### sending %d values to %d\n", cnt, s+1 ); REPORT::rpt.Output( text ); } # endif MPI_Send( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD ); if( cnt ) MPI_Send( inface[s].send, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD ); } } } # endif //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// // 2.4 MPI: backward solve for interior nodes # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) starting with 2.4\n" ); # endif for( int i=neq_up-1; i>=0; i-- ) { for( int j=1; j<width[i]; j++ ) { int eq = index[i][j]; if( eq > i ) { X[i] -= ILU[i][j] * X[eq]; } } if( fabs(ILU[i][0]) < kZero ) REPORT::rpt.Error( kParameterFault, "division by zero - EQS::ILU_solver(2)" ); X[i] /= ILU[i][0]; } # ifdef kDebug { FILE* dbg; char filename[80]; MODEL* model = project->M2D; GRID* region = model->region; if( project->subdom.npr == 1 ) sprintf( filename, "backX.dbg" ); else sprintf( filename, "backX_%02d.dbg", project->subdom.pid ); dbg = fopen( filename, "w" ); fprintf( dbg, "%d\n", region->Getnp() ); for( int n=0; n<region->Getnp(); n++ ) { NODE* nd = region->Getnode( n ); for( int e=0; e<eqs->dfcn; e++ ) { fprintf( dbg, "%5d %1d ", nd->Getname(), e ); int eqno = eqs->GetEqno( nd, e ); if( eqno >= 0 ) fprintf( dbg, "%14.6le\n", X[eqno] ); else fprintf( dbg, "%14.6le\n", 0.0 ); } } fclose( dbg ); } MPI_Barrier( MPI_COMM_WORLD ); # endif # ifdef _MPI_DBG REPORT::rpt.Output( " (PRECO_ILUT::Solve) backward solve finished\n" ); # endif }
int countQueen(GRID g, int n, int x, int y, const VVV& ava, VVB pos, MAP& hash) { if (n == 0) return 1; int count = 0; if (g[x][y] != '.') { y ++; if (y == g[0].size()) { y = 0; x ++; } if(x == g.size()) return count; count += countQueen(g, n, x, y, ava, pos, hash); count %= 1000000007; return count; } Key key; key.status = pos; key.n = n; MAP::iterator iter = hash.find(key); if(iter != hash.end()) { assert(key.n == iter->first.n); return iter->second; } if(pos[x][y]) { if(validate(g, x, y, ava)) { GRID cp(g); VVB cpb(pos); cp[x][y] = 'q'; resetPos(g, x, y, cpb); int r = countQueen(cp, n - 1, x, y, ava, cpb, hash); count += r; //countQueen(cp, n - 1, x, y, ava, cpb, hash); count %= 1000000007; } } pos[x][y] = false; bool record = (g[x][y] == '.'); y ++; if (y == g[0].size()) { y = 0; x ++; } if(x == g.size()) return count; count += countQueen(g, n, x, y, ava, pos, hash); count %= 1000000007; if (record) hash[key] = count; return count; }
void resetPos(const GRID & g, int i, int j, VVB& pos) { int x, y; //down check x = i, y = j; while(x < g.size() && g[x][y] != '#') { pos[x][y]=false; --x; } //left check x = i, y = j; while(y < g[0].size() && g[x][y] != '#') { pos[x][y]=false; --y; } //up left check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { pos[x][y]=false; --x, --y; } //up right check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { pos[x][y]=false; --x, ++y; } //down check x = i, y = j; while(x < g.size() && g[x][y] != '#') { pos[x][y]=false; ++x; } //right check x = i, y = j; while(y < g[0].size() && g[x][y] != '#') { pos[x][y]=false; ++y; } //down left check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { pos[x][y]=false; ++x, --y; } //down right check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { pos[x][y]=false; ++x, ++y; } }
int main(int narg, char **args) { GRID grid; EM_FIELD myfield; CURRENT current; std::vector<SPECIE*> species; std::vector<SPECIE*>::const_iterator spec_iterator; gsl_rng* rng = gsl_rng_alloc(gsl_rng_ranlxd1); //*******************************************BEGIN GRID DEFINITION******************************************************* grid.setXrange(-50.0, 0.0); grid.setYrange(-15.0, 15.0); grid.setZrange(-1, +1); grid.setNCells(1536, 512, 1); grid.setNProcsAlongY(NPROC_ALONG_Y); grid.setNProcsAlongZ(NPROC_ALONG_Z); //grid.enableStretchedGrid(); //grid.setXandNxLeftStretchedGrid(-20.0,1000); //grid.setYandNyLeftStretchedGrid(-8.0,21); //grid.setXandNxRightStretchedGrid(20.0,1000); //grid.setYandNyRightStretchedGrid(8.0,21); grid.setBoundaries(xOpen | yPBC | zPBC); grid.mpi_grid_initialize(&narg, args); grid.setCourantFactor(0.98); grid.setSimulationTime(100.0); grid.with_particles = YES;//NO; grid.with_current = YES;//YES; grid.setStartMovingWindow(0); //grid.setBetaMovingWindow(1.0); //grid.setFrequencyMovingWindow(20); grid.setMasterProc(0); srand(time(NULL)); grid.initRNG(rng, RANDOM_NUMBER_GENERATOR_SEED); grid.finalize(); grid.visualDiag(); //********************************************END GRID DEFINITION******************************************************** //*******************************************BEGIN FIELD DEFINITION********************************************************* myfield.allocate(&grid); myfield.setAllValuesToZero(); laserPulse pulse1; pulse1.setGaussianPulse(); pulse1.setWaist(4.0); pulse1.setDurationFWHM(10.0); pulse1.setNormalizedAmplitude(0.5); pulse1.setCircularPolarization(); pulse1.setPulseInitialPosition(-10.1); pulse1.setFocusPosition(0.0); pulse1.setLambda(1.0); pulse1.setFocusPosition(0.0); // pulse1.setRotationAngleAndCenter(2.0*M_PI*(-30.0 / 360.0), 0.0); myfield.addPulse(&pulse1); myfield.boundary_conditions(); current.allocate(&grid); current.setAllValuesToZero(); //*******************************************END FIELD DEFINITION*********************************************************** //*******************************************BEGIN SPECIES DEFINITION********************************************************* PLASMA plasma1; plasma1.density_function = box; plasma1.setXRangeBox(0.0, 100.0); plasma1.setYRangeBox(grid.rmin[1], grid.rmax[1]); plasma1.setZRangeBox(grid.rmin[2], grid.rmax[2]); plasma1.setDensityCoefficient(0.0025); SPECIE electrons1(&grid); electrons1.plasma = plasma1; electrons1.setParticlesPerCellXYZ(2, 2, 2); electrons1.setName("ELE1"); electrons1.type = ELECTRON; electrons1.creation(); species.push_back(&electrons1); SPECIE ions1(&grid); ions1.plasma = plasma1; ions1.setParticlesPerCellXYZ(2, 2, 2); ions1.setName("ION1"); ions1.type = ION; ions1.Z = 6.0; ions1.A = 12.0; //ions1.creation(); //species.push_back(&ions1); //tempDistrib distribution; //distribution.setWaterbag(1.0e-8); //electrons1.add_momenta(rng,0.0,0.0,0.0,distribution); //ions1.add_momenta(rng,0.0, 0.0, 0.0, distribution); for (spec_iterator = species.begin(); spec_iterator != species.end(); spec_iterator++){ (*spec_iterator)->printParticleNumber(); } //*******************************************END SPECIED DEFINITION*********************************************************** //*******************************************BEGIN DIAGNOSTICS DEFINITION************************************************** OUTPUT_MANAGER manager(&grid, &myfield, ¤t, species); // manager.addEBFieldFrom(0.0,10.0); // manager.addSpeciesDensityFrom(electrons1.name, 0.0, 10.0); // manager.addSpeciesPhaseSpaceFrom(electrons1.name, 0.0, 10.0); // //manager.addSpeciesDensityFrom(ions1.name, 0.0, 1.0); // manager.addDiagFrom(0.0, 1.0); manager.initialize(DIRECTORY_OUTPUT); //*******************************************END DIAGNOSTICS DEFINITION************************************************** grid.setDumpPath(DIRECTORY_DUMP); //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MAIN CYCLE (DO NOT MODIFY!!) @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (grid.myid == grid.master_proc){ printf("----- START temporal cicle -----\n"); fflush(stdout); } int Nstep = grid.getTotalNumberOfTimesteps(); int dumpID = 1, dumpEvery; if (DO_DUMP){ dumpEvery = (int)(TIME_BTW_DUMP / grid.dt); } grid.istep = 0; if (_DO_RESTART){ dumpID = _RESTART_FROM_DUMP; restartFromDump(&dumpID, &grid, &myfield, species); } while (grid.istep <= Nstep) { grid.printTStepEvery(FREQUENCY_STDOUT_STATUS); manager.callDiags(grid.istep); myfield.openBoundariesE_1(); myfield.new_halfadvance_B(); myfield.boundary_conditions(); current.setAllValuesToZero(); for (spec_iterator = species.begin(); spec_iterator != species.end(); spec_iterator++){ (*spec_iterator)->current_deposition_standard(¤t); } current.pbc(); for (spec_iterator = species.begin(); spec_iterator != species.end(); spec_iterator++){ (*spec_iterator)->position_parallel_pbc(); } myfield.openBoundariesB(); myfield.new_advance_E(¤t); myfield.boundary_conditions(); myfield.openBoundariesE_2(); myfield.new_halfadvance_B(); myfield.boundary_conditions(); for (spec_iterator = species.begin(); spec_iterator != species.end(); spec_iterator++){ (*spec_iterator)->momenta_advance(&myfield); } grid.time += grid.dt; moveWindow(&grid, &myfield, species); grid.istep++; if (DO_DUMP){ if (grid.istep != 0 && !(grid.istep % (dumpEvery))) { dumpFilesForRestart(&dumpID, &grid, &myfield, species); } } } manager.close(); MPI_Finalize(); exit(1); }
void run_Zmatrices_calculation_scattered_field(Zmatrices& Z_matrices, UINT Lagrange_degree, MATRIX M, MATRIX J, GRID& rho, double material_param, const char* result_file) { // Simulation parameters int N_T = Z_matrices.z_N_T; double dt = Z_matrices.z_dt; double c = Z_matrices.z_c; UINT inner_points = 1; printf("\nSimulation parameters for scattered field:" "\n\tNumber of grid vertices = %i" "\n\tMaterial parameter = %e" "\n\tc = %e" "\n\tdt = %e" "\n\tN_T = %i" "\n\tinner_points = %i" "\n\tLagrange_degree = %i\n\n", (int)rho.size(), material_param, c, dt, N_T, inner_points, Lagrange_degree); // Lagrange interpolators (temporal basis functions) CLagrange_interp timeBasis = CLagrange_interp(dt, Lagrange_degree); Z_matrices.timeBasis_D = timeBasis; CLagrange_interp timeBasis_Ns = timeBasis; timeBasis_Ns.diff(); Z_matrices.timeBasis_Ns = timeBasis_Ns; Z_matrices.z_inner_points = inner_points; // do main computation cube S, D; #ifdef OS_WIN clock_t t; #else struct timeval * t = new struct timeval; #endif start_timing(t); Z_matrices.compute_fields(S, D, rho); S *= material_param; finish_timing(t); start_timing(t); MATRIX rhs(D.n_rows, N_T, fill::zeros); VECTOR rhs_(D.n_rows, fill::zeros); printf("%s\n\n", "Marching on in time..."); int j(0), k(0); //#pragma omp parallel default(shared) private(j,k) for (j = 0; j < N_T; j++) { //#pragma omp for for (k = 0; k < j+1; k++) { rhs_ += D.slice(k)*M.col(j - k) - S.slice(k)*J.col(j - k); } rhs.col(j) = rhs_; rhs_.zeros(); //Status printf("\r%i ", j + 1); fflush(stdout); } finish_timing(t); // Output MAT file that stores the operators printf("Compressing matrices into Matlab form..."); mat_t *matfpZ = NULL; matvar_t *matvar = NULL; // Save matrices as separate matlab variables if (CreateMatFile(&matfpZ, result_file) == -1) { return; } else { double NT = (double)N_T; InsertVar(&matfpZ, "N_T", &NT); InsertMatrix(&matfpZ, "E", rhs); FinishMatFile(&matfpZ); // free memory S.clear(), D.clear(); printf("\t- done.\nOutput file location: %s\n\n", result_file); } }
void EQS_KD2D::Execute( PROJECT* project, int steadyFlow, int shape ) { switch( shape ) { case 0: linearShape = false; quarterShape = false; break; case 1: linearShape = true; quarterShape = false; break; case 2: linearShape = false; quarterShape = true; break; } MODEL* model = project->M2D; GRID* rg = project->M2D->region; NODE** node = model->node; ELEM** elem = model->elem; int np = model->np; int ne = model->ne; int diverged_cg = 0; double* B = NULL; double* xKD = NULL; double* xKDo = NULL; double* cxKo = NULL; double* cxDo = NULL; model->Incinit(); // print information on actual iteration ----------------------------------------------- project->PrintTheCycle( 1 ); REPORT::rpt.PrintTime( 1 ); // set parameters according to time integration and relaxation ------------------------- double th = project->timeint.thetaTurb; double dt = project->timeint.incTime.Getsec(); if( fabs(th) < 1.0e-10 && fabs(dt) < 1.0e-10 ) { REPORT::rpt.Error( kParameterFault, "theta and timeInterval too small (EQS_KD2D::execute - 1)" ); } double thdt = 1.0 / dt / th; double dt_KD; double relaxDt_KD = project->timeint.relaxTimeTurb.Getsec(); int relaxMethod = project->relaxMethod; if( steadyFlow ) { if( relaxMethod >= 3 ) { dt_KD = relaxDt_KD; relaxThdt_KD = 1.0 / dt_KD; } else { dt_KD = dt; relaxThdt_KD = 0.0; } for( int i=0; i<np; i++ ) { node[i]->v.dKdt = 0.0; node[i]->v.dDdt = 0.0; } } else { if( relaxMethod >= 3 ) { dt_KD = relaxDt_KD; } else { dt_KD = dt; } relaxThdt_KD = 1.0 / dt_KD / th; // time prediction ------------------------------------------------------------------- for( int i=0; i<np; i++ ) { VARS* v = &(node[i]->v); //VARS* vo = &(node[i]->vo); //v->K = vo->K + vo->dKdt * dt; //v->D = vo->D + vo->dDdt * dt; //v->dKdt = (1.0 - 1.0/th)*vo->dKdt + thdt*(v->K - vo->K); //v->dDdt = (1.0 - 1.0/th)*vo->dDdt + thdt*(v->D - vo->D); v->dKdt = 0.0; v->dDdt = 0.0; } } // check KD-values for validity (>= 0) ------------------------------------------------- Validate( project, np, node ); // determine friction coefficients ----------------------------------------------------- model->DoFriction( project ); // initialize Reynolds stresses and eddy viscosity ------------------------------------- rg->Turbulence( project ); // set KD boundary conditions ---------------------------------------------------------- model->SetBoundKD( project ); // ------------------------------------------------------------------------------------- // in case of quartered elements: // compute averaged values of U, V, S, K and D for the virtual center node in quads int nq = 0; double* cxK = NULL; double* cxD = NULL; if( quarterShape ) { // count number of quadrilaterals for( int e=0; e<ne; e++ ) { if( elem[e]->Getncn() == 4 ) nq++; } // allocate memory for nq center nodes if( !cbuf ) cbuf = new NODE [nq]; if( !cbuf ) { REPORT::rpt.Error( kMemoryFault, "cannot allocate memory (EQS_KD2D::execute - 2)" ); } cent = (NODE**) MEMORY::memo.Array_el( ne ); cxK = (double*) MEMORY::memo.Array_el( ne ); cxD = (double*) MEMORY::memo.Array_el( ne ); nq = 0; for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; if( isFS(el->flag, ELEM::kRegion) ) { int no = el->Getno(); int ncn = el->Getncn(); cent[no] = NULL; if( ncn == 4 ) { cent[no] = &cbuf[nq++]; cent[no]->Setno( no ); cent[no]->x = 0.0; cent[no]->y = 0.0; cent[no]->z = 0.0; cent[no]->cf = 0.0; cent[no]->v.U = 0.0; cent[no]->v.V = 0.0; cent[no]->v.S = 0.0; cent[no]->v.K = 0.0; cent[no]->v.D = 0.0; cent[no]->v.dKdt = 0.0; cent[no]->v.dDdt = 0.0; for( int i=0; i<ncn; i++ ) { cent[no]->x += el->nd[i]->x; cent[no]->y += el->nd[i]->y; cent[no]->z += el->nd[i]->z; cent[no]->cf += el->nd[i]->cf; cent[no]->v.U += el->nd[i]->v.U; cent[no]->v.V += el->nd[i]->v.V; cent[no]->v.S += el->nd[i]->v.S; cent[no]->v.K += el->nd[i]->v.K; cent[no]->v.D += el->nd[i]->v.D; cent[no]->v.dKdt += el->nd[i]->v.dKdt; cent[no]->v.dDdt += el->nd[i]->v.dDdt; } cent[no]->x /= ncn; cent[no]->y /= ncn; cent[no]->z /= ncn; cent[no]->cf /= ncn; cent[no]->v.U /= ncn; cent[no]->v.V /= ncn; cent[no]->v.S /= ncn; cent[no]->v.K /= ncn; cent[no]->v.D /= ncn; cent[no]->v.dKdt /= ncn; cent[no]->v.dDdt /= ncn; } } } } // ------------------------------------------------------------------------------------- // iteration loop double dt_KDo = 0.0; double relaxo = 1.0; double maxKDo = -1.0; int conv; for( int it=0; it<project->actualCycit; it++ ) { conv = true; // print information on actual iteration --------------------------------------------- if( it > 0 ) { project->PrintTheCycle( it+1 ); REPORT::rpt.PrintTime( 1 ); } // initialize Reynolds stresses and eddy viscosity ----------------------------------- if( it > 0 && isFS(project->actualTurb, BCONSET::kVtIterat) && !isFS(project->actualTurb, BCONSET::kVtPrandtlKol) ) { rg->Turbulence( project ); } // set up equation numbers ----------------------------------------------------------- if( model->Getinit() != modelInit ) { initStructure = true; modelInit = model->Getinit(); project->fix[0] = BCON::kFixK; project->fix[1] = BCON::kFixD; project->elemKind = ELEM::kRegion; if( linearShape ) { SetEqno( model, 2, 0, 0, project->fix, project->elemKind ); } else { SetEqno( model, 2, 2, 0, project->fix, project->elemKind ); } if( B ) MEMORY::memo.Detach( B ); if( xKD ) MEMORY::memo.Detach( xKD ); B = (double*) MEMORY::memo.Array_eq( neq ); xKD = (double*) MEMORY::memo.Array_eq( neq ); // allocate memory for relaxed Newton-Rahpson if( relaxMethod >= 3 ) { xKDo = (double*) MEMORY::memo.Array_eq( neq ); if( quarterShape ) { cxKo = (double*) MEMORY::memo.Array_el( ne ); cxDo = (double*) MEMORY::memo.Array_el( ne ); } } } // solve equations with frontal solving algorithm ------------------------------------ for( int i=0; i<neq; i++ ) xKD[i] = 0.0; diverged_cg = Solve( model, neq, B, xKD, project ); // ----------------------------------------------------------------------------------- // determine new values for K and D at virtual center nodes if( quarterShape ) { for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; if( isFS(el->flag, ELEM::kRegion) ) { int no = el->Getno(); int ncn = el->Getncn(); if( ncn == 4 ) { Coefs( el, project, estifm, force ); cxK[no] = force[16]; cxD[no] = force[17]; for( int i=0; i<8; i++ ) { int eqK = GetEqno( el->nd[i], 0 ); int eqD = GetEqno( el->nd[i], 1 ); cxK[no] -= estifm[16][i] * xKD[eqK] + estifm[16][i+8] * xKD[eqD]; cxD[no] -= estifm[17][i] * xKD[eqK] + estifm[17][i+8] * xKD[eqD]; } cxK[no] /= estifm[16][16]; cxD[no] -= estifm[17][16] * cxK[no]; cxD[no] /= estifm[17][17]; } } } } // ----------------------------------------------------------------------------------- // statistics REPORT::rpt.Message( 2, "\n\n%-25s%s\n\n %s\n\n", " (EQS_KD2D::Execute)", "convergence parameters ...", " variable node average maximum" ); // compute averaged changes and standard deviation of K and D ------------------------ double stdevK = 0.0; double stdevD = 0.0; double aveAbsK = 0.0; double aveAbsD = 0.0; for( int i=0; i<np; i++ ) { int eqno; double dK = 0.0; double dD = 0.0; eqno = GetEqno( node[i], 0 ); if( eqno >= 0 ) dK = xKD[eqno]; eqno = GetEqno( node[i], 1 ); if( eqno >= 0 ) dD = xKD[eqno]; aveAbsK += dK; stdevK += dK*dK; aveAbsD += dD; stdevD += dD*dD; } if( quarterShape ) { for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; if( isFS(el->flag, ELEM::kRegion) ) { int no = el->Getno(); int ncn = el->Getncn(); if( ncn == 4 ) { double dK = cxK[no]; double dD = cxD[no]; aveAbsK += dK; stdevK += dK*dK; aveAbsD += dD; stdevD += dD*dD; } } } } // ----------------------------------------------------------------------------------- int nptot = 0; for( int i=0; i<np; i++ ) { NODE* nd = rg->Getnode(i); if( !isFS(nd->flag, NODE::kInface_DN) ) nptot++; } ////////////////////////////////////////////////////////////////////////////////////// // MPI: broadcast statistic # ifdef _MPI_ aveAbsK = project->subdom.Mpi_sum( aveAbsK ); stdevK = project->subdom.Mpi_sum( stdevK ); aveAbsD = project->subdom.Mpi_sum( aveAbsD ); stdevD = project->subdom.Mpi_sum( stdevD ); nptot = project->subdom.Mpi_sum( nptot ); # endif ////////////////////////////////////////////////////////////////////////////////////// aveAbsK /= nptot; stdevK = sqrt( stdevK / nptot ); aveAbsD /= nptot; stdevD = sqrt( stdevD / nptot ); double norm = stdevK + stdevD; double fractK = 2.0 * sqrt( stdevK ); double fractD = 2.0 * sqrt( stdevD ); // compute maximum changes of K and D limited to ~95% fractile ----------------------- int cntK = 0; int cntD = 0; int noPerK = 0; double avePerK = 0.0; double maxPerK = 0.0; int noAbsK = 0; double maxAbsK = 0.0; int noPerD = 0; double avePerD = 0.0; double maxPerD = 0.0; int noAbsD = 0; double maxAbsD = 0.0; for( int i=0; i<np; i++ ) { int eqno; double dK = 0.0; double dD = 0.0; eqno = GetEqno( node[i], 0 ); if( eqno >= 0 ) { dK = xKD[eqno]; if( fabs(dK) > project->maxDeltaKD && fabs(dK) > fractK ) { xKD[eqno] = dK/fabs(dK) * fractK; } } eqno = GetEqno( node[i], 1 ); if( eqno >= 0 ) { dD = xKD[eqno]; if( fabs(dD) > project->maxDeltaKD && fabs(dD) > fractD ) { xKD[eqno] = dD/fabs(dD) * fractD; } } // maximum changes and percentage if( node[i]->v.K + dK > 0.0 ) { if( fabs(dK) > fabs(maxAbsK) ) { maxAbsK = dK; noAbsK = node[i]->Getname(); } if( node[i]->v.K > 0.0 ) { double per = dK / node[i]->v.K; avePerK += fabs(per); cntK++; if( fabs(per) > fabs(maxPerK) ) { maxPerK = per; noPerK = node[i]->Getname(); } } } if( node[i]->v.D + dD > 0.0 ) { if( fabs(dD) > fabs(maxAbsD) ) { maxAbsD = dD; noAbsD = node[i]->Getname(); } if( node[i]->v.D > 0.0 ) { double per = dD / node[i]->v.D; avePerD += fabs(per); cntD++; if( fabs(per) > fabs(maxPerD) ) { maxPerD = per; noPerD = node[i]->Getname(); } } } } if( quarterShape ) { for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; if( isFS(el->flag, ELEM::kRegion) ) { int no = el->Getno(); int ncn = el->Getncn(); if( ncn == 4 ) { double dK = cxK[no]; double dD = cxD[no]; if( fabs(dK) > project->maxDeltaKD && fabs(dK) > fractK ) { cxK[no] = dK/fabs(dK) * fractK; } if( fabs(dD) > project->maxDeltaKD && fabs(dD) > fractD ) { cxD[no] = dD/fabs(dD) * fractD; } // maximum changes and percentage if( cent[no]->v.K + dK > 0.0 ) { if( fabs(dK) > fabs(maxAbsK) ) { maxAbsK = dK; noAbsK = -(no+1); } if( cent[no]->v.K > 0.0 ) { double per = dK / cent[no]->v.K; avePerK += fabs(per); cntK++; if( fabs(per) > fabs(maxPerK) ) { maxPerK = per; noPerK = -(no+1); } } } if( cent[no]->v.D + dD > 0.0 ) { if( fabs(dD) > fabs(maxAbsD) ) { maxAbsD = dD; noAbsD = -(no+1); } if( cent[no]->v.D > 0.0 ) { double per = dD / cent[no]->v.D; avePerD += fabs(per); cntD++; if( fabs(per) > fabs(maxPerD) ) { maxPerD = per; noPerD = -(no+1); } } } } } } } ////////////////////////////////////////////////////////////////////////////////////// // MPI: broadcast statistic # ifdef _MPI_ cntK = project->subdom.Mpi_sum( cntK ); maxAbsK = project->subdom.Mpi_maxabs( maxAbsK ); avePerK = project->subdom.Mpi_sum( avePerK ); maxPerK = project->subdom.Mpi_maxabs( maxPerK ); cntD = project->subdom.Mpi_sum( cntD ); maxAbsD = project->subdom.Mpi_maxabs( maxAbsD ); avePerD = project->subdom.Mpi_sum( avePerD ); maxPerD = project->subdom.Mpi_maxabs( maxPerD ); # endif ////////////////////////////////////////////////////////////////////////////////////// avePerK /= cntK; avePerD /= cntD; REPORT::rpt.Message( 2, " %1c %5d %12.5le %12.5le %s\n", 'K', noAbsK+1, aveAbsK, maxAbsK, " (abs)" ); REPORT::rpt.Message( 2, " %1c %5d %12.5lf %12.5lf %s\n\n", ' ', noPerK+1, avePerK, maxPerK, " ( % )" ); REPORT::rpt.Message( 2, " %1c %5d %12.5le %12.5le %s\n", 'D', noAbsD+1, aveAbsD, maxAbsD, " (abs)" ); REPORT::rpt.Message( 2, " %1c %5d %12.5lf %12.5lf %s\n\n", ' ', noPerD+1, avePerD, maxPerD, " ( % )" ); if( fabs(maxAbsK) > project->convKD ) conv = false; if( fabs(maxAbsD) > project->convKD ) conv = false; // determine relaxation parameter for NEWTON-RAPHSON --------------------------------- double relax; double maxKD = fabs(maxAbsK); if( fabs(maxAbsD) > maxKD ) maxKD = fabs(maxAbsD); switch( relaxMethod ) { default: REPORT::rpt.Warning( kParameterFault, "relaxation method %d not supported", relaxMethod ); case 0: relax = 1.0; REPORT::rpt.Message( 2, "\n%-25s%s %12.4le\n%-25s%s %12.4le\n\n", " ", "relaxation (0): norm =", norm, " ", " relax =", relax ); break; case 2: relax = project->maxDeltaKD / maxKD; if( relax > 1.0 ) relax = 1.0; REPORT::rpt.Message( 2, "\n%-25s%s %12.4le\n%-25s%s %12.4le\n\n", " ", "relaxation (2): norm =", norm, " ", " relax =", relax ); break; case 3: REPORT::rpt.Message( 2, "\n%-25s%s %12.4le\n", " ", "relaxed time: dt_KD =", dt_KD ); if( dt_KD < dt ) conv = false; relax = project->maxDeltaKD / maxKD; dt_KD *= relax; if( dt_KD > dt ) dt_KD = dt; if( dt_KD < relaxDt_KD ) dt_KD = relaxDt_KD; if( steadyFlow ) relaxThdt_KD = 1.0 / dt_KD; else relaxThdt_KD = 1.0 / dt_KD / th; if( relax > 1.0 ) relax = 1.0; REPORT::rpt.Message( 2, "\n%-25s%s %12.4le\n%-25s%s %12.4le\n\n", " ", "relaxation (3): norm =", norm, " ", " relax =", relax ); break; case 4: REPORT::rpt.Message( 2, "\n%-25s%s %12.4le\n", " ", "relaxed time: dt_KD =", dt_KD ); if( dt_KD < dt ) conv = false; relax = project->maxDeltaKD / maxKD; if( relax < project->relaxMax ) { if( maxKDo < 0.0 || maxKD < maxKDo ) // initialisation: maxKDo = -1 { if( relax < project->relaxMin ) relax = project->relaxMin; dt_KDo = dt_KD; maxKDo = maxKD; } else { if( relaxo > 1.01 * project->relaxMin ) { // relaxed Newton-Raphson: restore K and D from previous iteration for( int i=0; i<np; i++ ) { int n; n = GetEqno( node[i], 0 ); if( n >= 0 ) { node[i]->v.K -= relaxo * xKDo[n]; xKD[n] = xKDo[n]; } n = GetEqno( node[i], 1 ); if( n >= 0 ) { node[i]->v.D -= relaxo * xKDo[n]; xKD[n] = xKDo[n]; } } if( quarterShape ) { for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; if( isFS(el->flag, ELEM::kRegion) ) { if( el->Getncn() == 4 ) { int no = el->Getno(); cent[no]->v.K -= relaxo * cxKo[no]; cent[no]->v.D -= relaxo * cxDo[no]; cxK[no] = cxKo[no]; cxD[no] = cxDo[no]; } } } } } if( relax < project->relaxMin ) relax = project->relaxMin; dt_KDo = dt_KD; dt_KD *= relax; // decrease dt_KD if( dt_KD < relaxDt_KD ) dt_KD = relaxDt_KD; maxKDo = maxKD; } } else { dt_KDo = dt_KD; if( relax > 1.0 ) dt_KD *= relax; // increase dt_KD if( dt_KD > dt ) dt_KD = dt; relax = 1.0; maxKDo = maxKD; // if( relax > relaxo ) // { // relax = 0.1 * relaxo; // if( relax >= project->relaxMin ) // { // // relaxed Newton-Raphson: restore K and D from previous iteration // for( int i=0; i<np; i++ ) // { // int n; // n = GetEqno( node[i], 0 ); // if( n >= 0 ) // { // node[i]->v.K -= relaxo * xKDo[n]; // xKD[n] = xKDo[n]; // } // n = GetEqno( node[i], 1 ); // if( n >= 0 ) // { // node[i]->v.D -= relaxo * xKDo[n]; // xKD[n] = xKDo[n]; // } // } // if( quarterShape ) // { // for( int e=0; e<ne; e++ ) // { // ELEM* el = elem[e]; // if( isFS(el->flag, ELEM::kRegion) ) // { // if( el->Getncn() == 4 ) // { // int no = el->Getno(); // cent[no]->v.K -= relaxo * cxKo[no]; // cent[no]->v.D -= relaxo * cxDo[no]; // cxK[no] = cxKo[no]; // cxD[no] = cxDo[no]; // } // } // } // } // maxKDo = maxKD; // } // else // { // maxKDo = -1.0; // } // } // else // { // relax = project->relaxMax; // maxKDo = maxKD; // } // if( relax > project->relaxMax ) relax = project->relaxMax; // if( relax < project->relaxMin ) relax = project->relaxMin; // if( relax < 0.999 * relaxo ) conv = false; } if( steadyFlow ) relaxThdt_KD = 1.0 / dt_KD; else relaxThdt_KD = 1.0 / dt_KD / th; REPORT::rpt.Message( 2, "\n%-25s%s %12.4le\n%-25s%s %12.4le\n\n", " ", "relaxation (4): norm =", norm, " ", " relax =", relax ); // relaxed Newton-Raphson: store xKD, cxK and cxD for( int i=0; i<np; i++ ) { int n; n = GetEqno( node[i], 0 ); if( n >= 0 ) xKDo[n] = xKD[n]; n = GetEqno( node[i], 1 ); if( n >= 0 ) xKDo[n] = xKD[n]; } if( quarterShape ) { for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; if( isFS(el->flag, ELEM::kRegion) ) { if( el->Getncn() == 4 ) { int no = el->Getno(); cxKo[no] = cxK[no]; cxDo[no] = cxD[no]; } } } } break; } // update ---------------------------------------------------------------------------- relaxo = relax; for( int i=0; i<np; i++ ) { int n; n = GetEqno( node[i], 0 ); if( n >= 0 ) node[i]->v.K += relax * xKD[n]; n = GetEqno( node[i], 1 ); if( n >= 0 ) node[i]->v.D += relax * xKD[n]; } if( quarterShape ) { for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; if( isFS(el->flag, ELEM::kRegion) ) { if( el->Getncn() == 4 ) { int no = el->Getno(); cent[no]->v.K += relax * cxK[no]; cent[no]->v.D += relax * cxD[no]; } } } } // check for range of values --------------------------------------------------------- double minK = 0.0; double minD = 0.0; double maxK = 0.0; double maxD = 0.0; int first = true; int jk = 0; int jd = 0; for( int i=0; i<np; i++ ) { if( first ) { first = false; minK = maxK = node[i]->v.K; minD = maxD = node[i]->v.D; } else { if( node[i]->v.K < minK ) minK = node[i]->v.K; if( node[i]->v.K > maxK ) maxK = node[i]->v.K; if( node[i]->v.D < minD ) minD = node[i]->v.D; if( node[i]->v.D > maxD ) maxD = node[i]->v.D; } if( node[i]->v.K <= 0.0 ) { if( GetEqno(node[i],0) >= 0 ) jk++; } if( node[i]->v.D <= 0.0 ) { if( GetEqno(node[i],1) >= 0 ) jd++; } } ////////////////////////////////////////////////////////////////////////////////////// // MPI: broadcast statistic # ifdef _MPI_ jk = project->subdom.Mpi_sum( jk ); minK = project->subdom.Mpi_min( minK ); maxK = project->subdom.Mpi_max( maxK ); jd = project->subdom.Mpi_sum( jd ); minD = project->subdom.Mpi_min( minD ); maxD = project->subdom.Mpi_max( maxD ); # endif ////////////////////////////////////////////////////////////////////////////////////// // compute useful values for K and D where they are negative ------------------------- if( jk || jd ) { REPORT::rpt.Message( 3, "%-25s%d %s\n\n", " ", jk, "nodes with K out of range" ); REPORT::rpt.Message( 3, "%-25s%d %s\n\n", " ", jd, "nodes with D out of range" ); } REPORT::rpt.Message( 3, "%-25sminimum of K: %le\n", " ", minK ); REPORT::rpt.Message( 3, "%-25smaximum of K: %le\n", " ", maxK ); REPORT::rpt.Message( 3, "%-25sminimum of D: %le\n", " ", minD ); REPORT::rpt.Message( 3, "%-25smaximum of D: %le\n", " ", maxD ); Validate( project, np, node, ne, cent, elem ); // compute midside values (linear interpolation) ------------------------------------- if( linearShape ) { for( int e=0; e<ne; e++ ) { ELEM* el = elem[e]; int ncn = el->Getncn(); int nnd = el->Getnnd(); for( int i=ncn; i<nnd; i++ ) { // get left and right corner node to midside node i int il, ir; double left, rght; el->GetQShape()->getCornerNodes( i, &il, &ir ); left = el->nd[il]->v.K; rght = el->nd[ir]->v.K; el->nd[i]->v.K = 0.5 * (left + rght); left = el->nd[il]->v.D; rght = el->nd[ir]->v.D; el->nd[i]->v.D = 0.5 * (left + rght); } } } // compute time derivatives ---------------------------------------------------------- rg->ReportCuPe( dt, project->vk ); if( !steadyFlow ) { double iTheta = 1.0 - 1.0 / project->timeint.thetaTurb; for( int i=0; i<np; i++ ) { if( isFS(node[i]->flag, NODE::kDry) || isFS(node[i]->flag, NODE::kMarsh) ) { node[i]->v.dKdt = node[i]->v.dDdt = 0.0; } else { double K, pK, D, pD, pdKdt, pdDdt; VARS *v, *vo; v = &(node[i]->v); vo = &(node[i]->vo); K = v->K; pK = vo->K; pdKdt = vo->dKdt; D = v->D; pD = vo->D; pdDdt = vo->dDdt; // compute derivatives at actual time step node[i]->v.dKdt = iTheta*pdKdt + thdt*(K - pK); node[i]->v.dDdt = iTheta*pdDdt + thdt*(D - pD); } } } // ----------------------------------------------------------------------------------- if( conv || it == project->actualCycit-1 ) { if( REPORT::rpt.level == 1 && it == project->actualCycit-1 ) { REPORT::rpt.Message( 1, "\n\n%-25s%s: %d\n\n", " (EQS_KD2D::Execute)", "finished in iteration step", it+1 ); REPORT::rpt.Message( 1, "\n\n%-25s%s\n\n %s\n\n", " (EQS_KD2D::Execute)", "convergence parameters ...", " variable node average maximum" ); REPORT::rpt.Message( 1, " %1c %5d %12.5le %12.5le %s\n", 'K', noAbsK+1, aveAbsK, maxAbsK, " (abs)" ); REPORT::rpt.Message( 1, " %1c %5d %12.5lf %12.5lf %s\n\n", ' ', noPerK+1, avePerK, maxPerK, " ( % )" ); REPORT::rpt.Message( 1, " %1c %5d %12.5le %12.5le %s\n", 'D', noAbsD+1, aveAbsD, maxAbsD, " (abs)" ); REPORT::rpt.Message( 1, " %1c %5d %12.5lf %12.5lf %s\n\n", ' ', noPerD+1, avePerD, maxPerD, " ( % )" ); } break; } } // ------------------------------------------------------------------------------------- // finally: // compute eddy viscosity from revised turbulence parameters rg->Turbulence( project ); // ------------------------------------------------------------------------------------- MEMORY::memo.Detach( B ); MEMORY::memo.Detach( xKD ); if( cxK ) MEMORY::memo.Detach( cxK ); if( cxD ) MEMORY::memo.Detach( cxD ); if( cent ) MEMORY::memo.Detach( cent ); if( xKDo ) MEMORY::memo.Detach( xKDo ); if( cxKo ) MEMORY::memo.Detach( cxKo ); if( cxDo ) MEMORY::memo.Detach( cxDo ); // ------------------------------------------------------------------------------------- if( !conv ) project->errLevel |= kErr_some_errors | kErr_no_conv_nr; if( diverged_cg ) project->errLevel |= diverged_cg | kErr_no_conv_cg; }
void preProcess(const GRID & g, int i, int j, VVV& ava) { if(g[i][j] != '.') return; int x, y; //down check x = i, y = j; while(x < g.size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); --x; } //left check x = i, y = j; while(y < g[0].size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); --y; } //up left check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); --x, --y; } //up right check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); --x, ++y; } //down check x = i, y = j; while(x < g.size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); ++x; } //right check x = i, y = j; while(y < g[0].size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); ++y; } //down left check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); ++x, --y; } //down right check x = i, y = j; while(x >= 0 && y >= 0 && x < g.size() && y < g[0].size() && g[x][y] != '#') { Pair p; p.x = x; p.y = y; ava[i][j].push_back(p); ++x, ++y; } }
void ConstructGrid(OstreamGMV3DFmt& Out, GRID const& G, GEOM const& GEO, heterogeneous_list::List<GF,MOREGFS> GFS) { typedef OstreamGMV3DFmt GMV3D; std::ostream& out = Out.Out(); typedef grid_types<GRID> gt; typedef grid_types<GMV3D::archetype_type> gmv_agt; out << "gmvinput ascii\n"; out << "nodev " << G.NumOfVertices() << '\n'; for(typename gt::VertexIterator v(G); ! v.IsDone(); ++v) out << GEO.coord(*v) << '\n'; // map G's vertices to GMV numbers, starting from 1. element_numbering<typename gt::Vertex> G2GMV(G,1); // map archetypes of G to those of GMV typedef partial_grid_morphism<typename gt::archetype_type, GMV3D::archetype_type> morphism_type; bijective_mapping<typename gt::archetype_type const*, std::pair<morphism_type, int> > phi; for(typename gt::archetype_iterator a = G.BeginArchetype(); a != G.EndArchetype(); ++a) { bool found = false; int cnt_a = 0; // could be GMV::archetype_handle for(GMV3D::archetype_iterator a_gmv = Out.BeginArchetype(); a_gmv != Out.EndArchetype(); ++a_gmv, ++cnt_a) { morphism_type phi_a(*a,*a_gmv); found = construct_isomorphism(*a,*a_gmv, phi_a); if(found) { phi[&(*a)] = std::make_pair(phi_a,cnt_a); break; } } ENSURE(found, "sorry, no mapping to GMV cell type found!\n",1); // should use the general cell feature of GMV. } // map cells out << "cells " << G.NumOfCells() << "\n"; for(typename gt::CellIterator c(G); ! c.IsDone(); ++c) { // phi_a.inv c.V() G2GMV // gmv-archetype -> G::archetype -> G::global -> GMV::global morphism_type const& phi_a = phi(&G.ArchetypeOf(*c)).first; int cnt_a = phi(&G.ArchetypeOf(*c)).second; GMV3D::archetype_type const& archetype_gmv(phi_a.ImgGrid()); out << Out.name(cnt_a) << " " << archetype_gmv.NumOfVertices() << " "; for(gmv_agt::VertexIterator vc(archetype_gmv); !vc.IsDone(); ++vc) out << G2GMV( (*c).V(phi_a.inverse()(*vc))) << " "; out << '\n'; } Out.copy_grid_functions(GFS); out << "endgmv\n"; }
void EQS_D2D::Execute( PROJECT* project, int steadyFlow, int linearShape ) { MODEL* model = project->M2D; GRID* rg = project->M2D->region; NODE** node = model->node; ELEM** elem = model->elem; int np = model->np; int ne = model->ne; int div_cg = 0; double* B = NULL; double* X = NULL; model->Incinit(); // print information on actual iteration ----------------------------------------------- project->PrintTheCycle( 1 ); REPORT::rpt.PrintTime( 1 ); // set parameters according to time integration and relaxation ------------------------- double th = project->timeint.thetaTurb; double dt = project->timeint.incTime.Getsec(); if( fabs(th) < 1.0e-10 && fabs(dt) < 1.0e-10 ) { REPORT::rpt.Error( kParameterFault, "theta and timeInterval too small (EQS_D2D::execute - 1)" ); } double thdt = 1.0 / dt / th; double dt_KD; double relaxDt_KD = project->timeint.relaxTimeTurb.Getsec(); int relaxMethod = project->relaxMethod; if( steadyFlow ) { if( relaxMethod >= 3 ) { dt_KD = relaxDt_KD; relaxThdt_KD = 1.0 / dt_KD; } else { dt_KD = dt; relaxThdt_KD = 0.0; } for( int i=0; i<np; i++ ) { node[i]->v.dDdt = 0.0; } } else { if( relaxMethod >= 3 ) { dt_KD = relaxDt_KD; } else { dt_KD = dt; } relaxThdt_KD = 1.0 / dt_KD / th; // time prediction ------------------------------------------------------------------- for( int i=0; i<np; i++ ) { VARS* v = &node[i]->v; //VARS* vo = &(node[i]->vo); //v->D = vo->D + vo->dDdt * dt; //v->dDdt = (1.0 - 1.0/th)*vo->dDdt + thdt*(v->D - vo->D); v->dDdt = 0.0; } } // check KD-values for validity (>= 0) ------------------------------------------------- Validate( np, node, project ); // determine friction coefficients ----------------------------------------------------- model->DoFriction( project ); // initialize Reynolds stresses and eddy viscosity ------------------------------------- rg->Turbulence( project ); // set KD boundary conditions ---------------------------------------------------------- model->SetBoundKD( project ); // ------------------------------------------------------------------------------------- int conv = true; for( int it=0; it<project->actualCycit; it++ ) { conv = true; // print information on actual iteration --------------------------------------------- if( it > 0 ) { project->PrintTheCycle( it+1 ); REPORT::rpt.PrintTime( 1 ); } // initialize Reynolds stresses and eddy viscosity ----------------------------------- if( it > 0 && isFS(project->actualTurb, BCONSET::kVtIterat) && !isFS(project->actualTurb, BCONSET::kVtPrandtlKol) ) { rg->Turbulence( project ); } // set up equation numbers ----------------------------------------------------------- if( model->Getinit() != modelInit ) { initStructure = true; modelInit = model->Getinit(); project->fix[0] = BCON::kFixD; project->elemKind = ELEM::kRegion; SetEqno( model, 1, 1, 0, project->fix, project->elemKind ); if( B ) MEMORY::memo.Detach( B ); if( X ) MEMORY::memo.Detach( X ); B = (double*) MEMORY::memo.Array_eq( neq ); X = (double*) MEMORY::memo.Array_eq( neq ); } // solve equations with frontal solving algorithm ------------------------------------ for( int i=0; i<neq; i++ ) X[i] = 0.0; div_cg = Solve( model, neq, B, X, project ); // ----------------------------------------------------------------------------------- // statistics REPORT::rpt.Message( 1, "\n\n%-25s%s\n\n %s\n\n", " (EQS_D2D::Execute)","convergence parameters ...", " variable node average maximum" ); // compute averaged changes and standard deviation of D ------------------------------ double stdevD = 0.0; double aveAbsD = 0.0; for( int i=0; i<np; i++ ) { int eqno; double dD = 0.0; eqno = GetEqno( node[i], 0 ); if( eqno >= 0 ) dD = X[eqno]; aveAbsD += dD; stdevD += dD*dD; } int nptot = 0; for( int i=0; i<np; i++ ) { NODE* nd = rg->Getnode(i); if( !isFS(nd->flag, NODE::kInface_DN) ) nptot++; } ////////////////////////////////////////////////////////////////////////////////////// // MPI: broadcast statistic # ifdef _MPI_ aveAbsD = project->subdom.Mpi_sum( aveAbsD ); stdevD = project->subdom.Mpi_sum( stdevD ); nptot = project->subdom.Mpi_sum( nptot ); # endif ////////////////////////////////////////////////////////////////////////////////////// aveAbsD /= nptot; stdevD = sqrt( stdevD / nptot ); double norm = stdevD; double fractD = 2.0 * sqrt( stdevD ); // compute maximum changes of K and D limited to ~95% fractile ----------------------- int cntD = 0; int noPerD = 0; double avePerD = 0.0; double maxPerD = 0.0; int noAbsD = 0; double maxAbsD = 0.0; for( int i=0; i<np; i++ ) { int eqno; double dK = 0.0; double dD = 0.0; eqno = GetEqno( node[i], 0 ); if( eqno >= 0 ) { dD = X[eqno]; if( fabs(dD) > project->maxDeltaKD && fabs(dD) > fractD ) { X[eqno] = dD/fabs(dD) * fractD; } } if( node[i]->v.D + dD > 0.0 ) { if( fabs(dD) > fabs(maxAbsD) ) { maxAbsD = dD; noAbsD = node[i]->Getname(); } if( node[i]->v.D > 0.0 ) { double per = dD / node[i]->v.D; avePerD += fabs(per); cntD++; if( fabs(per) > fabs(maxPerD) ) { maxPerD = per; noPerD = node[i]->Getname(); } } } } ////////////////////////////////////////////////////////////////////////////////////// // MPI: broadcast statistic # ifdef _MPI_ cntD = project->subdom.Mpi_sum( cntD ); maxAbsD = project->subdom.Mpi_max( maxAbsD ); avePerD = project->subdom.Mpi_sum( avePerD ); maxPerD = project->subdom.Mpi_max( maxPerD ); # endif ////////////////////////////////////////////////////////////////////////////////////// avePerD /= cntD; REPORT::rpt.Message( 1, " %1c %5d %12.5le %12.5le %s\n", 'D', noAbsD+1, aveAbsD, maxAbsD, " (abs)" ); REPORT::rpt.Message( 1, " %1c %5d %12.5lf %12.5lf %s\n\n", ' ', noPerD+1, avePerD, maxPerD, " ( % )" ); if( fabs(maxAbsD) > project->convKD ) conv = false; // determine relaxation parameter for NEWTON-RAPHSON --------------------------------- double relax; double maxKD = fabs(maxAbsD); switch( relaxMethod ) { default: REPORT::rpt.Warning( kParameterFault, "relaxation method %d not supported", relaxMethod ); case 0: relax = 1.0; REPORT::rpt.Message( 1, "\n%-25s%s %12.4le\n %s %12.4le\n\n", " ", "relaxation: norm =", norm, " ", " relax =", relax ); break; case 2: relax = project->maxDeltaKD / maxKD; if( relax > 1.0 ) relax = 1.0; REPORT::rpt.Message( 1, "\n%-25s%s %12.4le\n%-25s%s %12.4le\n\n", " ", "relaxation: norm =", norm, " ", " relax =", relax ); break; case 3: case 4: REPORT::rpt.Message( 1, "\n%-25s%s %12.4le\n", " ", "relaxed time: dt_KD =", dt_KD ); if( dt_KD < dt ) conv = false; relax = project->maxDeltaKD / maxKD; dt_KD *= relax; if( dt_KD > dt ) dt_KD = dt; if( dt_KD < relaxDt_KD ) dt_KD = relaxDt_KD; if( steadyFlow ) relaxThdt_KD = 1.0 / dt_KD; else relaxThdt_KD = 1.0 / dt_KD / th; if( relax > 1.0 ) relax = 1.0; REPORT::rpt.Message( 1, "\n%-25s%s %12.4le\n%-25s%s %12.4le\n\n", " ", "relaxation: norm =", norm, " ", " relax =", relax ); break; } // update ---------------------------------------------------------------------------- for( int i=0; i<np; i++ ) { int n = GetEqno( node[i], 0 ); if( n >= 0 ) node[i]->v.D += relax * X[n]; } // check for range of values --------------------------------------------------------- double minD = 0.0; double maxD = 0.0; int first = true; int jd = 0; for( int i=0; i<np; i++ ) { if( first ) { first = false; minD = maxD = node[i]->v.D; } else { if( node[i]->v.D < minD ) minD = node[i]->v.D; if( node[i]->v.D > maxD ) maxD = node[i]->v.D; } if( node[i]->v.D <= 0.0 ) { // node[i]->v.D = project->minD; if( GetEqno(node[i],1) >= 0 ) jd++; } } // compute useful values for K and D where they are negative ------------------------- if( jd ) { REPORT::rpt.Message( 1, "%-25s%d %s\n\n", " ", jd, "nodes with D out of range" ); Validate( np, node, project ); } REPORT::rpt.Message( 1, "%-25sminimum of D: %le\n", " ", minD ); REPORT::rpt.Message( 1, "%-25smaximum of D: %le\n", " ", maxD ); // compute time derivatives ---------------------------------------------------------- rg->ReportCuPe( dt, project->vk ); if( !steadyFlow ) { double iTheta; iTheta = 1.0 - 1.0 / project->timeint.thetaTurb; for( int i=0; i<np; i++ ) { if( isFS(node[i]->flag, NODE::kDry) || isFS(node[i]->flag, NODE::kMarsh) ) { node[i]->v.dDdt = 0.0; } else { double D, pD, pdDdt; VARS *v, *vo; v = &(node[i]->v); vo = &(node[i]->vo); D = v->D; pD = vo->D; pdDdt = vo->dDdt; // compute derivatives at actual time step node[i]->v.dDdt = iTheta*pdDdt + thdt*(D - pD); } } } if( conv ) break; } // finally: compute eddy viscosity from revised turbulence parameters K,D -------------- rg->Turbulence( project ); // ------------------------------------------------------------------------------------- MEMORY::memo.Detach( B ); MEMORY::memo.Detach( X ); if( !conv ) project->errLevel |= kErr_some_errors | kErr_no_conv_nr; if( div_cg ) project->errLevel |= div_cg | kErr_no_conv_cg; }