Esempio n. 1
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;
}
Esempio n. 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;
            }
        }
Esempio n. 3
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]];
        }
    }
}