Skip to content

Commit

Permalink
Merge pull request #163 from timetravellers/feature-clone-field
Browse files Browse the repository at this point in the history
implement FieldData::clone()
  • Loading branch information
cwsmith committed Aug 13, 2018
2 parents 9c3069b + 86b4cdd commit 6f3c392
Show file tree
Hide file tree
Showing 15 changed files with 321 additions and 18 deletions.
7 changes: 7 additions & 0 deletions apf/apf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,13 @@ Field* createUserField(Mesh* m, const char* name, int valueType, FieldShape* s,
return makeField(m, name, valueType, 0, s, new UserData(f));
}

void updateUserField(Field* field, Function* newFunc)
{
UserData* ud = dynamic_cast<UserData*>(field->getData());
// ud will be null if the data is not user data
if (ud) ud->setFunction(newFunc);
}

void copyData(Field* to, Field* from)
{
copyFieldData(from->getData(), to->getData());
Expand Down
18 changes: 13 additions & 5 deletions apf/apf.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,14 +668,22 @@ struct Function
virtual void eval(MeshEntity* e, double* result) = 0;
};

/** \brief Create a Field from a user's analytic function.
\details This field will use no memory, has values on all
nodes, and calls the user Function for all value queries.
Writing to this field does nothing.
*/
/* \brief Create a Field from a user's analytic function.
* \details This field will use no memory, has values on all
* nodes, and calls the user Function for all value queries.
* Writing to this field does nothing.
* \warning if you copy the mesh with apf::convert you may want to use
* apf::updateUserField to update function that this field refers to. This is
* extremely important if the analytic function you use references user fields.
*/
Field* createUserField(Mesh* m, const char* name, int valueType, FieldShape* s,
Function* f);

/* \brief update the analytic function from a user field
* \details this field updates the apf::Function which the UserField refers to
*/
void updateUserField(Field* field, Function* newFunc);

/** \brief Compute a nodal gradient field from a nodal input field
\details given a nodal field, compute approximate nodal gradient
values by giving each node a volume-weighted average of the
Expand Down
8 changes: 8 additions & 0 deletions apf/apfArrayData.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ class ArrayDataOf : public FieldDataOf<T>
T* getDataArray() {
return this->dataArray;
}
virtual FieldData* clone() {
//FieldData* newData = new TagDataOf<double>();
FieldData* newData = new ArrayDataOf<T>();
newData->init(this->field);
copyFieldData(static_cast<FieldDataOf<T>*>(newData),
static_cast<FieldDataOf<T>*>(this->field->getData()));
return newData;
}

private:
/* data variables go here */
Expand Down
110 changes: 106 additions & 4 deletions apf/apfConvert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "apfNumbering.h"
#include <map>
#include <pcu_util.h>
#include <iostream>

