Added evaluation for solution at user-defined points

git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@900 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
kmo 2011-04-03 17:04:35 +00:00 committed by Knut Morten Okstad
parent 133153e045
commit a5eaefef22
17 changed files with 396 additions and 140 deletions

View File

@ -22,10 +22,8 @@
NonlinearElasticityUL::NonlinearElasticityUL (unsigned short int n, char lop) NonlinearElasticityUL::NonlinearElasticityUL (unsigned short int n, char lop)
: Elasticity(n) : Elasticity(n), loadOp(lop), plam(-999.9)
{ {
loadOp = lop;
// Only the current solution is needed // Only the current solution is needed
primsol.resize(1); primsol.resize(1);
} }
@ -94,10 +92,13 @@ void NonlinearElasticityUL::initIntegration (const TimeDomain& prm)
} }
void NonlinearElasticityUL::initResultPoints () void NonlinearElasticityUL::initResultPoints (double lambda)
{ {
if (material) if (material && lambda > plam)
{
material->initResultPoints(); material->initResultPoints();
plam = lambda;
}
} }

View File

@ -47,7 +47,8 @@ public:
//! \param[in] prm Nonlinear solution algorithm parameters //! \param[in] prm Nonlinear solution algorithm parameters
virtual void initIntegration(const TimeDomain& prm); virtual void initIntegration(const TimeDomain& prm);
//! \brief Initializes the integrand for a result point loop. //! \brief Initializes the integrand for a result point loop.
virtual void initResultPoints(); //! \param[in] lambda Load parameter
virtual void initResultPoints(double lambda);
//! \brief Evaluates the integrand at an interior point. //! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions //! \param elmInt The local integral object to receive the contributions
@ -94,6 +95,7 @@ protected:
private: private:
char loadOp; //!< Load option char loadOp; //!< Load option
double plam; //!< Load parameter of the previous result evaluation
friend class ElasticityNormUL; friend class ElasticityNormUL;
}; };

View File

