Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose NoSharing type through a simple API for external usage. Implement some more general entity and node counting APIs. #238

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions apf/apf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "apfNumberingClass.h"
#include <cstdio>
#include <cstdlib>
#include <PCU.h>
#include <pcu_util.h>
#include <lionPrint.h>

Expand Down Expand Up @@ -140,6 +141,46 @@ bool hasEntity(Field* f, MeshEntity* e)
return f->getData()->hasEntity(e);
}

int countLocalNodes(Field* f, Sharing* shr)
{
Mesh * msh = getMesh(f);
FieldShape * shp = getShape(f);
return countLocalNodes(msh,shp,shr);
}

int countLocalNodes(Mesh* m, FieldShape * shp, Sharing * shr)
{
// if shr is NULL, the default behavior of
// countEntitiesOfType is to count ALL
// entities on the local part of type tp
int nds = 0;
for(int tp = Mesh::VERTEX; tp != Mesh::TYPES; ++tp)
nds += countEntitiesOfType(m,tp,shr) * shp->countNodesOn(tp);
return nds;
}

int countGlobalNodes(Field* f, Sharing* shr)
{
Mesh * msh = getMesh(f);
FieldShape * shp = getShape(f);
return countGlobalNodes(msh,shp,shr);
}

int countGlobalNodes(Mesh* m, FieldShape* shp, Sharing* shr)
{
bool del = false;
if(shr == NULL)
{
shr = getSharing(m);
del = true;
}
int lcl_nds = countLocalNodes(m,shp,shr);
int gbl_nds = PCU_Add_Int(lcl_nds);
if(del)
delete shr;
return gbl_nds;
}

const char* getName(Field* f)
{
return f->getName();
Expand Down
20 changes: 19 additions & 1 deletion apf/apf.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,24 @@ Mesh* getMesh(Field* f);
*/
bool hasEntity(Field* f, MeshEntity* e);

/** \brief Count all field nodes owned according to shr, on all mesh
entities on the local part, default is all to count every node,
even those on owned entities
*/
int countLocalNodes(Field* f, Sharing* shr = NULL);
/** \brief same as countLocalNodes but you don't need to allocate a field
*/
int countLocalNodes(Mesh* m, FieldShape* shp, Sharing* shr = NULL);

/** \brief Count all field nodes owned according to shr, on all mesh
entities on all parts in PCU_COMM_WORLD, default is to use the
NormalSharing to define ownership.
*/
int countGlobalNodes(Field* f, Sharing* shr = NULL);
/** \brief same as countGlobalNodes but you don't need to allocate a field
*/
int countGlobalNodes(Mesh* m, FieldShape* shp, Sharing* shr = NULL);

/** \brief Get the name of a Field.
*
* \details Both for use convenience and for technical reasons
Expand Down Expand Up @@ -682,7 +700,7 @@ void synchronize(Field* f, Sharing* shr = 0);
*/
void accumulate(Field* f, Sharing* shr = 0, bool delete_shr = false);

/** \brief Apply a reudction operator along partition boundaries
/** \brief Apply a reduction operator along partition boundaries
\details Using the copies described by an apf::Sharing object, applied
the specified operation pairwise to the values of the field on each
partition. No guarantee is made about hte order of the pairwise
Expand Down
37 changes: 35 additions & 2 deletions apf/apfMesh.cc
Original file line number Diff line number Diff line change
Expand Up @@ -676,13 +676,16 @@ MeshEntity* getEdgeVertOppositeVert(Mesh* m, MeshEntity* edge, MeshEntity* v)
return ev[0];
}

int countEntitiesOfType(Mesh* m, int type)

int countEntitiesOfType(Mesh* m, int type, Sharing * shr)
{
if(shr == NULL)
shr = getNoSharing();
MeshIterator* it = m->begin(Mesh::typeDimension[type]);
MeshEntity* e;
int count = 0;
while ((e = m->iterate(it)))
if (m->getType(e)==type)
if (m->getType(e)==type && shr->isOwned(e))
++count;
m->end(it);
return count;
Expand Down Expand Up @@ -996,6 +999,36 @@ bool MatchedSharing::isShared(MeshEntity* e) {
return false;
}

// treat all entities as if they are not shared,
// used to count all local entities instead of
// all owned entities as the default
// The ONLY justification for this being a
// singleton is that it is essentially a functor
// at this point, as it retains no state, so there
// only ever needs to be a single instance of this
struct NoSharing : public Sharing
{
private:
static NoSharing * instance;
NoSharing() {}
~NoSharing() {}
public:
static NoSharing * Instance()
{
if(instance == NULL)
instance = new NoSharing;
return instance;
}
virtual int getOwner(MeshEntity*) { return PCU_Comm_Self(); }
virtual bool isOwned(MeshEntity*) { return true; }
virtual void getCopies(MeshEntity*,CopyArray&) { }
virtual bool isShared(MeshEntity*) { return false; }
};
NoSharing * NoSharing::instance = NULL;

// obfuscate the singleton just a bit
Sharing* getNoSharing() { return NoSharing::Instance(); }

Sharing* getSharing(Mesh* m)
{
if (m->hasMatching())
Expand Down
11 changes: 8 additions & 3 deletions apf/apfMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,6 @@ MeshEntity* getEdgeVertOppositeVert(Mesh* m, MeshEntity* edge, MeshEntity* v);
void getBridgeAdjacent(Mesh* m, MeshEntity* origin,
int bridgeDimension, int targetDimension, Adjacent& result);

/** \brief count all on-part entities of one topological type */
int countEntitiesOfType(Mesh* m, int type);

/** \brief return true if the topological type is a simplex */
bool isSimplex(int type);

Expand Down Expand Up @@ -516,13 +513,21 @@ struct MatchedSharing : public Sharing
std::map<int, size_t> countMap;
};

