fixed: extract proper components from field vectors with more components in field classes

- a field can be now instanced for a given component of a vector field
- a field can now be instanced for a given basis of a vector field
- fields can now be instanced for a field vector holding extra
  components / bases.

used for directly registering dependency fields from solution vectors
in coupled simulations (RANS, Boussinesq, Chorin, ..)
This commit is contained in:
Arne Morten Kvarving
2016-10-06 15:31:06 +02:00
parent 6f5a4a5637
commit ef1513d7c8
19 changed files with 101 additions and 42 deletions

View File

@@ -96,10 +96,10 @@ public:
virtual void registerDependency(SIMdependency* sim, const std::string& name,
short int nvc,
const std::vector<ASMbase*>& patches,
char diffBasis = 0)
char diffBasis = 0, int component = 1)
{
S1.registerDependency(sim, name, nvc, patches, diffBasis);
S2.registerDependency(sim, name, nvc, patches, diffBasis);
S1.registerDependency(sim, name, nvc, patches, diffBasis, component);
S2.registerDependency(sim, name, nvc, patches, diffBasis, component);
}
//! \brief Registers a dependency on a field from another SIM object.

View File

@@ -69,11 +69,11 @@ public:
const ProcessAdm& getProcessAdm() const { return base.getProcessAdm(); }
//! \copydoc SIMdependency::registerDependency(SIMdependency*,const std::string&,short int,const PatchVec&,char)
virtual void registerDependency(SIMdependency* sim, const std::string& name,
short int nvc, const PatchVec& patches,
char diffBasis = 0)
void registerDependency(SIMdependency* sim, const std::string& name,
short int nvc, const PatchVec& patches,
char diffBasis = 0, int component = 1) override
{
base.registerDependency(sim, name, nvc, patches, diffBasis);
base.registerDependency(sim, name, nvc, patches, diffBasis, component);
}
//! \copydoc SIMdependency::registerDependency(SIMdependency*,const std::string&,short int)

View File

@@ -51,7 +51,7 @@ public:
bool saveModel(char*, int&, int&) { return savemodel_called = true; }
bool init(const TimeStep&) { return init_called = true; }
void registerDependency(SIMdependency*, const std::string&,
short int, const std::vector<ASMbase*>&, bool)
short int, const std::vector<ASMbase*>&, char, int)
{
registerdependency1_called = true;
}

View File

@@ -64,7 +64,7 @@ public:
return result;
}
void registerDependency(SIMdependency*, const std::string&, short int,
const std::vector<ASMbase*>&, char)
const std::vector<ASMbase*>&, char, int)
{
registerdependency_called = true;
}

View File

@@ -20,19 +20,19 @@
Field* Field::create (const ASMbase* pch, const RealArray& v,
char basis, const char* name)
char basis, char cmp, const char* name)
{
const ASMs2DLag* pl2 = dynamic_cast<const ASMs2DLag*>(pch);
if (pl2) return new LagrangeField2D(pl2,v,basis,name);
if (pl2) return new LagrangeField2D(pl2,v,basis,cmp,name);
const ASMs2D* ps2 = dynamic_cast<const ASMs2D*>(pch);
if (ps2) return new SplineField2D(ps2,v,basis,name);
if (ps2) return new SplineField2D(ps2,v,basis,cmp,name);
const ASMs3DLag* pl3 = dynamic_cast<const ASMs3DLag*>(pch);
if (pl3) return new LagrangeField3D(pl3,v,basis,name);
if (pl3) return new LagrangeField3D(pl3,v,basis,cmp,name);
const ASMs3D* ps3 = dynamic_cast<const ASMs3D*>(pch);
if (ps3) return new SplineField3D(ps3,v,basis,name);
if (ps3) return new SplineField3D(ps3,v,basis,cmp,name);
return nullptr;
}

View File

@@ -41,9 +41,11 @@ public:
//! \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] basis Basis to use from patch
//! \param[in] cmp Component to use for field
//! \param[in] name Name of field
static Field* create(const ASMbase* pch, const RealArray& v,
char basis = 1, const char* name = nullptr);
char basis = 1, char cmp = 1,
const char* name = nullptr);
//! \brief Returns the name of field.
const char* getFieldName() const { return fname.c_str(); }

View File

@@ -21,7 +21,7 @@
LagrangeField2D::LagrangeField2D (const ASMs2DLag* patch,
const RealArray& v,
char basis,
char basis, char,
const char* name) : FieldBase(name)
{
patch->getNodalCoordinates(coord);

View File

@@ -33,9 +33,10 @@ public:
//! \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] basis Basis to use from patch
//! \param[in] cmp Component to use
//! \param[in] name Name of field
LagrangeField2D(const ASMs2DLag* patch, const RealArray& v,
char basis = 1, const char* name = nullptr);
char basis = 1, char cmp = 1, const char* name = nullptr);
//! \brief Empty destructor.
virtual ~LagrangeField2D() {}

View File

