示例#1
0
namespace Utilities
{

ModuleKey ProcessEquiSpacedOutput::className =
    GetModuleFactory().RegisterCreatorFunction(
           ModuleKey(eProcessModule, "equispacedoutput"),
           ProcessEquiSpacedOutput::create,
           "Write data as equi-spaced output using simplices to represent the data for connecting points");


ProcessEquiSpacedOutput::ProcessEquiSpacedOutput(FieldSharedPtr f)
    : ProcessModule(f)
{
    f->m_setUpEquiSpacedFields = true;

    m_config["tetonly"] = ConfigOption(true, "NotSet",
                                "Only process tetrahedral elements");

    m_config["modalenergy"] = ConfigOption(true,"NotSet","Write output as modal energy");

}

ProcessEquiSpacedOutput::~ProcessEquiSpacedOutput()
{
}

void ProcessEquiSpacedOutput::Process(po::variables_map &vm)
{
    SetupEquiSpacedField();
}


void ProcessEquiSpacedOutput::SetupEquiSpacedField(void)
{

    if(m_f->m_verbose)
    {
        cout << "Interpolating fields to equispaced" << endl;
    }

    int coordim  = m_f->m_exp[0]->GetCoordim(0);
    int shapedim = m_f->m_exp[0]->GetExp(0)->GetShapeDimension();
    int npts     = m_f->m_exp[0]->GetTotPoints();
    Array<OneD, Array<OneD, NekDouble> > coords(3);

    int nel = m_f->m_exp[0]->GetExpSize();

    // set up the number of points in each element
    int newpoints;
    int newtotpoints = 0;

    Array<OneD,int> conn;
    int prevNcoeffs = 0;
    int prevNpoints = 0;
    int cnt = 0;

    // identify face 1 connectivity for prisms
    map<int,StdRegions::Orientation > face0orient;
    set<int> prismorient;
    LocalRegions::ExpansionSharedPtr e;

    // prepare PtsField
    vector<std::string> fieldNames;
    vector<int> ppe;
    vector<Array<OneD, int> > ptsConn;
    int nfields;

    for(int i = 0; i < nel; ++i)
    {
        e = m_f->m_exp[0]->GetExp(i);
        if(e->DetShapeType() == LibUtilities::ePrism)
        {
            StdRegions::Orientation forient = e->GetForient(0);
            int fid = e->GetGeom()->GetFid(0);
            if(face0orient.count(fid))
            { // face 1 meeting face 1 so reverse this id
                prismorient.insert(i);
            }
            else
            {
                // just store if Dir 1 is fwd or bwd
                if((forient == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
                   (forient == StdRegions::eDir1BwdDir1_Dir2BwdDir2) ||
                   (forient == StdRegions::eDir1BwdDir2_Dir2FwdDir1) ||
                   (forient == StdRegions::eDir1BwdDir2_Dir2BwdDir1))
                {
                    face0orient[fid] = StdRegions::eBwd;
                }
                else
                {
                    face0orient[fid] = StdRegions::eFwd;
                }
            }
        }
    }

    for(int i = 0; i < nel; ++i)
    {
        e = m_f->m_exp[0]->GetExp(i);
        if(e->DetShapeType() == LibUtilities::ePrism)
        {
            int fid = e->GetGeom()->GetFid(2);
            // check to see if face 2 meets face 1
            if(face0orient.count(fid))
            {
                // check to see how face 2 is orientated
                StdRegions::Orientation forient2 = e->GetForient(2);
                StdRegions::Orientation forient0 = face0orient[fid];

                // If dir 1 or forient2 is bwd then check agains
                // face 1 value
                if((forient2 == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
                   (forient2 == StdRegions::eDir1BwdDir1_Dir2BwdDir2) ||
                   (forient2 == StdRegions::eDir1BwdDir2_Dir2FwdDir1) ||
                   (forient2 == StdRegions::eDir1BwdDir2_Dir2BwdDir1))
                {
                    if(forient0 == StdRegions::eFwd)
                    {
                        prismorient.insert(i);
                    }
                }
                else
                {
                    if(forient0 == StdRegions::eBwd)
                    {
                        prismorient.insert(i);
                    }
                }
            }
        }
    }

    for(int i = 0; i < nel; ++i)
    {
        e = m_f->m_exp[0]->GetExp(i);
        if(m_config["tetonly"].m_beenSet)
        {
            if(m_f->m_exp[0]->GetExp(i)->DetShapeType() !=
                    LibUtilities::eTetrahedron)
            {
                continue;
            }
        }

        ppe.push_back(newpoints);
        newtotpoints += newpoints;

        switch(e->DetShapeType())
        {
        case LibUtilities::eSegment:
            {
                int npoints0 = e->GetBasis(0)->GetNumPoints();

                newpoints = LibUtilities::StdSegData::
                                    getNumberOfCoefficients(npoints0);
            }
            break;
        case LibUtilities::eTriangle:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np = max(np0,np1);
                newpoints = LibUtilities::StdTriData::
                                    getNumberOfCoefficients(np,np);
            }
            break;
        case LibUtilities::eQuadrilateral:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np = max(np0,np1);

                newpoints = LibUtilities::StdQuadData::
                                    getNumberOfCoefficients(np,np);
            }
            break;
        case LibUtilities::eTetrahedron:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdTetData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        case LibUtilities::ePrism:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdPrismData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        case LibUtilities::ePyramid:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdPyrData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        case LibUtilities::eHexahedron:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdPyrData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        default:
            {
                ASSERTL0(false,"Points not known");
            }
        }

        if(e->DetShapeType() == LibUtilities::ePrism)
        {
            bool standard = true;

            if(prismorient.count(i))
            {
                standard = false; // reverse direction
            }

            e->GetSimplexEquiSpacedConnectivity(conn,standard);
        }
        else
        {

            if((prevNcoeffs != e->GetNcoeffs()) ||
               (prevNpoints != e->GetTotPoints()))
            {
                prevNcoeffs = e->GetNcoeffs();
                prevNpoints = e->GetTotPoints();

                e->GetSimplexEquiSpacedConnectivity(conn);
            }
        }
        Array<OneD, int> newconn(conn.num_elements());
        for(int j = 0; j < conn.num_elements(); ++j)
        {
            newconn[j] = conn[j] + cnt;
        }

        ptsConn.push_back(newconn);
        cnt += newpoints;
    }

    if(m_f->m_fielddef.size())
    {
        nfields = m_f->m_exp.size();
    }
    else // just the mesh points
    {
        nfields = 0;
    }

    Array<OneD, Array<OneD, NekDouble> > pts(nfields + coordim);

    for(int i = 0; i < nfields + coordim; ++i)
    {
        pts[i] = Array<OneD, NekDouble>(newtotpoints);
    }

    // Interpolate coordinates
    for(int i = 0; i < coordim; ++i)
    {
        coords[i] = Array<OneD, NekDouble>(npts);
    }

    for(int i = coordim; i < 3; ++i)
    {
        coords[i] = NullNekDouble1DArray;
    }

    m_f->m_exp[0]->GetCoords(coords[0],coords[1],coords[2]);

    int nq1 = m_f->m_exp[0]->GetTotPoints();

    Array<OneD, NekDouble> x1(nq1);
    Array<OneD, NekDouble> y1(nq1);
    Array<OneD, NekDouble> z1(nq1);

    m_f->m_exp[0]->GetCoords(x1, y1, z1);


    Array<OneD, NekDouble> tmp;

    for(int n = 0; n < coordim; ++n)
    {
        cnt = 0;
        int cnt1 = 0;
        for(int i = 0; i < nel; ++i)
        {
            m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
                                        coords[n] + cnt,
                                        tmp = pts[n] + cnt1);
            cnt1 += ppe[i];
            cnt  += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
        }
    }