Sharing* getNoSharing();

/** \brief create a default sharing object for this mesh
\details for normal meshes, the sharing object just
describes remote copies. For matched meshes, the
sharing object describes matches for matched entities
and remote copies for other entities */
Sharing* getSharing(Mesh* m);

/** \brief count all on-part entities of one topological type,
\details if a sharing is provided, only 'owned' entities of
the specified type are counted, otherwise all on-part entities
are counted */
int countEntitiesOfType(Mesh* m, int type, Sharing * shr = NULL);

/** \brief map from triangle edge order to triangle vertex order */
extern int const tri_edge_verts[3][2];
/** \brief map from quad edge order to quad vertex order */
Expand Down
24 changes: 7 additions & 17 deletions apf/apfNumbering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,6 @@ void synchronize(Numbering * n, Sharing* shr, bool delete_shr)
synchronizeFieldData<int>(n->getData(), shr, delete_shr);
}

struct NoSharing : public Sharing
{
int getOwner(MeshEntity*) {return PCU_Comm_Self();}
bool isOwned(MeshEntity*) {return true;}
virtual void getCopies(MeshEntity*, CopyArray&) {}
bool isShared(MeshEntity*) {return false;}
};

Numbering* numberNodes(
Mesh* mesh,
const char* name,
Expand Down Expand Up @@ -258,23 +250,22 @@ Numbering* numberNodes(
return n;
}

Numbering* numberOwnedDimension(Mesh* mesh, const char* name, int dim,
Sharing* shr)
Numbering* numberOwnedDimension(Mesh* mesh, const char* name, int dim, Sharing * shr)
{
bool delete_shr=false;
if (!shr)
bool delete_shr = false;
if (!shr)
{
shr = getSharing(mesh);
delete_shr=true;
delete_shr = true;
}
return numberNodes(mesh, name, getConstant(dim), shr, delete_shr);
}

Numbering* numberOverlapDimension(Mesh* mesh, const char* name, int dim)
{
FieldShape* s = getConstant(dim);
Sharing* shr = new NoSharing();
return numberNodes(mesh, name, s, shr, true);
Sharing* shr = getNoSharing();
return numberNodes(mesh, name, s, shr, false);
}

Numbering* numberElements(Mesh* mesh, const char* name)
Expand All @@ -286,8 +277,7 @@ Numbering* numberOverlapNodes(Mesh* mesh, const char* name, FieldShape* s)
{
if (!s)
s = mesh->getShape();
Sharing* shr = new NoSharing();
return numberNodes(mesh, name, s, shr, true);
return numberNodes(mesh, name, s, getNoSharing(), false);
}

Numbering* numberOwnedNodes(
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ test_exe_func(quality quality.cc)
test_exe_func(writeVtxPtn writeVtxPtn.cc)
test_exe_func(verify_2nd_order_shapes verify_2nd_order_shapes.cc)
test_exe_func(verify_convert verify_convert.cc)
test_exe_func(count_entities count_entities.cc)

# Geometric model utilities
if(ENABLE_SIMMETRIX)
Expand Down
71 changes: 71 additions & 0 deletions test/count_entities.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <apf.h>
#include <apfMDS.h>
#include <apfMesh2.h>
#include <gmi_mesh.h>
#include <gmi_null.h>
#include <PCU.h>
#include <pcu_util.h>
#include <stdlib.h>

int main(int ac, char * av[])
{

MPI_Init(&ac,&av);
PCU_Comm_Init();
if (ac < 2)
{
if (PCU_Comm_Self() == 0)
printf("USAGE1: %s <mesh.smb>\n", av[0]);
MPI_Finalize();
exit(EXIT_FAILURE);
}

gmi_register_mesh();
gmi_register_null();

apf::Mesh * msh = apf::loadMdsMesh(".null",av[1]);

int lcl_vrt = apf::countEntitiesOfType(msh,apf::Mesh::VERTEX);
int own_vrt = apf::countEntitiesOfType(msh,apf::Mesh::VERTEX,apf::getSharing(msh));

int lcl_vrt2 = apf::countOwned(msh,0,apf::getNoSharing());
int own_vrt2 = apf::countOwned(msh,0);

int lcl_edg = apf::countEntitiesOfType(msh,apf::Mesh::EDGE);
int own_edg = apf::countEntitiesOfType(msh,apf::Mesh::EDGE,apf::getSharing(msh));

int lcl_edg2 = apf::countOwned(msh,1,apf::getNoSharing());
int own_edg2 = apf::countOwned(msh,1);

// higher dimension mesh entities is where counting specific types gets tricky
// using the default interfaces,
// which is the entire reason for this function in the first place.

PCU_ALWAYS_ASSERT((lcl_vrt == lcl_vrt2) && (own_vrt == own_vrt2));
PCU_ALWAYS_ASSERT((lcl_edg == lcl_edg2) && (own_edg == own_edg2));

apf::Field * fld = apf::createPackedField(msh,"scalar",1);
apf::Sharing * shr = apf::getSharing(msh);

int lcl_nds = apf::countLocalNodes(fld);
int own_nds = apf::countLocalNodes(fld,shr);

PCU_ALWAYS_ASSERT((lcl_vrt == lcl_nds) && (own_vrt == own_nds));

int gbl_nds = apf::countGlobalNodes(fld);
int all_nds = apf::countGlobalNodes(fld,apf::getNoSharing());

int gbl_nds2 = PCU_Add_Int(own_nds);
int all_nds2 = PCU_Add_Int(lcl_nds);

PCU_ALWAYS_ASSERT((gbl_nds == gbl_nds2) && (all_nds == all_nds2));

delete shr;

msh->destroyNative();
apf::destroyMesh(msh);

PCU_Comm_Free();
MPI_Finalize();
}

6 changes: 6 additions & 0 deletions test/testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ mpi_test(qr_test 1 ./qr)
mpi_test(base64 1 ./base64)
mpi_test(tensor_test 1 ./tensor)
mpi_test(verify_convert 1 ./verify_convert)
mpi_test(count_serial 1
./count_entities
"${MESHES}/cube/pumi11/cube.smb")
mpi_test(count_parallel 2
./count_entities
"${MESHES}/cube/pumi670/2/cube.smb")
mpi_test(test_integrator 1
./test_integrator
"${MESHES}/cube/cube.dmg"
Expand Down