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:
parent
50011c37b8
commit
eda13b7381
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
// $Id: ASMstruct.h,v 1.8 2010-12-29 18:02:10 kmo Exp $
|
||||
// $Id$
|
||||
//==============================================================================
|
||||
//!
|
||||
//! \file ASMstruct.h
|
||||
|
Loading…
Reference in New Issue
Block a user