    if(m_f->m_fielddef.size())
    {
        ASSERTL0(m_f->m_fielddef[0]->m_fields.size() == m_f->m_exp.size(),
                 "More expansion defined than fields");

        for(int n = 0; n < m_f->m_exp.size(); ++n)
        {
            cnt = 0;
            int cnt1 = 0;

            if(m_config["modalenergy"].m_beenSet)
            {
                Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
                for(int i = 0; i < nel; ++i)
                {
                    GenOrthoModes(i,phys+cnt,tmp = pts[coordim + n] + cnt1);
                    cnt1 += ppe[i];
                    cnt  += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
                }
            }
            else
            {
                Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
                for(int i = 0; i < nel; ++i)
                {
                    m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
                            phys + cnt,
                            tmp = pts[coordim + n] + cnt1);
                    cnt1 += ppe[i];
                    cnt  += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
                }
            }

            // Set up Variable string.
            fieldNames.push_back(m_f->m_fielddef[0]->m_fields[n]);
        }
    }

    m_f->m_fieldPts = MemoryManager<LibUtilities::PtsField>::AllocateSharedPtr(coordim, fieldNames, pts);
    if (shapedim == 2)
    {
        m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTriBlock);
    }
    else if (shapedim == 3)
    {
        m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
    }
    m_f->m_fieldPts->SetConnectivity(ptsConn);
}


    void ProcessEquiSpacedOutput::GenOrthoModes(
            int n,
            const Array<OneD,const NekDouble> &phys,
                  Array<OneD, NekDouble> &coeffs)
    {
        LocalRegions::ExpansionSharedPtr e;
        e = m_f->m_exp[0]->GetExp(n);

        switch(e->DetShapeType())
        {
            case LibUtilities::eTriangle:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np = max(np0,np1);

                // to ensure points are correctly projected to np need
                // to increase the order slightly of coordinates
                LibUtilities::PointsKey pa(np+1,e->GetPointsType(0));
                LibUtilities::PointsKey pb(np,e->GetPointsType(1));
                Array<OneD, NekDouble> tophys(np*(np+1));

                LibUtilities::BasisKey Ba(LibUtilities::eOrtho_A,np,pa);
                LibUtilities::BasisKey Bb(LibUtilities::eOrtho_B,np,pb);
                StdRegions::StdTriExp OrthoExp(Ba,Bb);

                // interpolate points to new phys points!
                LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
                                       e->GetBasis(1)->GetBasisKey(),
                                       phys,Ba,Bb,tophys);

                OrthoExp.FwdTrans(tophys,coeffs);
                break;
            }
            case LibUtilities::eQuadrilateral:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np = max(np0,np1);

                LibUtilities::PointsKey pa(np+1,e->GetPointsType(0));
                LibUtilities::PointsKey pb(np+1,e->GetPointsType(1));
                Array<OneD, NekDouble> tophys((np+1)*(np+1));

                LibUtilities::BasisKey Ba(LibUtilities::eOrtho_A,np,pa);
                LibUtilities::BasisKey Bb(LibUtilities::eOrtho_A,np,pb);
                StdRegions::StdQuadExp OrthoExp(Ba,Bb);

                // interpolate points to new phys points!
                LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
                                       e->GetBasis(1)->GetBasisKey(),
                                       phys,Ba,Bb,tophys);

                OrthoExp.FwdTrans(phys,coeffs);
                break;
            }
            default:
                ASSERTL0(false,"Shape needs setting up");
                break;
        }
    }

}
示例#2
0
    namespace Utilities
    {
        ModuleKey ProcessDetectSurf::className = 
            GetModuleFactory().RegisterCreatorFunction(
                ModuleKey(eProcessModule, "detect"), ProcessDetectSurf::create,
                "Process elements to detect a surface.");

        ProcessDetectSurf::ProcessDetectSurf(MeshSharedPtr m) : ProcessModule(m)
        {
            m_config["vol"] = ConfigOption(false, "-1",
                "Tag identifying surface to process.");
        }

        ProcessDetectSurf::~ProcessDetectSurf()
        {
        }
        
        struct EdgeInfo {
            EdgeInfo() : count(0) {}
            int           count;
            EdgeSharedPtr edge;
            unsigned int  group;
        };

        void ProcessDetectSurf::Process()
        {
            if (m_mesh->m_expDim > 2)
            {
                cerr << "Surface detection only implemented for 2D meshes" << endl;
                return;
            }

            int i, j;
            string surf = m_config["vol"].as<string>();

            // Obtain vector of surface IDs from string.
            vector<unsigned int> surfs;
            if (surf != "-1")
            {
                ParseUtils::GenerateSeqVector(surf.c_str(), surfs);
                sort(surfs.begin(), surfs.end());
            }

            // If we're running in verbose mode print out a list of surfaces.
            if (m_mesh->m_verbose)
            {
                cout << "ProcessDetectSurf: detecting surfaces";
                if (surfs.size() > 0)
                {
                    cout << " for surface" << (surfs.size() == 1 ? "" : "s")
                         << " " << surf << endl;
                }
            }

            vector<ElementSharedPtr> &el = m_mesh->m_element[m_mesh->m_expDim];
            map<int, EdgeInfo> edgeCount;
            set<int> doneIds;
            map<int, int> idMap;

            // Iterate over list of surface elements.
            for (i = 0; i < el.size(); ++i)
            {
                // Work out whether this lies on our surface of interest.
                if (surfs.size() > 0)
                {
                    vector<int> inter, tags = el[i]->GetTagList();

                    sort(tags.begin(), tags.end());
                    set_intersection(surfs.begin(), surfs.end(),
                                     tags .begin(), tags .end(),
                                     back_inserter(inter));
                
                    // It doesn't continue to next element.
                    if (inter.size() != 1)
                    {
                        continue;
                    }
                }
                
                // List all edges.
                ElementSharedPtr elmt = el[i];
                for (j = 0; j < elmt->GetEdgeCount(); ++j)
                {
                    EdgeSharedPtr e = elmt->GetEdge(j);
                    int eId = e->m_id;
                    edgeCount[eId].count++;
                    edgeCount[eId].edge = e;
                }

                doneIds.insert(elmt->GetId());
                ASSERTL0(idMap.count(elmt->GetId()) == 0, "Shouldn't happen");
                idMap[elmt->GetId()] = i;
            }

            CompositeMap::iterator cIt;
            unsigned int maxId = 0;

            for (cIt = m_mesh->m_composite.begin(); cIt != m_mesh->m_composite.end(); ++cIt)
            {
                maxId = std::max(cIt->first, maxId);
            }

            ++maxId;

            map<int, EdgeInfo>::iterator eIt;

            while (doneIds.size() > 0)
            {
                ElementSharedPtr start
                    = m_mesh->m_element[m_mesh->m_expDim][idMap[*(doneIds.begin())]];

                vector<ElementSharedPtr> block;
                FindContiguousSurface(start, doneIds, block);
                ASSERTL0(block.size() > 0, "Contiguous block not found");

                // Loop over all edges in block.
                for (i = 0; i < block.size(); ++i)
                {
                    // Find edge info.
                    ElementSharedPtr elmt = block[i];

                    for (j = 0; j < elmt->GetEdgeCount(); ++j)
                    {
                        eIt = edgeCount.find(elmt->GetEdge(j)->m_id);
                        ASSERTL0(eIt != edgeCount.end(), "Couldn't find edge");
                        eIt->second.group = maxId;
                    }
                }

                ++maxId;
            }

            for (eIt = edgeCount.begin(); eIt != edgeCount.end(); ++eIt)
            {
                if (eIt->second.count > 1)
                {
                    continue;
                }

                unsigned int compId = eIt->second.group;
                CompositeMap::iterator cIt = m_mesh->m_composite.find(compId);

                if (cIt == m_mesh->m_composite.end())
                {
                    CompositeSharedPtr comp(new Composite());
                    comp->m_id  = compId;
                    comp->m_tag = "E";
                    cIt = m_mesh->m_composite.insert(std::make_pair(compId, comp)).first;
                }

                vector<int> tags(1);
                tags[0] = compId;
                vector<NodeSharedPtr> nodeList(2);
                nodeList[0] = eIt->second.edge->m_n1;
                nodeList[1] = eIt->second.edge->m_n2;

                ElmtConfig conf(LibUtilities::eSegment, 1, false, false);
                ElementSharedPtr elmt = GetElementFactory().
                    CreateInstance(LibUtilities::eSegment,conf,nodeList,tags);
                elmt->SetEdgeLink(eIt->second.edge);

                cIt->second->m_items.push_back(elmt);
            }
        }

        void ProcessDetectSurf::FindContiguousSurface(
            ElementSharedPtr          start,
            set<int>                 &doneIds,
            vector<ElementSharedPtr> &block)
        {
            block.push_back(start);
            doneIds.erase(start->GetId());

            vector<EdgeSharedPtr> edges = start->GetEdgeList();

            for (int i = 0; i < edges.size(); ++i)
            {
                for (int j = 0; j < edges[i]->m_elLink.size(); ++j)
                {
                    ElementSharedPtr elmt = edges[i]->m_elLink[j].first;
                    if (elmt == start)
                    {
                        continue;
                    }

                    if (doneIds.count(elmt->GetId()) == 0)
                    {
                        continue;
                    }

                    FindContiguousSurface(elmt, doneIds, block);
                }
            }
        }
    }
