Big revision of the spline field classes to avoid dangerous copy-pasting of internal GoTools code. Added a static create method in Field/Fields scope such that the fluid solvers can refer to fields independently of the discretization method.

git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@1327 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
kmo 2011-12-01 13:30:01 +00:00 committed by Knut Morten Okstad
parent 7d67391641
commit 7532977a13
26 changed files with 681 additions and 339 deletions

View File

@ -76,8 +76,10 @@ public:
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~ASMs2D() {} virtual ~ASMs2D() {}
//! \brief Returns the spline surface representing this patch. //! \brief Returns the spline surface representing the geometry of this patch.
Go::SplineSurface* getSurface() const { return surf; } Go::SplineSurface* getSurface() const { return surf; }
//! \brief Returns the spline surface representing the basis of this patch.
virtual Go::SplineSurface* getBasis() const { return surf; }
// Methods for model generation // Methods for model generation

View File

@ -138,6 +138,8 @@ protected:
//! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes //! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes
//! in one element //! in one element
virtual bool getElementCoordinates(Matrix& X, int iel) const; virtual bool getElementCoordinates(Matrix& X, int iel) const;
public:
//! \brief Returns a matrix with all nodal coordinates within the patch. //! \brief Returns a matrix with all nodal coordinates within the patch.
//! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes //! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes
//! in the patch //! in the patch

View File

@ -39,6 +39,9 @@ public:
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~ASMs2Dmx() {} virtual ~ASMs2Dmx() {}
//! \brief Returns the spline surface representing the basis of this patch.
virtual Go::SplineSurface* getBasis() const { return basis1; }
//! \brief Returns the spline surface representing this patch. //! \brief Returns the spline surface representing this patch.
Go::SplineSurface* getSurface() const { return surf; } Go::SplineSurface* getSurface() const { return surf; }

View File

@ -98,6 +98,8 @@ public:
//! \brief Returns the spline volume representing this patch. //! \brief Returns the spline volume representing this patch.
Go::SplineVolume* getVolume() const { return svol; } Go::SplineVolume* getVolume() const { return svol; }
//! \brief Returns the spline volume representing the basis of this patch.
virtual Go::SplineVolume* getBasis() const { return svol; }
// Methods for model generation // Methods for model generation

View File

@ -148,6 +148,8 @@ protected:
//! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes //! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes
//! in one element //! in one element
virtual bool getElementCoordinates(Matrix& X, int iel) const; virtual bool getElementCoordinates(Matrix& X, int iel) const;
public:
//! \brief Returns a matrix with all nodal coordinates within the patch. //! \brief Returns a matrix with all nodal coordinates within the patch.
//! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes //! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes
//! in the patch //! in the patch

View File

@ -42,6 +42,9 @@ public:
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~ASMs3Dmx() {} virtual ~ASMs3Dmx() {}
//! \brief Returns the spline volume representing the basis of this patch.
virtual Go::SplineVolume* getBasis() const { return basis1; }
// Methods for model generation // Methods for model generation
// ============================ // ============================

37
src/ASM/Field.C Normal file
View File

@ -0,0 +1,37 @@
// $Id$
//==============================================================================
//!
//! \file Field.C
//!
//! \date Mar 28 2011
//!
//! \author Runar Holdahl / SINTEF
//!
//! \brief Base class for scalar fields.
//!
//==============================================================================
#include "SplineField2D.h"
#include "SplineField3D.h"
#include "LagrangeField2D.h"
#include "LagrangeField3D.h"
#include "ASMs2DLag.h"
#include "ASMs3DLag.h"
Field* Field::create (const ASMbase* pch, const RealArray& v, const char* name)
{
const ASMs2DLag* pl2 = dynamic_cast<const ASMs2DLag*>(pch);
if (pl2) return new LagrangeField2D(pl2,v,name);
const ASMs2D* ps2 = dynamic_cast<const ASMs2D*>(pch);
if (ps2) return new SplineField2D(ps2,v,name);
const ASMs3DLag* pl3 = dynamic_cast<const ASMs3DLag*>(pch);
if (pl3) return new LagrangeField3D(pl3,v,name);
const ASMs3D* ps3 = dynamic_cast<const ASMs3D*>(pch);
if (ps3) return new SplineField3D(ps3,v,name);
return NULL;
}

View File

@ -17,6 +17,7 @@
#include "MatVec.h" #include "MatVec.h"
#include <string> #include <string>
class ASMbase;
class FiniteElement; class FiniteElement;
class Vec3; class Vec3;
@ -36,7 +37,8 @@ protected:
//! \brief The constructor sets the number of space dimensions and field name. //! \brief The constructor sets the number of space dimensions and field name.
//! \param[in] n Number of space dimensions (1, 2 or 3) //! \param[in] n Number of space dimensions (1, 2 or 3)
//! \param[in] name Name of field //! \param[in] name Name of field
Field(unsigned char n, char* name = 0) : nsd(n) { if (name) fname = name; } Field(unsigned char n, const char* name = 0) : nsd(n), nelm(0), nno(0)
{ if (name) fname = name; }
public: public:
//! \brief Empty destructor. //! \brief Empty destructor.
@ -46,27 +48,27 @@ public:
unsigned char getNoSpaceDim() const { return nsd; } unsigned char getNoSpaceDim() const { return nsd; }
//! \brief Returns number of elements. //! \brief Returns number of elements.
int getNoElm() const { return nelm; } size_t getNoElm() const { return nelm; }
//! \brief Returns number of control points. //! \brief Returns number of nodal/control points.
int getNoNodes() const { return nno; } size_t getNoNodes() const { return nno; }
//! \brief Returns name of field. //! \brief Returns the name of field.
const char* getFieldName() const { return fname.c_str(); } const char* getFieldName() const { return fname.c_str(); }
//! \brief Sets the name of the field. //! \brief Creates a dynamically allocated field object.
void setFieldName(const char* name) { fname = name; } //! \param[in] pch The spline patch on which the field is to be defined on
//! \param[in] v Array of nodal/control point field values
//! \param[in] name Name of field
static Field* create(const ASMbase* pch, const RealArray& v,
const char* name = NULL);
//! \brief Initializes the field values. // Methods to evaluate the field
void fill(const Vector& vec) { values = vec; } //==============================
// Methods to compute field values
//================================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
virtual double valueNode(int node) const = 0; virtual double valueNode(size_t node) const = 0;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition
@ -88,8 +90,8 @@ public:
protected: protected:
unsigned char nsd; //!< Number of space dimensions unsigned char nsd; //!< Number of space dimensions
int nelm; //!< Number of elements/knot-spans size_t nelm; //!< Number of elements/knot-spans
int nno; //!< Number of nodes/control points size_t nno; //!< Number of nodes/control points
std::string fname; //!< Name of the field std::string fname; //!< Name of the field
Vector values; //!< Field values Vector values; //!< Field values
}; };

38
src/ASM/Fields.C Normal file
View File

@ -0,0 +1,38 @@
// $Id$
//==============================================================================
//!
//! \file Fields.C
//!
//! \date Mar 28 2011
//!
//! \author Runar Holdahl / SINTEF
//!
//! \brief Base class for vector fields.
//!
//==============================================================================
#include "SplineFields2D.h"
#include "SplineFields3D.h"
#include "LagrangeFields2D.h"
#include "LagrangeFields3D.h"
#include "ASMs2DLag.h"
#include "ASMs3DLag.h"
Fields* Fields::create (const ASMbase* pch, const RealArray& v,
const char* name)
{
const ASMs2DLag* pl2 = dynamic_cast<const ASMs2DLag*>(pch);
if (pl2) return new LagrangeFields2D(pl2,v,name);
const ASMs2D* ps2 = dynamic_cast<const ASMs2D*>(pch);
if (ps2) return new SplineFields2D(ps2,v,name);
const ASMs3DLag* pl3 = dynamic_cast<const ASMs3DLag*>(pch);
if (pl3) return new LagrangeFields3D(pl3,v,name);
const ASMs3D* ps3 = dynamic_cast<const ASMs3D*>(pch);
if (ps3) return new SplineFields3D(ps3,v,name);
return NULL;
}

