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)
: Elasticity(n)
: Elasticity(n), loadOp(lop), plam(-999.9)
{
loadOp = lop;
// Only the current solution is needed
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();
plam = lambda;
}
}

View File

@ -47,7 +47,8 @@ public:
//! \param[in] prm Nonlinear solution algorithm parameters
virtual void initIntegration(const TimeDomain& prm);
//! \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.
//! \param elmInt The local integral object to receive the contributions
@ -94,6 +95,7 @@ protected:
private:
char loadOp; //!< Load option
double plam; //!< Load parameter of the previous result evaluation
friend class ElasticityNormUL;
};

View File

@ -104,12 +104,14 @@ void PlasticMaterial::initIntegration (const TimeDomain& prm)
if (prm.it > 0 || prm.first) return;
int nUpdated = 0;
for (size_t i = 0; i < itgPoints.size(); i++)
itgPoints[i]->updateHistoryVars();
if (itgPoints[i]->updateHistoryVars())
nUpdated++;
#if INT_DEBUG > 0
std::cout <<"PlasticMaterial::initIntegration: History updated "
<< itgPoints.size() << std::endl;
<< nUpdated << std::endl;
#endif
}
@ -123,12 +125,14 @@ void PlasticMaterial::initResultPoints ()
iP2 = 0;
iAmIntegrating = false;
int nUpdated = 0;
for (size_t i = 0; i < resPoints.size(); i++)
resPoints[i]->updateHistoryVars();
if (resPoints[i]->updateHistoryVars())
nUpdated++;
#if INT_DEBUG > 0
std::cout <<"PlasticMaterial::initResultPoints: History updated "
<< resPoints.size() << std::endl;
<< nUpdated << std::endl;
#endif
}
@ -170,7 +174,7 @@ bool PlasticMaterial::evaluate (Matrix& C, SymmTensor& sigma, double&,
PlasticMaterial::PlasticPoint::PlasticPoint (const PlasticMaterial* prm,
unsigned short int n)
: pMAT(prm->pMAT), Fp(n)
: pMAT(prm->pMAT), updated(false), Fp(n)
{
// Initialize the history variables
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
memcpy(HVp,HVc,sizeof(HVc));
updated = false;
return true;
}
@ -209,6 +218,12 @@ bool PlasticMaterial::PlasticPoint::evaluate (Matrix& C,
int ierr = -99;
#ifdef USE_FTNMAT
// 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)
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);
@ -223,5 +238,6 @@ bool PlasticMaterial::PlasticPoint::evaluate (Matrix& C,
std::cerr <<" *** PlasticMaterial::evaluate: Not included."<< std::endl;
#endif
const_cast<PlasticPoint*>(this)->updated = true;
return ierr == 0;
}

View File

@ -52,7 +52,7 @@ class PlasticMaterial : public Material
PlasticPoint(const PlasticMaterial* prm, unsigned short int n);
//! \brief Updates the internal history variables after convergence.
void updateHistoryVars();
bool updateHistoryVars();
//! \brief Evaluates the constitutive relation at this 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 HVp[10]; //!< History variables, previous configuration
bool updated; //!< Flag indicating whether history variables are updated
public:
Tensor Fp; //!< Deformation gradient, previous configuration

View File

@ -76,7 +76,7 @@ int main (int argc, char** argv)
bool twoD = false;
char* infile = 0;
LinAlgInit linalg(argc,argv);
const LinAlgInit& linalg = LinAlgInit::Init(argc,argv);
std::vector<int> options(2,0);
for (int i = 1; i < argc; i++)
@ -294,6 +294,9 @@ int main (int argc, char** argv)
if (!simulator.solveStep(params,SIM::STATIC))
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)
{
// 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.
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.
*/
@ -225,6 +225,12 @@ 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 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.
//! \param[out] grid The generated finite element grid
//! \param[in] npe Number of visualization nodes over each knot span
@ -295,7 +301,7 @@ public:
virtual void extractNodeVec(const Vector& globVec, Vector& nodeVec,
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 globVec Global solution vector in DOF-order
//! \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)
: 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::ifstream is(fileName);
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)
: ASMstruct(1,n_s,n_f)
: ASMstruct(1,n_s,n_f), curv(0)
{
curv = 0;
this->read(is);
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)
: 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
{
if (!curv) return false;
@ -772,6 +782,8 @@ Go::GeomObject* ASMs1D::evalSolution (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;
return 0;
}

View File

@ -122,6 +122,12 @@ public:
// 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.
//! \param[out] grid The generated line grid
//! \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)
: 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::ifstream is(fileName);
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)
: ASMstruct(2,n_s,n_f)
: ASMstruct(2,n_s,n_f), surf(0)
{
surf = 0;
this->read(is);
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)
: 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;
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;
return X;
@ -753,7 +748,7 @@ void ASMs2D::extractBasis (const Go::BasisDerivsSf2& spline,
#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]
<<" 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 v0 = 0.5*(gpar[1](1,i2-p2+1) + gpar[1](nGauss,i2-p2+1));
surf->point(X0,u0,v0);
X.x = X0[0];
X.y = X0[1];
for (unsigned char i = 0; i < nsd; i++)
X[i] = X0[i];
}
// 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
{
if (!surf) return false;

View File

@ -195,6 +195,12 @@ 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
virtual bool evalPoint(const double* xi, double* param, Vec3& X) const;
//! \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

View File

@ -31,11 +31,8 @@
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::ifstream is(fileName);
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)
: ASMstruct(3,3,n_f)
: ASMstruct(3,3,n_f), svol(0), swapW(false)
{
svol = 0;
swapW = false;
if (this->read(is) && checkRHS)
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
{
if (!svol) return false;

View File

@ -90,7 +90,7 @@ public:
//! \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; }
ASMs3D(unsigned char n_f = 3) : ASMstruct(3,3,n_f), svol(0), swapW(false) {}
//! \brief Empty destructor.
virtual ~ASMs3D() {}
@ -260,6 +260,12 @@ 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
virtual bool evalPoint(const double* xi, double* param, Vec3& X) const;
//! \brief Creates a hexahedron element model of this patch for visualization.
//! \param[out] grid The generated hexahedron grid
//! \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.
\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
containing all physical properties for the problem to be solved.
The interface has several overloaded versions of the \a evalInt method, for
evaluation of the coefficient matrix contributions at an element-interior
integration point. Only one of these methods needs to be implemented, and
which one to use is governed by the \a getIntegrandType method.
There is also one method intended for mixed field interpolation problems.
The interface consists of methods for evaluating the integrand at interior
integration points (\a evalInt), and at boundary integration points
(\a evalBou). The latter are used for Neumann boundary conditions, typically.
The integrand evaluation methods have access to the FE basis function values
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
@ -51,18 +53,28 @@ public:
//! \brief Empty destructor.
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 {}
// Global initialization interface
// ===============================
//! \brief Defines the solution mode before the element assembly is started.
virtual void setMode(SIM::SolutionMode) {}
//! \brief Initializes the integrand for a new integration loop.
//! \details This method is invoked once before starting the numerical
//! integration over the entire spatial domain.
virtual void initIntegration(const TimeDomain&) {}
//! \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.
//! \param[in] MNPC Matrix of nodal point correspondance for current element
@ -85,7 +97,7 @@ public:
//! \brief Initializes current element for numerical integration.
//! \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
//! integration loop is started.
virtual bool initElement(const std::vector<int>& MNPC)
@ -122,17 +134,18 @@ public:
return false;
}
//! \brief Finalizes the element quantities after the numerical integration.
//! \details This method is invoked once for each element, after the numerical
//! 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
//! 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;
}
// Integrand evaluation interface
// ==============================
//! \brief Defines which FE quantities are needed by the integrand.
//! \return 1: The basis functions and their gradients are needed
//! \return 2: As 1, but in addition the second derivatives of the basis
//! functions and the characteristic element size is needed
//! \return 3: As 1, but in addition the volume-averaged basis functions
//! 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.
//! \param elmInt The local integral object to receive the contributions
@ -163,6 +176,18 @@ public:
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.
//! \param elmInt The local integral object to receive the contributions
//! \param[in] fe Finite element data of current integration point
@ -212,6 +237,10 @@ protected:
const Vec3&, const Vec3&) const { return false; }
public:
// Solution field evaluation interface
// ===================================
//! \brief Evaluates the secondary solution at a result point.
//! \param[out] s The solution field values at current point
//! \param[in] N Basis function values at current point
@ -294,35 +323,24 @@ public:
return false;
}
// Various service methods
// =======================
//! \brief Writes surface tractions/fluxes for a given time step to VTF-file.
//! \param vtf The VTF-file object to receive the tractions
//! \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; }
virtual bool writeGlvT(VTF*, int, int&) const { return true; }
//! \brief Returns whether there are any traction/flux values to write to VTF.
virtual bool hasTractionValues() const { return false; }
//! \brief Returns which integrand to be used.
virtual int getIntegrandType() const { return 1; }
//! \brief Returns the number of secondary solution field components.
//! \brief Returns the number of (secondary) solution field components.
virtual size_t getNoFields() const { return 0; }
//! \brief Returns the number of secondary solution field components.
virtual size_t getNoSecFields() 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 the name of a (secondary) solution field component.
virtual const char* getFieldLabel(size_t, const char* = 0) const { return 0; }
//! \brief Returns a pointer to an Integrand for solution norm evaluation.
//! \param[in] asol Pointer to the analytical solution (optional)
virtual NormBase* getNormIntegrand(AnaSol* asol = 0) const { return 0; }
virtual NormBase* getNormIntegrand(AnaSol* = 0) const { return 0; }
//! \brief Returns the number of solution vectors.
size_t getNoSolutions() const { return primsol.size(); }
@ -331,7 +349,7 @@ public:
Vector& getSolution(size_t n = 0) { return primsol[n]; }
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
if (!solution.empty())
if (!model->writeGlvS(solution.front(),nViz,iStep,nBlock,psolOnly))
if (!model->writeGlvS(solution.front(),nViz,iStep,nBlock,time,psolOnly))
return false;
// 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 ()
{
return model->project(solution.front());

View File

@ -96,14 +96,19 @@ public:
//! \param[in] psolOnly If \e true, skip secondary solution field output
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] 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
void dumpStep(int iStep, double time, std::ostream& os,
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.
const Vector& getSolution() const { return solution.front(); }

View File

@ -26,13 +26,13 @@
#include "ElmNorm.h"
#include "AnaSol.h"
#include "Tensor.h"
#include "Vec3.h"
#include "Vec3Oper.h"
#include "EigSolver.h"
#include "Profiler.h"
#include "ElementBlock.h"
#include "VTF.h"
#include "Utilities.h"
#include <iomanip>
#include <ctype.h>
#include <stdio.h>
@ -103,7 +103,7 @@ bool SIMbase::parse (char* keyWord, std::istream& is)
char* cline = 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 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]))
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 ()
{
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
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
#ifdef PARALLEL_PETSC
mySam = new SAMpatchPara(l2gn);
@ -337,10 +398,11 @@ bool SIMbase::setMode (int mode)
void SIMbase::printProblem (std::ostream& os) const
{
if (!myProblem) return;
std::cout <<"\nProblem definition:"<< std::endl;
myProblem->print(os);
if (myProblem)
{
std::cout <<"\nProblem definition:"<< std::endl;
myProblem->print(os);
}
#if SP_DEBUG > 1
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
{
SystemVector* b = myEqSys->getVector();
@ -612,7 +701,7 @@ bool SIMbase::solutionNorms (const TimeDomain& time, const Vectors& psol,
myProblem->initIntegration(time);
size_t nNorms = norm->getNoFields() + norm->getNoSecFields();
size_t nNorms = norm->getNoFields();
const Vector& primsol = psol.front();
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,
const int* nViz, int iStep, int& nBlock, bool psolOnly)
bool SIMbase::writeGlvS (const Vector& psol, const int* nViz,
int iStep, int& nBlock, double time, bool psolOnly)
{
if (psol.empty())
return true;
@ -922,7 +1011,7 @@ bool SIMbase::writeGlvS (const Vector& psol,
return false;
if (!psolOnly)
myProblem->initResultPoints();
myProblem->initResultPoints(time);
Matrix field;
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 retVal = true;
for (size_t i = 0; i < myModel.size() && retVal; i++)
for (size_t i = 0; i < myModel.size(); i++)
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
LocalSystem::patch = i;
if (!myModel[i]->evalSolution(field,*myProblem,0))
if (!myModel[i]->evalSolution(field,*myProblem))
return false;
// 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();
mySolParams->read(is,npar);
}
if (psol.empty() || myPoints.empty())
return true;
myProblem->initResultPoints(time);
bool SIMbase::finalizeAssembly (bool newLHSmatrix)
{
// Communication of matrix and vector assembly (for PETSC only)
SystemMatrix* A = myEqSys->getMatrix();
if (A && newLHSmatrix)
size_t i, j, k;
Matrix sol1, sol2;
for (i = 0; i < myModel.size(); i++)
{
if (!A->beginAssembly()) return false;
if (!A->endAssembly()) return false;
#if SP_DEBUG > 3
std::cout <<"\nSystem coefficient matrix:"<< *A;
#endif
}
if (myModel[i]->empty()) continue; // skip empty patches
SystemVector* b = myEqSys->getVector();
if (b)
{
if (!b->beginAssembly()) return false;
if (!b->endAssembly()) return false;
#if SP_DEBUG > 3
std::cout <<"\nSystem right-hand-side vector:"<< *b;
#endif
ResPointVec::const_iterator p;
std::vector<size_t> points;
RealArray params[3];
// Find all evaluation points within this patch, if any
for (j = 0, p = myPoints.begin(); p != myPoints.end(); j++, p++)
if (this->getLocalPatchIndex(p->patch) == (int)(i+1))
{
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;
@ -1293,13 +1411,14 @@ bool SIMbase::finalizeAssembly (bool newLHSmatrix)
bool SIMbase::project (Vector& psol)
{
Matrix values;
Vector psol2(psol.size());
for (size_t i = 0; i < myModel.size(); ++i) {
Vector ssol(psol.size());
for (size_t i = 0; i < myModel.size(); i++)
{
myModel[i]->extractNodeVec(psol,myProblem->getSolution());
myModel[i]->evalSolution(values,*myProblem,NULL);
myModel[i]->injectNodeVec(values,psol2);
if (!myModel[i]->evalSolution(values,*myProblem)) return false;
myModel[i]->injectNodeVec(values,ssol);
}
psol = psol2;
psol = ssol;
return true;
}

View File

@ -19,6 +19,7 @@
#include "TimeDomain.h"
#include "Property.h"
#include "Function.h"
#include "Vec3.h"
#include <map>
class ASMbase;
@ -39,11 +40,28 @@ struct Mode
int eigNo; //!< Eigenvalue identifier
double eigVal; //!< Eigenvalue associated with this mode
Vector eigVec; //!< Eigenvector associated with this mode
// \brief Default constructor setting \a eigNo and \a eigVal to zero.
Mode() { eigNo = 0; eigVal = 0.0; }
// \brief Default constructor.
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.
\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 newLHSmatrix = true);
//! \brief Finalize system assembly.
// TODO: This HAS to be called from subclasses if assembleSystem
// is overridden. This need to be fixed, probably through
// a wrapper function
//! \brief Finalizes system assembly.
//TODO: This HAS to be called from subclasses if assembleSystem is overridden.
// This need to be fixed, probably through a wrapper function.
bool finalizeAssembly(bool newLHSmatrix);
//! \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] iStep Load/time step identifier
//! \param nBlock Running result block counter
//! \param[in] time Load/time step parameter
//! \param[in] psolOnly If \e true, skip secondary solution field evaluation
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.
//! \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 os Output stream to write the solution data to
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.
//! \param[in] psol Primary solution vector
//! \param os Output stream to write the solution data to
@ -376,6 +401,7 @@ protected:
Integrand* myProblem; //!< Problem-specific data and methods
AnaSol* mySol; //!< Analytical/Exact solution
VTF* myVtf; //!< VTF-file for result visualization
ResPointVec myPoints; //!< User-defined result sampling points
// Parallel computing attributes
int nGlPatches; //!< Number of global patches