@ -104,12 +104,14 @@ void PlasticMaterial::initIntegration (const TimeDomain& prm)
if (prm.it > 0 || prm.first) return; if (prm.it > 0 || prm.first) return;
int nUpdated = 0;
for (size_t i = 0; i < itgPoints.size(); i++) for (size_t i = 0; i < itgPoints.size(); i++)
itgPoints[i]->updateHistoryVars(); if (itgPoints[i]->updateHistoryVars())
nUpdated++;
#if INT_DEBUG > 0 #if INT_DEBUG > 0
std::cout <<"PlasticMaterial::initIntegration: History updated " std::cout <<"PlasticMaterial::initIntegration: History updated "
<< itgPoints.size() << std::endl; << nUpdated << std::endl;
#endif #endif
} }
@ -123,12 +125,14 @@ void PlasticMaterial::initResultPoints ()
iP2 = 0; iP2 = 0;
iAmIntegrating = false; iAmIntegrating = false;
int nUpdated = 0;
for (size_t i = 0; i < resPoints.size(); i++) for (size_t i = 0; i < resPoints.size(); i++)
resPoints[i]->updateHistoryVars(); if (resPoints[i]->updateHistoryVars())
nUpdated++;
#if INT_DEBUG > 0 #if INT_DEBUG > 0
std::cout <<"PlasticMaterial::initResultPoints: History updated " std::cout <<"PlasticMaterial::initResultPoints: History updated "
<< resPoints.size() << std::endl; << nUpdated << std::endl;
#endif #endif
} }
@ -170,7 +174,7 @@ bool PlasticMaterial::evaluate (Matrix& C, SymmTensor& sigma, double&,
PlasticMaterial::PlasticPoint::PlasticPoint (const PlasticMaterial* prm, PlasticMaterial::PlasticPoint::PlasticPoint (const PlasticMaterial* prm,
unsigned short int n) unsigned short int n)
: pMAT(prm->pMAT), Fp(n) : pMAT(prm->pMAT), updated(false), Fp(n)
{ {
// Initialize the history variables // Initialize the history variables
memset(HVc,0,sizeof(HVc)); memset(HVc,0,sizeof(HVc));
@ -179,10 +183,15 @@ PlasticMaterial::PlasticPoint::PlasticPoint (const PlasticMaterial* prm,
} }
void PlasticMaterial::PlasticPoint::updateHistoryVars () bool PlasticMaterial::PlasticPoint::updateHistoryVars ()
{ {
if (!updated) return false;
// Update history variables with values of the new converged solution // Update history variables with values of the new converged solution
memcpy(HVp,HVc,sizeof(HVc)); memcpy(HVp,HVc,sizeof(HVc));
updated = false;
return true;
} }
@ -209,6 +218,12 @@ bool PlasticMaterial::PlasticPoint::evaluate (Matrix& C,
int ierr = -99; int ierr = -99;
#ifdef USE_FTNMAT #ifdef USE_FTNMAT
// Invoke the FORTRAN routine for plasticity material models // Invoke the FORTRAN routine for plasticity material models
#if INT_DEBUG > 0
std::cout <<"PlasticMaterial::Fp =\n"<< Fp;
std::cout <<"PlasticMaterial::HV =";
for (int i = 0; i < 10; i++) std::cout <<" "<< HVc[i];
std::cout << std::endl;
#endif
if (ndim == 2) if (ndim == 2)
plas2d_(INT_DEBUG,6,prm.it,prm.first,4,&pMAT.front(),J,F.dim(), plas2d_(INT_DEBUG,6,prm.it,prm.first,4,&pMAT.front(),J,F.dim(),
F.ptr(),Fp.ptr(),HVc,HVc[6],HVc+7,sigma.ptr(),C.ptr(),ierr); F.ptr(),Fp.ptr(),HVc,HVc[6],HVc+7,sigma.ptr(),C.ptr(),ierr);
@ -223,5 +238,6 @@ bool PlasticMaterial::PlasticPoint::evaluate (Matrix& C,
std::cerr <<" *** PlasticMaterial::evaluate: Not included."<< std::endl; std::cerr <<" *** PlasticMaterial::evaluate: Not included."<< std::endl;
#endif #endif
const_cast<PlasticPoint*>(this)->updated = true;
return ierr == 0; return ierr == 0;
} }

View File

@ -52,7 +52,7 @@ class PlasticMaterial : public Material
PlasticPoint(const PlasticMaterial* prm, unsigned short int n); PlasticPoint(const PlasticMaterial* prm, unsigned short int n);
//! \brief Updates the internal history variables after convergence. //! \brief Updates the internal history variables after convergence.
void updateHistoryVars(); bool updateHistoryVars();
//! \brief Evaluates the constitutive relation at this point. //! \brief Evaluates the constitutive relation at this point.
//! \param[out] C Constitutive matrix at current point //! \param[out] C Constitutive matrix at current point
@ -67,6 +67,7 @@ class PlasticMaterial : public Material
double HVc[10]; //!< History variables, current configuration double HVc[10]; //!< History variables, current configuration
double HVp[10]; //!< History variables, previous configuration double HVp[10]; //!< History variables, previous configuration
bool updated; //!< Flag indicating whether history variables are updated
public: public:
Tensor Fp; //!< Deformation gradient, previous configuration Tensor Fp; //!< Deformation gradient, previous configuration

View File

@ -76,7 +76,7 @@ int main (int argc, char** argv)
bool twoD = false; bool twoD = false;
char* infile = 0; char* infile = 0;
LinAlgInit linalg(argc,argv); const LinAlgInit& linalg = LinAlgInit::Init(argc,argv);
std::vector<int> options(2,0); std::vector<int> options(2,0);
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
@ -294,6 +294,9 @@ int main (int argc, char** argv)
if (!simulator.solveStep(params,SIM::STATIC)) if (!simulator.solveStep(params,SIM::STATIC))
return 5; return 5;
// Print solution components at the user-defined points
simulator.dumpResults(params.time.t,std::cout);
if (params.time.t + epsT*params.time.dt > nextDump) if (params.time.t + epsT*params.time.dt > nextDump)
{ {
// Dump primary solution for inspection or external processing // Dump primary solution for inspection or external processing

View File

@ -47,7 +47,7 @@ typedef std::vector<ASMbase*> ASMVec; //!< Spline patch container
of a set of partial differential equations using splines as basis functions. of a set of partial differential equations using splines as basis functions.
The class does not contain any problem-specific data or methods. The class does not contain any problem-specific data or methods.
The methods that need access to problem information are provided that through The methods that need access to problem information are given that through
Integrand objects that are passed as arguments to those methods. Integrand objects that are passed as arguments to those methods.
*/ */
@ -225,6 +225,12 @@ public:
// Post-processing methods // 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 parameters of the point in the knot-span domain
//! \param[out] X The Cartesian coordinates of the point
virtual bool evalPoint(const double* xi, double* param, Vec3& X) const = 0;
//! \brief Creates a standard FE model of this patch for visualization. //! \brief Creates a standard FE model of this patch for visualization.
//! \param[out] grid The generated finite element grid //! \param[out] grid The generated finite element grid
//! \param[in] npe Number of visualization nodes over each knot span //! \param[in] npe Number of visualization nodes over each knot span
@ -295,7 +301,7 @@ public:
virtual void extractNodeVec(const Vector& globVec, Vector& nodeVec, virtual void extractNodeVec(const Vector& globVec, Vector& nodeVec,
unsigned char nndof = 0) const; unsigned char nndof = 0) const;
//! \brief Inject nodal results for this patch into the global vector. //! \brief Injects nodal results for this patch into the global vector.
//! \param[in] nodeVec Nodal result vector for this patch //! \param[in] nodeVec Nodal result vector for this patch
//! \param globVec Global solution vector in DOF-order //! \param globVec Global solution vector in DOF-order
//! \param[in] nndof Number of DOFs per node (the default is \a nf) //! \param[in] nndof Number of DOFs per node (the default is \a nf)

View File

@ -29,10 +29,8 @@
ASMs1D::ASMs1D (const char* fileName, unsigned char n_s, unsigned char n_f) ASMs1D::ASMs1D (const char* fileName, unsigned char n_s, unsigned char n_f)
: ASMstruct(1,n_s,n_f) : ASMstruct(1,n_s,n_f), curv(0)
{ {
curv = 0;
std::cout <<"\nReading patch file "<< fileName << std::endl; std::cout <<"\nReading patch file "<< fileName << std::endl;
std::ifstream is(fileName); std::ifstream is(fileName);
if (!is.good()) if (!is.good())
@ -45,10 +43,8 @@ ASMs1D::ASMs1D (const char* fileName, unsigned char n_s, unsigned char n_f)
ASMs1D::ASMs1D (std::istream& is, unsigned char n_s, unsigned char n_f) ASMs1D::ASMs1D (std::istream& is, unsigned char n_s, unsigned char n_f)
: ASMstruct(1,n_s,n_f) : ASMstruct(1,n_s,n_f), curv(0)
{ {
curv = 0;
this->read(is); this->read(is);
geo = curv; geo = curv;
@ -56,9 +52,8 @@ ASMs1D::ASMs1D (std::istream& is, unsigned char n_s, unsigned char n_f)
ASMs1D::ASMs1D (unsigned char n_s, unsigned char n_f) ASMs1D::ASMs1D (unsigned char n_s, unsigned char n_f)
: ASMstruct(1,n_s,n_f) : ASMstruct(1,n_s,n_f), curv(0)
{ {
curv = 0;
} }
@ -608,6 +603,21 @@ bool ASMs1D::integrate (Integrand& integrand, int lIndex,
} }
bool ASMs1D::evalPoint (const double* xi, double* param, Vec3& X) const
{
if (!curv) return false;
param[0] = (1.0-xi[0])*curv->startparam() + xi[0]*curv->endparam();
Go::Point X0;
curv->point(X0,param[0]);
for (unsigned char i = 0; i < nsd; i++)
X[i] = X0[i];
return true;
}
bool ASMs1D::getGridParameters (RealArray& prm, int nSegPerSpan) const bool ASMs1D::getGridParameters (RealArray& prm, int nSegPerSpan) const
{ {
if (!curv) return false; if (!curv) return false;
@ -772,6 +782,8 @@ Go::GeomObject* ASMs1D::evalSolution (const Integrand& integrand) const
Go::SplineCurve* ASMs1D::projectSolution (const Integrand& integrand) const Go::SplineCurve* ASMs1D::projectSolution (const Integrand& integrand) const
{ {
//TODO: This requires the method Go::CurveInterpolator::regularInterpolation
// which is not yet present in GoTools.
std::cerr <<"ASMs1D::projectSolution: Not implemented yet!"<< std::endl; std::cerr <<"ASMs1D::projectSolution: Not implemented yet!"<< std::endl;
return 0; return 0;
} }

View File

@ -122,6 +122,12 @@ public:
// Post-processing methods // Post-processing methods
// ======================= // =======================
//! \brief Evaluates the geometry at a specified point.
//! \param[in] xi Dimensionless parameter in range [0.0,1.0] of the point
//! \param[out] param The parameter of the point in the knot-span domain
//! \param[out] X The Cartesian coordinates of the point
virtual bool evalPoint(const double* xi, double* param, Vec3& X) const;
//! \brief Creates a line element model of this patch for visualization. //! \brief Creates a line element model of this patch for visualization.
//! \param[out] grid The generated line grid //! \param[out] grid The generated line grid
//! \param[in] npe Number of visualization nodes over each knot span //! \param[in] npe Number of visualization nodes over each knot span

View File

@ -31,10 +31,8 @@
ASMs2D::ASMs2D (const char* fileName, unsigned char n_s, unsigned char n_f) ASMs2D::ASMs2D (const char* fileName, unsigned char n_s, unsigned char n_f)
: ASMstruct(2,n_s,n_f) : ASMstruct(2,n_s,n_f), surf(0)
{ {
surf = 0;
std::cout <<"\nReading patch file "<< fileName << std::endl; std::cout <<"\nReading patch file "<< fileName << std::endl;
std::ifstream is(fileName); std::ifstream is(fileName);
if (!is.good()) if (!is.good())
@ -47,10 +45,8 @@ ASMs2D::ASMs2D (const char* fileName, unsigned char n_s, unsigned char n_f)
ASMs2D::ASMs2D (std::istream& is, unsigned char n_s, unsigned char n_f) ASMs2D::ASMs2D (std::istream& is, unsigned char n_s, unsigned char n_f)
: ASMstruct(2,n_s,n_f) : ASMstruct(2,n_s,n_f), surf(0)
{ {
surf = 0;
this->read(is); this->read(is);
geo = surf; geo = surf;
@ -58,9 +54,8 @@ ASMs2D::ASMs2D (std::istream& is, unsigned char n_s, unsigned char n_f)
ASMs2D::ASMs2D (unsigned char n_s, unsigned char n_f) ASMs2D::ASMs2D (unsigned char n_s, unsigned char n_f)
: ASMstruct(2,n_s,n_f) : ASMstruct(2,n_s,n_f), surf(0)
{ {
surf = 0;
} }
@ -659,7 +654,7 @@ Vec3 ASMs2D::getCoord (size_t inod) const
if (ip < 0) return X; if (ip < 0) return X;
RealArray::const_iterator cit = surf->coefs_begin() + ip; RealArray::const_iterator cit = surf->coefs_begin() + ip;
for (size_t i = 0; i < nsd; i++, cit++) for (unsigned char i = 0; i < nsd; i++, cit++)
X[i] = *cit; X[i] = *cit;
return X; return X;
@ -753,7 +748,7 @@ void ASMs2D::extractBasis (const Go::BasisDerivsSf2& spline,
#if SP_DEBUG > 4 #if SP_DEBUG > 4
std::ostream& operator<<(std::ostream& os, const Go::BasisDerivsSf& bder) std::ostream& operator<< (std::ostream& os, const Go::BasisDerivsSf& bder)
{ {
os <<" : (u,v) = "<< bder.param[0] <<" "<< bder.param[1] os <<" : (u,v) = "<< bder.param[0] <<" "<< bder.param[1]
<<" left_idx = "<< bder.left_idx[0] <<" "<< bder.left_idx[1] << std::endl; <<" left_idx = "<< bder.left_idx[0] <<" "<< bder.left_idx[1] << std::endl;
@ -876,8 +871,8 @@ bool ASMs2D::integrate (Integrand& integrand,
double u0 = 0.5*(gpar[0](1,i1-p1+1) + gpar[0](nGauss,i1-p1+1)); double u0 = 0.5*(gpar[0](1,i1-p1+1) + gpar[0](nGauss,i1-p1+1));
double v0 = 0.5*(gpar[1](1,i2-p2+1) + gpar[1](nGauss,i2-p2+1)); double v0 = 0.5*(gpar[1](1,i2-p2+1) + gpar[1](nGauss,i2-p2+1));
surf->point(X0,u0,v0); surf->point(X0,u0,v0);
X.x = X0[0]; for (unsigned char i = 0; i < nsd; i++)
X.y = X0[1]; X[i] = X0[i];
} }
// Initialize element quantities // Initialize element quantities
@ -1083,6 +1078,23 @@ bool ASMs2D::integrate (Integrand& integrand, int lIndex,
} }
bool ASMs2D::evalPoint (const double* xi, double* param, Vec3& X) const
{
if (!surf) return false;
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 i = 0; i < nsd; i++)
X[i] = X0[i];
return true;
}
bool ASMs2D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const bool ASMs2D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const
{ {
if (!surf) return false; if (!surf) return false;

View File

@ -195,6 +195,12 @@ public:
// Post-processing methods // 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
virtual bool evalPoint(const double* xi, double* param, Vec3& X) const;
//! \brief Creates a quad element model of this patch for visualization. //! \brief Creates a quad element model of this patch for visualization.
//! \param[out] grid The generated quadrilateral grid //! \param[out] grid The generated quadrilateral grid
//! \param[in] npe Number of visualization nodes over each knot span //! \param[in] npe Number of visualization nodes over each knot span

View File

@ -31,11 +31,8 @@
ASMs3D::ASMs3D (const char* fileName, bool checkRHS, unsigned char n_f) ASMs3D::ASMs3D (const char* fileName, bool checkRHS, unsigned char n_f)
: ASMstruct(3,3,n_f) : ASMstruct(3,3,n_f), svol(0), swapW(false)
{ {
svol = 0;
swapW = false;
std::cout <<"\nReading patch file "<< fileName << std::endl; std::cout <<"\nReading patch file "<< fileName << std::endl;
std::ifstream is(fileName); std::ifstream is(fileName);
if (!is.good()) if (!is.good())
@ -48,11 +45,8 @@ ASMs3D::ASMs3D (const char* fileName, bool checkRHS, unsigned char n_f)
ASMs3D::ASMs3D (std::istream& is, bool checkRHS, unsigned char n_f) ASMs3D::ASMs3D (std::istream& is, bool checkRHS, unsigned char n_f)
: ASMstruct(3,3,n_f) : ASMstruct(3,3,n_f), svol(0), swapW(false)
{ {
svol = 0;
swapW = false;
if (this->read(is) && checkRHS) if (this->read(is) && checkRHS)
this->checkRightHandSystem(); this->checkRightHandSystem();
@ -1599,6 +1593,23 @@ bool ASMs3D::integrateEdge (Integrand& integrand, int lEdge,
} }
bool ASMs3D::evalPoint (const double* xi, double* param, Vec3& X) const
{
if (!svol) return false;
for (int 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]);
X.x = X0[0];
X.y = X0[1];
X.z = X0[2];
return true;
}
bool ASMs3D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const bool ASMs3D::getGridParameters (RealArray& prm, int dir, int nSegPerSpan) const
{ {
if (!svol) return false; if (!svol) return false;

View File

@ -90,7 +90,7 @@ public:
//! \brief Constructor creating an instance by reading the given input stream. //! \brief Constructor creating an instance by reading the given input stream.
ASMs3D(std::istream& is, bool checkRHS = false, unsigned char n_f = 3); ASMs3D(std::istream& is, bool checkRHS = false, unsigned char n_f = 3);
//! \brief Default constructor creating an empty patch. //! \brief Default constructor creating an empty patch.
ASMs3D(unsigned char n_f = 3) : ASMstruct(3,3,n_f) { svol = 0; } ASMs3D(unsigned char n_f = 3) : ASMstruct(3,3,n_f), svol(0), swapW(false) {}
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~ASMs3D() {} virtual ~ASMs3D() {}
@ -260,6 +260,12 @@ public:
// Post-processing methods // 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
virtual bool evalPoint(const double* xi, double* param, Vec3& X) const;
//! \brief Creates a hexahedron element model of this patch for visualization. //! \brief Creates a hexahedron element model of this patch for visualization.
//! \param[out] grid The generated hexahedron grid //! \param[out] grid The generated hexahedron grid
//! \param[in] npe Number of visualization nodes over each knot span //! \param[in] npe Number of visualization nodes over each knot span

View File

@ -30,15 +30,17 @@ class VTF;
/*! /*!
\brief Abstract base class representing a system level integrated quantity. \brief Abstract base class representing a system level integrated quantity.
\details This class defines the interface between the finite element \details This class defines the interface between the finite element (FE)
assembly drivers of the ASM-hierarchy and the problem-dependent classes assembly drivers of the ASM-hierarchy and the problem-dependent classes
containing all physical properties for the problem to be solved. containing all physical properties for the problem to be solved.
The interface has several overloaded versions of the \a evalInt method, for The interface consists of methods for evaluating the integrand at interior
evaluation of the coefficient matrix contributions at an element-interior integration points (\a evalInt), and at boundary integration points
integration point. Only one of these methods needs to be implemented, and (\a evalBou). The latter are used for Neumann boundary conditions, typically.
which one to use is governed by the \a getIntegrandType method. The integrand evaluation methods have access to the FE basis function values
There is also one method intended for mixed field interpolation problems. and derivatives through the FiniteElement argument. There are also a set
of methods dedicated for mixed field interpolation problems, which take
and MxFiniteElement object as argument instead.
*/ */
class Integrand class Integrand
@ -51,18 +53,28 @@ public:
//! \brief Empty destructor. //! \brief Empty destructor.
virtual ~Integrand() {} virtual ~Integrand() {}
//! \brief Prints out problem definition to the given output stream. //! \brief Prints out the problem definition to the given output stream.
virtual void print(std::ostream&) const {} virtual void print(std::ostream&) const {}
// Global initialization interface
// ===============================
//! \brief Defines the solution mode before the element assembly is started. //! \brief Defines the solution mode before the element assembly is started.
virtual void setMode(SIM::SolutionMode) {} virtual void setMode(SIM::SolutionMode) {}
//! \brief Initializes the integrand for a new integration loop. //! \brief Initializes the integrand for a new integration loop.
//! \details This method is invoked once before starting the numerical //! \details This method is invoked once before starting the numerical
//! integration over the entire spatial domain. //! integration over the entire spatial domain.
virtual void initIntegration(const TimeDomain&) {} virtual void initIntegration(const TimeDomain&) {}
//! \brief Initializes the integrand for a new result point loop. //! \brief Initializes the integrand for a new result point loop.
virtual void initResultPoints() {} //! \details This method is invoked once before starting the evaluation of
//! the secondary solution at all result sampling points, after the converged
//! primary solution has been found.
virtual void initResultPoints(double) {}
// Element-level initialization interface
// ======================================
//! \brief Initializes current element for numerical integration. //! \brief Initializes current element for numerical integration.
//! \param[in] MNPC Matrix of nodal point correspondance for current element //! \param[in] MNPC Matrix of nodal point correspondance for current element
@ -85,7 +97,7 @@ public:
//! \brief Initializes current element for numerical integration. //! \brief Initializes current element for numerical integration.
//! \param[in] MNPC Matrix of nodal point correspondance for current element //! \param[in] MNPC Matrix of nodal point correspondance for current element
//! //!
//! \details Reimplement this method for problems not requiring the //! \details Reimplement this method for problems \e not requiring the
//! the element center nor the number of integration points before the //! the element center nor the number of integration points before the
//! integration loop is started. //! integration loop is started.
virtual bool initElement(const std::vector<int>& MNPC) virtual bool initElement(const std::vector<int>& MNPC)
@ -122,17 +134,18 @@ public:
return false; return false;
} }
//! \brief Finalizes the element quantities after the numerical integration.
//! \details This method is invoked once for each element, after the numerical // Integrand evaluation interface
//! integration loop is finished, and before the resulting element quantities // ==============================
//! are assembled into their system level equivalents.
//! It can also be used to implement multiple integration point loops within //! \brief Defines which FE quantities are needed by the integrand.
//! the same element, provided the necessary integration point values are //! \return 1: The basis functions and their gradients are needed
//! stored internally in the object during the first integration loop. //! \return 2: As 1, but in addition the second derivatives of the basis
virtual bool finalizeElement(LocalIntegral*&, const TimeDomain&) //! functions and the characteristic element size is needed
{ //! \return 3: As 1, but in addition the volume-averaged basis functions
return true; //! are needed
} //! \return 4: As 1, but in addition the element center coordinates are needed
virtual int getIntegrandType() const { return 1; }
//! \brief Evaluates the integrand at an interior point. //! \brief Evaluates the integrand at an interior point.
//! \param elmInt The local integral object to receive the contributions //! \param elmInt The local integral object to receive the contributions
@ -163,6 +176,18 @@ public:
return this->evalIntMx(elmInt,fe,X); return this->evalIntMx(elmInt,fe,X);
} }
//! \brief Finalizes the element quantities after the numerical integration.
//! \details This method is invoked once for each element, after the numerical
//! integration loop over interior points is finished and before the resulting
//! element quantities are assembled into their system level equivalents.
//! It can also be used to implement multiple integration point loops within
//! the same element, provided the necessary integration point values are
//! stored internally in the object during the first integration loop.
virtual bool finalizeElement(LocalIntegral*&, const TimeDomain&)
{
return true;
}
//! \brief Evaluates the integrand at a boundary point. //! \brief Evaluates the integrand at a boundary point.
//! \param elmInt The local integral object to receive the contributions //! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Finite element data of current integration point //! \param[in] fe Finite element data of current integration point
@ -212,6 +237,10 @@ protected:
const Vec3&, const Vec3&) const { return false; } const Vec3&, const Vec3&) const { return false; }
public: public:
// Solution field evaluation interface
// ===================================
//! \brief Evaluates the secondary solution at a result point. //! \brief Evaluates the secondary solution at a result point.
//! \param[out] s The solution field values at current point //! \param[out] s The solution field values at current point
//! \param[in] N Basis function values at current point //! \param[in] N Basis function values at current point
@ -294,35 +323,24 @@ public:
return false; return false;
} }
// Various service methods
// =======================
//! \brief Writes surface tractions/fluxes for a given time step to VTF-file. //! \brief Writes surface tractions/fluxes for a given time step to VTF-file.
//! \param vtf The VTF-file object to receive the tractions virtual bool writeGlvT(VTF*, int, int&) const { return true; }
//! \param[in] iStep Load/time step identifier
//! \param nBlck Running result block counter
virtual bool writeGlvT(VTF* vtf, int iStep, int& nBlck) const { return true; }
//! \brief Returns whether there are any traction/flux values to write to VTF. //! \brief Returns whether there are any traction/flux values to write to VTF.
virtual bool hasTractionValues() const { return false; } virtual bool hasTractionValues() const { return false; }
//! \brief Returns which integrand to be used. //! \brief Returns the number of (secondary) solution field components.
virtual int getIntegrandType() const { return 1; }
//! \brief Returns the number of secondary solution field components.
virtual size_t getNoFields() const { return 0; } virtual size_t getNoFields() const { return 0; }
//! \brief Returns the number of secondary solution field components. //! \brief Returns the name of a (secondary) solution field component.
virtual size_t getNoSecFields() const { return 0; } virtual const char* getFieldLabel(size_t, const char* = 0) const { return 0; }
//! \brief Returns the name of a secondary solution field component.
//! \param[in] i Field component index
//! \param[in] prefix Name prefix for all components
virtual const char* getFieldLabel(size_t i, const char* prefix = 0) const
{
return 0;
}
//! \brief Returns a pointer to an Integrand for solution norm evaluation. //! \brief Returns a pointer to an Integrand for solution norm evaluation.
//! \param[in] asol Pointer to the analytical solution (optional) virtual NormBase* getNormIntegrand(AnaSol* = 0) const { return 0; }
virtual NormBase* getNormIntegrand(AnaSol* asol = 0) const { return 0; }
//! \brief Returns the number of solution vectors. //! \brief Returns the number of solution vectors.
size_t getNoSolutions() const { return primsol.size(); } size_t getNoSolutions() const { return primsol.size(); }
@ -331,7 +349,7 @@ public:
Vector& getSolution(size_t n = 0) { return primsol[n]; } Vector& getSolution(size_t n = 0) { return primsol[n]; }
protected: protected:
Vectors primsol; //!< Primary solution vectors for this patch Vectors primsol; //!< Primary solution vectors for current patch
}; };

View File

@ -402,7 +402,7 @@ bool NonLinSIM::saveStep (int iStep, double time, int* nViz, bool psolOnly)
// Write solution fields // Write solution fields
if (!solution.empty()) if (!solution.empty())
if (!model->writeGlvS(solution.front(),nViz,iStep,nBlock,psolOnly)) if (!model->writeGlvS(solution.front(),nViz,iStep,nBlock,time,psolOnly))
return false; return false;
// Write element norms (only when no additional visualization points are used) // Write element norms (only when no additional visualization points are used)
@ -426,6 +426,12 @@ void NonLinSIM::dumpStep (int iStep, double time, std::ostream& os,
} }
bool NonLinSIM::dumpResults (double time, std::ostream& os) const
{
return model->dumpResults(solution.front(),time,os);
}
bool NonLinSIM::project () bool NonLinSIM::project ()
{ {
return model->project(solution.front()); return model->project(solution.front());

View File

@ -96,14 +96,19 @@ public:
//! \param[in] psolOnly If \e true, skip secondary solution field output //! \param[in] psolOnly If \e true, skip secondary solution field output
bool saveStep(int iStep, double time, int* nViz, bool psolOnly = false); bool saveStep(int iStep, double time, int* nViz, bool psolOnly = false);
//! \brief Dumps the primary solution to given stream for inspection. //! \brief Dumps the primary solution for inspection.
//! \param[in] iStep Load/time step identifier //! \param[in] iStep Load/time step identifier
//! \param[in] time Current time/load parameter //! \param[in] time Current time/load parameter
//! \param[in] os The output streeam to write to //! \param[in] os The output stream to write the solution to
//! \param[in] withID If \e true, write node ID and coordinates too //! \param[in] withID If \e true, write node ID and coordinates too
void dumpStep(int iStep, double time, std::ostream& os, void dumpStep(int iStep, double time, std::ostream& os,
bool withID = true) const; bool withID = true) const;
//! \brief Dumps solution variables at user-defined points.
//! \param[in] time Current time/load parameter
//! \param[in] os The output stream to write the solution to
bool dumpResults(double time, std::ostream& os) const;
//! \brief Returns a const reference to current solution vector. //! \brief Returns a const reference to current solution vector.
const Vector& getSolution() const { return solution.front(); } const Vector& getSolution() const { return solution.front(); }

View File

@ -26,13 +26,13 @@
#include "ElmNorm.h" #include "ElmNorm.h"
#include "AnaSol.h" #include "AnaSol.h"
#include "Tensor.h" #include "Tensor.h"
#include "Vec3.h"
#include "Vec3Oper.h" #include "Vec3Oper.h"
#include "EigSolver.h" #include "EigSolver.h"
#include "Profiler.h" #include "Profiler.h"
#include "ElementBlock.h" #include "ElementBlock.h"
#include "VTF.h" #include "VTF.h"
#include "Utilities.h" #include "Utilities.h"
#include <iomanip>
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
@ -103,7 +103,7 @@ bool SIMbase::parse (char* keyWord, std::istream& is)
char* cline = 0; char* cline = 0;
nGlPatches = 0; nGlPatches = 0;
for (int i = 0; i < nproc && (cline = utl::readLine(is));i++) for (int i = 0; i < nproc && (cline = utl::readLine(is)); i++)
{ {
int proc = atoi(strtok(cline," ")); int proc = atoi(strtok(cline," "));
int first = atoi(strtok(NULL," ")); int first = atoi(strtok(NULL," "));
@ -127,6 +127,30 @@ bool SIMbase::parse (char* keyWord, std::istream& is)
} }
} }
else if (!strncasecmp(keyWord,"RESULTPOINTS",12))
{
int nres = atoi(keyWord+12);
if (myPid == 0 && nres > 0)
std::cout <<"\nNumber of result points: "<< nres;
char* cline = 0;
myPoints.resize(nres);
for (int i = 0; i < nres && (cline = utl::readLine(is)); i++)
{
myPoints[i].patch = atoi(strtok(cline," "));
if (myPid == 0)
std::cout <<"\n\tPoint "<< i+1 <<": P"<< myPoints[i].patch <<" xi =";
for (int j = 0; j < 3 && (cline = strtok(NULL," ")); j++)
{
myPoints[i].param[j] = atof(cline);
if (myPid == 0)
std::cout <<' '<< myPoints[i].param[j];
}
}
if (myPid == 0 && nres > 0)
std::cout << std::endl;
}
else if (isalpha(keyWord[0])) else if (isalpha(keyWord[0]))
std::cerr <<" *** SIMbase::parse: Unknown keyword: "<< keyWord << std::endl; std::cerr <<" *** SIMbase::parse: Unknown keyword: "<< keyWord << std::endl;
@ -134,6 +158,15 @@ bool SIMbase::parse (char* keyWord, std::istream& is)
} }
void SIMbase::readLinSolParams (std::istream& is, int npar)
{
if (!mySolParams)
mySolParams = new LinSolParams();
mySolParams->read(is,npar);
}
bool SIMbase::createFEMmodel () bool SIMbase::createFEMmodel ()
{ {
for (size_t i = 0; i < myModel.size(); i++) for (size_t i = 0; i < myModel.size(); i++)
@ -267,6 +300,34 @@ bool SIMbase::preprocess (const std::vector<int>& ignoredPatches, bool fixDup)
// Resolve possibly chained multi-point constraints // Resolve possibly chained multi-point constraints
ASMbase::resolveMPCchains(myModel); ASMbase::resolveMPCchains(myModel);
// Preprocess the result points
for (ResPointVec::iterator p = myPoints.begin(); p != myPoints.end();)
{
int pid = this->getLocalPatchIndex(p->patch);
if (pid < 1 || myModel[pid-1]->empty())
p = myPoints.erase(p);
else
{
p->npar = myModel[pid-1]->getNoParamDim();
myModel[pid-1]->evalPoint(p->param,p->param,p->X);
std::cout <<"\nResult point #"<< 1+(int)(p-myPoints.begin())
<<": patch #"<< p->patch;
switch (p->npar) {
case 1: std::cout <<" u="; break;
case 2: std::cout <<" (u,v)=("; break;
case 3: std::cout <<" (u,v,w)=("; break;
}
std::cout << p->param[0];
for (unsigned char c = 1; c < p->npar; c++)
std::cout <<','<< p->param[c];
if (p->npar > 1) std::cout <<')';
std::cout <<", X = "<< p->X;
p++;
}
}
std::cout << std::endl;
// Initialize data structures for the algebraic system // Initialize data structures for the algebraic system
#ifdef PARALLEL_PETSC #ifdef PARALLEL_PETSC
mySam = new SAMpatchPara(l2gn); mySam = new SAMpatchPara(l2gn);
@ -337,10 +398,11 @@ bool SIMbase::setMode (int mode)
void SIMbase::printProblem (std::ostream& os) const void SIMbase::printProblem (std::ostream& os) const
{ {
if (!myProblem) return; if (myProblem)
{
std::cout <<"\nProblem definition:"<< std::endl; std::cout <<"\nProblem definition:"<< std::endl;
myProblem->print(os); myProblem->print(os);
}
#if SP_DEBUG > 1 #if SP_DEBUG > 1
std::cout <<"\nProperty mapping:"; std::cout <<"\nProperty mapping:";
@ -493,6 +555,33 @@ bool SIMbase::assembleSystem (const TimeDomain& time, const Vectors& prevSol,
} }
bool SIMbase::finalizeAssembly (bool newLHSmatrix)
{
// Communication of matrix and vector assembly (for PETSc only)
SystemMatrix* A = myEqSys->getMatrix();
if (A && newLHSmatrix)
{
if (!A->beginAssembly()) return false;
if (!A->endAssembly()) return false;
#if SP_DEBUG > 3
std::cout <<"\nSystem coefficient matrix:"<< *A;
#endif
}
SystemVector* b = myEqSys->getVector();
if (b)
{
if (!b->beginAssembly()) return false;
if (!b->endAssembly()) return false;
#if SP_DEBUG > 2
std::cout <<"\nSystem right-hand-side vector:"<< *b;
#endif
}
return true;
}
bool SIMbase::extractLoadVec (Vector& loadVec) const bool SIMbase::extractLoadVec (Vector& loadVec) const
{ {
SystemVector* b = myEqSys->getVector(); SystemVector* b = myEqSys->getVector();
@ -612,7 +701,7 @@ bool SIMbase::solutionNorms (const TimeDomain& time, const Vectors& psol,
myProblem->initIntegration(time); myProblem->initIntegration(time);
size_t nNorms = norm->getNoFields() + norm->getNoSecFields(); size_t nNorms = norm->getNoFields();
const Vector& primsol = psol.front(); const Vector& primsol = psol.front();
size_t i, nel = mySam->getNoElms(); size_t i, nel = mySam->getNoElms();
@ -913,8 +1002,8 @@ bool SIMbase::writeGlvV (const Vector& vec, const char* fieldName,
} }
bool SIMbase::writeGlvS (const Vector& psol, bool SIMbase::writeGlvS (const Vector& psol, const int* nViz,
const int* nViz, int iStep, int& nBlock, bool psolOnly) int iStep, int& nBlock, double time, bool psolOnly)
{ {
if (psol.empty()) if (psol.empty())
return true; return true;
@ -922,7 +1011,7 @@ bool SIMbase::writeGlvS (const Vector& psol,
return false; return false;
if (!psolOnly) if (!psolOnly)
myProblem->initResultPoints(); myProblem->initResultPoints(time);
Matrix field; Matrix field;
size_t i, j; size_t i, j;
@ -1193,12 +1282,12 @@ void SIMbase::dumpPrimSol (const Vector& psol, std::ostream& os,
bool SIMbase::dumpGeometry (std::ostream& os) const bool SIMbase::dumpGeometry (std::ostream& os) const
{ {
bool retVal = true; for (size_t i = 0; i < myModel.size(); i++)
for (size_t i = 0; i < myModel.size() && retVal; i++)
if (!myModel[i]->empty()) if (!myModel[i]->empty())
retVal = myModel[i]->write(os); if (!myModel[i]->write(os))
return false;
return retVal; return true;
} }
@ -1239,7 +1328,7 @@ bool SIMbase::dumpSolution (const Vector& psol, std::ostream& os) const
// Evaluate secondary solution variables // Evaluate secondary solution variables
LocalSystem::patch = i; LocalSystem::patch = i;
if (!myModel[i]->evalSolution(field,*myProblem,0)) if (!myModel[i]->evalSolution(field,*myProblem))
return false; return false;
// Write the secondary solution // Write the secondary solution
@ -1256,34 +1345,63 @@ bool SIMbase::dumpSolution (const Vector& psol, std::ostream& os) const
} }
void SIMbase::readLinSolParams (std::istream& is, int npar) bool SIMbase::dumpResults (const Vector& psol, double time, std::ostream& os,
std::streamsize outputPrecision) const
{ {
if (!mySolParams) mySolParams = new LinSolParams(); if (psol.empty() || myPoints.empty())
mySolParams->read(is,npar); return true;
}
myProblem->initResultPoints(time);
bool SIMbase::finalizeAssembly (bool newLHSmatrix) size_t i, j, k;
{ Matrix sol1, sol2;
// Communication of matrix and vector assembly (for PETSC only)
SystemMatrix* A = myEqSys->getMatrix(); for (i = 0; i < myModel.size(); i++)
if (A && newLHSmatrix)
{ {
if (!A->beginAssembly()) return false; if (myModel[i]->empty()) continue; // skip empty patches
if (!A->endAssembly()) return false;
#if SP_DEBUG > 3
std::cout <<"\nSystem coefficient matrix:"<< *A;
#endif
}
SystemVector* b = myEqSys->getVector(); ResPointVec::const_iterator p;
if (b) std::vector<size_t> points;
{ RealArray params[3];
if (!b->beginAssembly()) return false;
if (!b->endAssembly()) return false; // Find all evaluation points within this patch, if any
#if SP_DEBUG > 3 for (j = 0, p = myPoints.begin(); p != myPoints.end(); j++, p++)
std::cout <<"\nSystem right-hand-side vector:"<< *b; if (this->getLocalPatchIndex(p->patch) == (int)(i+1))
#endif {
points.push_back(j+1);
for (k = 0; k < myModel[i]->getNoParamDim(); k++)
params[k].push_back(p->param[k]);
}
if (points.empty()) continue; // no points in this patch
// Evaluate the primary solution variables
myModel[i]->extractNodeVec(psol,myProblem->getSolution());
if (!myModel[i]->evalSolution(sol1,myProblem->getSolution(),params,false))
return false;
// Evaluate the secondary solution variables
LocalSystem::patch = i;
if (!myModel[i]->evalSolution(sol2,*myProblem,params,false))
return false;
// Formatted output, use scientific notation with fixed field width
std::streamsize flWidth = 8 + outputPrecision;
std::streamsize oldPrec = os.precision(outputPrecision);
std::ios::fmtflags oldF = os.flags(std::ios::scientific | std::ios::right);
for (j = 0; j < points.size(); j++)
{
os <<" Result point #"<< points[j];
os <<": sol1 =";
for (k = 1; k <= sol1.rows(); k++)
os << std::setw(flWidth) << sol1(k,j+1);
os <<" sol2 =";
for (k = 1; k <= sol2.rows(); k++)
os << std::setw(flWidth) << sol2(k,j+1);
os << std::endl;
}
os.precision(oldPrec);
os.flags(oldF);
} }
return true; return true;
@ -1293,13 +1411,14 @@ bool SIMbase::finalizeAssembly (bool newLHSmatrix)
bool SIMbase::project (Vector& psol) bool SIMbase::project (Vector& psol)
{ {
Matrix values; Matrix values;
Vector psol2(psol.size()); Vector ssol(psol.size());
for (size_t i = 0; i < myModel.size(); ++i) { for (size_t i = 0; i < myModel.size(); i++)
{
myModel[i]->extractNodeVec(psol,myProblem->getSolution()); myModel[i]->extractNodeVec(psol,myProblem->getSolution());
myModel[i]->evalSolution(values,*myProblem,NULL); if (!myModel[i]->evalSolution(values,*myProblem)) return false;
myModel[i]->injectNodeVec(values,psol2); myModel[i]->injectNodeVec(values,ssol);
} }
psol = psol2; psol = ssol;
return true; return true;
} }

View File

@ -19,6 +19,7 @@
#include "TimeDomain.h" #include "TimeDomain.h"
#include "Property.h" #include "Property.h"
#include "Function.h" #include "Function.h"
#include "Vec3.h"
#include <map> #include <map>
class ASMbase; class ASMbase;
@ -39,11 +40,28 @@ struct Mode
int eigNo; //!< Eigenvalue identifier int eigNo; //!< Eigenvalue identifier
double eigVal; //!< Eigenvalue associated with this mode double eigVal; //!< Eigenvalue associated with this mode
Vector eigVec; //!< Eigenvector associated with this mode Vector eigVec; //!< Eigenvector associated with this mode
// \brief Default constructor setting \a eigNo and \a eigVal to zero. // \brief Default constructor.
Mode() { eigNo = 0; eigVal = 0.0; } Mode() : eigNo(0), eigVal(0.0) {}
}; };
/*!
\brief Struct defining a result sampling point.
*/
struct ResultPoint
{
unsigned char npar; //!< Number of parameters
size_t patch; //!< Patch index [0,nPatch>
double param[3]; //!< Parameters of the point (u,v,w)
Vec3 X; //!< Spatial coordinates of the point
// \brief Default constructor.
ResultPoint() : npar(0), patch(0) { param[0] = param[1] = param[2] = 0.0; }
};
typedef std::vector<ResultPoint> ResPointVec; //!< Result point container
/*! /*!
\brief Base class for NURBS-based FEM simulators. \brief Base class for NURBS-based FEM simulators.
\details This class incapsulates data and methods need for solving \details This class incapsulates data and methods need for solving
@ -136,10 +154,9 @@ public:
bool assembleSystem(const TimeDomain& time, const Vectors& pSol = Vectors(), bool assembleSystem(const TimeDomain& time, const Vectors& pSol = Vectors(),
bool newLHSmatrix = true); bool newLHSmatrix = true);
//! \brief Finalize system assembly. //! \brief Finalizes system assembly.
// TODO: This HAS to be called from subclasses if assembleSystem //TODO: This HAS to be called from subclasses if assembleSystem is overridden.
// is overridden. This need to be fixed, probably through // This need to be fixed, probably through a wrapper function.
// a wrapper function
bool finalizeAssembly(bool newLHSmatrix); bool finalizeAssembly(bool newLHSmatrix);
//! \brief Administers assembly of the linear equation system. //! \brief Administers assembly of the linear equation system.
@ -262,9 +279,10 @@ public:
//! \param[in] nViz Number of visualization points over each knot-span //! \param[in] nViz Number of visualization points over each knot-span
//! \param[in] iStep Load/time step identifier //! \param[in] iStep Load/time step identifier
//! \param nBlock Running result block counter //! \param nBlock Running result block counter
//! \param[in] time Load/time step parameter
//! \param[in] psolOnly If \e true, skip secondary solution field evaluation //! \param[in] psolOnly If \e true, skip secondary solution field evaluation
virtual bool writeGlvS(const Vector& psol, const int* nViz, int iStep, virtual bool writeGlvS(const Vector& psol, const int* nViz, int iStep,
int& nBlock, bool psolOnly = false); int& nBlock, double time = 0.0, bool psolOnly = false);
//! \brief Writes a mode shape and associated eigenvalue to the VTF-file. //! \brief Writes a mode shape and associated eigenvalue to the VTF-file.
//! \details The eigenvalue is used as a label on the step state info //! \details The eigenvalue is used as a label on the step state info
@ -299,6 +317,13 @@ public:
//! \param[in] psol Primary solution vector to derive other quantities from //! \param[in] psol Primary solution vector to derive other quantities from
//! \param os Output stream to write the solution data to //! \param os Output stream to write the solution data to
bool dumpSolution(const Vector& psol, std::ostream& os) const; bool dumpSolution(const Vector& psol, std::ostream& os) const;
//! \brief Dumps solution results at specified points in ASCII format.
//! \param[in] psol Primary solution vector to derive other quantities from
//! \param[in] time Load/time step parameter
//! \param os Output stream to write the solution data to
//! \param[in] outputPrecision Number of digits after the decimal point
bool dumpResults(const Vector& psol, double time, std::ostream& os,
std::streamsize outputPrecision = 3) const;
//! \brief Dumps the primary solution in ASCII format for inspection. //! \brief Dumps the primary solution in ASCII format for inspection.
//! \param[in] psol Primary solution vector //! \param[in] psol Primary solution vector
//! \param os Output stream to write the solution data to //! \param os Output stream to write the solution data to
@ -376,6 +401,7 @@ protected:
Integrand* myProblem; //!< Problem-specific data and methods Integrand* myProblem; //!< Problem-specific data and methods
AnaSol* mySol; //!< Analytical/Exact solution AnaSol* mySol; //!< Analytical/Exact solution
VTF* myVtf; //!< VTF-file for result visualization VTF* myVtf; //!< VTF-file for result visualization
ResPointVec myPoints; //!< User-defined result sampling points
// Parallel computing attributes // Parallel computing attributes
int nGlPatches; //!< Number of global patches int nGlPatches; //!< Number of global patches