Extended the mixed methods framework such that neigboring patches are properly connected when using the TOPOLOGY command, and such that output of nodal variables gives correct results

git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@904 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
kmo 2011-04-09 15:36:46 +00:00 committed by Knut Morten Okstad
parent 50011c37b8
commit eda13b7381
24 changed files with 574 additions and 236 deletions

View File

@ -242,8 +242,8 @@ public:
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
virtual bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
//! \brief Evaluates the primary solution field at all visualization points.
//! \param[out] sField Solution field
@ -272,7 +272,7 @@ public:
//! \param[in] npe Number of visualization nodes over each knot span
//!
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored in the \a integrand for current patch.
//! which is assumed to be stored within the \a integrand for current patch.
//! If \a npe is NULL, the solution is evaluated at the Greville points and
//! then projected onto the spline basis to obtain the control point values,
//! which then are returned through \a sField.
@ -285,8 +285,10 @@ public:
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
//!
//! \details When \a regular is \e true, it is assumed that the parameter
//! value array \a gpar forms a regular tensor-product point grid of dimension
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! When \a regular is \e true, it is assumed that the parameter value array
//! \a gpar forms a regular tensor-product point grid of dimension
//! \a gpar[0].size() \a X \a gpar[1].size() \a X \a gpar[2].size().
//! Otherwise, we assume that it contains the \a u, \a v and \a w parameters
//! directly for each sampling point.

View File

@ -1,4 +1,4 @@
// $Id: ASMmxBase.C,v 1.1 2010-12-29 18:41:38 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMmxBase.C
@ -23,7 +23,7 @@ ASMmxBase::ASMmxBase (unsigned char n_f1, unsigned char n_f2, bool geo1)
}
void ASMmxBase::init (const std::vector<int>& MLGN, const int* sysMadof)
void ASMmxBase::initMx (const std::vector<int>& MLGN, const int* sysMadof)
{
MADOF.resize(MLGN.size());
for (size_t i = 0; i < MADOF.size(); i++)
@ -31,7 +31,7 @@ void ASMmxBase::init (const std::vector<int>& MLGN, const int* sysMadof)
}
void ASMmxBase::extrNodeVec (const Vector& globRes, Vector& nodeVec) const
void ASMmxBase::extractNodeVecMx (const Vector& globRes, Vector& nodeVec) const
{
nodeVec.resize(nf1*nb1 + nf2*nb2);
@ -51,3 +51,42 @@ void ASMmxBase::extrNodeVec (const Vector& globRes, Vector& nodeVec) const
nodeVec[ldof] = globRes[idof++];
}
}
bool ASMmxBase::getSolutionMx (Matrix& sField, const Vector& locSol,
const std::vector<int>& nodes) const
{
if (nodes.empty()) return true;
int low, high, nvar;
if ((size_t)nodes.front() <= nb1)
{
nvar = nf1;
low = 1;
high = nb1;
}
else
{
nvar = nf2;
low = nb1+1;
high = nb1+nb2;
}
sField.resize(nvar,nodes.size());
for (size_t i = 0; i < nodes.size(); i++)
if (nodes[i] < low || nodes[i] > high)
{
std::cerr <<" *** ASMmxBase::getSolutionMx: Node #"<< nodes[i]
<<" is out of range ["<< low <<","<< high <<"]."<< std::endl;
return false;
}
else
{
int idof = nvar*(nodes[i]-1);
if (low > 1) idof += nf1*nb1;
for (int j = 0; j < nvar; j++)
sField(j+1,i+1) = locSol[idof++];
}
return true;
}

View File

@ -1,4 +1,4 @@
// $Id: ASMmxBase.h,v 1.1 2010-12-29 18:41:38 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMmxBase.h
@ -33,12 +33,19 @@ protected:
//! \brief Initializes the patch level MADOF array.
//! \param[in] MLGN Matrix of local-to-global node numbers
//! \param[out] sysMadof System-level matrix of accumulated DOFs
void init(const std::vector<int>& MLGN, const int* sysMadof);
void initMx(const std::vector<int>& MLGN, const int* sysMadof);
//! \brief Extracts nodal results for this patch from the global vector.
//! \param[in] globVec Global solution vector in DOF-order
//! \param[out] nodeVec Nodal result vector for this patch
void extrNodeVec(const Vector& globVec, Vector& nodeVec) const;
void extractNodeVecMx(const Vector& globVec, Vector& nodeVec) const;
//! \brief Extract the primary solution field at the specified nodes.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
bool getSolutionMx(Matrix& sField, const Vector& locSol,
const std::vector<int>& nodes) const;
private:
std::vector<int> MADOF; //!< Matrix of accumulated DOFs for this patch

View File

