/** * Probably should be pushed back into ContField? */ void IncNavierStokes::SetRadiationBoundaryForcing(int fieldid) { int i,n; Array<OneD, const SpatialDomains::BoundaryConditionShPtr > BndConds; Array<OneD, MultiRegions::ExpListSharedPtr> BndExp; BndConds = m_fields[fieldid]->GetBndConditions(); BndExp = m_fields[fieldid]->GetBndCondExpansions(); StdRegions::StdExpansionSharedPtr elmt; StdRegions::StdExpansionSharedPtr Bc; int cnt; int elmtid,nq,offset, boundary; Array<OneD, NekDouble> Bvals, U; int cnt1 = 0; for(cnt = n = 0; n < BndConds.num_elements(); ++n) { std::string type = BndConds[n]->GetUserDefined(); if((BndConds[n]->GetBoundaryConditionType() == SpatialDomains::eRobin)&&(boost::iequals(type,"Radiation"))) { for(i = 0; i < BndExp[n]->GetExpSize(); ++i,cnt++) { elmtid = m_fieldsBCToElmtID[fieldid][cnt]; elmt = m_fields[fieldid]->GetExp(elmtid); offset = m_fields[fieldid]->GetPhys_Offset(elmtid); U = m_fields[fieldid]->UpdatePhys() + offset; Bc = BndExp[n]->GetExp(i); boundary = m_fieldsBCToTraceID[fieldid][cnt]; // Get edge values and put into ubc nq = Bc->GetTotPoints(); Array<OneD, NekDouble> ubc(nq); elmt->GetTracePhysVals(boundary,Bc,U,ubc); Vmath::Vmul(nq,&m_fieldsRadiationFactor[fieldid][cnt1 + BndExp[n]->GetPhys_Offset(i)],1,&ubc[0],1,&ubc[0],1); Bvals = BndExp[n]->UpdateCoeffs()+BndExp[n]->GetCoeff_Offset(i); Bc->IProductWRTBase(ubc,Bvals); } cnt1 += BndExp[n]->GetTotPoints(); } else { cnt += BndExp[n]->GetExpSize(); } } }
void FilterAeroForces::v_Update( const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields, const NekDouble &time) { // Only output every m_outputFrequency. if ((m_index++) % m_outputFrequency) { return; } int n, cnt, elmtid, nq, offset, nt, boundary; nt = pFields[0]->GetNpoints(); int dim = pFields.num_elements()-1; StdRegions::StdExpansionSharedPtr elmt; Array<OneD, int> BoundarytoElmtID; Array<OneD, int> BoundarytoTraceID; Array<OneD, MultiRegions::ExpListSharedPtr> BndExp; Array<OneD, const NekDouble> P(nt); Array<OneD, const NekDouble> U(nt); Array<OneD, const NekDouble> V(nt); Array<OneD, const NekDouble> W(nt); Array<OneD, Array<OneD, NekDouble> > gradU(dim); Array<OneD, Array<OneD, NekDouble> > gradV(dim); Array<OneD, Array<OneD, NekDouble> > gradW(dim); Array<OneD, Array<OneD, NekDouble> > fgradU(dim); Array<OneD, Array<OneD, NekDouble> > fgradV(dim); Array<OneD, Array<OneD, NekDouble> > fgradW(dim); Array<OneD, NekDouble> values; LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm(); NekDouble Fx,Fy,Fz,Fxp,Fxv,Fyp,Fyv,Fzp,Fzv; Fxp = 0.0; // x-component of the force due to pressure difference Fxv = 0.0; // x-component of the force due to viscous stress Fx = 0.0; // x-component of the force (total) Fx = Fxp + Fxv (Drag) Fyp = 0.0; // y-component of the force due to pressure difference Fyv = 0.0; // y-component of the force due to viscous stress Fy = 0.0; // y-component of the force (total) Fy = Fyp + Fyv (Lift) Fzp = 0.0; // z-component of the force due to pressure difference Fzv = 0.0; // z-component of the force due to viscous stress Fz = 0.0; // z-component of the force (total) Fz = Fzp + Fzv (Side) NekDouble rho = (m_session->DefinesParameter("rho")) ? (m_session->GetParameter("rho")) : 1; NekDouble mu = rho*m_session->GetParameter("Kinvis"); for(int i = 0; i < pFields.num_elements(); ++i) { pFields[i]->SetWaveSpace(false); pFields[i]->BwdTrans(pFields[i]->GetCoeffs(), pFields[i]->UpdatePhys()); pFields[i]->SetPhysState(true); } // Homogeneous 1D case Compute forces on all WALL boundaries // This only has to be done on the zero (mean) Fourier mode. if(m_isHomogeneous1D) { if(vComm->GetColumnComm()->GetRank() == 0) { pFields[0]->GetPlane(0)->GetBoundaryToElmtMap( BoundarytoElmtID,BoundarytoTraceID); BndExp = pFields[0]->GetPlane(0)->GetBndCondExpansions(); StdRegions::StdExpansion1DSharedPtr bc; // loop over the types of boundary conditions for(cnt = n = 0; n < BndExp.num_elements(); ++n) { if(m_boundaryRegionIsInList[n] == 1) { for(int i = 0; i < BndExp[n]->GetExpSize(); ++i, cnt++) { // find element of this expansion. elmtid = BoundarytoElmtID[cnt]; elmt = pFields[0]->GetPlane(0)->GetExp(elmtid); nq = elmt->GetTotPoints(); offset = pFields[0]->GetPlane(0)->GetPhys_Offset(elmtid); // Initialise local arrays for the velocity // gradients size of total number of quadrature // points for each element (hence local). for(int j = 0; j < dim; ++j) { gradU[j] = Array<OneD, NekDouble>(nq,0.0); gradV[j] = Array<OneD, NekDouble>(nq,0.0); gradW[j] = Array<OneD, NekDouble>(nq,0.0); } // identify boundary of element boundary = BoundarytoTraceID[cnt]; // Extract fields U = pFields[0]->GetPlane(0)->GetPhys() + offset; V = pFields[1]->GetPlane(0)->GetPhys() + offset; P = pFields[3]->GetPlane(0)->GetPhys() + offset; // compute the gradients elmt->PhysDeriv(U,gradU[0],gradU[1]); elmt->PhysDeriv(V,gradV[0],gradV[1]); // Get face 1D expansion from element expansion bc = boost::dynamic_pointer_cast<LocalRegions ::Expansion1D> (BndExp[n]->GetExp(i)); // number of points on the boundary int nbc = bc->GetTotPoints(); // several vectors for computing the forces Array<OneD, NekDouble> Pb(nbc,0.0); for(int j = 0; j < dim; ++j) { fgradU[j] = Array<OneD, NekDouble>(nbc,0.0); fgradV[j] = Array<OneD, NekDouble>(nbc,0.0); } Array<OneD, NekDouble> drag_t(nbc,0.0); Array<OneD, NekDouble> lift_t(nbc,0.0); Array<OneD, NekDouble> drag_p(nbc,0.0); Array<OneD, NekDouble> lift_p(nbc,0.0); Array<OneD, NekDouble> temp(nbc,0.0); Array<OneD, NekDouble> temp2(nbc,0.0); // identify boundary of element . boundary = BoundarytoTraceID[cnt]; // extraction of the pressure and wss on the // boundary of the element elmt->GetEdgePhysVals(boundary,bc,P,Pb); for(int j = 0; j < dim; ++j) { elmt->GetEdgePhysVals(boundary,bc,gradU[j], fgradU[j]); elmt->GetEdgePhysVals(boundary,bc,gradV[j], fgradV[j]); } //normals of the element const Array<OneD, Array<OneD, NekDouble> > &normals = elmt->GetEdgeNormal(boundary); // // Compute viscous tractive forces on wall from // // t_i = - T_ij * n_j (minus sign for force // exerted BY fluid ON wall), // // where // // T_ij = viscous stress tensor (here in Cartesian // coords) // dU_i dU_j // = RHO * KINVIS * ( ---- + ---- ) . // dx_j dx_i //a) DRAG TERMS //-rho*kinvis*(2*du/dx*nx+(du/dy+dv/dx)*ny Vmath::Vadd(nbc,fgradU[1],1,fgradV[0],1,drag_t,1); Vmath::Vmul(nbc,drag_t,1,normals[1],1,drag_t,1); Vmath::Smul(nbc,2.0,fgradU[0],1,fgradU[0],1); Vmath::Vmul(nbc,fgradU[0],1,normals[0],1,temp2,1); Vmath::Smul(nbc,0.5,fgradU[0],1,fgradU[0],1); Vmath::Vadd(nbc,temp2,1,drag_t,1,drag_t,1); Vmath::Smul(nbc,-mu,drag_t,1,drag_t,1); //zero temporary storage vector Vmath::Zero(nbc,temp,0); Vmath::Zero(nbc,temp2,0); //b) LIFT TERMS //-rho*kinvis*(2*dv/dy*nx+(du/dy+dv/dx)*nx Vmath::Vadd(nbc,fgradU[1],1,fgradV[0],1,lift_t,1); Vmath::Vmul(nbc,lift_t,1,normals[0],1,lift_t,1); Vmath::Smul(nbc,2.0,fgradV[1],1,fgradV[1],1); Vmath::Vmul(nbc,fgradV[1],1,normals[1],1,temp2,1); Vmath::Smul(nbc,-0.5,fgradV[1],1,fgradV[1],1); Vmath::Vadd(nbc,temp2,1,lift_t,1,lift_t,1); Vmath::Smul(nbc,-mu,lift_t,1,lift_t,1); // Compute normal tractive forces on all WALL // boundaries Vmath::Vvtvp(nbc,Pb,1,normals[0],1, drag_p,1,drag_p, 1); Vmath::Vvtvp(nbc,Pb,1,normals[1],1, lift_p,1,lift_p,1); //integration over the boundary Fxv += bc->Integral(drag_t); Fyv += bc->Integral(lift_t); Fxp += bc->Integral(drag_p); Fyp += bc->Integral(lift_p); } } else { cnt += BndExp[n]->GetExpSize(); } } } for(int i = 0; i < pFields.num_elements(); ++i) { pFields[i]->SetWaveSpace(true); pFields[i]->BwdTrans(pFields[i]->GetCoeffs(), pFields[i]->UpdatePhys()); pFields[i]->SetPhysState(false); } } //3D WALL case else if(dim==3 && !m_isHomogeneous1D) { pFields[0]->GetBoundaryToElmtMap(BoundarytoElmtID, BoundarytoTraceID); BndExp = pFields[0]->GetBndCondExpansions(); LocalRegions::Expansion2DSharedPtr bc; // loop over the types of boundary conditions for(cnt = n = 0; n < BndExp.num_elements(); ++n) { if(m_boundaryRegionIsInList[n] == 1) { for(int i = 0; i < BndExp[n]->GetExpSize(); ++i, cnt++) { // find element of this expansion. elmtid = BoundarytoElmtID[cnt]; elmt = pFields[0]->GetExp(elmtid); nq = elmt->GetTotPoints(); offset = pFields[0]->GetPhys_Offset(elmtid); // Initialise local arrays for the velocity // gradients size of total number of quadrature // points for each element (hence local). for(int j = 0; j < dim; ++j) { gradU[j] = Array<OneD, NekDouble>(nq,0.0); gradV[j] = Array<OneD, NekDouble>(nq,0.0); gradW[j] = Array<OneD, NekDouble>(nq,0.0); } //identify boundary of element boundary = BoundarytoTraceID[cnt]; //Extract fields U = pFields[0]->GetPhys() + offset; V = pFields[1]->GetPhys() + offset; W = pFields[2]->GetPhys() + offset; P = pFields[3]->GetPhys() + offset; //compute the gradients elmt->PhysDeriv(U,gradU[0],gradU[1],gradU[2]); elmt->PhysDeriv(V,gradV[0],gradV[1],gradV[2]); elmt->PhysDeriv(W,gradW[0],gradW[1],gradW[2]); // Get face 2D expansion from element expansion bc = boost::dynamic_pointer_cast<LocalRegions ::Expansion2D> (BndExp[n]->GetExp(i)); //number of points on the boundary int nbc = bc->GetTotPoints(); //several vectors for computing the forces Array<OneD, NekDouble> Pb(nbc,0.0); for(int j = 0; j < dim; ++j) { fgradU[j] = Array<OneD, NekDouble>(nbc,0.0); fgradV[j] = Array<OneD, NekDouble>(nbc,0.0); fgradW[j] = Array<OneD, NekDouble>(nbc,0.0); } Array<OneD, NekDouble> drag_t(nbc,0.0); Array<OneD, NekDouble> lift_t(nbc,0.0); Array<OneD, NekDouble> side_t(nbc,0.0); Array<OneD, NekDouble> drag_p(nbc,0.0); Array<OneD, NekDouble> lift_p(nbc,0.0); Array<OneD, NekDouble> side_p(nbc,0.0); Array<OneD, NekDouble> temp(nbc,0.0); Array<OneD, NekDouble> temp2(nbc,0.0); // identify boundary of element . boundary = BoundarytoTraceID[cnt]; // extraction of the pressure and wss on the // boundary of the element elmt->GetFacePhysVals(boundary,bc,P,Pb); for(int j = 0; j < dim; ++j) { elmt->GetFacePhysVals(boundary,bc,gradU[j], fgradU[j]); elmt->GetFacePhysVals(boundary,bc,gradV[j], fgradV[j]); elmt->GetFacePhysVals(boundary,bc,gradW[j], fgradW[j]); } // normals of the element const Array<OneD, Array<OneD, NekDouble> > &normals = elmt->GetFaceNormal(boundary); // // Compute viscous tractive forces on wall from // // t_i = - T_ij * n_j (minus sign for force // exerted BY fluid ON wall), // // where // // T_ij = viscous stress tensor (here in Cartesian // coords) // dU_i dU_j // = RHO * KINVIS * ( ---- + ---- ) . // dx_j dx_i //a) DRAG TERMS //-rho*kinvis* // (2*du/dx*nx+(du/dy+dv/dx)*ny+(du/dz+dw/dx)*nz) Vmath::Vadd(nbc,fgradU[2],1,fgradW[0],1,temp,1); Vmath::Neg(nbc,temp,1); Vmath::Vmul(nbc,temp,1,normals[2],1,temp,1); Vmath::Vadd(nbc,fgradU[1],1,fgradV[0],1,drag_t,1); Vmath::Neg(nbc,drag_t,1); Vmath::Vmul(nbc,drag_t,1,normals[1],1,drag_t,1); Vmath::Smul(nbc,-2.0,fgradU[0],1,fgradU[0],1); Vmath::Vmul(nbc,fgradU[0],1,normals[0],1,temp2,1); Vmath::Smul(nbc,-0.5,fgradU[0],1,fgradU[0],1); Vmath::Vadd(nbc,temp,1,temp2,1,temp,1); Vmath::Vadd(nbc,temp,1,drag_t,1,drag_t,1); Vmath::Smul(nbc,mu,drag_t,1,drag_t,1); //zero temporary storage vector Vmath::Zero(nbc,temp,0); Vmath::Zero(nbc,temp2,0); //b) LIFT TERMS //-rho*kinvis* // (2*dv/dy*nx+(du/dy+dv/dx)*nx+(dv/dz+dw/dy)*nz) Vmath::Vadd(nbc,fgradV[2],1,fgradW[1],1,temp,1); Vmath::Neg(nbc,temp,1); Vmath::Vmul(nbc,temp,1,normals[2],1,temp,1); Vmath::Vadd(nbc,fgradU[1],1,fgradV[0],1,lift_t,1); Vmath::Neg(nbc,lift_t,1); Vmath::Vmul(nbc,lift_t,1,normals[0],1,lift_t,1); Vmath::Smul(nbc,-2.0,fgradV[1],1,fgradV[1],1); Vmath::Vmul(nbc,fgradV[1],1,normals[1],1,temp2,1); Vmath::Smul(nbc,-0.5,fgradV[1],1,fgradV[1],1); Vmath::Vadd(nbc,temp,1,temp2,1,temp,1); Vmath::Vadd(nbc,temp,1,lift_t,1,lift_t,1); Vmath::Smul(nbc,mu,lift_t,1,lift_t,1); //zero temporary storage vector Vmath::Zero(nbc,temp,0); Vmath::Zero(nbc,temp2,0); //b) SIDE TERMS //-rho*kinvis* // (2*dv/dy*nx+(du/dy+dv/dx)*nx+(dv/dz+dw/dy)*nz) Vmath::Vadd(nbc,fgradV[2],1,fgradW[1],1,temp,1); Vmath::Neg(nbc,temp,1); Vmath::Vmul(nbc,temp,1,normals[1],1,temp,1); Vmath::Vadd(nbc,fgradU[2],1,fgradW[0],1,side_t,1); Vmath::Neg(nbc,side_t,1); Vmath::Vmul(nbc,side_t,1,normals[0],1,side_t,1); Vmath::Smul(nbc,-2.0,fgradW[2],1,fgradW[2],1); Vmath::Vmul(nbc,fgradW[2],1,normals[2],1,temp2,1); Vmath::Smul(nbc,-0.5,fgradW[2],1,fgradW[2],1); Vmath::Vadd(nbc,temp,1,temp2,1,temp,1); Vmath::Vadd(nbc,temp,1,side_t,1,side_t,1); Vmath::Smul(nbc,mu,side_t,1,side_t,1); // Compute normal tractive forces on all WALL // boundaries Vmath::Vvtvp(nbc,Pb,1,normals[0],1, drag_p,1,drag_p,1); Vmath::Vvtvp(nbc,Pb,1,normals[1],1, lift_p,1,lift_p,1); Vmath::Vvtvp(nbc,Pb,1,normals[2],1, side_p,1,side_p,1); //integration over the boundary Fxv += bc->Expansion::Integral(drag_t); Fyv += bc->Expansion::Integral(lift_t); Fzv += bc->Expansion::Integral(side_t); Fxp += bc->Expansion::Integral(drag_p); Fyp += bc->Expansion::Integral(lift_p); Fzp += bc->Expansion::Integral(side_p); } } else { cnt += BndExp[n]->GetExpSize(); } } } //2D WALL Condition else { pFields[0]->GetBoundaryToElmtMap(BoundarytoElmtID, BoundarytoTraceID); BndExp = pFields[0]->GetBndCondExpansions(); StdRegions::StdExpansion1DSharedPtr bc; // loop over the types of boundary conditions for(cnt = n = 0; n < BndExp.num_elements(); ++n) { if(m_boundaryRegionIsInList[n] == 1) { for(int i = 0; i < BndExp[n]->GetExpSize(); ++i, cnt++) { elmtid = BoundarytoElmtID[cnt]; elmt = pFields[0]->GetExp(elmtid); nq = elmt->GetTotPoints(); offset = pFields[0]->GetPhys_Offset(elmtid); for(int j = 0; j < dim; ++j) { gradU[j] = Array<OneD, NekDouble>(nq,0.0); gradV[j] = Array<OneD, NekDouble>(nq,0.0); } boundary = BoundarytoTraceID[cnt]; U = pFields[0]->GetPhys() + offset; V = pFields[1]->GetPhys() + offset; P = pFields[2]->GetPhys() + offset; elmt->PhysDeriv(U,gradU[0],gradU[1]); elmt->PhysDeriv(V,gradV[0],gradV[1]); bc = boost::dynamic_pointer_cast<LocalRegions ::Expansion1D> (BndExp[n]->GetExp(i)); int nbc = bc->GetTotPoints(); Array<OneD, NekDouble> Pb(nbc,0.0); Array<OneD, NekDouble> drag_t(nbc,0.0); Array<OneD, NekDouble> lift_t(nbc,0.0); Array<OneD, NekDouble> drag_p(nbc,0.0); Array<OneD, NekDouble> lift_p(nbc,0.0); Array<OneD, NekDouble> temp(nbc,0.0); boundary = BoundarytoTraceID[cnt]; elmt->GetEdgePhysVals(boundary,bc,P,Pb); for(int j = 0; j < dim; ++j) { fgradU[j] = Array<OneD, NekDouble>(nbc,0.0); fgradV[j] = Array<OneD, NekDouble>(nbc,0.0); } for(int j = 0; j < dim; ++j) { elmt->GetEdgePhysVals(boundary,bc,gradU[j], fgradU[j]); elmt->GetEdgePhysVals(boundary,bc,gradV[j], fgradV[j]); } const Array<OneD, Array<OneD, NekDouble> > &normals = elmt->GetEdgeNormal(boundary); Vmath::Vadd(nbc,fgradU[1],1,fgradV[0],1,drag_t,1); Vmath::Neg(nbc,drag_t,1); Vmath::Vmul(nbc,drag_t,1,normals[1],1,drag_t,1); Vmath::Smul(nbc,-2.0,fgradU[0],1,fgradU[0],1); Vmath::Vmul(nbc,fgradU[0],1,normals[0],1,temp,1); Vmath::Vadd(nbc,temp,1,drag_t,1,drag_t,1); Vmath::Smul(nbc,mu,drag_t,1,drag_t,1); Vmath::Vadd(nbc,fgradU[1],1,fgradV[0],1,lift_t,1); Vmath::Neg(nbc,lift_t,1); Vmath::Vmul(nbc,lift_t,1,normals[0],1,lift_t,1); Vmath::Smul(nbc,-2.0,fgradV[1],1,fgradV[1],1); Vmath::Vmul(nbc,fgradV[1],1,normals[1],1,temp,1); Vmath::Vadd(nbc,temp,1,lift_t,1,lift_t,1); Vmath::Smul(nbc,mu,lift_t,1,lift_t,1); Vmath::Vvtvp(nbc,Pb,1,normals[0],1, drag_p,1,drag_p,1); Vmath::Vvtvp(nbc,Pb,1,normals[1],1, lift_p,1,lift_p,1); Fxp += bc->Integral(drag_p); Fyp += bc->Integral(lift_p); Fxv += bc->Integral(drag_t); Fyp += bc->Integral(lift_t); } } else { cnt += BndExp[n]->GetExpSize(); } } } vComm->AllReduce(Fxp, LibUtilities::ReduceSum); vComm->AllReduce(Fxv, LibUtilities::ReduceSum); Fx = Fxp + Fxv; vComm->AllReduce(Fyp, LibUtilities::ReduceSum); vComm->AllReduce(Fyv, LibUtilities::ReduceSum); Fy = Fyp + Fyv; vComm->AllReduce(Fzp, LibUtilities::ReduceSum); vComm->AllReduce(Fzv, LibUtilities::ReduceSum); Fz = Fzp + Fzv; if (vComm->GetRank() == 0) { m_outputStream.width(8); m_outputStream << setprecision(6) << time; m_outputStream.width(25); m_outputStream << setprecision(8) << Fxp; m_outputStream.width(25); m_outputStream << setprecision(8) << Fxv; m_outputStream.width(25); m_outputStream << setprecision(8) << Fx; m_outputStream.width(25); m_outputStream << setprecision(8) << Fyp; m_outputStream.width(25); m_outputStream << setprecision(8) << Fyv; m_outputStream.width(25); m_outputStream << setprecision(8) << Fy; m_outputStream.width(25); m_outputStream << setprecision(8) << Fzp; m_outputStream.width(25); m_outputStream << setprecision(8) << Fzv; m_outputStream.width(25); m_outputStream << setprecision(8) << Fz; m_outputStream << endl; } }
int main(int argc, char *argv[]) { int i,j; int surfID; if(argc != 5) { fprintf(stderr,"Usage: FldAddScalGrad meshfile infld outfld BoundaryID\n"); exit(1); } surfID = boost::lexical_cast<int>(argv[argc - 1]); argv[argc -1] = argv[argc - 2]; LibUtilities::SessionReaderSharedPtr vSession = LibUtilities::SessionReader::CreateInstance(argc, argv); //---------------------------------------------- // Read in mesh from input file string meshfile(argv[argc-4]); SpatialDomains::MeshGraphSharedPtr graphShPt = SpatialDomains::MeshGraph::Read(vSession); //---------------------------------------------- //---------------------------------------------- // Import field file. string fieldfile(argv[argc-3]); vector<LibUtilities::FieldDefinitionsSharedPtr> fielddef; vector<vector<NekDouble> > fielddata; LibUtilities::Import(fieldfile,fielddef,fielddata); //---------------------------------------------- //---------------------------------------------- // Define Expansion int expdim = graphShPt->GetMeshDimension(); int nfields = 1; int addfields = 7; Array<OneD, MultiRegions::ExpListSharedPtr> exp(nfields + addfields); MultiRegions::AssemblyMapCGSharedPtr m_locToGlobalMap; switch(expdim) { case 1: { ASSERTL0(false,"Expansion dimension not recognised"); } break; case 2: { ASSERTL0(false,"Expansion dimension not recognised"); } break; case 3: { MultiRegions::ContField3DSharedPtr originalfield = MemoryManager<MultiRegions::ContField3D> ::AllocateSharedPtr(vSession, graphShPt, vSession->GetVariable(0)); m_locToGlobalMap = originalfield->GetLocalToGlobalMap(); exp[0] = originalfield; for (i=0; i<addfields; i++) { exp[i+1] = MemoryManager<MultiRegions::ContField3D> ::AllocateSharedPtr(*originalfield, graphShPt, vSession->GetVariable(0)); } } break; default: ASSERTL0(false,"Expansion dimension not recognised"); break; } //---------------------------------------------- //---------------------------------------------- // Copy data from field file for(j = 0; j < nfields+addfields; ++j) { for(int i = 0; i < fielddata.size(); ++i) { exp[j]->ExtractDataToCoeffs(fielddef [i], fielddata[i], fielddef [i]->m_fields[0], exp[j]->UpdateCoeffs()); } exp[j]->BwdTrans(exp[j]->GetCoeffs(),exp[j]->UpdatePhys()); } //---------------------------------------------- //---------------------------------------------- int n, cnt, elmtid, nq, offset, nt, boundary, nfq; nt = exp[0]->GetNpoints(); Array<OneD, Array<OneD, NekDouble> > grad(expdim); Array<OneD, Array<OneD, NekDouble> > fgrad(expdim); Array<OneD, Array<OneD, NekDouble> > values(addfields); // Set up mapping from Boundary condition to element details. StdRegions::StdExpansionSharedPtr elmt; StdRegions::StdExpansion2DSharedPtr bc; Array<OneD, int> BoundarytoElmtID; Array<OneD, int> BoundarytoTraceID; Array<OneD, Array<OneD, MultiRegions::ExpListSharedPtr> > BndExp(addfields); Array<OneD, const NekDouble> U(nt); Array<OneD, NekDouble> outvalues; exp[0]->GetBoundaryToElmtMap(BoundarytoElmtID,BoundarytoTraceID); //get boundary expansions for each field for (i = 0; i<addfields; i++) { BndExp[i] = exp[i]->GetBndCondExpansions(); } // loop over the types of boundary conditions for(cnt = n = 0; n < BndExp[0].num_elements(); ++n) { // identify boundary which the user wanted if(n == surfID) { for(i = 0; i < BndExp[0][n]->GetExpSize(); ++i, cnt++) { // find element and face of this expansion. elmtid = BoundarytoElmtID[cnt]; elmt = exp[0]->GetExp(elmtid); nq = elmt->GetTotPoints(); offset = exp[0]->GetPhys_Offset(elmtid); // Initialise local arrays for the velocity gradients // size of total number of quadrature points for each element (hence local). for(j = 0; j < expdim; ++j) { grad[j] = Array<OneD, NekDouble>(nq); } if(expdim == 2) { } else { for (j = 0; j< addfields; j++) { values[j] = BndExp[j][n]->UpdateCoeffs() + BndExp[j][n]->GetCoeff_Offset(i); } // Get face 2D expansion from element expansion bc = boost::dynamic_pointer_cast<StdRegions::StdExpansion2D> (BndExp[0][n]->GetExp(i)); // Number of face quadrature points nfq = bc->GetTotPoints(); //identify boundary of element boundary = BoundarytoTraceID[cnt]; //Extract scalar field U = exp[0]->GetPhys() + offset; //Compute gradients elmt->PhysDeriv(U,grad[0],grad[1],grad[2]); if(i ==0) { for (j = 0; j< nq; j++) { cout << "element grad: " << grad[0][j] << endl; } } for(j = 0; j < expdim; ++j) { fgrad[j] = Array<OneD, NekDouble>(nfq); } // Get gradient at the quadrature points of the face for(j = 0; j < expdim; ++j) { elmt->GetFacePhysVals(boundary,bc,grad[j],fgrad[j]); bc->FwdTrans(fgrad[j],values[j]); } if(i ==0) { for (j = 0; j< nfq; j++) { cout << "face grad: " << fgrad[0][j] << endl; } } const SpatialDomains::GeomFactorsSharedPtr m_metricinfo=bc->GetMetricInfo(); const Array<OneD, const Array<OneD, NekDouble> > normals = elmt->GetFaceNormal(boundary); Array<OneD, NekDouble> gradnorm(nfq); if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed) { Vmath::Vvtvvtp(nfq,normals[0],1,fgrad[0],1, normals[1],1,fgrad[1],1,gradnorm,1); Vmath::Vvtvp (nfq,normals[2],1,fgrad[2],1,gradnorm,1,gradnorm,1); } else { Vmath::Svtsvtp(nfq,normals[0][0],fgrad[0],1, normals[1][0],fgrad[1],1,gradnorm,1); Vmath::Svtvp(nfq,normals[2][0],fgrad[2],1,gradnorm,1,gradnorm,1); } for(j = 0; j<expdim; j++) { bc->FwdTrans(normals[j],values[j+expdim]); } //gradient (grad(u) n) Vmath::Smul(nfq,-1.0,gradnorm,1,gradnorm,1); bc->FwdTrans(gradnorm,values[expdim*2]); } } } else { cnt += BndExp[0][n]->GetExpSize(); } } for(int j = 0; j < addfields; ++j) { int ncoeffs = exp[0]->GetNcoeffs(); Array<OneD, NekDouble> output(ncoeffs); output=exp[j+1]->UpdateCoeffs(); int nGlobal=m_locToGlobalMap->GetNumGlobalCoeffs(); Array<OneD, NekDouble> outarray(nGlobal,0.0); int bndcnt=0; const Array<OneD,const int>& map = m_locToGlobalMap->GetBndCondCoeffsToGlobalCoeffsMap(); NekDouble sign; for(int i = 0; i < BndExp[j].num_elements(); ++i) { if(i==surfID) { const Array<OneD,const NekDouble>& coeffs = BndExp[j][i]->GetCoeffs(); for(int k = 0; k < (BndExp[j][i])->GetNcoeffs(); ++k) { sign = m_locToGlobalMap->GetBndCondCoeffsToGlobalCoeffsSign(bndcnt); outarray[map[bndcnt++]] = sign * coeffs[k]; } } else { bndcnt += BndExp[j][i]->GetNcoeffs(); } } m_locToGlobalMap->GlobalToLocal(outarray,output); } //----------------------------------------------- // Write solution to file with additional computed fields string out(argv[argc-2]); std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef = exp[0]->GetFieldDefinitions(); std::vector<std::vector<NekDouble> > FieldData(FieldDef.size()); vector<string > outname; outname.push_back("du/dx"); outname.push_back("du/dy"); outname.push_back("du/dz"); outname.push_back("nx"); outname.push_back("ny"); outname.push_back("nz"); outname.push_back("gradient"); for(j = 0; j < nfields+addfields; ++j) { for(i = 0; i < FieldDef.size(); ++i) { if (j >= nfields) { FieldDef[i]->m_fields.push_back(outname[j-nfields]); } else { FieldDef[i]->m_fields.push_back(fielddef[i]->m_fields[j]); } exp[j]->AppendFieldData(FieldDef[i], FieldData[i]); } } LibUtilities::Write(out, FieldDef, FieldData); //----------------------------------------------- return 0; }
/** * Main function. * * Usage: VtkToFld session.xml input.vtk output.fld [options] */ int main(int argc, char* argv[]) { // Set up available options po::options_description desc("Available options"); desc.add_options() ("help,h", "Produce this help message.") ("name,n", po::value<string>()->default_value("Intensity"), "Name of field in VTK file to use for intensity.") ("outname,m", po::value<string>()->default_value("intensity"), "Name of field in output FLD file.") ("precision,p", po::value<double>()->default_value(1), "Precision of vertex matching."); po::options_description hidden("Hidden options"); hidden.add_options() ("file", po::value<vector<string> >(), "Input filename"); po::options_description cmdline_options; cmdline_options.add(desc).add(hidden); po::positional_options_description p; p.add("file", -1); po::variables_map vm; // Parse command-line options try { po::store(po::command_line_parser(argc, argv). options(cmdline_options).positional(p).run(), vm); po::notify(vm); } catch (const std::exception& e) { cerr << e.what() << endl; cerr << desc; return 1; } if ( vm.count("help") || vm.count("file") == 0 || vm["file"].as<vector<string> >().size() != 3) { cerr << "Usage: VtkToFld session.xml intensity.vtk output.fld [options]" << endl; cerr << desc; return 1; } // Extract command-line argument values std::vector<std::string> vFiles = vm["file"].as<vector<string> >(); const string infile = vFiles[1]; const string outfile = vFiles[2]; const double factor = vm["precision"].as<double>(); const string name = vm["name"].as<string>(); const string outname = vm["outname"].as<string>(); std::vector<std::string> vFilenames; LibUtilities::SessionReaderSharedPtr vSession; SpatialDomains::MeshGraphSharedPtr graph2D; MultiRegions::ExpList2DSharedPtr Exp; vFilenames.push_back(vFiles[0]); vSession = LibUtilities::SessionReader::CreateInstance(2, argv, vFilenames); try { //---------------------------------------------- // Read in mesh from input file graph2D = MemoryManager<SpatialDomains::MeshGraph2D>:: AllocateSharedPtr(vSession); //---------------------------------------------- //---------------------------------------------- // Define Expansion Exp = MemoryManager<MultiRegions::ExpList2D>:: AllocateSharedPtr(vSession,graph2D); //---------------------------------------------- //---------------------------------------------- // Set up coordinates of mesh int coordim = Exp->GetCoordim(0); int nq = Exp->GetNpoints(); Array<OneD, NekDouble> xc0(nq,0.0); Array<OneD, NekDouble> xc1(nq,0.0); Array<OneD, NekDouble> xc2(nq,0.0); switch(coordim) { case 2: Exp->GetCoords(xc0,xc1); break; case 3: Exp->GetCoords(xc0,xc1,xc2); break; default: ASSERTL0(false,"Coordim not valid"); break; } //---------------------------------------------- vtkPolyDataReader *vtkMeshReader = vtkPolyDataReader::New(); vtkMeshReader->SetFileName(infile.c_str()); vtkMeshReader->Update(); vtkPolyData *vtkMesh = vtkMeshReader->GetOutput(); vtkCellDataToPointData* c2p = vtkCellDataToPointData::New(); #if VTK_MAJOR_VERSION <= 5 c2p->SetInput(vtkMesh); #else c2p->SetInputData(vtkMesh); #endif c2p->PassCellDataOn(); c2p->Update(); vtkPolyData *vtkDataAtPoints = c2p->GetPolyDataOutput(); vtkPoints *vtkPoints = vtkMesh->GetPoints(); ASSERTL0(vtkPoints, "ERROR: cannot get points from mesh."); vtkCellArray *vtkPolys = vtkMesh->GetPolys(); ASSERTL0(vtkPolys, "ERROR: cannot get polygons from mesh."); vtkPointData *vtkPData = vtkDataAtPoints->GetPointData(); ASSERTL0(vtkPolys, "ERROR: cannot get point data from file."); VertexSet points; VertexSet::iterator vIter; double p[3]; double val; double x, y, z; int coeff_idx; int i,j,n; if (!vtkDataAtPoints->GetPointData()->HasArray(name.c_str())) { n = vtkDataAtPoints->GetPointData()->GetNumberOfArrays(); cerr << "Input file '" << infile << "' does not have a field named '" << name << "'" << endl; cerr << "There are " << n << " arrays in this file." << endl; for (int i = 0; i < n; ++i) { cerr << " " << vtkDataAtPoints->GetPointData()->GetArray(i)->GetName() << endl; } return 1; } // Build up an unordered set of vertices from the VTK file. For each // vertex a hashed value of the coordinates is generated to within a // given tolerance. n = vtkPoints->GetNumberOfPoints(); for (i = 0; i < n; ++i) { vtkPoints->GetPoint(i,p); val = vtkPData->GetScalars(name.c_str())->GetTuple1(i); boost::shared_ptr<Vertex> v(new Vertex(p[0],p[1],p[2],val,factor)); points.insert(v); } // Now process each vertex of each element in the mesh SpatialDomains::PointGeomSharedPtr vert; for (i = 0; i < Exp->GetNumElmts(); ++i) { StdRegions::StdExpansionSharedPtr e = Exp->GetExp(i); for (j = 0; j < e->GetNverts(); ++j) { // Get the index of the coefficient corresponding to this vertex coeff_idx = Exp->GetCoeff_Offset(i) + e->GetVertexMap(j); // Get the coordinates of the vertex vert = e->as<LocalRegions::Expansion2D>()->GetGeom2D() ->GetVertex(j); vert->GetCoords(x,y,z); // Look up the vertex in the VertexSet boost::shared_ptr<Vertex> v(new Vertex(x,y,z,0.0,factor)); vIter = points.find(v); // If not found, maybe the tolerance should be reduced? // If found, record the scalar value from the VTK file in the // corresponding coefficient. if (vIter == points.end()) { cerr << "Vertex " << i << " not found. Looking for (" << x << ", " << y << ", " << z << ")" << endl; } else { Exp->UpdateCoeffs()[coeff_idx] = (*vIter)->scalar; } } } Exp->SetPhysState(false); //----------------------------------------------- // Write solution to file std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef = Exp->GetFieldDefinitions(); std::vector<std::vector<NekDouble> > FieldData(FieldDef.size()); for(i = 0; i < FieldDef.size(); ++i) { FieldDef[i]->m_fields.push_back(outname); Exp->AppendFieldData(FieldDef[i], FieldData[i]); } LibUtilities::FieldIO vFld(vSession->GetComm()); vFld.Write(outfile, FieldDef, FieldData); //----------------------------------------------- } catch (...) { cout << "An error occurred." << endl; } }
void MappingExtrapolate::v_CorrectPressureBCs( const Array<OneD, NekDouble> &pressure) { if(m_HBCdata.num_elements()>0) { int cnt, n; int physTot = m_fields[0]->GetTotPoints(); int nvel = m_fields.num_elements()-1; Array<OneD, NekDouble> Vals; // Remove previous correction for(cnt = n = 0; n < m_PBndConds.num_elements(); ++n) { if(m_PBndConds[n]->GetUserDefined() == "H") { int nq = m_PBndExp[n]->GetNcoeffs(); Vmath::Vsub(nq, &(m_PBndExp[n]->GetCoeffs()[0]), 1, &(m_bcCorrection[cnt]), 1, &(m_PBndExp[n]->UpdateCoeffs()[0]), 1); cnt += nq; } } // Calculate new correction Array<OneD, NekDouble> Jac(physTot, 0.0); m_mapping->GetJacobian(Jac); Array<OneD, Array<OneD, NekDouble> > correction(nvel); Array<OneD, Array<OneD, NekDouble> > gradP(nvel); Array<OneD, Array<OneD, NekDouble> > wk(nvel); Array<OneD, Array<OneD, NekDouble> > wk2(nvel); for (int i=0; i<nvel; i++) { wk[i] = Array<OneD, NekDouble> (physTot, 0.0); gradP[i] = Array<OneD, NekDouble> (physTot, 0.0); correction[i] = Array<OneD, NekDouble> (physTot, 0.0); } // Calculate G(p) for(int i = 0; i < nvel; ++i) { m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i], pressure, gradP[i]); if(m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousBwdTrans(gradP[i], wk[i]); } else { Vmath::Vcopy(physTot, gradP[i], 1, wk[i], 1); } } m_mapping->RaiseIndex(wk, correction); // G(p) // alpha*J*(G(p)) if (!m_mapping->HasConstantJacobian()) { for(int i = 0; i < nvel; ++i) { Vmath::Vmul(physTot, correction[i], 1, Jac, 1, correction[i], 1); } } for(int i = 0; i < nvel; ++i) { Vmath::Smul(physTot, m_pressureRelaxation, correction[i], 1, correction[i], 1); } if(m_pressure->GetWaveSpace()) { for(int i = 0; i < nvel; ++i) { m_pressure->HomogeneousFwdTrans(correction[i], correction[i]); } } // p_i - alpha*J*div(G(p)) for (int i = 0; i < nvel; ++i) { Vmath::Vsub(physTot, gradP[i], 1, correction[i], 1, correction[i], 1); } // Get value at boundary and calculate Inner product StdRegions::StdExpansionSharedPtr Pbc; StdRegions::StdExpansionSharedPtr elmt; Array<OneD, Array<OneD, const NekDouble> > correctionElmt(m_bnd_dim); Array<OneD, Array<OneD, NekDouble> > BndValues(m_bnd_dim); for(int i = 0; i < m_bnd_dim; i++) { BndValues[i] = Array<OneD, NekDouble> (m_pressureBCsMaxPts,0.0); } for(int j = 0 ; j < m_HBCdata.num_elements() ; j++) { /// Casting the boundary expansion to the specific case Pbc = boost::dynamic_pointer_cast<StdRegions::StdExpansion> (m_PBndExp[m_HBCdata[j].m_bndryID] ->GetExp(m_HBCdata[j].m_bndElmtID)); /// Picking up the element where the HOPBc is located elmt = m_pressure->GetExp(m_HBCdata[j].m_globalElmtID); /// Assigning for(int i = 0; i < m_bnd_dim; i++) { correctionElmt[i] = correction[i] + m_HBCdata[j].m_physOffset; } Vals = m_bcCorrection + m_HBCdata[j].m_coeffOffset; // Getting values on the edge and filling the correction switch(m_pressure->GetExpType()) { case MultiRegions::e2D: case MultiRegions::e3DH1D: { elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[0], BndValues[0]); elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[1], BndValues[1]); // InnerProduct Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], Vals); } break; case MultiRegions::e3D: { elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[0], BndValues[0]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[1], BndValues[1]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, correctionElmt[2], BndValues[2]); Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], BndValues[2], Vals); } break; default: ASSERTL0(0,"Dimension not supported"); break; } } // Apply new correction for(cnt = n = 0; n < m_PBndConds.num_elements(); ++n) { if(m_PBndConds[n]->GetUserDefined() == "H") { int nq = m_PBndExp[n]->GetNcoeffs(); Vmath::Vadd(nq, &(m_PBndExp[n]->GetCoeffs()[0]), 1, &(m_bcCorrection[cnt]), 1, &(m_PBndExp[n]->UpdateCoeffs()[0]), 1); cnt += nq; } } } }
void MappingExtrapolate::v_CalcNeumannPressureBCs( const Array<OneD, const Array<OneD, NekDouble> > &fields, const Array<OneD, const Array<OneD, NekDouble> > &N, NekDouble kinvis) { if (m_mapping->HasConstantJacobian() && !m_implicitViscous) { Extrapolate::v_CalcNeumannPressureBCs( fields, N, kinvis); } else { int physTot = m_fields[0]->GetTotPoints(); int nvel = m_fields.num_elements()-1; Array<OneD, NekDouble> Pvals; StdRegions::StdExpansionSharedPtr Pbc; StdRegions::StdExpansionSharedPtr elmt; Array<OneD, Array<OneD, const NekDouble> > Velocity(m_bnd_dim); Array<OneD, Array<OneD, const NekDouble> > Advection(m_bnd_dim); // Get transformation Jacobian Array<OneD, NekDouble> Jac(physTot,0.0); m_mapping->GetJacobian(Jac); // Declare variables Array<OneD, Array<OneD, NekDouble> > BndValues(m_bnd_dim); Array<OneD, Array<OneD, NekDouble> > Q(m_bnd_dim); Array<OneD, Array<OneD, NekDouble> > Q_field(nvel); Array<OneD, Array<OneD, NekDouble> > fields_new(nvel); Array<OneD, Array<OneD, NekDouble> > N_new(m_bnd_dim); // Temporary variables Array<OneD, NekDouble> tmp(physTot,0.0); Array<OneD, NekDouble> tmp2(physTot,0.0); for(int i = 0; i < m_bnd_dim; i++) { BndValues[i] = Array<OneD, NekDouble> (m_pressureBCsMaxPts,0.0); Q[i] = Array<OneD, NekDouble> (m_pressureBCsElmtMaxPts,0.0); N_new[i] = Array<OneD, NekDouble> (physTot,0.0); } for(int i = 0; i < nvel; i++) { Q_field[i] = Array<OneD, NekDouble> (physTot,0.0); fields_new[i] = Array<OneD, NekDouble> (physTot,0.0); } // Multiply convective terms by Jacobian for(int i = 0; i < m_bnd_dim; i++) { if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousBwdTrans(N[i],N_new[i]); } else { Vmath::Vcopy(physTot, N[i], 1, N_new[i], 1); } Vmath::Vmul(physTot, Jac, 1, N_new[i], 1, N_new[i], 1); if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousFwdTrans(N_new[i],N_new[i]); } } // Get velocity in physical space for(int i = 0; i < nvel; i++) { if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousBwdTrans(fields[i],fields_new[i]); } else { Vmath::Vcopy(physTot, fields[i], 1, fields_new[i], 1); } } // Calculate appropriate form of the CurlCurl operator m_mapping->CurlCurlField(fields_new, Q_field, m_implicitViscous); // If viscous terms are treated explicitly, // add grad(U/J \dot grad J) to CurlCurl if ( !m_implicitViscous) { m_mapping->DotGradJacobian(fields_new, tmp); Vmath::Vdiv(physTot, tmp, 1, Jac, 1, tmp, 1); bool wavespace = m_fields[0]->GetWaveSpace(); m_fields[0]->SetWaveSpace(false); for(int i = 0; i < m_bnd_dim; i++) { m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i], tmp, tmp2); Vmath::Vadd(physTot, Q_field[i], 1, tmp2, 1, Q_field[i], 1); } m_fields[0]->SetWaveSpace(wavespace); } // Multiply by Jacobian and convert to wavespace (if necessary) for(int i = 0; i < m_bnd_dim; i++) { Vmath::Vmul(physTot, Jac, 1, fields_new[i], 1, fields_new[i], 1); Vmath::Vmul(physTot, Jac, 1, Q_field[i] , 1, Q_field[i] , 1); if (m_fields[0]->GetWaveSpace()) { m_fields[0]->HomogeneousFwdTrans(fields_new[i],fields_new[i]); m_fields[0]->HomogeneousFwdTrans(Q_field[i],Q_field[i]); } } for(int j = 0 ; j < m_HBCdata.num_elements() ; j++) { /// Casting the boundary expansion to the specific case Pbc = boost::dynamic_pointer_cast<StdRegions::StdExpansion> (m_PBndExp[m_HBCdata[j].m_bndryID] ->GetExp(m_HBCdata[j].m_bndElmtID)); /// Picking up the element where the HOPBc is located elmt = m_pressure->GetExp(m_HBCdata[j].m_globalElmtID); /// Assigning for(int i = 0; i < m_bnd_dim; i++) { Velocity[i] = fields_new[i] + m_HBCdata[j].m_physOffset; Advection[i] = N_new[i] + m_HBCdata[j].m_physOffset; Q[i] = Q_field[i] + m_HBCdata[j].m_physOffset; } // Mounting advection component into the high-order condition for(int i = 0; i < m_bnd_dim; i++) { MountHOPBCs(m_HBCdata[j].m_ptsInElmt,kinvis,Q[i],Advection[i]); } Pvals = m_pressureHBCs[0] + m_HBCdata[j].m_coeffOffset; // Getting values on the edge and filling the pressure boundary // expansion and the acceleration term. Multiplication by the // normal is required switch(m_pressure->GetExpType()) { case MultiRegions::e2D: case MultiRegions::e3DH1D: { elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[0], BndValues[0]); elmt->GetEdgePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[1], BndValues[1]); // InnerProduct Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], Pvals); } break; case MultiRegions::e3DH2D: { if(m_HBCdata[j].m_elmtTraceID == 0) { (m_PBndExp[m_HBCdata[j].m_bndryID]->UpdateCoeffs() + m_PBndExp[m_HBCdata[j].m_bndryID] ->GetCoeff_Offset( m_HBCdata[j].m_bndElmtID))[0] = -1.0*Q[0][0]; } else if (m_HBCdata[j].m_elmtTraceID == 1) { (m_PBndExp[m_HBCdata[j].m_bndryID]->UpdateCoeffs() + m_PBndExp[m_HBCdata[j].m_bndryID] ->GetCoeff_Offset( m_HBCdata[j].m_bndElmtID))[0] = Q[0][m_HBCdata[j].m_ptsInElmt-1]; } else { ASSERTL0(false, "In the 3D homogeneous 2D approach BCs edge " "ID can be just 0 or 1 "); } } break; case MultiRegions::e3D: { elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[0], BndValues[0]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[1], BndValues[1]); elmt->GetFacePhysVals(m_HBCdata[j].m_elmtTraceID, Pbc, Q[2], BndValues[2]); Pbc->NormVectorIProductWRTBase(BndValues[0], BndValues[1], BndValues[2], Pvals); } break; default: ASSERTL0(0,"Dimension not supported"); break; } } } // If pressure terms are treated implicitly, we need to multiply // by the relaxation parameter, and zero the correction term if (m_implicitPressure) { Vmath::Smul(m_pressureHBCs[0].num_elements(), m_pressureRelaxation, m_pressureHBCs[0], 1, m_pressureHBCs[0], 1); } m_bcCorrection = Array<OneD, NekDouble> (m_pressureHBCs[0].num_elements(), 0.0); }
void ProcessWSS::Process(po::variables_map &vm) { if (m_f->m_verbose) { cout << "ProcessWSS: Calculating wall shear stress..." << endl; } m_f->m_addNormals = m_config["addnormals"].m_beenSet; // Set up Field options to output boundary fld string bvalues = m_config["bnd"].as<string>(); if(bvalues.compare("All") == 0) { Array<OneD, const MultiRegions::ExpListSharedPtr> BndExp = m_f->m_exp[0]->GetBndCondExpansions(); for(int i = 0; i < BndExp.num_elements(); ++i) { m_f->m_bndRegionsToWrite.push_back(i); } } else { ASSERTL0(ParseUtils::GenerateOrderedVector(bvalues.c_str(), m_f->m_bndRegionsToWrite),"Failed to interpret range string"); } NekDouble m_kinvis; m_kinvis = m_f->m_session->GetParameter("Kinvis"); int i, j; int spacedim = m_f->m_graph->GetSpaceDimension(); if ((m_f->m_fielddef[0]->m_numHomogeneousDir) == 1 || (m_f->m_fielddef[0]->m_numHomogeneousDir) == 2) { spacedim = 3; } int nfields = m_f->m_fielddef[0]->m_fields.size(); ASSERTL0(nfields == spacedim +1,"Implicit assumption that input is in incompressible format of (u,v,p) or (u,v,w,p)"); nfields = nfields - 1; if (spacedim == 1) { ASSERTL0(false, "Error: wss for a 1D problem cannot " "be computed"); } int newfields = (spacedim == 2)? 3:4; int nshear = (spacedim == 2)? 3:4; int nstress = (spacedim == 2)? 3:6; int ngrad = nfields*nfields; int n, cnt, elmtid, nq, offset, boundary, nfq; int npoints = m_f->m_exp[0]->GetNpoints(); Array<OneD, Array<OneD, NekDouble> > velocity(nfields), grad(ngrad), fgrad(ngrad); Array<OneD, Array<OneD, NekDouble> > stress(nstress), fstress(nstress); Array<OneD, Array<OneD, NekDouble> > outfield(newfields), fshear(nshear); StdRegions::StdExpansionSharedPtr elmt; StdRegions::StdExpansion2DSharedPtr bc; Array<OneD, int> BoundarytoElmtID, BoundarytoTraceID; Array<OneD, Array<OneD, MultiRegions::ExpListSharedPtr> > BndExp(newfields); m_f->m_exp.resize(newfields); string var = "u"; for(i = nfields+1; i < newfields; ++i) { m_f->m_exp[i] = m_f->AppendExpList(m_f->m_fielddef[0]->m_numHomogeneousDir, var); } m_f->m_fielddef[0]->m_fields.resize(newfields); if(spacedim == 2) { m_f->m_fielddef[0]->m_fields[0] = "Shear_x"; m_f->m_fielddef[0]->m_fields[1] = "Shear_y"; m_f->m_fielddef[0]->m_fields[2] = "Shear_mag"; } else { m_f->m_fielddef[0]->m_fields[0] = "Shear_x"; m_f->m_fielddef[0]->m_fields[1] = "Shear_y"; m_f->m_fielddef[0]->m_fields[2] = "Shear_z"; m_f->m_fielddef[0]->m_fields[3] = "Shear_mag"; } for (i = 0; i < newfields; ++i) { outfield[i] = Array<OneD, NekDouble>(npoints); } for (i = 0; i < nfields; ++i) { velocity[i] = Array<OneD, NekDouble>(npoints); } m_f->m_exp[0]->GetBoundaryToElmtMap(BoundarytoElmtID, BoundarytoTraceID); //get boundary expansions for each field for(int j = 0; j < newfields; ++j) { BndExp[j] = m_f->m_exp[j]->GetBndCondExpansions(); } // loop over the types of boundary conditions for(cnt = n = 0; n < BndExp[0].num_elements(); ++n) { bool doneBnd = false; // identify if boundary has been defined for(int b = 0; b < m_f->m_bndRegionsToWrite.size(); ++b) { if(n == m_f->m_bndRegionsToWrite[b]) { doneBnd = true; for(int i = 0; i < BndExp[0][n]->GetExpSize(); ++i, cnt++) { // find element and face of this expansion. elmtid = BoundarytoElmtID[cnt]; elmt = m_f->m_exp[0]->GetExp(elmtid); nq = elmt->GetTotPoints(); offset = m_f->m_exp[0]->GetPhys_Offset(elmtid); // Initialise local arrays for the velocity gradients, and stress components // size of total number of quadrature points for each element (hence local). for(int j = 0; j < ngrad; ++j) { grad[j] = Array<OneD, NekDouble>(nq); } for(int j = 0; j < nstress; ++j) { stress[j] = Array<OneD, NekDouble>(nq); } if(nfields == 2) { ASSERTL0(false, "Error: not implemented in 2D."); } else { // Get face 2D expansion from element expansion bc = boost::dynamic_pointer_cast<StdRegions::StdExpansion2D> (BndExp[0][n]->GetExp(i)); nfq = bc->GetTotPoints(); //identify boundary of element looking at. boundary = BoundarytoTraceID[cnt]; //Get face normals const SpatialDomains::GeomFactorsSharedPtr m_metricinfo = bc->GetMetricInfo(); const Array<OneD, const Array<OneD, NekDouble> > normals = elmt->GetFaceNormal(boundary); // initialise arrays for(int j = 0; j < nstress; ++j) { fstress[j] = Array<OneD, NekDouble>(nfq); } for(int j = 0; j < nfields*nfields; ++j) { fgrad[j] = Array<OneD, NekDouble>(nfq); } for(int j = 0; j < nshear; ++j) { fshear[j] = Array<OneD, NekDouble>(nfq); } //Extract Velocities for(int j = 0; j < nfields; ++j) { velocity[j] = m_f->m_exp[j]->GetPhys() + offset; } //Compute gradients (velocity correction scheme method) elmt->PhysDeriv(velocity[0],grad[0],grad[1],grad[2]); elmt->PhysDeriv(velocity[1],grad[3],grad[4],grad[5]); elmt->PhysDeriv(velocity[2],grad[6],grad[7],grad[8]); //Compute stress component terms // t_xx = 2.mu.Ux Vmath::Smul (nq,(2*m_kinvis),grad[0],1,stress[0],1); // tyy = 2.mu.Vy Vmath::Smul (nq,(2*m_kinvis),grad[4],1,stress[1],1); // tzz = 2.mu.Wz Vmath::Smul (nq,(2*m_kinvis),grad[8],1,stress[2],1); // txy = mu.(Uy+Vx) Vmath::Vadd (nq,grad[1],1,grad[3],1,stress[3],1); Vmath::Smul (nq,m_kinvis,stress[3],1,stress[3],1); // txz = mu.(Uz+Wx) Vmath::Vadd (nq,grad[2],1,grad[6],1,stress[4],1); Vmath::Smul (nq,m_kinvis,stress[4],1,stress[4],1); // tyz = mu.(Vz+Wy) Vmath::Vadd (nq,grad[5],1,grad[7],1,stress[5],1); Vmath::Smul (nq,m_kinvis,stress[5],1,stress[5],1); // Get face stress values. for(j = 0; j < nstress; ++j) { elmt->GetFacePhysVals(boundary,bc,stress[j],fstress[j]); } //calcuate wss, and update velocity coeffs in the elemental boundary expansion for (j = 0; j< newfields; j++) { outfield[j] = BndExp[j][n]->UpdateCoeffs() + BndExp[j][n]->GetCoeff_Offset(i); } //surface curved if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed) { // Sx Vmath::Vvtvvtp(nfq,normals[0],1,fstress[0],1, normals[1],1,fstress[3],1,fshear[0],1); Vmath::Vvtvp (nfq,normals[2],1,fstress[4],1,fshear[0],1,fshear[0],1); // Sy Vmath::Vvtvvtp(nfq,normals[0],1,fstress[3],1, normals[1],1,fstress[1],1,fshear[1],1); Vmath::Vvtvp (nfq,normals[2],1,fstress[5],1,fshear[1],1,fshear[1],1); // Sz Vmath::Vvtvvtp(nfq,normals[0],1,fstress[4],1, normals[1],1,fstress[5],1,fshear[2],1); Vmath::Vvtvp (nfq,normals[2],1,fstress[2],1,fshear[2],1,fshear[2],1); } else { // Sx Vmath::Svtsvtp(nfq,normals[0][0],fstress[0],1, normals[1][0],fstress[3],1,fshear[0],1); Vmath::Svtvp(nfq,normals[2][0],fstress[4],1,fshear[0],1,fshear[0],1); // Sy Vmath::Svtsvtp(nfq,normals[0][0],fstress[3],1, normals[1][0],fstress[1],1,fshear[1],1); Vmath::Svtvp(nfq,normals[2][0],fstress[5],1,fshear[1],1,fshear[1],1); // Sz Vmath::Svtsvtp(nfq,normals[0][0],fstress[4],1, normals[1][0],fstress[5],1,fshear[2],1); Vmath::Svtvp(nfq,normals[2][0],fstress[2],1,fshear[2],1,fshear[2],1); } // T = T - (T.n)n if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed) { Vmath::Vvtvvtp(nfq,normals[0],1,fshear[0],1, normals[1],1, fshear[1],1,fshear[3],1); Vmath::Vvtvp (nfq,normals[2],1, fshear[2],1,fshear[3],1,fshear[3],1); Vmath::Smul(nfq, -1.0, fshear[3], 1, fshear[3], 1); for (j = 0; j < nfields; j++) { Vmath::Vvtvp(nfq,normals[j], 1, fshear[3], 1, fshear[j], 1, fshear[j], 1); bc->FwdTrans(fshear[j], outfield[j]); } } else { Vmath::Svtsvtp(nfq,normals[0][0],fshear[0],1, normals[1][0],fshear[1],1,fshear[3],1); Vmath::Svtvp(nfq,normals[2][0],fshear[2],1,fshear[3],1,fshear[3],1); Vmath::Smul(nfq, -1.0, fshear[3], 1,fshear[3], 1); for (j = 0; j < nfields; j++) { Vmath::Svtvp(nfq,normals[j][0],fshear[3],1,fshear[j],1,fshear[j],1); bc->FwdTrans(fshear[j], outfield[j]); } } // Tw Vmath::Vvtvvtp(nfq, fshear[0], 1, fshear[0], 1, fshear[1], 1, fshear[1], 1, fshear[3], 1); Vmath::Vvtvp(nfq, fshear[2], 1, fshear[2], 1, fshear[3], 1, fshear[3], 1); Vmath::Vsqrt(nfq, fshear[3], 1, fshear[3], 1); bc->FwdTrans(fshear[3], outfield[3]); } } } } if(doneBnd == false) { cnt += BndExp[0][n]->GetExpSize(); } } for(int j = 0; j < newfields; ++j) { for(int b = 0; b < m_f->m_bndRegionsToWrite.size(); ++b) { m_f->m_exp[j]->UpdateBndCondExpansion(m_f->m_bndRegionsToWrite[b]) = BndExp[j][m_f->m_bndRegionsToWrite[b]]; } } }