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

Initial implementation of support for complex fields #234

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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 CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ endif()

set(Trilinos_PREFIX "" CACHE STRING "Trilinos installation directory")

option(PUMI_CXX_COMPLEX "Use std::complex<double> instead of double_complex" OFF)
if(PUMI_CXX_COMPLEX)
set(PUMI_COMPLEX PUMI_CXX_COMPLEX)
else()
set(PUMI_COMPLEX PUMI_C_COMPLEX)
endif()

option(SKIP_SIMMETRIX_VERSION_CHECK "enable at your own risk; it may result in undefined behavior" OFF)
option(ENABLE_SIMMETRIX "Build with Simmetrix support" OFF)
message(STATUS "ENABLE_SIMMETRIX: ${ENABLE_SIMMETRIX}")
Expand Down
10 changes: 9 additions & 1 deletion apf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ if(DEFINED TRIBITS_PACKAGE)
return()
endif()

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/apfComplexType.h.in
${CMAKE_CURRENT_SOURCE_DIR}/apfComplexType.h @ONLY)

# Package sources
set(SOURCES
apf.cc
Expand All @@ -29,6 +32,7 @@ set(SOURCES
apfVectorElement.cc
apfVectorField.cc
apfPackedField.cc
apfComplexField.cc
apfNumbering.cc
apfMixedNumbering.cc
apfAdjReorder.cc
Expand All @@ -47,6 +51,7 @@ set(SOURCES
apfSimplexAngleCalcs.cc
apfFile.cc
apfMIS.cc
apfZero.cc
)

# Package headers
Expand All @@ -73,6 +78,9 @@ set(HEADERS
apfField.h
apfFieldData.h
apfNumberingClass.h
apfComplex.h
wrtobin marked this conversation as resolved.
Show resolved Hide resolved
apfComplexType.h
apfElementType.h
)

# Add the apf library
Expand All @@ -92,7 +100,7 @@ target_link_libraries(apf
lion
can
mth
)
)

scorec_export_library(apf)

Expand Down
28 changes: 21 additions & 7 deletions apf/apf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
*/

#include "apf.h"
#include "apfElement.h"
#include "apfScalarField.h"
#include "apfScalarElement.h"
#include "apfVectorField.h"
#include "apfVectorElement.h"
#include "apfMatrixField.h"
#include "apfMatrixElement.h"
#include "apfPackedField.h"
#include "apfComplexField.h"
#include "apfIntegrate.h"
#include "apfArrayData.h"
#include "apfTagData.h"
Expand Down Expand Up @@ -74,7 +76,7 @@ Field* makeField(
else if (valueType == PACKED)
f = new PackedField(components);
else
fail("invalid valueType in field construction\n");
fail("invalid valueType in double field construction\n");
f->init(name,m,shape,data);
m->addField(f);
return f;
Expand Down Expand Up @@ -126,8 +128,12 @@ Field* createPackedField(Mesh* m, const char* name, int components,

Field* cloneField(Field* f, Mesh* onto)
{
return makeField(onto, f->getName(), f->getValueType(), f->countComponents(),
f->getShape(), f->getData()->clone());
return makeField(onto,
f->getName(),
f->getValueType(),
f->countComponents(),
f->getShape(),
f->getData()->clone());
}

Mesh* getMesh(Field* f)
Expand Down Expand Up @@ -371,7 +377,7 @@ double computeCosAngle(Mesh* m, MeshEntity* pe, MeshEntity* e1, MeshEntity* e2,

int countNodes(Element* e)
{
return e->getShape()->countNodes();
return countNodes<double>(e);
}

void getScalarNodes(Element* e, NewArray<double>& values)
Expand All @@ -392,16 +398,24 @@ void getMatrixNodes(Element* e, NewArray<Matrix3x3>& values)
element->getValues(values);
}

void getPackedNodes(Element* e, NewArray<double>& values)
{
FieldBase* f = e->getFieldBase();
int cmps = f->countComponents();
ElementOf<double>* element = static_cast<ElementOf<double>*>(e);
element->getValues(values,cmps);
}

void getShapeValues(Element* e, Vector3 const& local,
NewArray<double>& values)
{
e->getShape()->getValues(e->getMesh(), e->getEntity(), local,values);
getShapeValues<double>(e,local,values);
}

void getShapeGrads(Element* e, Vector3 const& local,
NewArray<Vector3>& grads)
{
e->getGlobalGradients(local,grads);
getShapeGrads<double>(e,local,grads);
}

FieldShape* getShape(Field* f)
Expand Down Expand Up @@ -473,7 +487,7 @@ void unfreeze(Field* f)

bool isFrozen(Field* f)
{
return f->getData()->isFrozen();
return isFrozen(static_cast<FieldBase*>(f));
}

Function::~Function()
Expand Down
23 changes: 20 additions & 3 deletions apf/apf.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define APF_H

#include "apfMatrix.h"
#include "apfElementType.h"
#include "apfNew.h"
#include "apfDynamicArray.h"

Expand All @@ -31,7 +32,6 @@
namespace apf {

class Field;
class Element;
class Mesh;
class MeshEntity;
class VectorElement;
Expand All @@ -43,7 +43,7 @@ template <class T> class ReductionOp;
template <class T> class ReductionSum;

/** \brief Base class for applying operations to make a Field consistent
* in parallel
* in parallel
* \details This function gets applied pairwise to the Field values
* from every partition, resulting in a single unique value. No guarantees
* are made about the order in which this function is applied to the
Expand Down Expand Up @@ -569,6 +569,10 @@ void getVectorNodes(Element* e, NewArray<Vector3>& values);
*/
void getMatrixNodes(Element* e, NewArray<Matrix3x3>& values);

/** \brief Returns the element nodal values for a packed field
*/
void getPackedNodes(Element* e, NewArray<double>& values);

/** \brief Returns the shape function values at a point
*/
void getShapeValues(Element* e, Vector3 const& local,
Expand Down Expand Up @@ -717,8 +721,21 @@ bool isFrozen(Field* f);
\details This function is only defined for fields
which are using array storage, for which apf::isFrozen
returns true.
\note If the underlying field data type is NOT double,
this will cause an assert fail in all compile modes.
*/
double * getDoubleArrayData(Field* f);
// \note deprecated, retained for legacy compatibility until C++14 switch
inline double* getArrayData(Field* f) { return getDoubleArrayData(f); }

/** \brief Return the contiguous array storing this field.
\details This function is only defined for fields
which are using array storage, for which apf::isFrozen
returns true.
\note If the underlying field data type is NOT int,
this will cause an assert fail in all compile modes.
*/
double* getArrayData(Field* f);
int* getIntArrayData(Field* f);

/** \brief Initialize all nodal values with all-zero components */
void zeroField(Field* f);
Expand Down
40 changes: 35 additions & 5 deletions apf/apfArrayData.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "apfArrayData.h"
#include "apfComplex.h"
#include "apfNumbering.h"
#include "apfTagData.h"
#include <pcu_util.h>
#include <type_traits>

namespace apf {

Expand Down Expand Up @@ -125,19 +128,46 @@ void unfreezeFieldData(FieldBase* field) {
}

/* instantiate here */
template void freezeFieldData<double_complex>(FieldBase* field);
template void freezeFieldData<int>(FieldBase* field);
template void freezeFieldData<double>(FieldBase* field);
template void unfreezeFieldData<double_complex>(FieldBase * field);
template void unfreezeFieldData<int>(FieldBase* field);
template void unfreezeFieldData<double>(FieldBase* field);

double* getArrayData(Field* f) {
if (!isFrozen(f)) {
template <typename T>
T* getArrayDataT(FieldBase* f)
{
int scalar = f->getScalarType();
// having to assert this is terrible and if we add more field types
// unsustainable and bad practice, but the current other option is
// changing the API and being more explicit about type storage
// since Field assumes it has Scalars of type double
PCU_ALWAYS_ASSERT(
(scalar == Mesh::DOUBLE && std::is_same<T,double>::value) ||
(scalar == Mesh::INT && std::is_same<T,int>::value) ||
(scalar == Mesh::LONG && std::is_same<T,long>::value) ||
(scalar == Mesh::COMPLEX && std::is_same<T,double_complex>::value)
);
if(!isFrozen(f))
return 0;
} else {
FieldDataOf<double>* p = f->getData();
ArrayDataOf<double>* a = static_cast<ArrayDataOf<double>* > (p);
else
{
FieldDataOf<T>* p = reinterpret_cast<FieldDataOf<T>*>(f->getData());
ArrayDataOf<T>* a = static_cast<ArrayDataOf<T>*>(p);
return a->getDataArray();
}
}

template double_complex* getArrayDataT(FieldBase* field);
template int* getArrayDataT(FieldBase* field);
template double* getArrayDataT(FieldBase* field);

double * getDoubleArrayData(Field * f) { return getArrayDataT<double>(f); }
int * getIntArrayData(Field * f) { return getArrayDataT<int>(f); }

class ComplexField;
double_complex * getComplexArrayData(ComplexField * f) { return getArrayDataT<double_complex>(reinterpret_cast<FieldBase*>(f)); }


}
58 changes: 58 additions & 0 deletions apf/apfComplex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef APFCOMPLEX_H_
#define APFCOMPLEX_H_

#include "apfComplexType.h"
#include "apfElementType.h"

namespace apf
{

// forward decls for the interface
class ComplexField;
class Mesh;
class FieldShape;
class MeshEntity;
class VectorElement;
typedef VectorElement MeshElement;
class Vector3;
template <class T>
class NewArray;

ComplexField* createComplexPackedField(Mesh* m,
const char* name,
int components,
FieldShape* shape = NULL);

void freeze(ComplexField* f);
void unfreeze(ComplexField* f);
bool isFrozen(ComplexField* f);

/** \brief Return the contiguous array storing this field.
\details This function is only defined for fields
which are using array storage, for which apf::isFrozen
returns true.
\note If the underlying field data type is NOT double_complex,
this will cause an assert fail in all compile modes.
*/
double_complex* getComplexArrayData(ComplexField * f);
void zeroField(ComplexField* f);

void setComponents(ComplexField* f, MeshEntity* e, int node, double_complex const * components);
void getComponents(ComplexField* f, MeshEntity* e, int node, double_complex * components);

ComplexElement* createElement(ComplexField* f, MeshElement* e);
ComplexElement* createElement(ComplexField* f, MeshEntity* e);
void destroyElement(ComplexElement* e);

MeshElement* getMeshElement(ComplexElement* e);
MeshEntity* getMeshEntity(ComplexElement* e);

void getComponents(ComplexElement* e, Vector3 const& param, double_complex* components);
int countNodes(ComplexElement* e);
void getShapeValues(ComplexElement* e, Vector3 const& local, NewArray<double>& values);
void getShapeGrads(ComplexElement* e, Vector3 const& local, NewArray<double>& grades);
void getPackedNodes(ComplexElement* e, NewArray<double_complex>& values);
wrtobin marked this conversation as resolved.
Show resolved Hide resolved

}

#endif
Loading