int main() { ElementArray elementArray; ///////////////////////////////////////////////////// // 데이터 구성 ///////////////////////////////////////////////////// size_t elementSize, intervalSize; cin >> elementSize >> intervalSize; elementArray.assign(elementSize, 0); // 각 원소 입력 for (size_t i = 0; i < elementArray.size(); i++) cin >> elementArray[i]; ///////////////////////////////////////////////////// // 각 구간별 최대값 계산 & 출력 ///////////////////////////////////////////////////// for (size_t i = 0; i < intervalSize; i++) { size_t begin; size_t end; cin >> begin >> end; cout << elementArray.calcMax(begin - 1, end) << endl; } #ifdef _WIN32 system("pause"); #endif return 0; }
TEST(ArrayTest, testConstruction) { // fundamental type typedef Poco::Array<float,6> FloatArray; FloatArray a = { { 42.f } }; for (unsigned i=1; i<a.size(); ++i) { a[i] = a[i-1]+1.f; } // copy constructor and assignment operator FloatArray b(a); FloatArray c; c = a; EXPECT_TRUE (a==b && a==c); typedef Poco::Array<double,6> DArray; typedef Poco::Array<int,6> IArray; IArray ia = {{1, 2, 3, 4, 5, 6 }}; DArray da; da = ia; da.assign(42); // user-defined type typedef Poco::Array<Element,10> ElementArray; ElementArray g; for (unsigned i=0; i<g.size(); ++i) { g[i]._data = i; } for (unsigned i=0; i<g.size(); ++i) { EXPECT_TRUE(g[i]._data == i); } }
int main(int argc, char ** argv) { double nx = 2.0/7.0, ny = 6.0/7.0, nz = 3.0/7.0; double px = 0.5, py = 0.5, pz = 0.5; if( argc < 2 ) { std::cout << "Usage: " << argv[0] << " mesh [mesh_out=grid.pmf] [nx=0] [ny=0] [nz=1] [px=0.5] [py=0.5] [pz=0.5]" << std::endl; return -1; } std::string grid_out = "grid.pmf"; if( argc > 2 ) grid_out = std::string(argv[2]); if( argc > 3 ) nx = atof(argv[3]); if( argc > 4 ) ny = atof(argv[4]); if( argc > 5 ) nz = atof(argv[5]); if( argc > 6 ) px = atof(argv[6]); if( argc > 7 ) py = atof(argv[7]); if( argc > 8 ) pz = atof(argv[8]); double d = nx*px+ny*py+nz*pz; Mesh m; m.Load(argv[1]); m.SetTopologyCheck(NEED_TEST_CLOSURE|PROHIBIT_MULTILINE|PROHIBIT_MULTIPOLYGON|GRID_CONFORMITY|DEGENERATE_EDGE|DEGENERATE_FACE|DEGENERATE_CELL | FACE_EDGES_ORDER); //m.RemTopologyCheck(THROW_EXCEPTION); Tag sliced = m.CreateTag("SLICED",DATA_BULK,FACE|EDGE|NODE,FACE|EDGE|NODE,1); std::cout << "Cells: " << m.NumberOfCells() << std::endl; std::cout << "Faces: " << m.NumberOfFaces() << std::endl; MarkerType slice = m.CreateMarker(); int nslice = 0, nmark = 0; for(Mesh::iteratorEdge it = m.BeginEdge(); it != m.EndEdge(); ++it) { double p[3]; Storage::real_array c0 = it->getBeg()->Coords(); Storage::real_array c1 = it->getEnd()->Coords(); double r0 = c0[0]*nx+c0[1]*ny+c0[2]*nz - d; double r1 = c1[0]*nx+c1[1]*ny+c1[2]*nz - d; //std::cout << "r0 " << r0 << " r1 " << r1 << std::endl; if( r0*r1 < -1.0e-12 ) { p[0] = (r0*c1[0] - r1*c0[0])/(r0-r1); p[1] = (r0*c1[1] - r1*c0[1])/(r0-r1); p[2] = (r0*c1[2] - r1*c0[2])/(r0-r1); //std::cout << "p " << p[0] << " " << p[1] << " " << p[2] << std::endl; Node n = m.CreateNode(p); n.Bulk(sliced) = 1; n.SetMarker(slice); bool was_sliced = it->HaveData(sliced) ? true : false; ElementArray<Edge> ret = Edge::SplitEdge(it->self(),ElementArray<Node>(&m,1,n.GetHandle()),0); if( was_sliced ) for(int q = 0; q < ret.size(); ++q) ret[q]->Bulk(sliced) = 1; nslice++; } else { if( fabs(r0) < 1.0e-6 ) { it->getBeg()->SetMarker(slice); nmark++; } if( fabs(r1) < 1.0e-6 ) { it->getEnd()->SetMarker(slice); nmark++; } } } std::cout << "sliced edges: " << nslice << " marked nodes: " << nmark << std::endl; if( !Element::CheckConnectivity(&m) ) std::cout << "Connectivity is broken" << std::endl; nslice = 0; for(Mesh::iteratorFace it = m.BeginFace(); it != m.EndFace(); ++it) { ElementArray<Node> nodes = it->getNodes(slice); //those nodes should be ordered so that each pair forms an edge if( nodes.size() > 1 ) // if there is 1, then only one vertex touches the plane { //if there is more then two, then original face is non-convex if( nodes.size() > 2 ) std::cout << "Looks like face " << it->LocalID() << " is nonconvex" << std::endl; else { Edge e = m.CreateEdge(nodes).first; e.Bulk(sliced) = 1; e.SetMarker(slice); bool was_sliced = it->HaveData(sliced) ? true : false; ElementArray<Face> ret = Face::SplitFace(it->self(),ElementArray<Edge>(&m,1,e.GetHandle()),0); if( was_sliced ) for(int q = 0; q < ret.size(); ++q) ret[q]->Bulk(sliced) = 1; nslice++; } } //else std::cout << "Only one adjacent slice node, face " << it->LocalID() << std::endl; } nmark = 0; for(Mesh::iteratorEdge it = m.BeginEdge(); it != m.EndEdge(); ++it) if( !it->GetMarker(slice) && it->getBeg()->GetMarker(slice) && it->getEnd()->GetMarker(slice) ) { it->SetMarker(slice); nmark++; } std::cout << "sliced faces: " << nslice << " marked edges: " << nmark << std::endl; if( !Element::CheckConnectivity(&m) ) std::cout << "Connectivity is broken" << std::endl; nslice = 0; MarkerType visited = m.CreateMarker(); for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) { ElementArray<Edge> edges = it->getEdges(slice); if( edges.size() >= 3 ) //these should form a triangle { //order edges ElementArray<Edge> order_edges(&m); order_edges.push_back(edges[0]); order_edges.SetMarker(visited); while(order_edges.size() != edges.size() ) { for(int k = 0; k < edges.size(); ++k) if( !edges[k]->GetMarker(visited) ) { if( edges[k]->getBeg() == order_edges.back()->getBeg() || edges[k]->getBeg() == order_edges.back()->getEnd() || edges[k]->getEnd() == order_edges.back()->getBeg() || edges[k]->getEnd() == order_edges.back()->getEnd() ) { order_edges.push_back(edges[k]); order_edges.back().SetMarker(visited); } } } edges.RemMarker(visited); Face f = m.CreateFace(order_edges).first; f.Bulk(sliced) = 1; Cell::SplitCell(it->self(),ElementArray<Face>(&m,1,f.GetHandle()),0); nslice++; } } m.ReleaseMarker(visited); std::cout << "sliced cells: " << nslice << std::endl; if( !Element::CheckConnectivity(&m) ) std::cout << "Connectivity is broken" << std::endl; Tag material = m.CreateTag("MATERIAL",DATA_INTEGER,CELL,NONE,1); for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) { double cnt[3]; it->Centroid(cnt); double v = cnt[0]*nx+cnt[1]*ny+cnt[2]*nz-d; if( v < 0.0 ) it->Integer(material) = 0; else it->Integer(material) = 1; } m.ReleaseMarker(slice,NODE|EDGE); m.Save(grid_out); return 0; }
ConvectionDiffusion::ConvectionDiffusion(Mesh * _m, Tag _tag_U, Tag _tag_K, Tag _tag_BC, MarkerType _boundary_face, bool correct_convection, bool correct_diffusion) : m(_m), tag_U(_tag_U), tag_K(_tag_K), tag_BC(_tag_BC), boundary_face(_boundary_face) { perform_correction_diffusion = correct_convection; perform_correction_convection = correct_diffusion; if( tag_U.isValid() ) { //4 entries - triplet for upwind corrector, including the cell //back cell corrector tag_CONV_CB = m->CreateTag("CONV_BACK_COEFS" ,DATA_REAL ,FACE,NONE,4); tag_CONV_EB = m->CreateTag("CONV_BACK_ELEMS" ,DATA_REFERENCE,FACE,NONE,4); tag_CONV_RB = m->CreateTag("CONV_BACK_RHS" ,DATA_REAL ,FACE,NONE,1); //front cell corrector tag_CONV_CF = m->CreateTag("CONV_FRONT_COEFS" ,DATA_REAL ,FACE,NONE,4); tag_CONV_EF = m->CreateTag("CONV_FRONT_ELEMS" ,DATA_REFERENCE,FACE,NONE,4); tag_CONV_RF = m->CreateTag("CONV_FRONT_RHS" ,DATA_REAL ,FACE,NONE,1); //upstream tag_CONV_CU = m->CreateTag("CONV_UPSTREAM_COEF",DATA_REAL ,FACE,NONE,1); tag_CONV_EU = m->CreateTag("CONV_UPSTREAM_ELEM",DATA_REFERENCE,FACE,NONE,1); tag_CONV_RU = m->CreateTag("CONV_UPSTREAM_RHS" ,DATA_REAL ,FACE,NONE,1); tag_CONV_VU = m->CreateTag("CONV_UPSTREAM_CORR",DATA_REAL ,FACE,NONE,6); //flag tag_CONV_F = m->CreateTag("CONV_FLAG" ,DATA_BULK ,FACE,NONE,1); } if( tag_K.isValid() ) { //4 entries - triplet for transversal corrector, including the cell //back cell corrector tag_DIFF_CB = m->CreateTag("DIFF_BACK_COEFS" ,DATA_REAL ,FACE,NONE,4); tag_DIFF_EB = m->CreateTag("DIFF_BACK_ELEMS" ,DATA_REFERENCE,FACE,NONE,4); tag_DIFF_RB = m->CreateTag("DIFF_BACK_RHS" ,DATA_REAL ,FACE,NONE,1); //front cell corrector tag_DIFF_CF = m->CreateTag("DIFF_FRONT_COEFS" ,DATA_REAL ,FACE,NONE,4); tag_DIFF_EF = m->CreateTag("DIFF_FRONT_ELEMS" ,DATA_REFERENCE,FACE,NONE,4); tag_DIFF_RF = m->CreateTag("DIFF_FRONT_RHS" ,DATA_REAL ,FACE,NONE,1); //two-point transmissibility tag_DIFF_CT = m->CreateTag("DIFF_TP_COEF" ,DATA_REAL ,FACE,NONE,1); tag_DIFF_RT = m->CreateTag("DIFF_TP_RHS" ,DATA_REAL ,FACE,NONE,1); tag_DIFF_VT = m->CreateTag("DIFF_TP_CORR" ,DATA_REAL ,FACE,NONE,6); //flag tag_DIFF_F = m->CreateTag("DIFF_FLAG" ,DATA_BULK ,FACE,NONE,1); } build_flux = 0; if( m->GetProcessorsNumber() > 1 ) { build_flux = m->CreateMarker(); #if defined(USE_OMP) #pragma omp for #endif for(integer q = 0; q < m->FaceLastLocalID(); ++q ) if( m->isValidFace(q) ) { Face fKL = m->FaceByLocalID(q); Element::Status stat = fKL->BackCell()->GetStatus(); if( fKL->FrontCell().isValid() ) stat |= fKL->FrontCell()->GetStatus(); if( stat & (Element::Shared | Element::Owned) ) fKL->SetMarker(build_flux); } } initialization_failure = false; //there is a failure during intialization //Precompute two-point part, transversal correction direction, // upstream and upstream correction directions and flags #if defined(USE_OMP) #pragma omp parallel #endif { //private memory rMatrix xK(1,3), //center of cell K yK(1,3), //projection of xK onto interface xL(1,3), //center of cell L yL(1,3), //projection of xL onto interface xKL(1,3), //center of face common to K and L nKL(1,3), //normal vector to face KKn(1,3), //co-normal at cell K KLn(1,3), //co-normal at cell L v(1,3), //vector for correction uK(1,3), //vector for upwind correction in back cell uL(1,3), //vector for upwind correction in front cell r(1,3), //path to reach upstream concentration from downstream concentration r0(1,3), KK(3,3), //tenosr at cell K KL(3,3), //tensor at cell L KD(3,3), //difference of tensors gammaK(1,3), //transversal part of co-normal at cell K gammaL(1,3), //transversal part of co-normal at cell L iT(3,3), //heterogeneous interpolation tensor iC(1,3) //heterogeneous interpolation correction ; real A, //area of the face U, //normal component of the velocity C, //coefficient for upstream cell T, //two-point transmissibility R, //right hand side dK, //distance from center to interface at cell K dL, //distance from center to interface at cell L lambdaK, //projection of co-normal onto normal at cell K lambdaL //projection of co-normal onto normal at cell L ; const real eps = degenerate_diffusion_regularization; Cell cK, cL, cU; Face fKL; bulk flag_DIFF, flag_CONV; KK.Zero(); KL.Zero(); KD.Zero(); U = 0.0; #if defined(USE_OMP) #pragma omp for #endif for(integer q = 0; q < m->FaceLastLocalID(); ++q ) if( m->isValidFace(q) ) { fKL = m->FaceByLocalID(q); if( !BuildFlux(fKL) ) continue; fKL.Centroid(xKL.data()); fKL.UnitNormal(nKL.data()); A = fKL.Area(); if( tag_U.isValid() ) U = fKL.Real(tag_U); cK = fKL.BackCell(); cL = fKL.FrontCell(); assert(cK.isValid()); cK.Centroid(xK.data()); dK = nKL.DotProduct(xKL-xK); yK = xK + dK*nKL; if( tag_K.isValid() ) KK = rMatrix::FromTensor(cK.RealArray(tag_K).data(),cK.RealArray(tag_K).size());//.Transpose(); KKn = nKL*KK; lambdaK = nKL.DotProduct(KKn); gammaK = KKn - lambdaK*nKL; //Diffusion part uK.Zero(); uL.Zero(); if( cL.isValid() ) //internal, both cells are present { cL.Centroid(xL.data()); dL = nKL.DotProduct(xL-xKL); yL = xL - dL*nKL; if( tag_K.isValid() ) KL = rMatrix::FromTensor(cL.RealArray(tag_K).data(),cL.RealArray(tag_K).size());//.Transpose(); KLn = nKL*KL; lambdaL = nKL.DotProduct(KLn); gammaL = KLn - lambdaL*nKL; //don't forget the area! R = 0; if( split_diffusion ) { uK = A * (lambdaK*lambdaL*(yK-yL) + lambdaL*dK*gammaK + lambdaK*dL*gammaL)/(dK*lambdaL+dL*lambdaK + 1.0e-100); uL = uK; T = A * lambdaK*lambdaL/(dK*lambdaL+dL*lambdaK + 1.0e-100); } else //un-splitted diffusion { uK = A * KKn; uL = A * KLn; T = 0; } //internal if( uK.FrobeniusNorm() > 0 || uL.FrobeniusNorm() > 0 ) flag_DIFF = 3; else flag_DIFF = 2; } else if( fKL.GetMarker(boundary_face) ) //boundary interface { //don't forget the area! if( split_diffusion ) { uK = KKn - ((xKL - xK) * lambdaK / dK); T = lambdaK / dK; } else //un-splitted diffusion { uK = KKn; T = 0; } real bcconds[3] = {0.0,1.0,0.0}; //pure neumann boundary condition if( tag_BC.isValid() && fKL.HaveData(tag_BC) ) //are there boundary conditions on face? { //retrive boundary conditions real_array bc = fKL.RealArray(tag_BC); bcconds[0] = bc[0]; bcconds[1] = bc[1]; bcconds[2] = bc[2]; } //account for boundary conditions R = A*T*bcconds[2]/(bcconds[0] + bcconds[1]*T + 1.0e-100); uK *=A* bcconds[0]/(bcconds[0] + bcconds[1]*T + 1.0e-100); T *=A* bcconds[0]/(bcconds[0] + bcconds[1]*T + 1.0e-100); //on BC if( uK.FrobeniusNorm() > 0 ) flag_DIFF = 1; else flag_DIFF = 0; } else std::cout << "No adjacent cell on non-boundary face" << std::endl; //record data for diffusion part if( tag_K.isValid() ) { fKL.Bulk(tag_DIFF_F) = flag_DIFF; fKL.Real(tag_DIFF_RT) = R; fKL.Real(tag_DIFF_CT) = T; real_array VT = fKL.RealArray(tag_DIFF_VT); VT[0] = uK(0,0); VT[1] = uK(0,1); VT[2] = uK(0,2); VT[3] = -uL(0,0); VT[4] = -uL(0,1); VT[5] = -uL(0,2); } //Advection part uK.Zero(); uL.Zero(); C = 0.0; cU = InvalidCell(); R = 0; if( U > 0.0 ) //flow out of back cell to front cell { cU = cK; C = U*A; //upstream corrector uK = (xK - xKL)*U*A; //downstream corrector if( cL.isValid() ) //internal face { r0 = r = xK - xL; if( tag_K.isValid() ) //heterogeneous media { KD = KL - KK; if( KD.FrobeniusNorm() > 0.0 ) { KD /= lambdaK + eps; iT = (rMatrix::Unit(3) + nKL.Transpose()*nKL*KD); iC = -nKL*dL*KD; r = (r*iT - iC)*(lambdaK/(lambdaK+eps)) + r*(eps/(lambdaK+eps)); //r = (r*iT - iC)*(lambdaK/(lambdaK+eps)) + (r + nKL*(KL-KK)/(U+eps))*(eps/(lambdaK+eps)); } } uL = (xKL - xL - r)*U*A; flag_CONV = 2; //internal } else if( fKL.GetMarker(boundary_face) ) flag_CONV = 1; //on outlet BC else std::cout << "No adjacent cell on non-boundary face" << std::endl; } else if( U < 0.0 ) //flow out of front cell to back cell { if( cL.isValid() ) //internal face { cU = cL; C = U*A; uL = (xKL - xL)*U*A; r = xL - xK; if( tag_K.isValid() ) //heterogeneous media { KD = KK - KL; if( KD.FrobeniusNorm() > 0.0 ) { KD /= lambdaL + eps; iT = (rMatrix::Unit(3) + nKL.Transpose()*nKL*KD); iC = nKL*dK*KD; r = (r*iT - iC)*(lambdaL/(lambdaL+eps)) + r*(eps/(lambdaL+eps)); //r = (r*iT - iC)*(lambdaL/(lambdaL+eps)) + (r + nKL*(KK-KL)/(U-eps))*(eps/(lambdaL+eps)); } } uK = (r + xK - xKL)*U*A; flag_CONV = 2; //internal } else if( fKL.GetMarker(boundary_face) )//boundary face { real bcconds[3] = {0.0,1.0,0.0}; //pure neumann boundary condition if( tag_BC.isValid() && fKL.HaveData(tag_BC) ) //are there boundary conditions on face? { //retrive boundary conditions real_array bc = fKL.RealArray(tag_BC); bcconds[0] = bc[0]; bcconds[1] = bc[1]; bcconds[2] = bc[2]; } if( bcconds[0] > 0 && fabs(bcconds[1]) < 1.0e-7 ) //Dirichlet BC { C = 0; R = U*A*bcconds[2]/bcconds[0]; flag_CONV = 0; //on inlet BC } else if( tag_K.isValid() ) //get expression out of diffusion { v = - A * (KKn - (xKL - xK) * lambdaK / dK); T = A * lambdaK / dK; cU = cK; C = U*A*T*bcconds[1]/(bcconds[0] + bcconds[1]*T + 1.0e-100); R = U*A *bcconds[2]/(bcconds[0] + bcconds[1]*T + 1.0e-100); uK =U*A*v*bcconds[1]/(bcconds[0] + bcconds[1]*T + 1.0e-100); flag_CONV = 1; //treat as outlet BC } else { if( bcconds[0] > 0 && bcconds[1] > 0 ) //Mixed BC { initialization_failure = true; std::cout << "Mixed BC type on inlet boundary face " << fKL->LocalID() << " is inconsistent for pure advection" << std::endl; } else if( bcconds[1] > 0 ) // Neumann BC { initialization_failure = true; std::cout << "Neumann BC type on inlet boundary face " << fKL->LocalID() << " is inconsistent for pure advection" << std::endl; } } } else std::cout << "No adjacent cell on non-boundary face" << std::endl; } else flag_CONV = 0; //otherwise velocity is zero, no flow through face //record data for advection part if( tag_U.isValid() ) { fKL.Bulk(tag_CONV_F) = flag_CONV; fKL.Real(tag_CONV_CU) = C; fKL.Reference(tag_CONV_EU) = cU.GetHandle(); fKL.Real(tag_CONV_RU) = R; real_array VU = fKL.RealArray(tag_CONV_VU); VU[0] = uK(0,0); VU[1] = uK(0,1); VU[2] = uK(0,2); VU[3] = uL(0,0); VU[4] = uL(0,1); VU[5] = uL(0,2); } // tag_U is defined } // for q } //openmp Tag failure = m->CreateTag("FAILURE",DATA_INTEGER,CELL,NONE,1); //Compute triplets integer negative = 0, total = 0; #if defined(USE_OMP) #pragma omp parallel reduction(+:negative,total) #endif { Cell cK; //current cell Face fKL; ElementArray<Face> faces; //faces of the cell std::vector<Stencil> compute; //approximations to be computed Tag tag_iC, tag_iT; //temporary data used for interpolation tensors { std::stringstream name; name << "INTERPOLATION_TENSOR_" << m->GetLocalProcessorRank(); tag_iT = m->CreateTag(name.str(),DATA_REAL,CELL,NONE); name.clear(); name << "INTERPOLATION_CORRECTION_" << m->GetLocalProcessorRank(); tag_iC = m->CreateTag(name.str(),DATA_REAL,CELL,NONE); } bulk flag; real_array v; #if defined(USE_OMP) #pragma omp for #endif for(integer q = 0; q < m->CellLastLocalID(); ++q ) if( m->isValidCell(q) ) { cK = m->CellByLocalID(q); compute.clear(); faces = cK.getFaces(); for(integer k = 0; k < faces.size(); ++k) { fKL = faces[k]; if( !BuildFlux(fKL) ) continue; //Diffusion stencils if( tag_K.isValid() ) { flag = fKL.Bulk(tag_DIFF_F); if( flag == 3 || flag == 1 ) { Stencil s; s.type = DIFFUSION; if( fKL.FaceOrientedOutside(cK) ) { s.coefs = fKL.RealArray(tag_DIFF_CB); s.elems = fKL.ReferenceArray(tag_DIFF_EB); s.rhs = &fKL.Real(tag_DIFF_RB); v = fKL.RealArray(tag_DIFF_VT); s.v[0] = v[0]; s.v[1] = v[1]; s.v[2] = v[2]; s.sign = 1; } else { s.coefs = fKL.RealArray(tag_DIFF_CF); s.elems = fKL.ReferenceArray(tag_DIFF_EF); s.rhs = &fKL.Real(tag_DIFF_RF); v = fKL.RealArray(tag_DIFF_VT); s.v[0] = v[3]; s.v[1] = v[4]; s.v[2] = v[5]; s.sign = -1; } if( s.v[0]*s.v[0] + s.v[1]*s.v[1] + s.v[2]*s.v[2] > 0.0 ) compute.push_back(s); } } //Advection stencils if( tag_U.isValid() ) { flag = fKL.Bulk(tag_CONV_F); if( flag >= 2 || flag == 1 ) { Stencil s; s.type = CONVECTION; if( fKL.FaceOrientedOutside(cK) ) { s.coefs = fKL.RealArray(tag_CONV_CB); s.elems = fKL.ReferenceArray(tag_CONV_EB); s.rhs = &fKL.Real(tag_CONV_RB); v = fKL.RealArray(tag_CONV_VU); s.v[0] = v[0]; s.v[1] = v[1]; s.v[2] = v[2]; s.sign = -1; } else { s.coefs = fKL.RealArray(tag_CONV_CF); s.elems = fKL.ReferenceArray(tag_CONV_EF); s.rhs = &fKL.Real(tag_CONV_RF); v = fKL.RealArray(tag_CONV_VU); s.v[0] = v[3]; s.v[1] = v[4]; s.v[2] = v[5]; s.sign = 1; } if( s.v[0]*s.v[0] + s.v[1]*s.v[1] + s.v[2]*s.v[2] > 0.0 ) compute.push_back(s); } } } //Gathered all the stencils at once if( !compute.empty() ) { if( !find_stencils(cK,compute,tag_BC,tag_K,tag_iT,tag_iC,boundary_face,bridge_layers,degenerate_diffusion_regularization,max_layers) ) { initialization_failure = true; cK.Integer(failure) = 1; std::cout << "Cannot find stencil for cell " << cK->LocalID() << std::endl; for(size_t it = 0; it < compute.size(); ++it) { if( !compute[it].computed ) { std::cout << (compute[it].type == DIFFUSION ? "Diffusion" : "Advection"); std::cout << " vec (" << compute[it].v[0] << "," << compute[it].v[1] << "," << compute[it].v[2] << ")"; std::cout << std::endl; } } std::cout << "Total: " << compute.size() << std::endl; find_stencils(cK,compute,tag_BC,tag_K,tag_iT,tag_iC,boundary_face,bridge_layers,degenerate_diffusion_regularization,max_layers); } else for(size_t it = 0; it < compute.size(); ++it) if( !compute[it].nonnegative ) negative++; total += (integer)compute.size(); } } //end of loop over cells //release interpolation tags m->DeleteTag(tag_iC); m->DeleteTag(tag_iT); } //openmp negative = m->Integrate(negative); total = m->Integrate(total); if( m->GetProcessorRank() == 0 ) std::cout << " negative flux approximation: " << negative << "/" << total << std::endl; { //Synchronize initialization_failure integer sync = (initialization_failure ? 1 : 0); sync = m->Integrate(sync); if( sync ) initialization_failure = true; } if( !initialization_failure ) m->DeleteTag(failure); }