示例#3
0
namespace Utilities
{

ModuleKey ProcessAddFld::className =
    GetModuleFactory().RegisterCreatorFunction(
        ModuleKey(eProcessModule, "addfld"),
        ProcessAddFld::create, "rescale input field by a constant factor.");

ProcessAddFld::ProcessAddFld(FieldSharedPtr f) : ProcessModule(f)
{
    m_config["scale"]   = ConfigOption(false, "1.0", "scale factor");

    m_config["fromfld"] = ConfigOption(false, "NotSet",
                                "Fld file form which to interpolate field");

    ASSERTL0(m_config["fromfld"].as<string>().compare("NotSet") != 0,
             "Need to specify fromfld=file.fld ");

}

ProcessAddFld::~ProcessAddFld()
{
}

void ProcessAddFld::Process(po::variables_map &vm)
{
    if (m_f->m_verbose)
    {
        cout << "ProcessAddFld: Adding new fld to input fld" << endl;
    }

    ASSERTL0(m_f->m_data.size() != 0,"No input data defined");
    
    string scalestr = m_config["scale"].as<string>();
    NekDouble scale = boost::lexical_cast<NekDouble>(scalestr);

    string fromfld = m_config["fromfld"].as<string>();
    FieldSharedPtr fromField = boost::shared_ptr<Field>(new Field());

    if(m_f->m_exp.size())
    {
        // Set up ElementGIDs in case of parallel processing
        Array<OneD,int> ElementGIDs(m_f->m_exp[0]->GetExpSize());
        for (int i = 0; i < m_f->m_exp[0]->GetExpSize(); ++i)
        {
            ElementGIDs[i] = m_f->m_exp[0]->GetExp(i)->GetGeom()->GetGlobalID();
        }
        m_f->m_fld->Import(fromfld,fromField->m_fielddef,
                           fromField->m_data,
                           LibUtilities::NullFieldMetaDataMap,
                           ElementGIDs);
    }
    else
    {
        m_f->m_fld->Import(fromfld,fromField->m_fielddef,
                           fromField->m_data,
                           LibUtilities::NullFieldMetaDataMap);
    }

    bool samelength = true;
    if(fromField->m_data.size() != m_f->m_data.size())
    {
        samelength = false;
    }

    // scale input field
    for(int i = 0; i < fromField->m_data.size(); ++i)
    {
        int datalen = fromField->m_data[i].size();

        Vmath::Smul(datalen, scale, &(fromField->m_data[i][0]), 1,
                                    &(fromField->m_data[i][0]), 1);

        if(samelength)
        {
            if(datalen != m_f->m_data[i].size())
            {
                samelength = false;
            }
        }
    }

    if(samelength == true)
    {
        for(int i = 0; i < m_f->m_data.size(); ++i)
        {
            int datalen = m_f->m_data[i].size();

            Vmath::Vadd(datalen, &(m_f->m_data[i][0]),       1,
                                 &(fromField->m_data[i][0]), 1,
                                 &(m_f->m_data[i][0]),       1);
        }
    }
    else
    {
        ASSERTL0(m_f->m_exp.size() != 0 ,
                 "Input fields have partitions of different length and so xml "
                 "file needs to be specified");

        int nfields = m_f->m_fielddef[0]->m_fields.size();
        int ncoeffs = m_f->m_exp[0]->GetNcoeffs();
        Array<OneD, NekDouble> SaveFld(ncoeffs);

        for (int j = 0; j < nfields; ++j)
        {
            Vmath::Vcopy(ncoeffs,m_f->m_exp[j]->GetCoeffs(),1, SaveFld,1);

            // load new field
            for (int i = 0; i < fromField->m_data.size(); ++i)
            {
                m_f->m_exp[j]->ExtractDataToCoeffs(
                                       fromField->m_fielddef[i],
                                       fromField->m_data[i],
                                       fromField->m_fielddef[i]->m_fields[j],
                                       m_f->m_exp[j]->UpdateCoeffs());
            }

            Vmath::Vadd(ncoeffs, m_f->m_exp[j]->GetCoeffs(),    1,
                                 SaveFld,                       1,
                                 m_f->m_exp[j]->UpdateCoeffs(), 1);
        }

        std::vector<LibUtilities::FieldDefinitionsSharedPtr> FieldDef
            = m_f->m_exp[0]->GetFieldDefinitions();
        std::vector<std::vector<NekDouble> > FieldData(FieldDef.size());

        for(int i = 0; i < nfields; ++i)
        {
            for (int j = 0; j < FieldDef.size(); ++j)
            {
                FieldDef[j]->m_fields.push_back(m_f->m_fielddef[0]->m_fields[i]);
                m_f->m_exp[i]->AppendFieldData(FieldDef[j], FieldData[j]);
            }
        }

        m_f->m_fielddef = FieldDef;
        m_f->m_data     = FieldData;

    }
}

}
示例#4
0
namespace Utilities
{

ModuleKey ProcessWSS::className =
    GetModuleFactory().RegisterCreatorFunction(
        ModuleKey(eProcessModule, "wss"),
        ProcessWSS::create, "Computes wall shear stress field.");

ProcessWSS::ProcessWSS(FieldSharedPtr f) : ProcessModule(f)
{
    m_config["bnd"] = ConfigOption(false,"All","Boundary to be extracted");
    m_config["addnormals"] = ConfigOption(true,"NotSet","Add normals to output");
    f->m_writeBndFld = true;
    f->m_declareExpansionAsContField = true;
    m_f->m_fldToBnd = false;
}

ProcessWSS::~ProcessWSS()
{
}

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]];
        }
    }
}

}
示例#5
0
    namespace Utilities
    {
        ModuleKey InputVtk::className =
            GetModuleFactory().RegisterCreatorFunction(
                ModuleKey(eInputModule, "vtk"), InputVtk::create,
                "Reads VTK format.");

        InputVtk::InputVtk(MeshSharedPtr m) : InputModule(m)
        {

        }

        InputVtk::~InputVtk()
        {

        }


        /**
         * Gmsh file contains a list of nodes and their coordinates, along with
         * a list of elements and those nodes which define them. We read in and
         * store the list of nodes in #m_node and store the list of elements in
         * #m_element. Each new element is supplied with a list of entries from
         * #m_node which defines the element. Finally some mesh statistics are
         * printed.
         *
         * @param   pFilename           Filename of Gmsh file to read.
         */
        void InputVtk::Process()
        {
            if (m_mesh->m_verbose)
            {
                cout << "InputVtk: Start reading file..." << endl;
            }

            vtkPolyDataReader *vtkMeshReader = vtkPolyDataReader::New();
            vtkMeshReader->SetFileName(m_config["infile"].as<string>().c_str());
            vtkMeshReader->Update();
            vtkPolyData *vtkMesh = vtkMeshReader->GetOutput();

            vtkPoints *vtkPoints = vtkMesh->GetPoints();

            const int numCellTypes = 3;
            vtkCellArray* vtkCells[numCellTypes];
            LibUtilities::ShapeType vtkCellTypes[numCellTypes];
            int vtkNumPoints[numCellTypes];
            vtkCells[0] = vtkMesh->GetPolys();
            vtkCells[1] = vtkMesh->GetStrips();
            vtkCells[2] = vtkMesh->GetLines();
            vtkCellTypes[0] = LibUtilities::eTriangle;
            vtkCellTypes[1] = LibUtilities::eTriangle;
            vtkCellTypes[2] = LibUtilities::eSegment;
            vtkNumPoints[0] = 3;
            vtkNumPoints[1] = 3;
            vtkNumPoints[2] = 2;

            vtkIdType npts;
            vtkIdType *pts = 0;
            double p[3];

            for (int i = 0; i < vtkPoints->GetNumberOfPoints(); ++i)
            {
                vtkPoints->GetPoint(i, p);

                if ((p[0] * p[0]) > 0.000001 && m_mesh->m_spaceDim < 1)
                {
                    m_mesh->m_spaceDim = 1;
                }
                if ((p[1] * p[1]) > 0.000001 && m_mesh->m_spaceDim < 2)
                {
                    m_mesh->m_spaceDim = 2;
                }
                if ((p[2] * p[2]) > 0.000001 && m_mesh->m_spaceDim < 3)
                {
                    m_mesh->m_spaceDim = 3;
                }

                m_mesh->m_node.push_back(boost::shared_ptr<Node>(new Node(i, p[0], p[1], p[2])));
            }

            for (int c = 0; c < numCellTypes; ++c)
            {
                vtkCells[c]->InitTraversal();
                for (int i = 0; vtkCells[c]->GetNextCell(npts, pts); ++i)
                {
                    for (int j = 0; j < npts - vtkNumPoints[c] + 1; ++j)
                    {
                        // Create element tags
                        vector<int> tags;
                        tags.push_back(0); // composite
                        tags.push_back(vtkCellTypes[c]); // element type

                        // Read element node list
                        vector<NodeSharedPtr> nodeList;
                        for (int k = j; k < j + vtkNumPoints[c]; ++k)
                        {
                            nodeList.push_back(m_mesh->m_node[pts[k]]);
                        }

                        // Create element
                        ElmtConfig conf(vtkCellTypes[c],1,false,false);
                        ElementSharedPtr E = GetElementFactory().
                            CreateInstance(vtkCellTypes[c],
                                            conf,nodeList,tags);

                        // Determine mesh expansion dimension
                        if (E->GetDim() > m_mesh->m_expDim) {
                            m_mesh->m_expDim = E->GetDim();
                        }
                        m_mesh->m_element[E->GetDim()].push_back(E);
                    }
                }
            }

            ProcessVertices();
            ProcessEdges();
            ProcessFaces();
            ProcessElements();
            ProcessComposites();
        }
    }