View File

@ -17,6 +17,7 @@
#include "MatVec.h" #include "MatVec.h"
#include <string> #include <string>
class ASMbase;
class FiniteElement; class FiniteElement;
class Vec3; class Vec3;
@ -58,20 +59,20 @@ public:
//! \brief Returns name of field. //! \brief Returns name of field.
const char* getFieldName() const { return fname.c_str(); } const char* getFieldName() const { return fname.c_str(); }
//! \brief Sets the name of the field. //! \brief Creates a dynamically allocated field object.
void setFieldName(const char* name) { fname = name; } //! \param[in] pch The spline patch on which the field is to be defined on
//! \param[in] v Array of nodal/control point field values
//! \param[in] name Name of field
static Fields* create(const ASMbase* pch, const RealArray& v,
const char* name = NULL);
//! \brief Initializes the field values. // Methods to evaluate the field
void fill(const Vector& vec) { values = vec; nf = values.size()/nno; } //==============================
// Methods to compute field values
//================================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
//! \param[out] vals Node values //! \param[out] vals Node values
virtual bool valueNode(int node, Vector& vals) const = 0; virtual bool valueNode(size_t node, Vector& vals) const = 0;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition

View File

@ -12,24 +12,32 @@
//============================================================================== //==============================================================================
#include "LagrangeField2D.h" #include "LagrangeField2D.h"
#include "ASMs2DLag.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "Lagrange.h" #include "Lagrange.h"
#include "CoordinateMapping.h" #include "CoordinateMapping.h"
#include "Vec3.h" #include "Vec3.h"
LagrangeField2D::LagrangeField2D (const Matrix& X, int nx, int ny, LagrangeField2D::LagrangeField2D (const ASMs2DLag* patch, const RealArray& v,
int px, int py, char* name) const char* name) : Field(2,name)
: Field(2,name), coord(X), n1(nx), n2(ny), p1(px), p2(py)
{ {
patch->getNodalCoordinates(coord);
patch->getSize(n1,n2);
patch->getOrder(p1,p2);
nno = n1*n2; nno = n1*n2;
nelm = (n1-1)*(n2-1)/(p1*p2); nelm = (n1-1)*(n2-1)/(p1*p2);
// Ensure the values array has compatible length, pad with zeros if necessary
values.resize(nno);
RealArray::const_iterator end = v.size() > nno ? v.begin()+nno : v.end();
std::copy(v.begin(),end,values.begin());
} }
double LagrangeField2D::valueNode (int node) const double LagrangeField2D::valueNode (size_t node) const
{ {
return values(node); return node > 0 && node <= nno ? values(node) : 0.0;
} }

View File

