Skip to content

implement FieldData::clone() #163

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

Merged
merged 4 commits into from
Aug 13, 2018
Merged
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
7 changes: 7 additions & 0 deletions apf/apf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,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 @@ -721,14 +721,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 @@ -25,7 +25,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 @@ -58,6 +58,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;
};


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