@ -28,17 +28,18 @@
#include <fstream>
ASMs1D::ASMs1D (const char* fileName, unsigned char n_s, unsigned char n_f)
ASMs1D::ASMs1D (const char* fName, unsigned char n_s, unsigned char n_f)
: ASMstruct(1,n_s,n_f), curv(0)
{
std::cout <<"\nReading patch file "<< fileName << std::endl;
std::ifstream is(fileName);
if (!is.good())
std::cerr <<" *** ASMs1D: Failure opening patch file"<< std::endl;
else
this->read(is);
geo = curv;
if (fName)
{
std::cout <<"\nReading patch file "<< fName << std::endl;
std::ifstream is(fName);
if (!is.good())
std::cerr <<" *** ASMs1D: Failure opening patch file"<< std::endl;
else
this->read(is);
}
}
@ -46,14 +47,6 @@ ASMs1D::ASMs1D (std::istream& is, unsigned char n_s, unsigned char n_f)
: ASMstruct(1,n_s,n_f), curv(0)
{
this->read(is);
geo = curv;
}
ASMs1D::ASMs1D (unsigned char n_s, unsigned char n_f)
: ASMstruct(1,n_s,n_f), curv(0)
{
}
@ -85,6 +78,8 @@ bool ASMs1D::read (std::istream& is)
{
std::cerr <<" *** ASMs1D::read: Invalid spline curve patch, dim="
<< curv->dimension() << std::endl;
delete curv;
curv = 0;
return false;
}
else if (curv->dimension() < nsd)
@ -96,6 +91,7 @@ bool ASMs1D::read (std::istream& is)
nsd = curv->dimension();
}
geo = curv;
return true;
}
@ -245,17 +241,24 @@ bool ASMs1D::generateFEMTopology ()
bool ASMs1D::connectPatch (int vertex, ASMs1D& neighbor, int nvertex)
{
return this->connectBasis(vertex,neighbor,nvertex);
}
bool ASMs1D::connectBasis (int vertex, ASMs1D& neighbor, int nvertex,
int basis, int slave, int master)
{
// Set up the slave node number for this curve patch
int n1 = this->getSize();
int node = 1;
int n1 = this->getSize(basis);
switch (vertex)
{
case 2: // Positive I-direction
node = n1;
slave += n1;
case 1: // Negative I-direction
slave += 1;
break;
default:
@ -266,14 +269,14 @@ bool ASMs1D::connectPatch (int vertex, ASMs1D& neighbor, int nvertex)
// Set up the master node number for the neighboring patch
n1 = neighbor.getSize();
int nnode = 1;
n1 = neighbor.getSize(basis);
switch (nvertex)
{
case 2: // Positive I-direction
nnode = n1;
master += n1;
case 1: // Negative I-direction
master += 1;
break;
default:
@ -283,25 +286,26 @@ bool ASMs1D::connectPatch (int vertex, ASMs1D& neighbor, int nvertex)
}
const double xtol = 1.0e-4;
if (!neighbor.getCoord(nnode).equal(this->getCoord(node),xtol))
if (!neighbor.getCoord(master).equal(this->getCoord(slave),xtol))
{
std::cerr <<" *** ASMs1D::connectPatch: Non-matching nodes "
<< nnode <<": "<< neighbor.getCoord(nnode)
<< master <<": "<< neighbor.getCoord(master)
<<"\n and "
<< node <<": "<< this->getCoord(node) << std::endl;
<< slave <<": "<< this->getCoord(slave) << std::endl;
return false;
}
else
ASMbase::collapseNodes(neighbor.MLGN[nnode-1],MLGN[node-1]);
ASMbase::collapseNodes(neighbor.MLGN[master-1],MLGN[slave-1]);
return true;
}
void ASMs1D::closeEnds ()
void ASMs1D::closeEnds (int basis, int master)
{
int n1 = this->getSize();
this->makePeriodic(1,n1);
if (basis < 1) basis = 1;
int n1 = this->getSize(basis < 1 ? 1 : basis);
this->makePeriodic(1,master+n1-1);
}
@ -418,7 +422,7 @@ Vec3 ASMs1D::getCoord (size_t inod) const
}
int ASMs1D::getSize () const
int ASMs1D::getSize (int) const
{
if (!curv) return 0;

View File

@ -30,11 +30,9 @@ class ASMs1D : public ASMstruct
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs1D(const char* fileName, unsigned char n_s = 1, unsigned char n_f = 1);
ASMs1D(const char* fName = 0, unsigned char n_s = 1, unsigned char n_f = 1);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs1D(std::istream& is, unsigned char n_s = 1, unsigned char n_f = 1);
//! \brief Default constructor creating an empty patch.
ASMs1D(unsigned char n_s = 1, unsigned char n_f = 1);
//! \brief Empty destructor.
virtual ~ASMs1D() {}
@ -70,11 +68,8 @@ public:
bool raiseOrder(int ru);
// Various methods for preprocessing of boundary conditions
// ========================================================
//! \brief Makes the two end vertices of the curve periodic.
void closeEnds();
// Various methods for preprocessing of boundary conditions and patch topology
// ===========================================================================
//! \brief Constrains a node identified by a relative parameter value.
//! \param[in] xi Parameter value along the curve
@ -92,7 +87,12 @@ public:
//! \param[in] vertex Local vertex index of this patch, in range [1,2]
//! \param neighbor The neighbor patch
//! \param[in] nvertex Local vertex index of neighbor patch, in range [1,2]
bool connectPatch(int vertex, ASMs1D& neighbor, int nvertex);
virtual bool connectPatch(int vertex, ASMs1D& neighbor, int nvertex);
//! \brief Makes the two end vertices of the curve periodic.
//! \param[in] basis Which basis to connect (mixed methods), 0 means both
//! \param[in] master 1-based index of the first master node in this basis
virtual void closeEnds(int basis = 0, int master = 1);
// Methods for integration of finite element quantities.
@ -155,9 +155,11 @@ public:
//! \param[in] integrand Object with problem-specific data and methods
//! \param[in] npe Number of visualization nodes over each knot span
//!
//! \details If \a npe is NULL, the solution is evaluated at the Greville
//! points and then projected onto the spline basis to obtain the control
//! point values, which then are returned through \a sField.
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! If \a npe is NULL, the solution is evaluated at the Greville points and
//! then projected onto the spline basis to obtain the control point values,
//! which then are returned through \a sField.
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const int* npe = 0) const;
@ -172,6 +174,9 @@ public:
//! \param[out] sField Solution field
//! \param[in] integrand Object with problem-specific data and methods
//! \param[in] gpar Parameter values of the result sampling points
//!
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const RealArray* gpar, bool = true) const;
@ -180,6 +185,16 @@ protected:
// Internal utility methods
// ========================
//! \brief Connects matching nodes on two adjacent vertices.
//! \param[in] vertex Local vertex index of this patch, in range [1,2]
//! \param neighbor The neighbor patch
//! \param[in] nvertex Local vertex index of neighbor patch, in range [1,2]
//! \param[in] basis Which basis to connect the nodes for (mixed methods)
//! \param[in] slave 0-based index of the first slave node in this basis
//! \param[in] master 0-based index of the first master node in this basis
bool connectBasis(int vertex, ASMs1D& neighbor, int nvertex,
int basis = 1, int slave = 0, int master = 0);
//! \brief Calculates parameter values for the visualization nodal points.
//! \param[out] prm Parameter values for all points
//! \param[in] nSegSpan Number of visualization segments over each knot-span
@ -200,7 +215,8 @@ protected:
virtual void getNodalCoordinates(Matrix& X) const;
//! \brief Returns the number of nodal points in the patch.
virtual int getSize() const;
//! \param[in] basis Which basis to return size parameters for (mixed methods)
virtual int getSize(int basis = 0) const;
private:
//! \brief Establishes vectors with basis functions and 1st derivatives.

View File

@ -27,11 +27,9 @@ class ASMs1DLag : public ASMs1D
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs1DLag(const char* fileName, unsigned char n_s = 1, unsigned char n_f = 1);
ASMs1DLag(const char* fNam = 0, unsigned char n_s = 1, unsigned char n_f = 1);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs1DLag(std::istream& is, unsigned char n_s = 1, unsigned char n_f = 1);
//! \brief Default constructor creating an empty patch.
ASMs1DLag(unsigned char n_s = 1, unsigned char n_f = 1) : ASMs1D(n_s,n_f) {}
//! \brief Empty destructor.
virtual ~ASMs1DLag() {}

View File

@ -1,4 +1,4 @@
// $Id: ASMs1DSpec.h,v 1.2 2010-10-05 07:25:25 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMs1DSpec.h
@ -26,14 +26,11 @@ class ASMs1DSpec : public ASMs1DLag
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs1DSpec(const char* fileName, unsigned char n_s = 1, unsigned char n_f = 1)
: ASMs1DLag(fileName,n_s,n_f) {}
ASMs1DSpec(const char* fNam = 0, unsigned char n_s = 1, unsigned char n_f = 1)
: ASMs1DLag(fNam,n_s,n_f) {}
//! \brief Constructor creating an instance by reading the given input stream.
ASMs1DSpec(std::istream& is, unsigned char n_s = 1, unsigned char n_f = 1)
: ASMs1DLag(is,n_s,n_f) {}
//! \brief Default constructor creating an empty patch.
ASMs1DSpec(unsigned char n_s = 1, unsigned char n_f = 1)
: ASMs1DLag(n_s,n_f) {}
//! \brief Empty destructor.
virtual ~ASMs1DSpec() {}

View File