namespace apf {

Expand All @@ -31,6 +32,9 @@ class Converter
convertFields();
convertNumberings();
convertGlobalNumberings();
// this must be called after anything that might create tags e.g. fields
// or numberings to avoid problems with tag duplication
convertTags();
outMesh->acceptChanges();
}
ModelEntity* getNewModelFromOld(ModelEntity* oldC)
Expand Down Expand Up @@ -210,6 +214,48 @@ class Converter
}
}
}
void convertTag(Mesh* inMesh, MeshTag* in, Mesh* outMesh, MeshTag* out)
{
for (int d = 0; d <= 3; ++d) {
int tagType = inMesh->getTagType(in);
int tagSize = inMesh->getTagSize(in);
PCU_DEBUG_ASSERT(tagType == outMesh->getTagType(out));
PCU_DEBUG_ASSERT(tagSize == outMesh->getTagSize(out));
MeshIterator* it = inMesh->begin(d);
MeshEntity* e;
while ((e = inMesh->iterate(it))) {
if(inMesh->hasTag(e, in)) {
// these initializations cannot go into the cases due to compiler
// warnings on gcc 7.3.0
double* dblData;
int* intData;
long* lngData;
switch (tagType) {
case apf::Mesh::TagType::DOUBLE:
dblData = new double[tagSize];
inMesh->getDoubleTag(e, in, dblData);
outMesh->setDoubleTag(newFromOld[e], out, dblData);
break;
case apf::Mesh::TagType::INT:
intData = new int[tagSize];
inMesh->getIntTag(e, in, intData);
outMesh->setIntTag(newFromOld[e], out, intData);
break;
case apf::Mesh::TagType::LONG:
lngData = new long[tagSize];
inMesh->getLongTag(e, in, lngData);
outMesh->setLongTag(newFromOld[e], out, lngData);
break;
default:
std::cerr << "Tried to convert unknown tag type\n";
abort();
break;
}
}
}
inMesh->end(it);
}
}
void convertFields()
{
for (int i = 0; i < inMesh->countFields(); ++i) {
Expand All @@ -222,20 +268,76 @@ class Converter
{
for (int i = 0; i < inMesh->countNumberings(); ++i) {
Numbering* in = inMesh->getNumbering(i);
Numbering* out = createNumbering(outMesh,
getName(in), getShape(in), countComponents(in));
Numbering* out;
if (getField(in)) {
// here we assume that the fields have already been copied into the
// mesh
Field* outField = outMesh->findField(getName(getField(in)));
PCU_DEBUG_ASSERT(outField);
out = createNumbering(outField);
}
else {
out = createNumbering(outMesh, getName(in), getShape(in),
countComponents(in));
}
convertNumbering(in, out);
}
}
void convertGlobalNumberings()
{
for (int i = 0; i < inMesh->countGlobalNumberings(); ++i) {
GlobalNumbering* in = inMesh->getGlobalNumbering(i);
GlobalNumbering* out = createGlobalNumbering(outMesh,
getName(in), getShape(in), countComponents(in));
GlobalNumbering* out;
if (getField(in)) {
// here we assume that the fields have already been copied into the
// mesh
Field* outField = outMesh->findField(getName(getField(in)));
PCU_DEBUG_ASSERT(outField);
out = createGlobalNumbering(outField);
}
else {
out = createGlobalNumbering(outMesh, getName(in), getShape(in),
countComponents(in));
}
convertGlobalNumbering(in, out);
}
}
void convertTags()
{
DynamicArray<MeshTag*> tags;
inMesh->getTags(tags);
for (std::size_t i = 0; i < tags.getSize(); ++i) {
apf::MeshTag* in = tags[i];
PCU_DEBUG_ASSERT(in);
// create a new tag on the outMesh
int tagType = inMesh->getTagType(in);
int tagSize = inMesh->getTagSize(in);
const char* tagName = inMesh->getTagName(in);
PCU_DEBUG_ASSERT(tagName);
// need to make sure that the tag wasn't already created by a field or
// numbering
if (!outMesh->findTag(tagName)) {
apf::MeshTag* out = NULL;
switch (tagType) {
case apf::Mesh::TagType::DOUBLE:
out = outMesh->createDoubleTag(tagName, tagSize);
break;
case apf::Mesh::TagType::INT:
out = outMesh->createIntTag(tagName, tagSize);
break;
case apf::Mesh::TagType::LONG:
out = outMesh->createLongTag(tagName, tagSize);
break;
default:
std::cerr << "Tried to convert unknown tag type\n";
abort();
}
PCU_DEBUG_ASSERT(out);
// copy the tag on the inMesh to the outMesh
convertTag(inMesh, in, outMesh, out);
}
}
}
void convertQuadratic()
{
if (inMesh->getShape() != getLagrange(2) && inMesh->getShape() != getSerendipity())
Expand Down
8 changes: 8 additions & 0 deletions apf/apfCoordData.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@

namespace apf {

FieldData* CoordData::clone() {
FieldData* newData = new CoordData();
newData->init(field);
copyFieldData(static_cast<FieldDataOf<double>*>(newData),
static_cast<FieldDataOf<double>*>(field->getData()));
return newData;

}
void CoordData::init(FieldBase* f)
{
FieldData::field = f;
Expand Down
1 change: 1 addition & 0 deletions apf/apfCoordData.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class CoordData : public FieldDataOf<double>
virtual void get(MeshEntity* e, double* data);
virtual void set(MeshEntity* e, double const* data);
virtual bool isFrozen() { return false; }
virtual FieldData* clone();
private:
Mesh* mesh;
FieldShape* shape;
Expand Down
5 changes: 0 additions & 5 deletions apf/apfFieldData.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ FieldData::~FieldData()
{
}

FieldData* FieldData::clone()
{
abort();
}

void FieldData::rename(const char*)
{
abort();
Expand Down
3 changes: 2 additions & 1 deletion apf/apfFieldData.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class FieldData
virtual bool hasEntity(MeshEntity* e) = 0;
virtual void removeEntity(MeshEntity* e) = 0;
virtual bool isFrozen() = 0;
virtual FieldData* clone();
virtual FieldData* clone() = 0;
virtual void rename(const char* newName);
FieldBase* getField() {return field;}
protected:
Expand Down Expand Up @@ -55,6 +55,7 @@ class FieldDataOf : public FieldData
void setNodeComponents(MeshEntity* e, int node, T const* components);
void getNodeComponents(MeshEntity* e, int node, T* components);
int getElementData(MeshEntity* entity, NewArray<T>& data);
virtual FieldData* clone()=0;
};

} //namespace apf
Expand Down
10 changes: 9 additions & 1 deletion apf/apfNumbering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,14 @@ GlobalNumbering* createGlobalNumbering(
return n;
}

GlobalNumbering* createGlobalNumbering(Field* f)
{
GlobalNumbering* n = new GlobalNumbering();
n->init(f);
f->getMesh()->addGlobalNumbering(n);
return n;
}

FieldShape* getShape(GlobalNumbering* n)
{
return n->getShape();
Expand Down Expand Up @@ -601,5 +609,5 @@ void getNodes(GlobalNumbering* n, DynamicArray<Node>& nodes)
getFieldNodes(n,nodes);
}

Field* getField(GlobalNumbering* n) { return n->getField(); }
}

8 changes: 8 additions & 0 deletions apf/apfNumbering.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ GlobalNumbering* createGlobalNumbering(
const char* name,
FieldShape* shape,
int components=1);

/** \brief Create a Numbering of degrees of freedom of a Field.
*/
GlobalNumbering* createGlobalNumbering(Field* f);

FieldShape* getShape(GlobalNumbering* n);
const char* getName(GlobalNumbering* n);
/** \brief get the mesh associated with a global numbering */
Expand All @@ -176,6 +181,9 @@ long getNumber(GlobalNumbering* n, MeshEntity* e, int node, int component=0);
/** \brief get an element's global node numbers */
int getElementNumbers(GlobalNumbering* n, MeshEntity* e,
NewArray<long>& numbers);
/** \brief get the field being numbered
*/
Field* getField(GlobalNumbering* n);

/** \brief converts a local numbering into a global numbering.
\param destroy Should the input Numbering* be destroyed?
Expand Down
9 changes: 9 additions & 0 deletions apf/apfUserData.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,13 @@ bool UserData::isFrozen()
return false;
}

FieldData* UserData::clone()
{
FieldData* newData = new UserData(function);
newData->init(field);
copyFieldData(static_cast<FieldDataOf<double>*>(newData),
static_cast<FieldDataOf<double>*>(field->getData()));
return newData;
}

}
8 changes: 6 additions & 2 deletions apf/apfUserData.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ struct UserData : public FieldDataOf<double>
void get(MeshEntity* e, double* data);
void set(MeshEntity* e, double const* data);
bool isFrozen();
virtual FieldData* clone();
// using const * const gives an error on gcc/7.3.0 because the return is an
// r-value which cannot be modified anyways
Function const* getFunction() const { return function; }
void setFunction(Function* func) { function = func; }
private:
Function* function;
};

}

#endif


1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ util_exe_func(describe describe.cc)
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)

# Geometric model utilities
if(ENABLE_SIMMETRIX)
Expand Down
1 change: 1 addition & 0 deletions test/testing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mpi_test(integrate 1 ./integrate)
mpi_test(qr_test 1 ./qr)
mpi_test(base64 1 ./base64)
mpi_test(tensor_test 1 ./tensor)
mpi_test(verify_convert 1 ./verify_convert)

if(ENABLE_SIMMETRIX)
mpi_test(in_closure_of 1
Expand Down
Loading

0 comments on commit 6f3c392

Please sign in to comment.