@ -16,6 +16,8 @@
#include "Field.h" #include "Field.h"
class ASMs2DLag;
/*! /*!
\brief Class for Lagrange-based finite element scalar fields in 2D. \brief Class for Lagrange-based finite element scalar fields in 2D.
@ -28,23 +30,20 @@ class LagrangeField2D : public Field
{ {
public: public:
//! \brief The constructor sets the number of space dimensions and fields. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] X Matrix of nodal coordinates //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] nx Number of nodes in first parameter direction //! \param[in] v Array of control point field values
//! \param[in] ny Number of nodes in second parameter direction
//! \param[in] px Element order in first parameter direction
//! \param[in] py Element order in second parameter direction
//! \param[in] name Name of field //! \param[in] name Name of field
LagrangeField2D(const Matrix& X, LagrangeField2D(const ASMs2DLag* patch, const RealArray& v,
int nx, int ny, int px, int py, char* name = NULL); const char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~LagrangeField2D() {} virtual ~LagrangeField2D() {}
// Methods to compute field values // Methods to evaluate the field
//================================ //==============================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
double valueNode(int node) const; double valueNode(size_t node) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition

View File

@ -12,24 +12,32 @@
//============================================================================== //==============================================================================
#include "LagrangeField3D.h" #include "LagrangeField3D.h"
#include "ASMs3DLag.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "Lagrange.h" #include "Lagrange.h"
#include "CoordinateMapping.h" #include "CoordinateMapping.h"
#include "Vec3.h" #include "Vec3.h"
LagrangeField3D::LagrangeField3D (const Matrix& X, int nx, int ny, int nz, LagrangeField3D::LagrangeField3D (const ASMs3DLag* patch, const RealArray& v,
int px, int py, int pz, char* name) const char* name) : Field(3,name)
: Field(3,name), coord(X), n1(nx), n2(ny), n3(nz), p1(px), p2(py), p3(pz)
{ {
patch->getNodalCoordinates(coord);
patch->getSize(n1,n2,n3);
patch->getOrder(p1,p2,p3);
nno = n1*n2*n3; nno = n1*n2*n3;
nelm = (n1-1)*(n2-1)*(n3-1)/(p1*p2*p3); nelm = (n1-1)*(n2-1)*(n3-1)/(p1*p2*p3);
// Ensure the values array has compatible length, pad with zeros if necessary
values.resize(nno);
RealArray::const_iterator end = v.size() > nno ? v.begin()+nno : v.end();
std::copy(v.begin(),end,values.begin());
} }
double LagrangeField3D::valueNode (int node) const double LagrangeField3D::valueNode (size_t node) const
{ {
return values(node); return node > 0 && node <= nno ? values(node) : 0.0;
} }

View File

@ -16,6 +16,8 @@
#include "Field.h" #include "Field.h"
class ASMs3DLag;
/*! /*!
\brief Class for Lagrange-based finite element scalar fields in 3D. \brief Class for Lagrange-based finite element scalar fields in 3D.
@ -28,31 +30,26 @@ class LagrangeField3D : public Field
{ {
public: public:
//! \brief The constructor sets the number of space dimensions and fields. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] X Matrix of nodal coordinates //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] nx Number of nodes in first parameter direction //! \param[in] v Array of control point field values
//! \param[in] ny Number of nodes in second parameter direction
//! \param[in] nz Number of nodes in third parameter direction
//! \param[in] px Element order in first parameter direction
//! \param[in] py Element order in second parameter direction
//! \param[in] pz Element order in third parameter direction
//! \param[in] name Name of field //! \param[in] name Name of field
LagrangeField3D(const Matrix& X, int nx, int ny, int nz, LagrangeField3D(const ASMs3DLag* patch, const RealArray& v,
int px, int py, int pz, char* name = NULL); const char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~LagrangeField3D() {} virtual ~LagrangeField3D() {}
// Methods to compute field values // Methods to evaluate the field
//================================ //==============================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
double valueNode(int node) const; double valueNode(size_t node) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition
double valueFE(const FiniteElement& fe) const; double valueFE(const FiniteElement& fe) const;
//! \brief Computed the value at a given global coordinate. //! \brief Computes the value at a given global coordinate.
//! \param[in] x Global/physical coordinate for point //! \param[in] x Global/physical coordinate for point
double valueCoor(const Vec3& x) const; double valueCoor(const Vec3& x) const;

View File

@ -12,24 +12,33 @@
//============================================================================== //==============================================================================
#include "LagrangeFields2D.h" #include "LagrangeFields2D.h"
#include "ASMs2DLag.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "Lagrange.h" #include "Lagrange.h"
#include "CoordinateMapping.h" #include "CoordinateMapping.h"
#include "Vec3.h" #include "Vec3.h"
LagrangeFields2D::LagrangeFields2D (const Matrix& X, int nx, int ny, LagrangeFields2D::LagrangeFields2D (const ASMs2DLag* patch, const RealArray& v,
int px, int py, char* name) const char* name) : Fields(2,name)
: Fields(2,name), coord(X), n1(nx), n2(ny), p1(px), p2(py)
{ {
patch->getNodalCoordinates(coord);
patch->getSize(n1,n2);
patch->getOrder(p1,p2);
nno = n1*n2; nno = n1*n2;
nelm = (n1-1)*(n2-1)/(p1*p2); nelm = (n1-1)*(n2-1)/(p1*p2);
nf = v.size()/nno;
// Ensure the values array has compatible length, pad with zeros if necessary
values.resize(nf*nno);
RealArray::const_iterator end = v.size() > nf*nno ? v.begin()+nf*nno:v.end();
std::copy(v.begin(),end,values.begin());
} }
bool LagrangeFields2D::valueNode (int node, Vector& vals) const bool LagrangeFields2D::valueNode (size_t node, Vector& vals) const
{ {
if (node < 1 || (size_t)node > nno) return false; if (node < 1 || node > nno) return false;
vals.resize(nf); vals.resize(nf);
vals.fill(values.ptr()+nf*(node-1)); vals.fill(values.ptr()+nf*(node-1));

View File

@ -16,6 +16,8 @@
#include "Fields.h" #include "Fields.h"
class ASMs2DLag;
/*! /*!
\brief Class for Lagrange-based finite element vector fields in 2D. \brief Class for Lagrange-based finite element vector fields in 2D.
@ -27,25 +29,22 @@
class LagrangeFields2D : public Fields class LagrangeFields2D : public Fields
{ {
public: public:
//! \brief The constructor sets the field name. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] X Matrix of nodal coordinates //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] nx Number of nodes in first parameter direction //! \param[in] v Array of control point field values
//! \param[in] ny Number of nodes in second parameter direction
//! \param[in] px Element order in first parameter direction
//! \param[in] py Element order in second parameter direction
//! \param[in] name Name of field //! \param[in] name Name of field
LagrangeFields2D(const Matrix& X, LagrangeFields2D(const ASMs2DLag* patch, const RealArray& v,
int nx, int ny, int px, int py, char* name = NULL); const char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~LagrangeFields2D() {} virtual ~LagrangeFields2D() {}
// Methods to compute field values // Methods to evaluate the field
//================================ //==============================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
//! \param[out] vals Node values //! \param[out] vals Node values
bool valueNode(int node, Vector& vals) const; bool valueNode(size_t node, Vector& vals) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition

View File

@ -12,24 +12,33 @@
//============================================================================== //==============================================================================
#include "LagrangeFields3D.h" #include "LagrangeFields3D.h"
#include "ASMs3DLag.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "Lagrange.h" #include "Lagrange.h"
#include "CoordinateMapping.h" #include "CoordinateMapping.h"
#include "Vec3.h" #include "Vec3.h"
LagrangeFields3D::LagrangeFields3D (const Matrix& X, int nx, int ny, int nz, LagrangeFields3D::LagrangeFields3D (const ASMs3DLag* patch, const RealArray& v,
int px, int py, int pz, char* name) const char* name) : Fields(3,name)
: Fields(3,name), coord(X), n1(nx), n2(ny), n3(nz), p1(px), p2(py), p3(pz)
{ {
patch->getNodalCoordinates(coord);
patch->getSize(n1,n2,n3);
patch->getOrder(p1,p2,p3);
nno = n1*n2*n3; nno = n1*n2*n3;
nelm = (n1-1)*(n2-1)*(n3-1)/(p1*p2*p3); nelm = (n1-1)*(n2-1)*(n3-1)/(p1*p2*p3);
nf = v.size()/nno;
// Ensure the values array has compatible length, pad with zeros if necessary
values.resize(nf*nno);
RealArray::const_iterator end = v.size() > nf*nno ? v.begin()+nf*nno:v.end();
std::copy(v.begin(),end,values.begin());
} }
bool LagrangeFields3D::valueNode (int node, Vector& vals) const bool LagrangeFields3D::valueNode (size_t node, Vector& vals) const
{ {
if (node < 1 || (size_t)node > nno) return false; if (node < 1 || node > nno) return false;
vals.resize(nf); vals.resize(nf);
vals.fill(values.ptr()+nf*(node-1)); vals.fill(values.ptr()+nf*(node-1));

View File

@ -16,6 +16,8 @@
#include "Fields.h" #include "Fields.h"
class ASMs3DLag;
/*! /*!
\brief Class for Lagrange-based finite element vector fields in 3D. \brief Class for Lagrange-based finite element vector fields in 3D.
@ -27,17 +29,12 @@
class LagrangeFields3D : public Fields class LagrangeFields3D : public Fields
{ {
public: public:
//! \brief The constructor sets the field name. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] X Matrix of nodal coordinates //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] nx Number of nodes in first parameter direction //! \param[in] v Array of control point field values
//! \param[in] ny Number of nodes in second parameter direction
//! \param[in] nz Number of nodes in third parameter direction
//! \param[in] px Element order in first parameter direction
//! \param[in] py Element order in second parameter direction
//! \param[in] pz Element order in third parameter direction
//! \param[in] name Name of field //! \param[in] name Name of field
LagrangeFields3D(const Matrix& X, int nx, int ny, int nz, LagrangeFields3D(const ASMs3DLag* patch, const RealArray& v,
int px, int py, int pz, char* name = NULL); const char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~LagrangeFields3D() {} virtual ~LagrangeFields3D() {}
@ -47,7 +44,7 @@ public:
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
//! \param[out] vals Node values //! \param[out] vals Node values
bool valueNode(int node, Vector& vals) const; bool valueNode(size_t node, Vector& vals) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition

View File

@ -12,15 +12,18 @@
//============================================================================== //==============================================================================
#include "SplineField2D.h" #include "SplineField2D.h"
#include "ASMs2D.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "CoordinateMapping.h"
#include "Utilities.h"
#include "Vec3.h" #include "Vec3.h"
#include "GoTools/geometry/SplineSurface.h" #include "GoTools/geometry/SplineSurface.h"
#include "GoTools/geometry/SplineUtils.h"
SplineField2D::SplineField2D(Go::SplineSurface *bf, char* name) SplineField2D::SplineField2D (const ASMs2D* patch,
: Field(2,name), basis(bf), surf(bf) const RealArray& v, const char* name)
: Field(2,name), basis(patch->getBasis()), surf(patch->getSurface())
{ {
const int n1 = basis->numCoefs_u(); const int n1 = basis->numCoefs_u();
const int n2 = basis->numCoefs_v(); const int n2 = basis->numCoefs_v();
@ -29,44 +32,41 @@ SplineField2D::SplineField2D(Go::SplineSurface *bf, char* name)
const int p1 = basis->order_u(); const int p1 = basis->order_u();
const int p2 = basis->order_v(); const int p2 = basis->order_v();
nelm = (n1-p1+1)*(n2-p2+1); nelm = (n1-p1+1)*(n2-p2+1);
// Ensure the values array has compatible length, pad with zeros if necessary
values.resize(nno);
RealArray::const_iterator end = v.size() > nno ? v.begin()+nno : v.end();
std::copy(v.begin(),end,values.begin());
} }
SplineField2D::SplineField2D(Go::SplineSurface *bf, double SplineField2D::valueNode (size_t node) const
Go::SplineSurface *geometry,
char* name)
: Field(2,name), basis(bf), surf(geometry)
{ {
const int n1 = basis->numCoefs_u(); return node > 0 && node <= nno ? values(node) : 0.0;
const int n2 = basis->numCoefs_v();
nno = n1*n2;
const int p1 = basis->order_u();
const int p2 = basis->order_v();
nelm = (n1-p1+1)*(n2-p2+1);
} }
SplineField2D::~SplineField2D() double SplineField2D::valueFE (const FiniteElement& fe) const
{ {
// Set basis and geometry pointers to NULL, should not be deallocated here if (!basis) return false;
basis = surf = NULL;
// Evaluate the basis functions at the given point
Go::BasisPtsSf spline;
basis->computeBasis(fe.u,fe.v,spline);
// Evaluate the solution field at the given point
std::vector<int> ip;
ASMs2D::scatterInd(basis->numCoefs_u(),basis->numCoefs_v(),
basis->order_u(),basis->order_v(),
spline.left_idx,ip);
Vector Vnod;
utl::gather(ip,1,values,Vnod);
return Vnod.dot(spline.basisValues);
} }
/* Old procedure, way too complex...
double SplineField2D::valueNode(int node) const The above code is more in line with how we do it in ASMs2D.
{
// Not implemented yet
return 0.0;
}
double SplineField2D::valueFE(const FiniteElement& fe) const
{
// Go::Point pt;
// basis->pointValue(pt,values,fe.u,fe.v);
// return pt[0];
const int uorder = basis->order_u(); const int uorder = basis->order_u();
const int vorder = basis->order_v(); const int vorder = basis->order_v();
const int unum = basis->numCoefs_u(); const int unum = basis->numCoefs_u();
@ -140,19 +140,82 @@ double SplineField2D::valueFE(const FiniteElement& fe) const
return val; return val;
} }
*/
double SplineField2D::valueCoor (const Vec3& x) const
double SplineField2D::valueCoor(const Vec3& x) const
{ {
// Not implemented yet // Not implemented yet
return 0.0; return 0.0;
} }
bool SplineField2D::gradFE(const FiniteElement& fe, Vector& grad) const bool SplineField2D::gradFE (const FiniteElement& fe, Vector& grad) const
{ {
if (!basis) return false; if (!basis) return false;
if (!surf) return false;
// Evaluate the basis functions at the given point
/*
Go::BasisDerivsSf spline;
surf->computeBasis(fe.u,fe.v,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
std::vector<Go::BasisDerivsSf> tmpSpline(1);
surf->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),tmpSpline);
Go::BasisDerivsSf& spline = tmpSpline.front();
const int uorder = surf->order_u();
const int vorder = surf->order_v();
const size_t nen = uorder*vorder;
Matrix dNdu(nen,2), dNdX;
for (size_t n = 1; n <= nen; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
}
std::vector<int> ip;
ASMs2D::scatterInd(surf->numCoefs_u(),surf->numCoefs_v(),
uorder,vorder,spline.left_idx,ip);
// Evaluate the Jacobian inverse
Matrix Xnod, Jac;
Vector Xctrl(&(*surf->coefs_begin()),surf->coefs_end()-surf->coefs_begin());
utl::gather(ip,surf->dimension(),Xctrl,Xnod);
utl::Jacobian(Jac,dNdX,Xnod,dNdu);
// Evaluate the gradient of the solution field at the given point
if (basis != surf)
{
// Mixed formulation, the solution uses a different basis than the geometry
/*
basis->computeBasis(fe.u,fe.v,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
basis->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),tmpSpline);
Go::BasisDerivsSf& spline = tmpSpline.front();
const size_t nbf = basis->order_u()*basis->order_v();
dNdu.resize(nbf,2);
for (size_t n = 1; n <= nbf; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
}
dNdX.multiply(dNdu,Jac); // dNdX = dNdu * Jac
ASMs2D::scatterInd(basis->numCoefs_u(),basis->numCoefs_v(),
basis->order_u(),basis->order_v(),
spline.left_idx,ip);
}
Vector Vnod;
utl::gather(ip,1,values,Vnod);
return dNdX.multiply(Vnod,grad,true);
}
/*
// // Derivatives of solution in parametric space // // Derivatives of solution in parametric space
// std::vector<Go::Point> pts(3); // std::vector<Go::Point> pts(3);
// basis->pointValue(pts,values,fe.u,fe.v,1); // basis->pointValue(pts,values,fe.u,fe.v,1);
@ -303,9 +366,10 @@ bool SplineField2D::gradFE(const FiniteElement& fe, Vector& grad) const
return true; return true;
} }
*/
bool SplineField2D::gradCoor(const Vec3& x, Vector& grad) const bool SplineField2D::gradCoor (const Vec3& x, Vector& grad) const
{ {
// Not implemented yet // Not implemented yet
return false; return false;

View File

@ -16,6 +16,8 @@
#include "Field.h" #include "Field.h"
class ASMs2D;
namespace Go { namespace Go {
class SplineSurface; class SplineSurface;
} }
@ -24,40 +26,34 @@ namespace Go {
/*! /*!
\brief Class for spline-based finite element scalar fields in 2D. \brief Class for spline-based finite element scalar fields in 2D.
\details This class implements the functions required to evaluate a 2D \details This class implements the methods required to evaluate a 2D
spline scalar field at a given point in parametrical or physical coordinates. spline scalar field at a given point in parametrical or physical coordinates.
*/ */
class SplineField2D : public Field class SplineField2D : public Field
{ {
public: public:
//! \brief The constructor sets the number of space dimensions and fields. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] bf Spline basis description //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] v Array of control point field values
//! \param[in] name Name of spline field //! \param[in] name Name of spline field
SplineField2D(Go::SplineSurface *bf, char* name = NULL); SplineField2D(const ASMs2D* patch, const RealArray& v,
//! \brief The constructor sets the number of space dimensions and fields. const char* name = NULL);
//! \param[in] bf Spline basis description
//! \param[in] geometry Spline geometry description
//! \param[in] name Name of spline field
SplineField2D(Go::SplineSurface *bf,
Go::SplineSurface *geometry,
char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~SplineField2D(); virtual ~SplineField2D() {}
// Methods to compute field values // Methods to evaluate the field
//================================ //==============================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
double valueNode(int node) const; double valueNode(size_t node) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition
double valueFE(const FiniteElement& fe) const; double valueFE(const FiniteElement& fe) const;
//! \brief Computed the value at a given global coordinate. //! \brief Computes the value at a given global coordinate.
//! \param[in] x Global/physical coordinate for point //! \param[in] x Global/physical coordinate for point
double valueCoor(const Vec3& x) const; double valueCoor(const Vec3& x) const;
@ -72,8 +68,8 @@ public:
bool gradCoor(const Vec3& x, Vector& grad) const; bool gradCoor(const Vec3& x, Vector& grad) const;
protected: protected:
Go::SplineSurface* basis; //!< Spline basis description const Go::SplineSurface* basis; //!< Spline basis description
Go::SplineSurface* surf; //!< Spline geometry description const Go::SplineSurface* surf; //!< Spline geometry description
}; };
#endif #endif

View File

@ -12,19 +12,18 @@
//============================================================================== //==============================================================================
#include "SplineField3D.h" #include "SplineField3D.h"
#include "ASMs3D.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "CoordinateMapping.h"
#include "Utilities.h"
#include "Vec3.h" #include "Vec3.h"
#include "GoTools/trivariate/SplineVolume.h" #include "GoTools/trivariate/SplineVolume.h"
#include "GoTools/geometry/SplineUtils.h"
namespace Go {
void volume_ratder(double const eder[],int idim,int ider,double gder[]);
}
SplineField3D::SplineField3D(Go::SplineVolume *bf, char* name) SplineField3D::SplineField3D (const ASMs3D* patch,
: Field(3,name), basis(bf), vol(bf) const RealArray& v, const char* name)
: Field(3,name), basis(patch->getBasis()), vol(patch->getVolume())
{ {
const int n1 = basis->numCoefs(0); const int n1 = basis->numCoefs(0);
const int n2 = basis->numCoefs(1); const int n2 = basis->numCoefs(1);
@ -35,46 +34,41 @@ SplineField3D::SplineField3D(Go::SplineVolume *bf, char* name)
const int p2 = basis->order(1); const int p2 = basis->order(1);
const int p3 = basis->order(2); const int p3 = basis->order(2);
nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1); nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1);
// Ensure the values array has compatible length, pad with zeros if necessary
values.resize(nno);
RealArray::const_iterator end = v.size() > nno ? v.begin()+nno : v.end();
std::copy(v.begin(),end,values.begin());
} }
SplineField3D::SplineField3D(Go::SplineVolume *bf, double SplineField3D::valueNode (size_t node) const
Go::SplineVolume *geometry,
char* name)
: Field(3,name), basis(bf), vol(geometry)
{ {
const int n1 = basis->numCoefs(0); return node > 0 && node <= nno ? values(node) : 0.0;
const int n2 = basis->numCoefs(1);
const int n3 = basis->numCoefs(2);
nno = n1*n2*n3;
const int p1 = basis->order(0);
const int p2 = basis->order(1);
const int p3 = basis->order(2);
nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1);
} }
SplineField3D::~SplineField3D() double SplineField3D::valueFE (const FiniteElement& fe) const
{ {
// Set basis and geometry pointers to NULL, should not be deallocated here if (!basis) return false;
basis = vol = NULL;
// Evaluate the basis functions at the given point
Go::BasisPts spline;
basis->computeBasis(fe.u,fe.v,fe.w,spline);
// Evaluate the solution field at the given point
std::vector<int> ip;
ASMs3D::scatterInd(basis->numCoefs(0),basis->numCoefs(1),basis->numCoefs(2),
basis->order(0),basis->order(1),basis->order(2),
spline.left_idx,ip);
Vector Vnod;
utl::gather(ip,1,values,Vnod);
return Vnod.dot(spline.basisValues);
} }
/* Old procedure, way too complex...
double SplineField3D::valueNode(int node) const The above code is more in line with how we do it in ASMs3D.
{
// Not implemented yet
return 0.0;
}
double SplineField3D::valueFE(const FiniteElement& fe) const
{
// Go::Point pt;
// basis->pointValue(pt,values,fe.u,fe.v,fe.w);
// return pt[0];
double val = 0.0; double val = 0.0;
const int uorder = basis->order(0); const int uorder = basis->order(0);
@ -168,19 +162,85 @@ double SplineField3D::valueFE(const FiniteElement& fe) const
val = tempResult/w; val = tempResult/w;
return val; return val;
} }
*/
double SplineField3D::valueCoor (const Vec3& x) const
double SplineField3D::valueCoor(const Vec3& x) const
{ {
// Not implemented yet // Not implemented yet
return 0.0; return 0.0;
} }
bool SplineField3D::gradFE(const FiniteElement& fe, Vector& grad) const bool SplineField3D::gradFE (const FiniteElement& fe, Vector& grad) const
{ {
if (!basis) return false; if (!basis) return false;
if (!vol) return false;
// Evaluate the basis functions at the given point
/*
Go::BasisDerivs spline;
vol->computeBasis(fe.u,fe.v,fe.w,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
std::vector<Go::BasisDerivs> tmpSpline(1);
vol->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),RealArray(1,fe.w),tmpSpline);
Go::BasisDerivs& spline = tmpSpline.front();
const int uorder = vol->order(0);
const int vorder = vol->order(1);
const int worder = vol->order(2);
const size_t nen = uorder*vorder*worder;
Matrix dNdu(nen,3), dNdX;
for (size_t n = 1; n <= nen; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
dNdu(n,3) = spline.basisDerivs_w[n-1];
}
std::vector<int> ip;
ASMs3D::scatterInd(vol->numCoefs(0),vol->numCoefs(1),vol->numCoefs(2),
uorder,vorder,worder,spline.left_idx,ip);
// Evaluate the Jacobian inverse
Matrix Xnod, Jac;
Vector Xctrl(&(*vol->coefs_begin()),vol->coefs_end()-vol->coefs_begin());
utl::gather(ip,vol->dimension(),Xctrl,Xnod);
utl::Jacobian(Jac,dNdX,Xnod,dNdu);
// Evaluate the gradient of the solution field at the given point
if (basis != vol)
{
// Mixed formulation, the solution uses a different basis than the geometry
/*
basis->computeBasis(fe.u,fe.v,fe.w,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
basis->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),RealArray(1,fe.w),tmpSpline);
Go::BasisDerivs& spline = tmpSpline.front();
const size_t nbf = basis->order(0)*basis->order(1)*basis->order(2);
dNdu.resize(nbf,3);
for (size_t n = 1; n <= nbf; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
dNdu(n,3) = spline.basisDerivs_w[n-1];
}
dNdX.multiply(dNdu,Jac);
ASMs3D::scatterInd(basis->numCoefs(0),basis->numCoefs(1),basis->numCoefs(2),
basis->order(0),basis->order(1),basis->order(2),
spline.left_idx,ip);
}
Vector Vnod;
utl::gather(ip,1,values,Vnod);
return dNdX.multiply(Vnod,grad,true);
}
/*
// // Derivatives of solution in parametric space // // Derivatives of solution in parametric space
// std::vector<Go::Point> pts; // std::vector<Go::Point> pts;
// basis->pointValue(pts,values,fe.u,fe.v,fe.w,1); // basis->pointValue(pts,values,fe.u,fe.v,fe.w,1);
@ -376,9 +436,9 @@ bool SplineField3D::gradFE(const FiniteElement& fe, Vector& grad) const
return true; return true;
} }
*/
bool SplineField3D::gradCoor (const Vec3& x, Vector& grad) const
bool SplineField3D::gradCoor(const Vec3& x, Vector& grad) const
{ {
// Not implemented yet // Not implemented yet
return false; return false;

View File

@ -16,6 +16,8 @@
#include "Field.h" #include "Field.h"
class ASMs3D;
namespace Go { namespace Go {
class SplineVolume; class SplineVolume;
} }
@ -28,35 +30,30 @@ namespace Go {
spline scalar field at a given point in parametrical or physical coordinates. spline scalar field at a given point in parametrical or physical coordinates.
*/ */
class SplineField3D : public Field class SplineField3D : public Field
{ {
public: public:
//! \brief The constructor sets the number of space dimensions and fields. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] bf Spline basis description //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] v Array of control point field values
//! \param[in] name Name of spline field //! \param[in] name Name of spline field
SplineField3D(Go::SplineVolume *bf, char* name = NULL); SplineField3D(const ASMs3D* patch, const RealArray& v,
//! \param[in] bf Spline basis description const char* name = NULL);
//! \param[in] geometry Spline geometry description
//! \param[in] name Name of spline field
SplineField3D(Go::SplineVolume *bf,
Go::SplineVolume *geometry,
char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~SplineField3D(); virtual ~SplineField3D() {}
// Methods to compute field values // Methods to evaluate the field
//================================ //==============================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
double valueNode(int node) const; double valueNode(size_t node) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition
double valueFE(const FiniteElement& fe) const; double valueFE(const FiniteElement& fe) const;
//! \brief Computed the value at a given global coordinate. //! \brief Computes the value at a given global coordinate.
//! \param[in] x Global/physical coordinate for point //! \param[in] x Global/physical coordinate for point
double valueCoor(const Vec3& x) const; double valueCoor(const Vec3& x) const;
@ -71,8 +68,8 @@ public:
bool gradCoor(const Vec3& x, Vector& grad) const; bool gradCoor(const Vec3& x, Vector& grad) const;
protected: protected:
Go::SplineVolume* basis; //!< Spline basis description const Go::SplineVolume* basis; //!< Spline basis description
Go::SplineVolume* vol; //!< Spline volume description const Go::SplineVolume* vol; //!< Spline geometry description
}; };
#endif #endif

View File

@ -12,18 +12,18 @@
//============================================================================== //==============================================================================
#include "SplineFields2D.h" #include "SplineFields2D.h"
#include "ASMs2D.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "CoordinateMapping.h"
#include "Utilities.h"
#include "Vec3.h" #include "Vec3.h"
#include "GoTools/geometry/SplineSurface.h" #include "GoTools/geometry/SplineSurface.h"
#include "GoTools/geometry/SplineUtils.h"
#ifndef __BORLANDC__
#include "boost/lambda/lambda.hpp"
#endif
SplineFields2D::SplineFields2D(Go::SplineSurface *bf, char* name) SplineFields2D::SplineFields2D (const ASMs2D* patch,
: Fields(2,name), basis(bf), surf(bf) const RealArray& v, const char* name)
: Fields(2,name), basis(patch->getBasis()), surf(patch->getSurface())
{ {
const int n1 = basis->numCoefs_u(); const int n1 = basis->numCoefs_u();
const int n2 = basis->numCoefs_v(); const int n2 = basis->numCoefs_v();
@ -33,53 +33,47 @@ SplineFields2D::SplineFields2D(Go::SplineSurface *bf, char* name)
const int p2 = basis->order_v(); const int p2 = basis->order_v();
nelm = (n1-p1+1)*(n2-p2+1); nelm = (n1-p1+1)*(n2-p2+1);
// Number of fields set in fill // Ensure the values array has compatible length, pad with zeros if necessary
nf = 0; nf = v.size()/nno;
values.resize(nf*nno);
RealArray::const_iterator end = v.size() > nf*nno ? v.begin()+nf*nno:v.end();
std::copy(v.begin(),end,values.begin());
} }
SplineFields2D::SplineFields2D(Go::SplineSurface *bf, bool SplineFields2D::valueNode (size_t node, Vector& vals) const
Go::SplineSurface *geometry,
char* name)
: Fields(2,name), basis(bf), surf(geometry)
{ {
const int n1 = basis->numCoefs_u(); if (node < 1 || node > nno) return false;
const int n2 = basis->numCoefs_v();
nno = n1*n2;
const int p1 = basis->order_u(); vals.resize(nf);
const int p2 = basis->order_v(); vals.fill(values.ptr()+(node-1)*nf);
nelm = (n1-p1+1)*(n2-p2+1); return true;
// Number of fields set in fill
nf = 0;
} }
SplineFields2D::~SplineFields2D() bool SplineFields2D::valueFE (const FiniteElement& fe, Vector& vals) const
{
// Set geometry to NULL; should not be deallocated here
basis = surf = NULL;
}
bool SplineFields2D::valueNode(int node, Vector& vals) const
{
// Not implemented yet
return false;
}
bool SplineFields2D::valueFE(const FiniteElement& fe, Vector& vals) const
{ {
if (!basis) return false; if (!basis) return false;
// Go::Point pt; // Evaluate the basis functions at the given point
// basis->pointValue(pt,values,fe.u,fe.v); Go::BasisPtsSf spline;
// vals.resize(pt.size()); basis->computeBasis(fe.u,fe.v,spline);
// for (int i = 0;i < pt.size();i++)
// vals[i] = pt[i];
// Evaluate the solution field at the given point
std::vector<int> ip;
ASMs2D::scatterInd(basis->numCoefs_u(),basis->numCoefs_v(),
basis->order_u(),basis->order_v(),
spline.left_idx,ip);
Matrix Vnod;
utl::gather(ip,nf,values,Vnod);
Vnod.multiply(spline.basisValues,vals); // vals = Vnod * basisValues
return true;
}
/* Old procedure, way too complex...
The above code is more in line with how we do it in ASMs2D.
const int uorder = basis->order_u(); const int uorder = basis->order_u();
const int vorder = basis->order_v(); const int vorder = basis->order_v();
const int unum = basis->numCoefs_u(); const int unum = basis->numCoefs_u();
@ -175,19 +169,82 @@ bool SplineFields2D::valueFE(const FiniteElement& fe, Vector& vals) const
return true; return true;
} }
*/
bool SplineFields2D::valueCoor (const Vec3& x, Vector& vals) const
bool SplineFields2D::valueCoor(const Vec3& x, Vector& vals) const
{ {
// Not implemented yet // Not implemented yet
return false; return false;
} }
bool SplineFields2D::gradFE(const FiniteElement& fe, Matrix& grad) const bool SplineFields2D::gradFE (const FiniteElement& fe, Matrix& grad) const
{ {
if (!basis) return false; if (!basis) return false;
if (!surf) return false;
// Evaluate the basis functions at the given point
/*
Go::BasisDerivsSf spline;
surf->computeBasis(fe.u,fe.v,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
std::vector<Go::BasisDerivsSf> tmpSpline(1);
surf->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),tmpSpline);
Go::BasisDerivsSf& spline = tmpSpline.front();
const int uorder = surf->order_u();
const int vorder = surf->order_v();
const size_t nen = uorder*vorder;
Matrix dNdu(nen,2), dNdX;
for (size_t n = 1; n <= nen; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
}
std::vector<int> ip;
ASMs2D::scatterInd(surf->numCoefs_u(),surf->numCoefs_v(),
uorder,vorder,spline.left_idx,ip);
// Evaluate the Jacobian inverse
Matrix Xnod, Jac;
Vector Xctrl(&(*surf->coefs_begin()),surf->coefs_end()-surf->coefs_begin());
utl::gather(ip,surf->dimension(),Xctrl,Xnod);
utl::Jacobian(Jac,dNdX,Xnod,dNdu);
// Evaluate the gradient of the solution field at the given point
if (basis != surf)
{
// Mixed formulation, the solution uses a different basis than the geometry
/*
basis->computeBasis(fe.u,fe.v,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
basis->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),tmpSpline);
Go::BasisDerivsSf& spline = tmpSpline.front();
const size_t nbf = basis->order_u()*basis->order_v();
dNdu.resize(nbf,2);
for (size_t n = 1; n <= nbf; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
}
dNdX.multiply(dNdu,Jac); // dNdX = dNdu * Jac
ASMs2D::scatterInd(basis->numCoefs_u(),basis->numCoefs_v(),
basis->order_u(),basis->order_v(),
spline.left_idx,ip);
}
utl::gather(ip,nf,values,Xnod);
grad.multiply(Xnod,dNdX); // grad = Xnod * dNdX
return true;
}
// // Derivatives of solution in parametric space // // Derivatives of solution in parametric space
// std::vector<Go::Point> pts(3); // std::vector<Go::Point> pts(3);
@ -215,7 +272,7 @@ bool SplineFields2D::gradFE(const FiniteElement& fe, Matrix& grad) const
// // Gradient of solution in given parametric point // // Gradient of solution in given parametric point
// // df/dX = df/dXi * Jac^-1 = df/dXi * [dX/dXi]^-1 // // df/dX = df/dXi * Jac^-1 = df/dXi * [dX/dXi]^-1
// grad.multiply(gradXi,Jac); // grad.multiply(gradXi,Jac);
/*
// Gradient of field // Gradient of field
Matrix gradXi(nf,2); Matrix gradXi(nf,2);
@ -351,9 +408,10 @@ bool SplineFields2D::gradFE(const FiniteElement& fe, Matrix& grad) const
return true; return true;
} }
*/
bool SplineFields2D::gradCoor(const Vec3& x, Matrix& grad) const bool SplineFields2D::gradCoor (const Vec3& x, Matrix& grad) const
{ {
// Not implemented yet // Not implemented yet
return false; return false;

View File

@ -16,6 +16,8 @@
#include "Fields.h" #include "Fields.h"
class ASMs2D;
namespace Go { namespace Go {
class SplineSurface; class SplineSurface;
} }
@ -24,44 +26,38 @@ namespace Go {
/*! /*!
\brief Class for spline-based finite element vector fields in 2D. \brief Class for spline-based finite element vector fields in 2D.
\details This class implements the functions required to evaluate a 2D \details This class implements the methods required to evaluate a 2D
spline vector field at a given point in parametrical or physical coordinates. spline vector field at a given point in parametrical or physical coordinates.
*/ */
class SplineFields2D : public Fields class SplineFields2D : public Fields
{ {
public: public:
//! \brief The constructor sets the field name. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] bf Spline basis description //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] v Array of control point field values
//! \param[in] name Name of spline field //! \param[in] name Name of spline field
SplineFields2D(Go::SplineSurface *bf, char* name = NULL); SplineFields2D(const ASMs2D* patch, const RealArray& v,
//! \brief The constructor sets the field name. const char* name = NULL);
//! \param[in] bf Spline basis description
//! \param[in] geometry Spline geometry description
//! \param[in] name Name of spline field
SplineFields2D(Go::SplineSurface *bf,
Go::SplineSurface *geoemtry,
char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~SplineFields2D(); virtual ~SplineFields2D() {}
// Methods to compute field values // Methods to evaluate the field
//================================ //==============================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
//! \param[out] vals Node values //! \param[out] vals Node values
bool valueNode(int node, Vector& vals) const; bool valueNode(size_t node, Vector& vals) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition
//! \param[out] vals Values in local point in given element //! \param[out] vals Values in local point in given element
bool valueFE(const FiniteElement& fe, Vector& vals) const; bool valueFE(const FiniteElement& fe, Vector& vals) const;
//! \brief Computed the value at a given global coordinate. //! \brief Computes the value at a given global coordinate.
//! \param[in] x Global/physical coordinate for point //! \param[in] x Global/physical coordinate for point
//! \param[in] vals Values in given physical coordinate //! \param[out] vals Values in given physical coordinate
bool valueCoor(const Vec3& x, Vector& vals) const; bool valueCoor(const Vec3& x, Vector& vals) const;
//! \brief Computes the gradient for a given local coordinate. //! \brief Computes the gradient for a given local coordinate.
@ -75,8 +71,8 @@ public:
bool gradCoor(const Vec3& x, Matrix& grad) const; bool gradCoor(const Vec3& x, Matrix& grad) const;
protected: protected:
Go::SplineSurface* basis; //!< Spline basis description const Go::SplineSurface* basis; //!< Spline basis description
Go::SplineSurface* surf; //!< Spline geoemtry description const Go::SplineSurface* surf; //!< Spline geometry description
}; };
#endif #endif

View File

@ -12,20 +12,18 @@
//============================================================================== //==============================================================================
#include "SplineFields3D.h" #include "SplineFields3D.h"
#include "ASMs3D.h"
#include "FiniteElement.h" #include "FiniteElement.h"
#include "CoordinateMapping.h"
#include "Utilities.h"
#include "Vec3.h" #include "Vec3.h"
#include "GoTools/trivariate/SplineVolume.h" #include "GoTools/trivariate/SplineVolume.h"
#include "GoTools/geometry/SplineUtils.h"
#include "boost/lambda/lambda.hpp"
namespace Go {
void volume_ratder(double const eder[],int idim,int ider,double gder[]);
}
SplineFields3D::SplineFields3D(Go::SplineVolume *bf, char* name) SplineFields3D::SplineFields3D (const ASMs3D* patch,
: Fields(3,name), basis(bf), vol(bf) const RealArray& v, const char* name)
: Fields(3,name), basis(patch->getBasis()), vol(patch->getVolume())
{ {
const int n1 = basis->numCoefs(0); const int n1 = basis->numCoefs(0);
const int n2 = basis->numCoefs(1); const int n2 = basis->numCoefs(1);
@ -37,56 +35,48 @@ SplineFields3D::SplineFields3D(Go::SplineVolume *bf, char* name)
const int p3 = basis->order(2); const int p3 = basis->order(2);
nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1); nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1);
// Number of fields set in fill // Ensure the values array has compatible length, pad with zeros if necessary
nf = 0; nf = v.size()/nno;
values.resize(nf*nno);
RealArray::const_iterator end = v.size() > nf*nno ? v.begin()+nf*nno:v.end();
std::copy(v.begin(),end,values.begin());
} }
SplineFields3D::SplineFields3D(Go::SplineVolume *bf, bool SplineFields3D::valueNode (size_t node, Vector& vals) const
Go::SplineVolume *geometry,
char* name)
: Fields(3,name), basis(bf), vol(geometry)
{ {
const int n1 = basis->numCoefs(0); if (node < 1 || node > nno) return false;
const int n2 = basis->numCoefs(1);
const int n3 = basis->numCoefs(2);
nno = n1*n2*n3;
const int p1 = basis->order(0); vals.resize(nf);
const int p2 = basis->order(1); vals.fill(values.ptr()+(node-1)*nf);
const int p3 = basis->order(2); return true;
nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1);
// Number of fields set in fill
nf = 0;
} }
bool SplineFields3D::valueFE (const FiniteElement& fe, Vector& vals) const
SplineFields3D::~SplineFields3D()
{
// Set geometry to NULL; should not be deallocated here
basis = NULL;
}
bool SplineFields3D::valueNode(int node, Vector& vals) const
{
// Not implemented yet
return false;
}
bool SplineFields3D::valueFE(const FiniteElement& fe, Vector& vals) const
{ {
if (!basis) return false; if (!basis) return false;
Go::Point pt; // Evaluate the basis functions at the given point
Go::BasisPts spline;
basis->computeBasis(fe.u,fe.v,fe.w,spline);
// basis->pointValue(pt,values,fe.u,fe.v,fe.w); // Evaluate the solution field at the given point
// vals.resize(pt.size()); std::vector<int> ip;
// for (int i = 0;i < pt.size();i++) ASMs3D::scatterInd(basis->numCoefs(0),basis->numCoefs(1),basis->numCoefs(2),
// vals[i] = pt[i]; basis->order(0),basis->order(1),basis->order(2),
spline.left_idx,ip);
Matrix Vnod;
utl::gather(ip,nf,values,Vnod);
Vnod.multiply(spline.basisValues,vals); // vals = Vnod * basisValues
return true;
}
/* Old procedure, way too complex...
The above code is more in line with how we do it in ASMs3D.
Go::Point pt;
const int uorder = basis->order(0); const int uorder = basis->order(0);
const int vorder = basis->order(1); const int vorder = basis->order(1);
@ -213,10 +203,10 @@ bool SplineFields3D::valueFE(const FiniteElement& fe, Vector& vals) const
return true; return true;
} }
*/
bool SplineFields3D::valueCoor (const Vec3& x, Vector& vals) const
bool SplineFields3D::valueCoor(const Vec3& x, Vector& vals) const
{ {
// Not implemented yet // Not implemented yet
return false; return false;
@ -226,6 +216,72 @@ bool SplineFields3D::valueCoor(const Vec3& x, Vector& vals) const
bool SplineFields3D::gradFE(const FiniteElement& fe, Matrix& grad) const bool SplineFields3D::gradFE(const FiniteElement& fe, Matrix& grad) const
{ {
if (!basis) return false; if (!basis) return false;
if (!vol) return false;
// Evaluate the basis functions at the given point
/*
Go::BasisDerivs spline;
vol->computeBasis(fe.u,fe.v,fe.w,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
std::vector<Go::BasisDerivs> tmpSpline(1);
vol->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),RealArray(1,fe.w),tmpSpline);
Go::BasisDerivs& spline = tmpSpline.front();
const int uorder = vol->order(0);
const int vorder = vol->order(1);
const int worder = vol->order(2);
const size_t nen = uorder*vorder*worder;
Matrix dNdu(nen,3), dNdX;
for (size_t n = 1; n <= nen; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
dNdu(n,3) = spline.basisDerivs_w[n-1];
}
std::vector<int> ip;
ASMs3D::scatterInd(vol->numCoefs(0),vol->numCoefs(1),vol->numCoefs(2),
uorder,vorder,worder,spline.left_idx,ip);
// Evaluate the Jacobian inverse
Matrix Xnod, Jac;
Vector Xctrl(&(*vol->coefs_begin()),vol->coefs_end()-vol->coefs_begin());
utl::gather(ip,vol->dimension(),Xctrl,Xnod);
utl::Jacobian(Jac,dNdX,Xnod,dNdu);
// Evaluate the gradient of the solution field at the given point
if (basis != vol)
{
// Mixed formulation, the solution uses a different basis than the geometry
/*
basis->computeBasis(fe.u,fe.v,fe.w,spline);
TODO: The above is not available yet, the below is temporary workaround.
*/
basis->computeBasisGrid(RealArray(1,fe.u),RealArray(1,fe.v),RealArray(1,fe.w),tmpSpline);
Go::BasisDerivs& spline = tmpSpline.front();
const size_t nbf = basis->order(0)*basis->order(1)*basis->order(2);
dNdu.resize(nbf,3);
for (size_t n = 1; n <= nbf; n++)
{
dNdu(n,1) = spline.basisDerivs_u[n-1];
dNdu(n,2) = spline.basisDerivs_v[n-1];
dNdu(n,3) = spline.basisDerivs_w[n-1];
}
dNdX.multiply(dNdu,Jac); // dNdX = dNdu * Jac
ASMs3D::scatterInd(basis->numCoefs(0),basis->numCoefs(1),basis->numCoefs(2),
basis->order(0),basis->order(1),basis->order(2),
spline.left_idx,ip);
}
utl::gather(ip,nf,values,Xnod);
grad.multiply(Xnod,dNdX); // grad = Xnod * dNdX
return true;
}
// // Derivatives of solution in parametric space // // Derivatives of solution in parametric space
// std::vector<Go::Point> pts; // std::vector<Go::Point> pts;
@ -252,6 +308,7 @@ bool SplineFields3D::gradFE(const FiniteElement& fe, Matrix& grad) const
// // df/dX = df/dXi * Jac^-1 = df/dXi * [dX/dXi]^-1 // // df/dX = df/dXi * Jac^-1 = df/dXi * [dX/dXi]^-1
// grad.multiply(gradXi,Jac); // grad.multiply(gradXi,Jac);
/*
// Derivatives of solution in parametric space // Derivatives of solution in parametric space
std::vector<Go::Point> pts(4); std::vector<Go::Point> pts(4);
@ -438,9 +495,9 @@ bool SplineFields3D::gradFE(const FiniteElement& fe, Matrix& grad) const
return true; return true;
} }
*/
bool SplineFields3D::gradCoor (const Vec3& x, Matrix& grad) const
bool SplineFields3D::gradCoor(const Vec3& x, Matrix& grad) const
{ {
// Not implemented yet // Not implemented yet
return false; return false;

View File

@ -16,6 +16,8 @@
#include "Fields.h" #include "Fields.h"
class ASMs3D;
namespace Go { namespace Go {
class SplineVolume; class SplineVolume;
} }
@ -24,44 +26,38 @@ namespace Go {
/*! /*!
\brief Class for spline-based finite element vector fields in 3D. \brief Class for spline-based finite element vector fields in 3D.
\details This class implements the functions required to evaluate a 3D \details This class implements the methods required to evaluate a 3D
spline vector field at a given point in parametrical or physical coordinates. spline vector field at a given point in parametrical or physical coordinates.
*/ */
class SplineFields3D : public Fields class SplineFields3D : public Fields
{ {
public: public:
//! \brief The constructor sets the field name. //! \brief The constructor sets the number of space dimensions and fields.
//! \param[in] bf Spline basis description //! \param[in] patch The spline patch on which the field is to be defined
//! \param[in] v Array of control point field values
//! \param[in] name Name of spline field //! \param[in] name Name of spline field
SplineFields3D(Go::SplineVolume *bf, char* name = NULL); SplineFields3D(const ASMs3D* patch, const RealArray& v,
//! \brief The constructor sets the field name. const char* name = NULL);
//! \param[in] bf Spline basis description
//! \param[in] geometry Spline geometry description
//! \param[in] name Name of spline field
SplineFields3D(Go::SplineVolume *bf,
Go::SplineVolume *geometry,
char* name = NULL);
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~SplineFields3D(); virtual ~SplineFields3D() {}
// Methods to compute field values // Methods to evaluate the field
//================================ //==============================
//! \brief Computes the value in a given node/control point. //! \brief Computes the value in a given node/control point.
//! \param[in] node Node number //! \param[in] node Node number
//! \param[out] vals Node values //! \param[out] vals Node values
bool valueNode(int node, Vector& vals) const; bool valueNode(size_t node, Vector& vals) const;
//! \brief Computes the value at a given local coordinate. //! \brief Computes the value at a given local coordinate.
//! \param[in] fe Finite element definition //! \param[in] fe Finite element definition
//! \param[out] vals Values in local point in given element //! \param[out] vals Values in local point in given element
bool valueFE(const FiniteElement& fe, Vector& vals) const; bool valueFE(const FiniteElement& fe, Vector& vals) const;
//! \brief Computed the value at a given global coordinate. //! \brief Computes the value at a given global coordinate.
//! \param[in] x Global/physical coordinate for point //! \param[in] x Global/physical coordinate for point
//! \param[in] vals Values in given physical coordinate //! \param[out] vals Values in given physical coordinate
bool valueCoor(const Vec3& x, Vector& vals) const; bool valueCoor(const Vec3& x, Vector& vals) const;
//! \brief Computes the gradient for a given local coordinate. //! \brief Computes the gradient for a given local coordinate.
@ -75,8 +71,8 @@ public:
bool gradCoor(const Vec3& x, Matrix& grad) const; bool gradCoor(const Vec3& x, Matrix& grad) const;
protected: protected:
Go::SplineVolume* basis; //!< Spline basis description const Go::SplineVolume* basis; //!< Spline basis description
Go::SplineVolume* vol; //!< Spline geometry description const Go::SplineVolume* vol; //!< Spline geometry description
}; };
#endif #endif