@ -30,17 +30,18 @@
#include <fstream>
ASMs2D::ASMs2D (const char* fileName, unsigned char n_s, unsigned char n_f)
ASMs2D::ASMs2D (const char* fName, unsigned char n_s, unsigned char n_f)
: ASMstruct(2,n_s,n_f), surf(0)
{
std::cout <<"\nReading patch file "<< fileName << std::endl;
std::ifstream is(fileName);
if (!is.good())
std::cerr <<" *** ASMs2D: Failure opening patch file"<< std::endl;
else
this->read(is);
geo = surf;
if (fName)
{
std::cout <<"\nReading patch file "<< fName << std::endl;
std::ifstream is(fName);
if (!is.good())
std::cerr <<" *** ASMs2D: Failure opening patch file"<< std::endl;
else
this->read(is);
}
}
@ -48,14 +49,6 @@ ASMs2D::ASMs2D (std::istream& is, unsigned char n_s, unsigned char n_f)
: ASMstruct(2,n_s,n_f), surf(0)
{
this->read(is);
geo = surf;
}
ASMs2D::ASMs2D (unsigned char n_s, unsigned char n_f)
: ASMstruct(2,n_s,n_f), surf(0)
{
}
@ -87,6 +80,8 @@ bool ASMs2D::read (std::istream& is)
{
std::cerr <<" *** ASMs2D::read: Invalid spline surface patch, dim="
<< surf->dimension() << std::endl;
delete surf;
surf = 0;
return false;
}
else if (surf->dimension() < nsd)
@ -98,6 +93,7 @@ bool ASMs2D::read (std::istream& is)
nsd = surf->dimension();
}
geo = surf;
return true;
}
@ -352,25 +348,32 @@ bool ASMs2D::assignNodeNumbers (BlockNodes& nodes, int basis)
}
bool ASMs2D::connectPatch (int edge, ASMs2D& neighbor, int nedge, bool rev)
bool ASMs2D::connectPatch (int edge, ASMs2D& neighbor, int nedge, bool revers)
{
return this->connectBasis(edge,neighbor,nedge,revers);
}
bool ASMs2D::connectBasis (int edge, ASMs2D& neighbor, int nedge, bool revers,
int basis, int slave, int master)
{
// Set up the slave node numbers for this surface patch
int n1, n2;
if (!this->getSize(n1,n2)) return false;
int node = 1, i1 = 0;
if (!this->getSize(n1,n2,basis)) return false;
int node = slave+1, i1 = 0;
switch (edge)
{
case 2: // Positive I-direction
node = n1;
node += n1-1;
case 1: // Negative I-direction
i1 = n1;
n1 = n2;
break;
case 4: // Positive J-direction
node = n1*(n2-1)+1;
node += n1*(n2-1);
case 3: // Negative J-direction
i1 = 1;
break;
@ -388,20 +391,20 @@ bool ASMs2D::connectPatch (int edge, ASMs2D& neighbor, int nedge, bool rev)
// Set up the master node numbers for the neighboring surface patch
if (!neighbor.getSize(n1,n2)) return false;
node = 1; i1 = 0;
if (!neighbor.getSize(n1,n2,basis)) return false;
node = master+1; i1 = 0;
switch (nedge)
{
case 2: // Positive I-direction
node = n1;
node += n1-1;
case 1: // Negative I-direction
i1 = n1;
n1 = n2;
break;
case 4: // Positive J-direction
node = n1*(n2-1)+1;
node += n1*(n2-1);
case 3: // Negative J-direction
i1 = 1;
break;
@ -422,7 +425,7 @@ bool ASMs2D::connectPatch (int edge, ASMs2D& neighbor, int nedge, bool rev)
const double xtol = 1.0e-4;
for (i = 0; i < n1; i++, node += i1)
{
int k = rev ? n1-i-1 : i;
int k = revers ? n1-i-1 : i;
if (!neighbor.getCoord(node).equal(this->getCoord(slaveNodes[k]),xtol))
{
std::cerr <<" *** ASMs2D::connectPatch: Non-matching nodes "
@ -440,10 +443,11 @@ bool ASMs2D::connectPatch (int edge, ASMs2D& neighbor, int nedge, bool rev)
}
void ASMs2D::closeEdges (int dir)
void ASMs2D::closeEdges (int dir, int basis, int master)
{
int n1, n2, master = 1;
if (!this->getSize(n1,n2)) return;
int n1, n2;
if (basis < 1) basis = 1;
if (!this->getSize(n1,n2,basis)) return;
switch (dir)
{
@ -1111,7 +1115,6 @@ int ASMs2D::evalPoint (const double* xi, double* param, Vec3& X) const
}
bool ASMs2D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const
{
if (!surf) return false;

View File

@ -67,11 +67,9 @@ public:
};
//! \brief Constructor creating an instance by reading the given file.
ASMs2D(const char* fileName, unsigned char n_s = 2, unsigned char n_f = 2);
ASMs2D(const char* fName = 0, unsigned char n_s = 2, unsigned char n_f = 2);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs2D(std::istream& is, unsigned char n_s = 2, unsigned char n_f = 2);
//! \brief Default constructor creating an empty patch.
ASMs2D(unsigned char n_s = 2, unsigned char n_f = 2);
//! \brief Empty destructor.
virtual ~ASMs2D() {}
@ -124,12 +122,8 @@ public:
bool raiseOrder(int ru, int rv);
// Various methods for preprocessing of boundary conditions
// ========================================================
//! \brief Makes two opposite boundary edges periodic.
//! \param[in] dir Parameter direction defining the periodic edges
void closeEdges(int dir);
// Various methods for preprocessing of boundary conditions and patch topology
// ===========================================================================
//! \brief Constrains all DOFs on a given boundary edge.
//! \param[in] dir Parameter direction defining the edge to constrain
@ -165,7 +159,14 @@ public:
//! \param neighbor The neighbor patch
//! \param[in] nedge Local edge index of neighbor patch, in range [1,4]
//! \param[in] revers Indicates whether the two edges have opposite directions
bool connectPatch(int edge, ASMs2D& neighbor, int nedge, bool revers = false);
virtual bool connectPatch(int edge, ASMs2D& neighbor, int nedge,
bool revers = false);
//! \brief Makes two opposite boundary edges periodic.
//! \param[in] dir Parameter direction defining the periodic edges
//! \param[in] basis Which basis to connect (mixed methods), 0 means both
//! \param[in] master 1-based index of the first master node in this basis
virtual void closeEdges(int dir, int basis = 0, int master = 1);
// Methods for integration of finite element quantities.
@ -235,9 +236,11 @@ public:
//! \param[in] integrand Object with problem-specific data and methods
//! \param[in] npe Number of visualization nodes over each knot span
//!
//! \details If \a npe is NULL, the solution is evaluated at the Greville
//! points and then projected onto the spline basis to obtain the control
//! point values, which then are returned through \a sField.
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! If \a npe is NULL, the solution is evaluated at the Greville points and
//! then projected onto the spline basis to obtain the control point values,
//! which then are returned through \a sField.
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const int* npe = 0) const;
@ -254,8 +257,10 @@ public:
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
//!
//! \details When \a regular is \e true, it is assumed that the parameter
//! value array \a gpar forms a regular tensor-product point grid of dimension
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! When \a regular is \e true, it is assumed that the parameter value array
//! \a gpar forms a regular tensor-product point grid of dimension
//! \a gpar[0].size() \a X \a gpar[1].size().
//! Otherwise, we assume that it contains the \a u and \a v parameters
//! directly for each sampling point.
@ -267,6 +272,17 @@ protected:
// Internal utility methods
// ========================
//! \brief Connects all matching nodes on two adjacent boundary edges.
//! \param[in] edge Local edge index of this patch, in range [1,4]
//! \param neighbor The neighbor patch
//! \param[in] nedge Local edge index of neighbor patch, in range [1,4]
//! \param[in] revers Indicates whether the two edges have opposite directions
//! \param[in] basis Which basis to connect the nodes for (mixed methods)
//! \param[in] slave 0-based index of the first slave node in this basis
//! \param[in] master 0-based index of the first master node in this basis
bool connectBasis(int edge, ASMs2D& neighbor, int nedge, bool revers,
int basis = 1, int slave = 0, int master = 0);
//! \brief Calculates parameter values for visualization nodal points.
//! \param[out] prm Parameter values in given direction for all points
//! \param[in] dir Parameter direction (0,1)

View File

@ -27,11 +27,9 @@ class ASMs2DLag : public ASMs2D
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs2DLag(const char* fileName, unsigned char n_s = 2, unsigned char n_f = 2);
ASMs2DLag(const char* fNam = 0, unsigned char n_s = 2, unsigned char n_f = 2);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs2DLag(std::istream& is, unsigned char n_s = 2, unsigned char n_f = 2);
//! \brief Default constructor creating an empty patch.
ASMs2DLag(unsigned char n_s = 2, unsigned char n_f = 2) : ASMs2D(n_s,n_f) {}
//! \brief Empty destructor.
virtual ~ASMs2DLag() {}
@ -104,8 +102,9 @@ public:
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
virtual bool evalSolution(Matrix& sField, const Vector& locSol,
const RealArray* gpar, bool = true) const;
const RealArray* gpar, bool regular = true) const;
//! \brief Evaluates the secondary solution field at all visualization points.
//! \details The number of visualization points is the same as the order of
@ -119,8 +118,9 @@ public:
//! \param[out] sField Solution field
//! \param[in] integrand Object with problem-specific data and methods
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const RealArray* gpar, bool = true) const;
const RealArray* gpar, bool regular = true) const;
protected:

View File

@ -1,4 +1,4 @@
// $Id: ASMs2DSpec.h,v 1.4 2010-10-05 07:25:25 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMs2DSpec.h
@ -26,14 +26,11 @@ class ASMs2DSpec : public ASMs2DLag
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs2DSpec(const char* fileName, unsigned char n_s = 2, unsigned char n_f = 2)
: ASMs2DLag(fileName,n_s,n_f) {}
ASMs2DSpec(const char* fNam = 0, unsigned char n_s = 2, unsigned char n_f = 2)
: ASMs2DLag(fNam,n_s,n_f) {}
//! \brief Constructor creating an instance by reading the given input stream.
ASMs2DSpec(std::istream& is, unsigned char n_s = 2, unsigned char n_f = 2)
: ASMs2DLag(is,n_s,n_f) {}
//! \brief Default constructor creating an empty patch.
ASMs2DSpec(unsigned char n_s = 2, unsigned char n_f = 2)
: ASMs2DLag(n_s,n_f) {}
//! \brief Empty destructor.
virtual ~ASMs2DSpec() {}

View File

@ -26,9 +26,9 @@
#include "Vec3.h"
ASMs2Dmx::ASMs2Dmx (const char* fileName, unsigned char n_s,
ASMs2Dmx::ASMs2Dmx (const char* fName, unsigned char n_s,
char n_f1, unsigned char n_f2)
: ASMs2D(fileName, n_s), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1, n_f2, n_f1 < 0)
: ASMs2D(fName,n_s), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1, n_f2, n_f1 < 0)
{
basis1 = basis2 = 0;
nf = nf1 + nf2;
@ -37,15 +37,7 @@ ASMs2Dmx::ASMs2Dmx (const char* fileName, unsigned char n_s,
ASMs2Dmx::ASMs2Dmx (std::istream& is, unsigned char n_s,
char n_f1, unsigned char n_f2)
: ASMs2D(is, n_s), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1, n_f2, n_f1 < 0)
{
basis1 = basis2 = 0;
nf = nf1 + nf2;
}
ASMs2Dmx::ASMs2Dmx (unsigned char n_s, char n_f1, unsigned char n_f2)
: ASMs2D(n_s), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1, n_f2, n_f1 < 0)
: ASMs2D(is,n_s), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1, n_f2, n_f1 < 0)
{
basis1 = basis2 = 0;
nf = nf1 + nf2;
@ -84,14 +76,21 @@ unsigned char ASMs2Dmx::getNodalDOFs (size_t inod) const
void ASMs2Dmx::initMADOF (const int* sysMadof)
{
this->init(MLGN,sysMadof);
this->initMx(MLGN,sysMadof);
}
void ASMs2Dmx::extractNodeVec (const Vector& globRes, Vector& nodeVec,
unsigned char) const
{
this->extrNodeVec(globRes,nodeVec);
this->extractNodeVecMx(globRes,nodeVec);
}
bool ASMs2Dmx::getSolution (Matrix& sField, const Vector& locSol,
const IntVec& nodes) const
{
return this->getSolutionMx(sField,locSol,nodes);
}
@ -269,6 +268,23 @@ bool ASMs2Dmx::generateFEMTopology ()
}
bool ASMs2Dmx::connectPatch (int edge, ASMs2D& neighbor, int nedge, bool revers)
{
ASMs2Dmx* neighMx = dynamic_cast<ASMs2Dmx*>(&neighbor);
if (!neighMx) return false;
return this->connectBasis(edge,neighbor,nedge,revers,1,0,0)
&& this->connectBasis(edge,neighbor,nedge,revers,2,nb1,neighMx->nb1);
}
void ASMs2Dmx::closeEdges (int dir, int, int)
{
this->ASMs2D::closeEdges(dir,1,1);
this->ASMs2D::closeEdges(dir,2,nb1+1);
}
bool ASMs2Dmx::getElementCoordinates (Matrix& X, int iel) const
{
#ifdef INDEX_CHECK
@ -636,6 +652,39 @@ bool ASMs2Dmx::integrate (Integrand& integrand, int lIndex,
}
int ASMs2Dmx::evalPoint (const double* xi, double* param, Vec3& X) const
{
if (!surf) return -2;
param[0] = (1.0-xi[0])*surf->startparam_u() + xi[0]*surf->endparam_u();
param[1] = (1.0-xi[1])*surf->startparam_v() + xi[1]*surf->endparam_v();
Go::Point X0;
surf->point(X0,param[0],param[1]);
for (unsigned char d = 0; d < nsd; d++)
X[d] = X0[d];
// Check if this point matches any of the basis1 control points (nodes)
Vec3 Xnod;
size_t inod = 1;
RealArray::const_iterator cit = basis1->coefs_begin();
for (int i = 0; cit != basis1->coefs_end(); cit++, i++)
{
if (i < nsd) Xnod[i] = *cit;
if (i+1 == basis1->dimension())
if (X.equal(Xnod,0.001))
return inod;
else
{
inod++;
i = -1;
}
}
return 0;
}
bool ASMs2Dmx::evalSolution (Matrix& sField, const Vector& locSol,
const RealArray* gpar, bool regular) const
{

View File

@ -32,13 +32,11 @@ class ASMs2Dmx : public ASMs2D, private ASMmxBase
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs2Dmx(const char* fileName, unsigned char n_s = 2,
ASMs2Dmx(const char* fName = 0, unsigned char n_s = 2,
char n_f1 = 2, unsigned char n_f2 = 1);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs2Dmx(std::istream& is, unsigned char n_s = 2,
char n_f1 = 2, unsigned char n_f2 = 1);
//! \brief Default constructor creating an empty patch.
ASMs2Dmx(unsigned char n_s = 2, char n_f1 = 2, unsigned char n_f2 = 1);
//! \brief Empty destructor.
virtual ~ASMs2Dmx() {}
@ -67,6 +65,18 @@ public:
//! \brief Initializes the patch level MADOF array for mixed problems.
virtual void initMADOF(const int* sysMadof);
//! \brief Connects all matching nodes on two adjacent boundary edges.
//! \param[in] edge Local edge index of this patch, in range [1,4]
//! \param neighbor The neighbor patch
//! \param[in] nedge Local edge index of neighbor patch, in range [1,4]
//! \param[in] revers Indicates whether the two edges have opposite directions
virtual bool connectPatch(int edge, ASMs2D& neighbor, int nedge,
bool revers = false);
//! \brief Makes two opposite boundary edges periodic.
//! \param[in] dir Parameter direction defining the periodic edges
virtual void closeEdges(int dir, int = 0, int = 1);
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.
@ -95,6 +105,21 @@ public:
// Post-processing methods
// =======================
//! \brief Evaluates the geometry at a specified point.
//! \param[in] xi Dimensionless parameters in range [0.0,1.0] of the point
//! \param[out] param The (u,v) parameters of the point in knot-span domain
//! \param[out] X The Cartesian coordinates of the point
//! \return Local node number within the patch that matches the point, if any
//! \return 0 if no node (control point) matches this point
virtual int evalPoint(const double* xi, double* param, Vec3& X) const;
//! \brief Extract the primary solution field at the specified nodes.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
virtual bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
//! \brief Evaluates the primary solution field at the given points.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
@ -115,8 +140,10 @@ public:
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
//!
//! \details When \a regular is \e true, it is assumed that the parameter
//! value array \a gpar forms a regular tensor-product point grid of dimension
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! When \a regular is \e true, it is assumed that the parameter value array
//! \a gpar forms a regular tensor-product point grid of dimension
//! \a gpar[0].size() \a X \a gpar[1].size().
//! Otherwise, we assume that it contains the \a u and \a v parameters
//! directly for each sampling point.

View File

@ -25,9 +25,9 @@
#include "Vec3Oper.h"
ASMs2DmxLag::ASMs2DmxLag (const char* fileName, unsigned char n_s,
ASMs2DmxLag::ASMs2DmxLag (const char* fName, unsigned char n_s,
unsigned char n_f1, unsigned char n_f2)
: ASMs2DLag(fileName,n_s), ASMmxBase(n_f1,n_f2)
: ASMs2DLag(fName,n_s), ASMmxBase(n_f1,n_f2)
{
nx2 = ny2 = 0;
nf = nf1 + nf2;
@ -43,15 +43,6 @@ ASMs2DmxLag::ASMs2DmxLag (std::istream& is, unsigned char n_s,
}
ASMs2DmxLag::ASMs2DmxLag (unsigned char n_s,
unsigned char n_f1, unsigned char n_f2)
: ASMs2DLag(n_s), ASMmxBase(n_f1,n_f2)
{
nx2 = ny2 = 0;
nf = nf1 + nf2;
}
void ASMs2DmxLag::clear ()
{
nx2 = ny2 = 0;
@ -79,14 +70,21 @@ unsigned char ASMs2DmxLag::getNodalDOFs (size_t inod) const
void ASMs2DmxLag::initMADOF (const int* sysMadof)
{
this->init(MLGN,sysMadof);
this->initMx(MLGN,sysMadof);
}
void ASMs2DmxLag::extractNodeVec (const Vector& globRes, Vector& nodeVec,
unsigned char) const
{
this->extrNodeVec(globRes,nodeVec);
this->extractNodeVecMx(globRes,nodeVec);
}
bool ASMs2DmxLag::getSolution (Matrix& sField, const Vector& locSol,
const IntVec& nodes) const
{
return this->getSolutionMx(sField,locSol,nodes);
}
@ -152,6 +150,24 @@ bool ASMs2DmxLag::generateFEMTopology ()
}
bool ASMs2DmxLag::connectPatch (int edge, ASMs2D& neighbor,
int nedge, bool revers)
{
ASMs2DmxLag* neighMx = dynamic_cast<ASMs2DmxLag*>(&neighbor);
if (!neighMx) return false;
return this->connectBasis(edge,neighbor,nedge,revers,1,0,0)
&& this->connectBasis(edge,neighbor,nedge,revers,2,nb1,neighMx->nb1);
}
void ASMs2DmxLag::closeEdges (int dir, int, int)
{
this->ASMs2D::closeEdges(dir,1,1);
this->ASMs2D::closeEdges(dir,2,nb1+1);
}
bool ASMs2DmxLag::getSize (int& n1, int& n2, int basis) const
{
if (basis != 2)

View File

@ -1,4 +1,4 @@
// $Id: ASMs2DmxLag.h,v 1.1 2010-12-29 18:41:38 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMs2DmxLag.h
@ -29,7 +29,7 @@ class ASMs2DmxLag : public ASMs2DLag, private ASMmxBase
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs2DmxLag(const char* fileName, unsigned char n_s = 2,
ASMs2DmxLag(const char* fName = 0, unsigned char n_s = 2,
unsigned char n_f1 = 2, unsigned char n_f2 = 1);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs2DmxLag(std::istream& is, unsigned char n_s = 2,
@ -61,6 +61,18 @@ public:
//! \brief Initializes the patch level MADOF array for mixed problems.
virtual void initMADOF(const int* sysMadof);
//! \brief Connects all matching nodes on two adjacent boundary edges.
//! \param[in] edge Local edge index of this patch, in range [1,4]
//! \param neighbor The neighbor patch
//! \param[in] nedge Local edge index of neighbor patch, in range [1,4]
//! \param[in] revers Indicates whether the two edges have opposite directions
virtual bool connectPatch(int edge, ASMs2D& neighbor, int nedge,
bool revers = false);
//! \brief Makes two opposite boundary edges periodic.
//! \param[in] dir Parameter direction defining the periodic edges
virtual void closeEdges(int dir, int = 0, int = 1);
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.
@ -89,6 +101,13 @@ public:
// Post-processing methods
// =======================
//! \brief Extract the primary solution field at the specified nodes.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
virtual bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
//! \brief Evaluates the primary solution field at all visualization points.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector in DOF-order

View File

@ -30,17 +30,18 @@
#include <fstream>
ASMs3D::ASMs3D (const char* fileName, bool checkRHS, unsigned char n_f)
ASMs3D::ASMs3D (const char* fName, bool checkRHS, unsigned char n_f)
: ASMstruct(3,3,n_f), svol(0), swapW(false)
{
std::cout <<"\nReading patch file "<< fileName << std::endl;
std::ifstream is(fileName);
if (!is.good())
std::cerr <<" *** ASMs3D: Failure opening patch file"<< std::endl;
else if (this->read(is) && checkRHS)
this->checkRightHandSystem();
geo = svol;
if (fName)
{
std::cout <<"\nReading patch file "<< fName << std::endl;
std::ifstream is(fName);
if (!is.good())
std::cerr <<" *** ASMs3D: Failure opening patch file"<< std::endl;
else if (this->read(is) && checkRHS)
this->checkRightHandSystem();
}
}
@ -49,8 +50,6 @@ ASMs3D::ASMs3D (std::istream& is, bool checkRHS, unsigned char n_f)
{
if (this->read(is) && checkRHS)
this->checkRightHandSystem();
geo = svol;
}
@ -82,9 +81,12 @@ bool ASMs3D::read (std::istream& is)
{
std::cerr <<" *** ASMs3D::read: Invalid spline volume patch, dim="
<< svol->dimension() << std::endl;
delete svol;
svol = 0;
return false;
}
geo = svol;
return true;
}
@ -457,16 +459,23 @@ bool ASMs3D::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
if (neighbor.swapW && face > 4) // Account for swapped parameter direction
nface = 11-nface;
return this->connectBasis(face,neighbor,nface,norient);
}
bool ASMs3D::connectBasis (int face, ASMs3D& neighbor, int nface, int norient,
int basis, int slave, int master)
{
// Set up the slave node numbers for this volume patch
int n1, n2, n3;
if (!this->getSize(n1,n2,n3,1)) return false;
int node = 1, i1 = 0, i2 = 0;
if (!this->getSize(n1,n2,n3,basis)) return false;
int node = slave+1, i1 = 0, i2 = 0;
switch (face)
{
case 2: // Positive I-direction
node = n1;
node += n1-1;
case 1: // Negative I-direction
i1 = n1;
n1 = n2;
@ -474,7 +483,7 @@ bool ASMs3D::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
break;
case 4: // Positive J-direction
node = n1*(n2-1)+1;
node += n1*(n2-1);
case 3: // Negative J-direction
i2 = n1*(n2-1);
i1 = 1;
@ -482,7 +491,7 @@ bool ASMs3D::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
break;
case 6: // Positive K-direction
node = n1*n2*(n3-1)+1;
node += n1*n2*(n3-1);
case 5: // Negative K-direction
i1 = 1;
break;
@ -501,13 +510,13 @@ bool ASMs3D::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
// Set up the master node numbers for the neighboring volume patch
if (!neighbor.getSize(n1,n2,n3,1)) return false;
node = 1; i1 = i2 = 0;
if (!neighbor.getSize(n1,n2,n3,basis)) return false;
node = master+1; i1 = i2 = 0;
switch (nface)
{
case 2: // Positive I-direction
node = n1;
node += n1-1;
case 1: // Negative I-direction
i1 = n1;
n1 = n2;
@ -515,7 +524,7 @@ bool ASMs3D::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
break;
case 4: // Positive J-direction
node = n1*(n2-1)+1;
node += n1*(n2-1);
case 3: // Negative J-direction
i2 = n1*(n2-1);
i1 = 1;
@ -523,7 +532,7 @@ bool ASMs3D::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
break;
case 6: // Positive K-direction
node = n1*n2*(n3-1)+1;
node += n1*n2*(n3-1);
case 5: // Negative K-direction
i1 = 1;
break;
@ -583,10 +592,11 @@ bool ASMs3D::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
}
void ASMs3D::closeFaces (int dir)
void ASMs3D::closeFaces (int dir, int basis, int master)
{
int n1, n2, n3, master = 1;
if (!this->getSize(n1,n2,n3,1)) return;
int n1, n2, n3;
if (basis < 1) basis = 1;
if (!this->getSize(n1,n2,n3,basis)) return;
switch (dir)
{

View File

@ -86,11 +86,9 @@ public:
};
//! \brief Constructor creating an instance by reading the given file.
ASMs3D(const char* fileName, bool checkRHS = false, unsigned char n_f = 3);
ASMs3D(const char* fName = 0, bool checkRHS = false, unsigned char n_f = 3);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs3D(std::istream& is, bool checkRHS = false, unsigned char n_f = 3);
//! \brief Default constructor creating an empty patch.
ASMs3D(unsigned char n_f = 3) : ASMstruct(3,3,n_f), svol(0), swapW(false) {}
//! \brief Empty destructor.
virtual ~ASMs3D() {}
@ -148,12 +146,8 @@ public:
bool raiseOrder(int ru, int rv, int rw);
// Various methods for preprocessing of boundary conditions
// ========================================================
//! \brief Makes two opposite boundary faces periodic.
//! \param[in] dir Parameter direction defining the periodic faces
void closeFaces(int dir);
// Various methods for preprocessing of boundary conditions and patch topology
// ===========================================================================
//! \brief Constrains all DOFs on a given boundary face.
//! \param[in] dir Parameter direction defining the face to constrain
@ -222,7 +216,14 @@ public:
//! - left digit = 1: The u and v parameters of the neighbor face are swapped
//! - middle digit = 1: Parameter \a u in neighbor patch face is reversed
//! - right digit = 1: Parameter \a v in neighbor patch face is reversed
bool connectPatch(int face, ASMs3D& neighbor, int nface, int norient = 0);
virtual bool connectPatch(int face, ASMs3D& neighbor, int nface,
int norient = 0);
//! \brief Makes two opposite boundary faces periodic.
//! \param[in] dir Parameter direction defining the periodic faces
//! \param[in] basis Which basis to connect (mixed methods), 0 means both
//! \param[in] master 1-based index of the first master node in this basis
virtual void closeFaces(int dir, int basis = 0, int master = 1);
// Methods for integration of finite element quantities.
@ -300,9 +301,11 @@ public:
//! \param[in] integrand Object with problem-specific data and methods
//! \param[in] npe Number of visualization nodes over each knot span
//!
//! \details If \a npe is NULL, the solution is evaluated at the Greville
//! points and then projected onto the spline basis to obtain the control
//! point values, which then are returned through \a sField.
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! If \a npe is NULL, the solution is evaluated at the Greville points and
//! then projected onto the spline basis to obtain the control point values,
//! which then are returned through \a sField.
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const int* npe = 0) const;
@ -318,8 +321,10 @@ public:
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
//!
//! \details When \a regular is \e true, it is assumed that the parameter
//! value array \a gpar forms a regular tensor-product point grid of dimension
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! When \a regular is \e true, it is assumed that the parameter value array
//! \a gpar forms a regular tensor-product point grid of dimension
//! \a gpar[0].size() \a X \a gpar[1].size() \a X \a gpar[2].size().
//! Otherwise, we assume that it contains the \a u, \a v and \a w parameters
//! directly for each sampling point.
@ -331,6 +336,17 @@ protected:
// Internal utility methods
// ========================
//! \brief Connects all matching nodes on two adjacent boundary faces.
//! \param[in] face Local face index of this patch, in range [1,6]
//! \param neighbor The neighbor patch
//! \param[in] nface Local face index of neighbor patch, in range [1,6]
//! \param[in] norient Relative face orientation flag (see \a connectPatch)
//! \param[in] basis Which basis to connect the nodes for (mixed methods)
//! \param[in] slave 0-based index of the first slave node in this basis
//! \param[in] master 0-based index of the first master node in this basis
bool connectBasis(int edge, ASMs3D& neighbor, int nedge, int norient,
int basis = 1, int slave = 0, int master = 0);
//! \brief Calculates parameter values for visualization nodal points.
//! \param[out] prm Parameter values in given direction for all points
//! \param[in] dir Parameter direction (0,1,2)

View File

@ -27,11 +27,9 @@ class ASMs3DLag : public ASMs3D
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs3DLag(const char* fileName, bool checkRHS = false, unsigned char n_f = 3);
ASMs3DLag(const char* fNam = 0, bool checkRHS = false, unsigned char n_f = 3);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs3DLag(std::istream& is, bool checkRHS = false, unsigned char n_f = 3);
//! \brief Default constructor creating an empty patch.
ASMs3DLag(unsigned char n_f = 3) : ASMs3D(n_f) {}
//! \brief Empty destructor.
virtual ~ASMs3DLag() {}
@ -112,8 +110,9 @@ public:
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
virtual bool evalSolution(Matrix& sField, const Vector& locSol,
const RealArray* gpar, bool = true) const;
const RealArray* gpar, bool regular = true) const;
//! \brief Evaluates the secondary solution field at all visualization points.
//! \details The number of visualization points is the same as the order of
@ -127,8 +126,9 @@ public:
//! \param[out] sField Solution field
//! \param[in] integrand Object with problem-specific data and methods
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const RealArray* gpar, bool = true) const;
const RealArray* gpar, bool regular = true) const;
protected:

View File

@ -1,4 +1,4 @@
// $Id: ASMs3DSpec.h,v 1.6 2010-10-17 13:10:47 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMs3DSpec.h
@ -26,13 +26,11 @@ class ASMs3DSpec : public ASMs3DLag
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs3DSpec(const char* fileName, bool checkRHS = false, unsigned char n_f = 3)
: ASMs3DLag(fileName,checkRHS,n_f) {}
ASMs3DSpec(const char* fNam = 0, bool checkRHS = false, unsigned char n_f = 3)
: ASMs3DLag(fNam,checkRHS,n_f) {}
//! \brief Constructor creating an instance by reading the given input stream.
ASMs3DSpec(std::istream& is, bool checkRHS = false, unsigned char n_f = 3)
: ASMs3DLag(is,checkRHS,n_f) {}
//! \brief Default constructor creating an empty patch.
ASMs3DSpec(unsigned char n_f = 3) : ASMs3DLag(n_f) {}
//! \brief Empty destructor.
virtual ~ASMs3DSpec() {}

View File

@ -26,9 +26,9 @@
#include "Vec3.h"
ASMs3Dmx::ASMs3Dmx (const char* fileName, bool checkRHS,
ASMs3Dmx::ASMs3Dmx (const char* fName, bool checkRHS,
char n_f1, unsigned char n_f2)
: ASMs3D(fileName,checkRHS), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1,n_f2, n_f1 < 0)
: ASMs3D(fName,checkRHS), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1,n_f2, n_f1 < 0)
{
basis1 = basis2 = 0;
nf = nf1 + nf2;
@ -44,14 +44,6 @@ ASMs3Dmx::ASMs3Dmx (std::istream& is, bool checkRHS,
}
ASMs3Dmx::ASMs3Dmx (bool checkRHS, char n_f1, unsigned char n_f2)
: ASMs3D(checkRHS), ASMmxBase(n_f1 < 0 ? -n_f1 : n_f1, n_f2, n_f1 < 0)
{
basis1 = basis2 = 0;
nf = nf1 + nf2;
}
void ASMs3Dmx::clear ()
{
// Erase the spline data
@ -84,14 +76,21 @@ unsigned char ASMs3Dmx::getNodalDOFs (size_t inod) const
void ASMs3Dmx::initMADOF (const int* sysMadof)
{
this->init(MLGN,sysMadof);
this->initMx(MLGN,sysMadof);
}
void ASMs3Dmx::extractNodeVec (const Vector& globRes, Vector& nodeVec,
unsigned char) const
{
this->extrNodeVec(globRes,nodeVec);
this->extractNodeVecMx(globRes,nodeVec);
}
bool ASMs3Dmx::getSolution (Matrix& sField, const Vector& locSol,
const IntVec& nodes) const
{
return this->getSolutionMx(sField,locSol,nodes);
}
@ -289,6 +288,29 @@ bool ASMs3Dmx::generateFEMTopology ()
}
bool ASMs3Dmx::connectPatch (int face, ASMs3D& neighbor, int nface, int norient)
{
ASMs3Dmx* neighMx = dynamic_cast<ASMs3Dmx*>(&neighbor);
if (!neighMx) return false;
if (swapW && face > 4) // Account for swapped parameter direction
face = 11-face;
if (neighMx->swapW && face > 4) // Account for swapped parameter direction
nface = 11-nface;
return this->connectBasis(face,neighbor,nface,norient,1,0,0)
&& this->connectBasis(face,neighbor,nface,norient,2,nb1,neighMx->nb1);
}
void ASMs3Dmx::closeFaces (int dir, int, int)
{
this->ASMs3D::closeFaces(dir,1,1);
this->ASMs3D::closeFaces(dir,2,nb1+1);
}
bool ASMs3Dmx::getElementCoordinates (Matrix& X, int iel) const
{
#ifdef INDEX_CHECK
@ -697,6 +719,40 @@ bool ASMs3Dmx::integrate (Integrand& integrand, int lIndex,
}
int ASMs3Dmx::evalPoint (const double* xi, double* param, Vec3& X) const
{
if (!svol) return -3;
int i;
for (i = 0; i < 3; i++)
param[i] = (1.0-xi[i])*svol->startparam(i) + xi[i]*svol->endparam(i);
Go::Point X0;
svol->point(X0,param[0],param[1],param[2]);
for (i = 0; i < 3 && i < svol->dimension(); i++)
X[i] = X0[i];
// Check if this point matches any of the basis1 control points (nodes)
Vec3 Xnod;
size_t inod = 1;
RealArray::const_iterator cit = basis1->coefs_begin();
for (i = 0; cit != basis1->coefs_end(); cit++, i++)
{
if (i < 3) Xnod[i] = *cit;
if (i+1 == basis1->dimension())
if (X.equal(Xnod,0.001))
return inod;
else
{
inod++;
i = -1;
}
}
return 0;
}
bool ASMs3Dmx::evalSolution (Matrix& sField, const Vector& locSol,
const RealArray* gpar, bool regular) const
{

View File

@ -32,13 +32,11 @@ class ASMs3Dmx : public ASMs3D, private ASMmxBase
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs3Dmx(const char* fileName, bool checkRHS = false,
ASMs3Dmx(const char* fName = 0, bool checkRHS = false,
char n_f1 = 3, unsigned char n_f2 = 1);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs3Dmx(std::istream& is, bool checkRHS = false,
char n_f1 = 3, unsigned char n_f2 = 1);
//! \brief Default constructor creating an empty patch.
ASMs3Dmx(bool checkRHS = false, char n_f1 = 3, unsigned char n_f2 = 1);
//! \brief Empty destructor.
virtual ~ASMs3Dmx() {}
@ -67,6 +65,18 @@ public:
//! \brief Initializes the patch level MADOF array for mixed problems.
virtual void initMADOF(const int* sysMadof);
//! \brief Connects all matching nodes on two adjacent boundary faces.
//! \param[in] face Local face index of this patch, in range [1,6]
//! \param neighbor The neighbor patch
//! \param[in] nface Local face index of neighbor patch, in range [1,6]
//! \param[in] norient Relative face orientation flag (see class ASMs3D)
virtual bool connectPatch(int face, ASMs3D& neighbor, int nface,
int norient = 0);
//! \brief Makes two opposite boundary faces periodic.
//! \param[in] dir Parameter direction defining the periodic faces
virtual void closeFaces(int dir, int = 0, int = 1);
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.
@ -95,6 +105,21 @@ public:
// Post-processing methods
// =======================
//! \brief Evaluates the geometry at a specified point.
//! \param[in] xi Dimensionless parameters in range [0.0,1.0] of the point
//! \param[out] param The (u,v,w) parameters of the point in knot-span domain
//! \param[out] X The Cartesian coordinates of the point
//! \return Local node number within the patch that matches the point, if any
//! \return 0 if no node (control point) matches this point
virtual int evalPoint(const double* xi, double* param, Vec3& X) const;
//! \brief Extract the primary solution field at the specified nodes.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
virtual bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
//! \brief Evaluates the primary solution field at the given points.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
@ -115,8 +140,10 @@ public:
//! \param[in] gpar Parameter values of the result sampling points
//! \param[in] regular Flag indicating how the sampling points are defined
//!
//! \details When \a regular is \e true, it is assumed that the parameter
//! value array \a gpar forms a regular tensor-product point grid of dimension
//! \details The secondary solution is derived from the primary solution,
//! which is assumed to be stored within the \a integrand for current patch.
//! When \a regular is \e true, it is assumed that the parameter value array
//! \a gpar forms a regular tensor-product point grid of dimension
//! \a gpar[0].size() \a X \a gpar[1].size() \a X \a gpar[2].size().
//! Otherwise, we assume that it contains the \a u, \a v and \a w parameters
//! directly for each sampling point.

View File

@ -25,9 +25,9 @@
#include "Vec3Oper.h"
ASMs3DmxLag::ASMs3DmxLag (const char* fileName, bool checkRHS,
ASMs3DmxLag::ASMs3DmxLag (const char* fName, bool checkRHS,
unsigned char n_f1, unsigned char n_f2)
: ASMs3DLag(fileName,checkRHS), ASMmxBase(n_f1,n_f2)
: ASMs3DLag(fName,checkRHS), ASMmxBase(n_f1,n_f2)
{
nx2 = ny2 = nz2 = 0;
nf = nf1 + nf2;
@ -43,15 +43,6 @@ ASMs3DmxLag::ASMs3DmxLag (std::istream& is, bool checkRHS,
}
ASMs3DmxLag::ASMs3DmxLag (bool checkRHS,
unsigned char n_f1, unsigned char n_f2)
: ASMs3DLag(checkRHS), ASMmxBase(n_f1,n_f2)
{
nx2 = ny2 = nz2 = 0;
nf = nf1 + nf2;
}
void ASMs3DmxLag::clear ()
{
nx2 = ny2 = nz2 = 0;
@ -79,14 +70,21 @@ unsigned char ASMs3DmxLag::getNodalDOFs (size_t inod) const
void ASMs3DmxLag::initMADOF (const int* sysMadof)
{
this->init(MLGN,sysMadof);
this->initMx(MLGN,sysMadof);
}
void ASMs3DmxLag::extractNodeVec (const Vector& globRes, Vector& nodeVec,
unsigned char) const
{
this->extrNodeVec(globRes,nodeVec);
this->extractNodeVecMx(globRes,nodeVec);
}
bool ASMs3DmxLag::getSolution (Matrix& sField, const Vector& locSol,
const IntVec& nodes) const
{
return this->getSolutionMx(sField,locSol,nodes);
}
@ -166,6 +164,30 @@ bool ASMs3DmxLag::generateFEMTopology ()
}
bool ASMs3DmxLag::connectPatch (int face, ASMs3D& neighbor,
int nface, int norient)
{
ASMs3DmxLag* neighMx = dynamic_cast<ASMs3DmxLag*>(&neighbor);
if (!neighMx) return false;
if (swapW && face > 4) // Account for swapped parameter direction
face = 11-face;
if (neighMx->swapW && face > 4) // Account for swapped parameter direction
nface = 11-nface;
return this->connectBasis(face,neighbor,nface,norient,1,0,0)
&& this->connectBasis(face,neighbor,nface,norient,2,nb1,neighMx->nb1);
}
void ASMs3DmxLag::closeFaces (int dir, int, int)
{
this->ASMs3D::closeFaces(dir,1,1);
this->ASMs3D::closeFaces(dir,2,nb1+1);
}
bool ASMs3DmxLag::getSize (int& n1, int& n2, int& n3, int basis) const
{
if (basis != 2)

View File

@ -1,4 +1,4 @@
// $Id: ASMs3DmxLag.h,v 1.1 2010-12-29 18:41:39 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMs3DmxLag.h
@ -29,7 +29,7 @@ class ASMs3DmxLag : public ASMs3DLag, private ASMmxBase
{
public:
//! \brief Constructor creating an instance by reading the given file.
ASMs3DmxLag(const char* fileName, bool checkRHS = false,
ASMs3DmxLag(const char* fName = 0, bool checkRHS = false,
unsigned char n_f1 = 3, unsigned char n_f2 = 1);
//! \brief Constructor creating an instance by reading the given input stream.
ASMs3DmxLag(std::istream& is, bool checkRHS = false,
@ -61,6 +61,18 @@ public:
//! \brief Initializes the patch level MADOF array for mixed problems.
virtual void initMADOF(const int* sysMadof);
//! \brief Connects all matching nodes on two adjacent boundary faces.
//! \param[in] face Local face index of this patch, in range [1,6]
//! \param neighbor The neighbor patch
//! \param[in] nface Local face index of neighbor patch, in range [1,6]
//! \param[in] norient Relative face orientation flag (see class ASMs3D)
virtual bool connectPatch(int face, ASMs3D& neighbor, int nface,
int norient = 0);
//! \brief Makes two opposite boundary faces periodic.
//! \param[in] dir Parameter direction defining the periodic faces
virtual void closeFaces(int dir, int = 0, int = 1);
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.
@ -89,6 +101,13 @@ public:
// Post-processing methods
// =======================
//! \brief Extract the primary solution field at the specified nodes.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector local to current patch
//! \param[in] nodes 1-based local node numbers to extract solution for
virtual bool getSolution(Matrix& sField, const Vector& locSol,
const IntVec& nodes) const;
//! \brief Evaluates the primary solution field at all visualization points.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector in DOF-order

View File

@ -1,4 +1,4 @@
// $Id: ASMstruct.h,v 1.8 2010-12-29 18:02:10 kmo Exp $
// $Id$
//==============================================================================
//!
//! \file ASMstruct.h