@@ -21,8 +21,8 @@
LagrangeField3D::LagrangeField3D (const ASMs3DLag* patch,
const RealArray& v,
char basis,
const char* name) : FieldBase(name)
char basis, char,
const char* name) : FieldBase(name)
{
patch->getNodalCoordinates(coord);
patch->getSize(n1,n2,n3);

View File

@@ -33,9 +33,10 @@ public:
//! \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] basis Basis to use from patch
//! \param[in] cmp Component to use
//! \param[in] name Name of field
LagrangeField3D(const ASMs3DLag* patch, const RealArray& v,
char basis = 1, const char* name = nullptr);
char basis = 1, char cmp = 1, const char* name = nullptr);
//! \brief Empty destructor.
virtual ~LagrangeField3D() {}

View File

@@ -24,7 +24,7 @@
SplineField2D::SplineField2D (const ASMs2D* patch,
const RealArray& v, char nbasis,
const char* name)
char cmp, const char* name)
: FieldBase(name), basis(patch->getBasis(nbasis)), surf(patch->getSurface())
{
const int n1 = basis->numCoefs_u();
@@ -36,9 +36,19 @@ SplineField2D::SplineField2D (const ASMs2D* patch,
nelm = (n1-p1+1)*(n2-p2+1);
// Ensure the values array has compatible length, pad with zeros if necessary
size_t ofs = 0;
for (char i = 1; i < nbasis; ++i)
ofs += patch->getNoNodes(i)*patch->getNoFields(i);
auto vit = v.begin()+ofs;
values.resize(nno);
RealArray::const_iterator end = v.size() > nno ? v.begin()+nno : v.end();
std::copy(v.begin(),end,values.begin());
int nf = patch->getNoFields(nbasis);
int ndof = nf > 1 && cmp > 0 ? nf*nno : nno;
auto end = v.size() > ofs+ndof ? vit+ndof : v.end();
if (nf == 1 || cmp == 0)
std::copy(vit,end,values.begin());
else
for (size_t i = 0; i < nno && vit != end; ++i, vit += nf)
values[i] = *(vit+cmp-1);
}

View File

@@ -37,9 +37,10 @@ public:
//! \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] basis Basis to use from patch
//! \param[in] cmp Component to use from source field. Pass 0 to use vector as-is.
//! \param[in] name Name of spline field
SplineField2D(const ASMs2D* patch, const RealArray& v,
char basis = 1, const char* name = nullptr);
char basis = 1, char cmp = 1, const char* name = nullptr);
//! \brief Empty destructor.
virtual ~SplineField2D() {}

View File

@@ -24,7 +24,7 @@
SplineField3D::SplineField3D (const ASMs3D* patch,
const RealArray& v, char nbasis,
const char* name)
char cmp, const char* name)
: FieldBase(name), basis(patch->getBasis(nbasis)), vol(patch->getVolume())
{
const int n1 = basis->numCoefs(0);
@@ -37,10 +37,19 @@ SplineField3D::SplineField3D (const ASMs3D* patch,
const int p3 = basis->order(2);
nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1);
// Ensure the values array has compatible length, pad with zeros if necessary
size_t ofs = 0;
for (char i = 1; i < nbasis; ++i)
ofs += patch->getNoNodes(i)*patch->getNoFields(i);
auto vit = v.begin()+ofs;
values.resize(nno);
RealArray::const_iterator end = v.size() > nno ? v.begin()+nno : v.end();
std::copy(v.begin(),end,values.begin());
int nf = patch->getNoFields(nbasis);
int ndof = nf > 1 && cmp > 0 ? nf*nno : nno;
auto end = v.size() > ofs+ndof ? vit+ndof : v.end();
if (nf == 1 || cmp == 0)
std::copy(vit,end,values.begin());
else
for (size_t i = 0; i < nno && vit != end; ++i, vit += nf)
values[i] = *(vit+cmp-1);
}

View File

@@ -37,9 +37,10 @@ public:
//! \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] basis Basis to use from patch
//! \param[in] cmp Component to use from source field. Pass 0 to use vector as-is.
//! \param[in] name Name of spline field
SplineField3D(const ASMs3D* patch, const RealArray& v,
char basis = 1, const char* name = nullptr);
char basis = 1, char cmp = 1, const char* name = nullptr);
//! \brief Empty destructor.
virtual ~SplineField3D() {}

View File

@@ -34,11 +34,23 @@ SplineFields2D::SplineFields2D (const ASMs2D* patch,
const int p2 = basis->order_v();
nelm = (n1-p1+1)*(n2-p2+1);
size_t ofs = 0;
for (char i = 1; i < nbasis; ++i)
ofs += patch->getNoNodes(i)*patch->getNoFields(i);
auto vit = v.begin()+ofs;
// Ensure the values array has compatible length, pad with zeros if necessary
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());
nf = 2;
int nfc = patch->getNoFields(nbasis);
values.resize(nno*nf);
int ndof = nfc*nno;
auto end = v.size() > ofs+ndof ? vit+ndof : v.end();
if (nfc == 2)
std::copy(vit,end,values.begin());
else
for (size_t i = 0; i < nno && vit != end; ++i, vit += nfc)
for (size_t j = 0; j < 2; ++j)
values[2*i+j] = *(vit+j);
}

