added: LR splines

git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@1149 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
kjetijo
2011-09-20 09:45:59 +00:00
committed by Knut Morten Okstad
parent caeee4aadc
commit 85aaeb74eb
8 changed files with 1971 additions and 43 deletions

View File

@@ -51,6 +51,9 @@ FIND_PACKAGE(VTFWriter)
IF(NOT "${DISABLE_HDF5}")
FIND_PACKAGE(HDF5)
ENDIF(NOT "${DISABLE_HDF5}")
IF(NOT "${DISABLE_LRSPLINE}")
FIND_PACKAGE(LRSpline)
ENDIF(NOT "${DISABLE_LRSPLINE}")
# Required libraries
SET(DEPLIBS ${GoTrivariate_LIBRARIES} ${GoTools_LIBRARIES}
@@ -131,6 +134,15 @@ IF(HDF5_LIBRARIES AND HDF5_INCLUDE_DIR)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_HDF5=1")
ENDIF(HDF5_LIBRARIES AND HDF5_INCLUDE_DIR)
IF(LRSpline_LIBRARIES AND LRSpline_INCLUDE_DIRS)
SET(DEPLIBS ${DEPLIBS} ${LRSpline_LIBRARIES})
SET(INCLUDES
${INCLUDES}
${LRSpline_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/src/ASM/LR)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAS_LRSPLINE=1")
ENDIF(LRSpline_LIBRARIES AND LRSpline_INCLUDE_DIRS)
INCLUDE_DIRECTORIES(${INCLUDES})
SET(EXECUTABLE_OUTPUT_PATH bin)
@@ -146,6 +158,9 @@ ENDIF(NOT WIN32)
# Make the IFEM library
FILE(GLOB_RECURSE IFEM_SRCS ${PROJECT_SOURCE_DIR}/src/*.[Cf]
${PROJECT_SOURCE_DIR}/3rdparty/*.C)
IF(NOT(LRSpline_LIBRARIES AND LRSpline_INCLUDE_DIRS))
string(REGEX REPLACE "${PROJECT_SOURCE_DIR}/src/ASM/LR/[^;]*" "" IFEM_SRCS "${IFEM_SRCS}")
ENDIF(NOT(LRSpline_LIBRARIES AND LRSpline_INCLUDE_DIRS))
ADD_LIBRARY(IFEM ${IFEM_SRCS})
# Make some Apps

View File

@@ -0,0 +1,28 @@
IF(LRSpline_INCLUDE_DIRS AND LRSpline_LIBRARIES)
SET(LRSpline_FIND_QUIETLY TRUE)
ENDIF(LRSpline_INCLUDE_DIRS AND LRSpline_LIBRARIES)
UNSET(LRSpline_INCLUDE_DIRS CACHE)
UNSET(LRSpline_LIBRARIES CACHE)
FIND_PATH(LRSpline_INCLUDE_DIRS
NAMES LRSpline/LRSplineSurface.h
PATHS "$ENV{HOME}/include"
"$ENV{HOME}/install/include"
/sima/libs/LRSpline/include
)
FIND_LIBRARY(LRSpline_LIBRARIES
NAMES LRSpline
PATHS "$ENV{HOME}/lib"
"$ENV{HOME}/install/lib"
/sima/libs/LRSpline/lib
PATH_SUFFIXES LRSpline
)
INCLUDE(FindPackageHandleStandardArgs)
IF(LRSpline_LIBRARIES)
find_package_handle_standard_args(LRSpline DEFAULT_MSG
LRSpline_INCLUDE_DIRS LRSpline_LIBRARIES)
ENDIF(LRSpline_LIBRARIES)

1365
src/ASM/LR/ASMu2D.C Normal file

File diff suppressed because it is too large Load Diff

367
src/ASM/LR/ASMu2D.h Normal file
View File

@@ -0,0 +1,367 @@
// $Id: ASMu2D.h 1108 2011-08-23 14:51:03Z kjetijo $
//==============================================================================
//!
//! \file ASMu2D.h
//!
//! \date September 2011
//!
//! \author Kjetil Andre Johannessen / SINTEF
//!
//! \brief Driver for assembly of unstructured 2D spline FE models.
//!
//==============================================================================
#ifndef _ASM_U2D_H
#define _ASM_U2D_H
#include "ASMunstruct.h"
namespace Go {
class SplineSurface;
class BasisDerivsSf;
class BasisDerivsSf2;
}
namespace LR {
class LRSplineSurface;
}
/*!
\brief Driver for assembly of structured 2D spline FE models.
\details This class contains methods common for structured 2D spline patches.
*/
class ASMu2D : public ASMunstruct
{
//! \brief Struct for nodal point data.
struct IJ
{
int I; //!< Index in first parameter direction
int J; //!< Index in second parameter direction
};
// topology-stuff like connecting multiple patches. Will be introduced later
#if 0
//! \brief Struct for edge node definitions.
struct Edge
{
int icnod; //!< Global node number of first interior point along the edge
int incr; //!< Increment in the global numbering along the edge
//! \brief Default constructor.
Edge() { icnod = incr = 0; }
//! \brief Returns \a icnod which then is incremented.
int next();
};
public:
//! \brief Struct with data for definition of global node numbers of a patch.
struct BlockNodes
{
int ibnod[4]; //!< Vertex nodes
Edge edges[4]; //!< Edge nodes
int iinod; //!< Global node number of the first interior node
int inc[2]; //!< Increment in global node numbering in each direction
int nnodI; //!< Number of nodes in parameter direction I
int indxI; //!< Running node index in the local I-direction
//! \brief Default constructor.
BlockNodes() { iinod = inc[0] = inc[1] = 0; indxI = 1; }
//! \brief Returns \a iinod which then is incremented.
int next();
};
#endif
public:
//! \brief Constructor creating an instance by reading the given file.
ASMu2D(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.
ASMu2D(std::istream& is, unsigned char n_s = 2, unsigned char n_f = 2);
//! \brief Empty destructor.
virtual ~ASMu2D() {}
// Methods to access data
// ============================
LR::LRSplineSurface* getSurface() { return lrspline; }
// Methods for model generation
// ============================
//! \brief Generates the finite element topology data for the patch.
//! \details The data generated are the element-to-node connectivity array,
//! the node-to-IJ-index array, as well as global node and element numbers.
virtual bool generateFEMTopology();
//! \brief Clears the contents of the patch, making it empty.
virtual void clear();
//! \brief Returns the global coordinates for the given node.
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Creates an instance by reading the given input stream.
bool read(std::istream&);
//! \brief Writes the geometry of the SplineSurface object to given stream.
virtual bool write(std::ostream&, int = 0) const;
#if 0
//! \brief Assigns new global node numbers for all nodes of the patch.
//! \param nodes Object with global nodes numbers to assign to this patch
//! \param[in] basis Which basis to assign node numbers for in mixed methods
//!
//! \details The global node numbers generated by \a generateFEMTopology are
//! non-unique in the sense that a node that is shared by two (or more)
//! patches along a common interface has a different number in each patch.
//! This method therefore assigns a new global number to each node in the
//! patch. The data provided through the \a nodes argument is sufficient
//! to determine the unique global number under the assumption that they
//! are ordered in the sequence determined by the local orientation of the
//! patch and its edges.
bool assignNodeNumbers();
#endif
//! \brief Progressively refine the diagonal until at least the LR-spline
//! contains at least \a minBasisfunctions basisfunctions
//! \param[in] minBasisfunctions lower bound on number of resulting basis functions
bool diagonalRefine(int minBasisfunctions);
//! \brief Progressively refine the lower left corner until at least the LR-spline
//! contains at least \a minBasisfunctions basisfunctions
//! \param[in] minBasisfunctions lower bound on number of resulting basis functions
bool cornerRefine(int minBasisfunctions);
//! \brief Inserts one (global)line at a time until the LR-spline contains at least
//! \a minBasisfunctions basisfunctions
//! \param[in] minBasisfunctions lower bound on number of resulting basis functions
bool uniformRefine(int minBasisfunctions);
// 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
//! \param[in] dof Which DOFs to constrain at each node on the edge
//! \param[in] code Inhomogeneous dirichlet condition code
void constrainEdge(int dir, int dof = 123, int code = 0);
//! \brief Constrains a corner node identified by the two parameter indices.
//! \param[in] I Parameter index in u-direction
//! \param[in] J Parameter index in v-direction
//! \param[in] dof Which DOFs to constrain at the node
//! \param[in] code Inhomogeneous dirichlet condition code
//!
//! \details The sign of the two indices is used to define whether we want
//! the node at the beginning or the end of that parameter direction.
//! The magnitude of the indices are not used.
void constrainCorner(int I, int J, int dof = 123, int code = 0);
//! \brief Constrains a node identified by two relative parameter values.
//! \param[in] xi Parameter in u-direction
//! \param[in] eta Parameter in v-direction
//! \param[in] dof Which DOFs to constrain at the node
//! \param[in] code Inhomogeneous dirichlet condition code
//!
//! \details The parameter values have to be in the domain [0.0,1.0], where
//! 0.0 means the beginning of the domain and 1.0 means the end. For values
//! in between, the actual index is taken as the integer value closest to
//! \a r*n, where \a r denotes the given relative parameter value,
//! and \a n is the number of nodes along that parameter direction.
void constrainNode(double xi, double eta, int dof = 123, int code = 0);
// More multipatch stuff
#if 0
//! \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, ASMu2D& 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);
#endif
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.
// ====================================================================
//! \brief Evaluates an integral over the interior patch domain.
//! \param integrand Object with problem-specific data and methods
//! \param glbInt The integrated quantity
//! \param[in] time Parameters for nonlinear/time-dependent simulations
//! \param locInt Vector of element-wise contributions to \a glbInt
virtual bool integrate(Integrand& integrand,
GlobalIntegral& glbInt, const TimeDomain& time,
const LintegralVec& locInt = LintegralVec());
//! \brief Evaluates a boundary integral over a patch edge.
//! \param integrand Object with problem-specific data and methods
//! \param[in] lIndex Local index of the boundary edge
//! \param glbInt The integrated quantity
//! \param[in] time Parameters for nonlinear/time-dependent simulations
//! \param locInt Vector of element-wise contributions to \a glbInt
virtual bool integrate(Integrand& integrand, int lIndex,
GlobalIntegral& glbInt, const TimeDomain& time,
const LintegralVec& locInt = LintegralVec());
// 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;
// we'll figure out the postprocessing later
#if 0
//! \brief Creates a quad element model of this patch for visualization.
//! \param[out] grid The generated quadrilateral grid
//! \param[in] npe Number of visualization nodes over each knot span
//! \note The number of element nodes must be set in \a grid on input.
virtual bool tesselate(ElementBlock& grid, const int* npe) const;
//! \brief Evaluates the primary solution field at all visualization points.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector in DOF-order
//! \param[in] npe Number of visualization nodes over each knot span
virtual bool evalSolution(Matrix& sField, const Vector& locSol,
const int* npe) 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
//! \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
//! \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.
virtual bool evalSolution(Matrix& sField, const Vector& locSol,
const RealArray* gpar, bool regular = true) const;
//! \brief Evaluates the secondary solution field at all visualization points.
//! \param[out] sField Solution field
//! \param[in] integrand Object with problem-specific data and methods
//! \param[in] npe Number of visualization nodes over each knot span
//! \param[in] project Flag indicating if the projected solution is wanted
//!
//! \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.
//! If \a npe is not NULL and \a project is \e true, the solution is also
//! projected onto the spline basis, and then evaluated at the \a npe points
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const int* npe = 0, bool project = false) const;
//! \brief Projects the secondary solution field onto the primary basis.
//! \param[in] integrand Object with problem-specific data and methods
Go::SplineSurface* projectSolution(const Integrand& integrand) const;
//! \brief Projects the secondary solution field onto the primary basis.
//! \param[in] integrand Object with problem-specific data and methods
virtual Go::GeomObject* evalSolution(const Integrand& integrand) const;
//! \brief Evaluates the secondary solution field at the given points.
//! \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
//!
//! \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.
virtual bool evalSolution(Matrix& sField, const Integrand& integrand,
const RealArray* gpar, bool regular = true) const;
//! \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)
//! \param[in] nSegSpan Number of visualization segments over each knot-span
virtual bool getGridParameters(RealArray& prm, int dir, int nSegSpan) const;
#endif
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, ASMu2D& neighbor, int nedge, bool revers,
int basis = 1, int slave = 0, int master = 0);
//! \brief Extracts parameter values of the Gauss points in one direction.
//! \param[out] uGP Parameter values in given direction for all points
//! \param[in] dir Parameter direction (0,1)
//! \param[in] nGauss Number of Gauss points along a knot-span
//! \param[in] iel Element index
//! \param[in] xi Dimensionless Gauss point coordinates [-1,1]
void getGaussPointParameters(Vector& uGP, int dir, int nGauss,
int iel, const double* xi) const;
//! \brief Calculates parameter values for the Greville points.
//! \param[out] prm Parameter values in given direction for all points
//! \param[in] dir Parameter direction (0,1)
bool getGrevilleParameters(RealArray& prm, int dir) const;
//! \brief Returns the area in the parameter space for an element.
//! \param[in] iel Element index
double getParametricArea(int iel) const;
//! \brief Returns boundary edge length in the parameter space for an element.
//! \param[in] iel Element index
//! \param[in] dir Local index of the boundary edge
double getParametricLength(int iel, int dir) const;
//! \brief Returns a matrix with nodal coordinates for an element.
//! \param[in] iel Element index
//! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes
//! in one element
virtual bool getElementCoordinates(Matrix& X, int iel) const;
//! \brief Returns a matrix with all nodal coordinates within the patch.
//! \param[out] X 3\f$\times\f$n-matrix, where \a n is the number of nodes
//! in the patch
virtual void getNodalCoordinates(Matrix& X) const;
//! \brief Establishes matrices with basis functions and 1st derivatives.
static void extractBasis(const Go::BasisDerivsSf& spline,
Vector& N, Matrix& dNdu);
//! \brief Establishes matrices with basis functions, 1st and 2nd derivatives.
static void extractBasis(const Go::BasisDerivsSf2& spline,
Vector& N, Matrix& dNdu, Matrix3D& d2Ndu2);
//! \brief Auxilliary function for computation of basis function indices.
static void scatterInd(int n1, int n2, int p1, int p2,
const int* start, IntVec& index);
private:
protected:
LR::LRSplineSurface* lrspline; //!< Pointer to the actual spline surface object
};
#endif

34
src/ASM/LR/ASMunstruct.C Normal file
View File

@@ -0,0 +1,34 @@
// $Id$
//==============================================================================
//!
//! \file ASMunstruct.C
//!
//! \date December 2010
//!
//! \author Kjetil Andre Johannessen / SINTEF
//!
//! \brief Base class for unstructured spline-based FE assembly drivers.
//!
//==============================================================================
#include "ASMunstruct.h"
#include "GoTools/geometry/GeomObject.h"
#include "LRSpline/LRSplineSurface.h"
int ASMunstruct::gEl = 0;
int ASMunstruct::gNod = 0;
ASMunstruct::ASMunstruct (unsigned char n_p, unsigned char n_s, unsigned char n_f)
: ASMbase(n_p,n_s,n_f)
{
geo = 0;
}
ASMunstruct::~ASMunstruct ()
{
if (geo) delete geo;
}

65
src/ASM/LR/ASMunstruct.h Normal file
View File

@@ -0,0 +1,65 @@
// $Id$
//==============================================================================
//!
//! \file ASMunstruct.h
//!
//! \date September 2011
//!
//! \author Kjetil Andre Johannessen / SINTEF
//!
//! \brief Base class for unstructured spline-based FE assembly drivers.
//!
//==============================================================================
#ifndef _ASM_UNSTRUCT_H
#define _ASM_UNSTRUCT_H
#include "ASMbase.h"
namespace Go {
class GeomObject;
class BoundingBox;
}
namespace LR {
class LRSplineSurface;
}
/*!
\brief Base class for structured spline-based FE assembly drivers.
\details This class contains methods common for structured spline patches.
*/
class ASMunstruct : public ASMbase
{
protected:
//! \brief The constructor sets the space dimensions.
//! \param[in] n_p Number of parameter dimensions
//! \param[in] n_s Number of spatial dimensions
//! \param[in] n_f Number of primary solution fields
ASMunstruct(unsigned char n_p, unsigned char n_s, unsigned char n_f);
public:
//! \brief The destructor frees the dynamically allocated spline object.
virtual ~ASMunstruct();
//! \brief Checks if the patch is empty.
virtual bool empty() const { return geo == 0; }
//! \brief Defines the numerical integration scheme to use.
//! \param[in] ng Number of Gauss points in each parameter direction
void setGauss(int ng) { nGauss = ng; }
//! \brief Resets global element and node counters
static void resetNumbering() { gEl = gNod = 0; }
protected:
LR::LRSplineSurface* geo; //!< Pointer to the actual spline geometry object
int nGauss; //!< Numerical integration scheme
static int gEl; //!< Global element counter
static int gNod; //!< Global node counter
};
#endif

View File

@@ -11,6 +11,9 @@
//!
//==============================================================================
#ifdef HAS_LRSPLINE
#include "LR/ASMu2D.h"
#endif
#include "SIM2D.h"
#include "ASMs2Dmx.h"
#include "ASMs2DmxLag.h"
@@ -51,6 +54,11 @@ bool SIM2D::parse (char* keyWord, std::istream& is)
case Spectral:
pch = new ASMs2DSpec(cline,2,nf[0]);
break;
#ifdef HAS_LRSPLINE
case LRSpline:
pch = new ASMu2D(cline,2,nf[0]);
break;
#endif
default:
if (nf[1] > 0)
pch = new ASMs2Dmx(cline,2,nf[0],nf[1]);
@@ -120,19 +128,21 @@ bool SIM2D::parse (char* keyWord, std::istream& is)
if (!oneBasedIdx)
{
// We always require the node numbers to be 1-based
for (i = 0; i < 4; i++) ++n.ibnod[i];
for (i = 0; i < 4; i++) ++n.edges[i].icnod;
++n.iinod;
// We always require the node numbers to be 1-based
for (i = 0; i < 4; i++) ++n.ibnod[i];
for (i = 0; i < 4; i++) ++n.edges[i].icnod;
++n.iinod;
}
if (isn.good() && pid > 0)
if (!static_cast<ASMs2D*>(myModel[pid-1])->assignNodeNumbers(n))
{
std::cerr <<" *** SIM2D::parse: Failed to assign node numbers"
<<" for patch "<< patch << std::endl;
return false;
}
{
if (!static_cast<ASMs2D*>(myModel[pid-1])->assignNodeNumbers(n))
{
std::cerr <<" *** SIM2D::parse: Failed to assign node numbers"
<<" for patch "<< patch << std::endl;
return false;
}
}
}
}
@@ -431,40 +441,79 @@ bool SIM2D::addConstraint (int patch, int lndx, int ldim, int dirs, int code)
return constrError("patch index ",patch);
std::cout <<"\tConstraining P"<< patch
<< (ldim == 0 ? " V" : " E") << lndx <<" in direction(s) "<< dirs;
<< (ldim == 0 ? " V" : " E") << lndx <<" in direction(s) "<< dirs;
if (code) std::cout <<" code = "<< code <<" ";
ASMs2D* pch = static_cast<ASMs2D*>(myModel[patch-1]);
switch (ldim)
{
case 0: // Vertex constraints
switch (lndx)
{
case 1: pch->constrainCorner(-1,-1,dirs,code); break;
case 2: pch->constrainCorner( 1,-1,dirs,code); break;
case 3: pch->constrainCorner(-1, 1,dirs,code); break;
case 4: pch->constrainCorner( 1, 1,dirs,code); break;
default: std::cout << std::endl;
return constrError("vertex index ",lndx);
}
break;
case 1: // Edge constraints
switch (lndx)
{
case 1: pch->constrainEdge(-1,dirs,code); break;
case 2: pch->constrainEdge( 1,dirs,code); break;
case 3: pch->constrainEdge(-2,dirs,code); break;
case 4: pch->constrainEdge( 2,dirs,code); break;
default: std::cout << std::endl;
return constrError("edge index ",lndx);
}
break;
default:
std::cout << std::endl;
return constrError("local dimension switch ",ldim);
}
if(discretization == LRSpline ) {
#ifdef HAS_LRSPLINE
ASMu2D* pch = static_cast<ASMu2D*>(myModel[patch-1]);
switch (ldim)
{
case 0: // Vertex constraints
switch (lndx)
{
case 1: pch->constrainCorner(-1,-1,dirs,code); break;
case 2: pch->constrainCorner( 1,-1,dirs,code); break;
case 3: pch->constrainCorner(-1, 1,dirs,code); break;
case 4: pch->constrainCorner( 1, 1,dirs,code); break;
default: std::cout << std::endl;
return constrError("vertex index ",lndx);
}
break;
case 1: // Edge constraints
switch (lndx)
{
case 1: pch->constrainEdge(-1,dirs,code); break;
case 2: pch->constrainEdge( 1,dirs,code); break;
case 3: pch->constrainEdge(-2,dirs,code); break;
case 4: pch->constrainEdge( 2,dirs,code); break;
default: std::cout << std::endl;
return constrError("edge index ",lndx);
}
break;
default:
std::cout << std::endl;
return constrError("local dimension switch ",ldim);
}
#else
std::cerr << "Error: No LR-spline library detected\n";
return constrError("discretization: LR-spline ", discretization);
#endif
} else {
ASMs2D* pch = static_cast<ASMs2D*>(myModel[patch-1]);
switch (ldim)
{
case 0: // Vertex constraints
switch (lndx)
{
case 1: pch->constrainCorner(-1,-1,dirs,code); break;
case 2: pch->constrainCorner( 1,-1,dirs,code); break;
case 3: pch->constrainCorner(-1, 1,dirs,code); break;
case 4: pch->constrainCorner( 1, 1,dirs,code); break;
default: std::cout << std::endl;
return constrError("vertex index ",lndx);
}
break;
case 1: // Edge constraints
switch (lndx)
{
case 1: pch->constrainEdge(-1,dirs,code); break;
case 2: pch->constrainEdge( 1,dirs,code); break;
case 3: pch->constrainEdge(-2,dirs,code); break;
case 4: pch->constrainEdge( 2,dirs,code); break;
default: std::cout << std::endl;
return constrError("edge index ",lndx);
}
break;
default:
std::cout << std::endl;
return constrError("local dimension switch ",ldim);
}
}
return true;
}
@@ -494,6 +543,11 @@ void SIM2D::readPatches (std::istream& isp)
case Spectral:
pch = new ASMs2DSpec(isp,2,nf[0]);
break;
case LRSpline:
#ifdef HAS_LRSPLINE
pch = new ASMu2D(isp,2,nf[0]);
#endif
break;
default:
if (nf[1] > 0)
pch = new ASMs2Dmx(isp,2,nf[0],nf[1]);

View File

@@ -492,7 +492,7 @@ protected:
public:
//! \brief Enum defining the available discretization methods.
enum Discretization { Spline, Lagrange, Spectral };
enum Discretization { Spline, Lagrange, Spectral, LRSpline };
static Discretization discretization; //!< Spatial discretization option