Example #1
0
    /**
     * 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();
            }
        }
    }
Example #2
0
        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;
            }
        }
Example #3
0
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;
}
Example #4
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);
    }
Example #7
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]];
        }
    }
}