View File

@@ -36,11 +36,22 @@ SplineFields3D::SplineFields3D (const ASMs3D* patch,
const int p3 = basis->order(2);
nelm = (n1-p1+1)*(n2-p2+1)*(n3-p3+1);
// Ensure the values array has compatible length, pad with zeros if necessary
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());
size_t ofs = 0;
for (char i = 1; i < nbasis; ++i)
ofs += patch->getNoNodes(i)*patch->getNoFields(i);
auto vit = v.begin()+ofs;
nf = 3;
int nfc = patch->getNoFields(nbasis);
values.resize(nno*nf);
int ndof = nfc*nno;
auto end = v.size() > ofs+ndof ? vit+ndof : v.end();
if (nfc == 3)
std::copy(vit,end,values.begin());
else
for (size_t i = 0; i < nno && vit != end; ++i, vit += nfc)
for (size_t j = 0; j < 3; ++j)
values[3*i+j] = *(vit+j);
}

View File

@@ -10,6 +10,7 @@
//!
//==============================================================================
#include "Field.h"
#include "Fields.h"
#include "FiniteElement.h"
#include "SIM2D.h"
@@ -31,6 +32,7 @@ TEST(TestSplineFields, Value2D)
1.0, -1.0,
3.0, 1.0};
Fields* fvector = Fields::create(sim.getPatch(1), vc);
Field* fscalar = Field::create(sim.getPatch(1), vc, 1, 2);
static std::vector<std::array<double,4>> tests_vector =
{{0.5, 0.5, 1.25, 0.25},
{1.0, 0.0, 1.0, 1.0},
@@ -44,7 +46,9 @@ TEST(TestSplineFields, Value2D)
fvector->valueFE(fe, v);
ASSERT_FLOAT_EQ(v(1), it[2]);
ASSERT_FLOAT_EQ(v(2), it[3]);
ASSERT_FLOAT_EQ(fscalar->valueFE(fe), it[3]);
}
}
@@ -90,6 +94,7 @@ TEST(TestSplineFields, Value3D)
2.0, 0.0, 0.0,
3.0, 1.0, 1.0};
Fields* fvector = Fields::create(sim.getPatch(1), vc);
Field* fscalar = Field::create(sim.getPatch(1), vc, 1, 2);
static std::vector<std::array<double,6>> tests_scalar =
{{0.5, 0.5, 0.5, 1.5, 0.5, 0.5},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
@@ -110,6 +115,7 @@ TEST(TestSplineFields, Value3D)
ASSERT_FLOAT_EQ(v(1), it[3]);
ASSERT_FLOAT_EQ(v(2), it[4]);
ASSERT_FLOAT_EQ(v(3), it[5]);
ASSERT_FLOAT_EQ(fscalar->valueFE(fe), it[4]);
}
}

View File

@@ -20,11 +20,13 @@
void SIMdependency::registerDependency (SIMdependency* sim,
const std::string& name, short int nvc,
const PatchVec& patches, char diffBasis)
const PatchVec& patches,
char diffBasis, int component)
{
this->SIMdependency::registerDependency(sim,name,nvc);
depFields.back().patches = patches;
depFields.back().differentBasis = diffBasis;
depFields.back().comp_use = component;
}
@@ -143,7 +145,8 @@ bool SIMdependency::extractPatchDependencies (IntegrandBase* problem,
if (it->differentBasis > 0) {
if (it->components == 1)
problem->setNamedField(it->name,Field::create(patch,*lvec,
it->differentBasis));
it->differentBasis,
it->comp_use));
else
problem->setNamedFields(it->name,Fields::create(patch,*lvec,
it->differentBasis));

View File

@@ -40,11 +40,12 @@ private:
PatchVec patches; //!< Patch geometry the field is defined over
std::string name; //!< Field name
short int components; //!< Number of field components per node
short int comp_use; //!< Component to use from field
char differentBasis; //!< Toggle usage of an independent basis
//! \brief Default constructor.
Dependency(SIMdependency* s = nullptr, const std::string& f = "",
short int n = 1) : sim(s), name(f), components(n),
differentBasis(0) {}
comp_use(1), differentBasis(0) {}
};
//! \brief SIM dependency container
@@ -71,9 +72,10 @@ public:
//! \param[in] nvc Number of components in field
//! \param[in] patches The geometry the field is defined over
//! \param[in] diffBasis If non-null, use diffBasis base from patch vector
//! \param[in] component Component to use from field
virtual void registerDependency(SIMdependency* sim, const std::string& name,
short int nvc, const PatchVec& patches,
char diffBasis = 0);
char diffBasis = 0, int component = 1);
//! \brief Registers a dependency on a field from another SIM object.
//! \param[in] sim The SIM object holding the field we depend on
//! \param[in] name Name of field we depend on