Files
IFEM/Apps/LinearElasticity/main_LinEl3D.C

398 lines
13 KiB
C

// $Id$
//==============================================================================
//!
//! \file main_LinEl3D.C
//!
//! \date Jan 28 2009
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Main program for the isogeometric linear elasticity solver.
//!
//==============================================================================
#include "SIMLinEl3D.h"
#include "SIMLinEl2D.h"
#include "LinAlgInit.h"
#include "HDF5Writer.h"
#include "XMLWriter.h"
#include "Utilities.h"
#include "Profiler.h"
#include <fstream>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*!
\brief Main program for the NURBS-based isogeometric linear elasticity solver.
The input to the program is specified through the following
command-line arguments. The arguments may be given in arbitrary order.
\arg \a input-file : Input file with model definition
\arg -dense : Use the dense LAPACK matrix equation solver
\arg -spr : Use the SPR direct equation solver
\arg -superlu : Use the sparse SuperLU equation solver
\arg -samg : Use the sparse algebraic multi-grid equation solver
\arg -petsc : Use equation solver from PETSc library
\arg -nGauss \a n : Number of Gauss points over a knot-span in each direction
\arg -vtf \a format : VTF-file format (-1=NONE, 0=ASCII, 1=BINARY)
\arg -nviz \a nviz : Number of visualization points over each knot-span
\arg -nu \a nu : Number of visualization points per knot-span in u-direction
\arg -nv \a nv : Number of visualization points per knot-span in v-direction
\arg -nw \a nw : Number of visualization points per knot-span in w-direction
\arg -hdf5 : Write primary and projected secondary solution to HDF5 file
\arg -dumpASC : Dump model and solution to ASCII files for external processing
\arg -ignore \a p1, \a p2, ... : Ignore these patches in the analysis
\arg -eig \a iop : Eigenproblem solver to use (1...6)
\arg -nev \a nev : Number of eigenvalues to compute
\arg -ncv \a ncv : Number of Arnoldi vectors to use in the eigenvalue analysis
\arg -shift \a shf : Shift value to use in the eigenproblem solver
\arg -free : Ignore all boundary conditions (use in free vibration analysis)
\arg -check : Data check only, read model and output to VTF (no solution)
\arg -checkRHS : Check that the patches are modelled in a right-hand system
\arg -vizRHS : Save the right-hand-side load vector on the VTF-file
\arg -fixDup : Resolve co-located nodes by merging them into a single node
\arg -2D : Use two-parametric simulation driver (plane stress)
\arg -2Dpstrain : Use two-parametric simulation driver (plane strain)
\arg -2Daxisymm : Use two-parametric simulation driver (axi-symmetric solid)
\arg -lag : Use Lagrangian basis functions instead of splines/NURBS
\arg -spec : Use Spectral basis functions instead of splines/NURBS
*/
int main (int argc, char** argv)
{
Profiler prof(argv[0]);
utl::profiler->start("Initialization");
SystemMatrix::Type solver = SystemMatrix::SPARSE;
int nGauss = 4;
int format = -1;
int n[3] = { 2, 2, 2 };
std::vector<int> ignoredPatches;
int iop = 0;
int nev = 10;
int ncv = 20;
double shf = 0.0;
bool checkRHS = false;
bool vizRHS = false;
bool fixDup = false;
bool dumpHDF5 = false;
bool dumpASCII = false;
bool twoD = false;
char* infile = 0;
LinAlgInit& linalg = LinAlgInit::Init(argc,argv);
for (int i = 1; i < argc; i++)
if (!strcmp(argv[i],"-dense"))
solver = SystemMatrix::DENSE;
else if (!strcmp(argv[i],"-spr"))
solver = SystemMatrix::SPR;
else if (!strncmp(argv[i],"-superlu",8))
{
solver = SystemMatrix::SPARSE;
if (isdigit(argv[i][8]))
SIMbase::num_threads_SLU = atoi(argv[i]+8);
}
else if (!strcmp(argv[i],"-samg"))
solver = SystemMatrix::SAMG;
else if (!strcmp(argv[i],"-petsc"))
solver = SystemMatrix::PETSC;
else if (!strcmp(argv[i],"-nGauss") && i < argc-1)
nGauss = atoi(argv[++i]);
else if (!strcmp(argv[i],"-vtf") && i < argc-1)
format = atoi(argv[++i]);
else if (!strcmp(argv[i],"-nviz") && i < argc-1)
n[0] = n[1] = n[2] = atoi(argv[++i]);
else if (!strcmp(argv[i],"-nu") && i < argc-1)
n[0] = atoi(argv[++i]);
else if (!strcmp(argv[i],"-nv") && i < argc-1)
n[1] = atoi(argv[++i]);
else if (!strcmp(argv[i],"-nw") && i < argc-1)
n[2] = atoi(argv[++i]);
else if (!strcmp(argv[i],"-hdf5"))
dumpHDF5 = true;
else if (!strcmp(argv[i],"-dumpASC"))
dumpASCII = true;
else if (!strcmp(argv[i],"-ignore"))
while (i < argc-1 && isdigit(argv[i+1][0]))
utl::parseIntegers(ignoredPatches,argv[++i]);
else if (!strcmp(argv[i],"-eig") && i < argc-1)
iop = atoi(argv[++i]);
else if (!strcmp(argv[i],"-nev") && i < argc-1)
nev = atoi(argv[++i]);
else if (!strcmp(argv[i],"-ncv") && i < argc-1)
ncv = atoi(argv[++i]);
else if (!strcmp(argv[i],"-shift") && i < argc-1)
shf = atof(argv[++i]);
else if (!strcmp(argv[i],"-free"))
SIMbase::ignoreDirichlet = true;
else if (!strcmp(argv[i],"-check"))
iop = 100;
else if (!strcmp(argv[i],"-checkRHS"))
checkRHS = true;
else if (!strcmp(argv[i],"-vizRHS"))
vizRHS = true;
else if (!strcmp(argv[i],"-fixDup"))
fixDup = true;
else if (!strncmp(argv[i],"-2Dpstra",8))
twoD = SIMLinEl2D::planeStrain = true;
else if (!strncmp(argv[i],"-2Daxi",6))
twoD = SIMLinEl2D::axiSymmetry = true;
else if (!strncmp(argv[i],"-2D",3))
twoD = true;
else if (!strncmp(argv[i],"-lag",4))
SIMbase::discretization = SIMbase::Lagrange;
else if (!strncmp(argv[i],"-spec",5))
SIMbase::discretization = SIMbase::Spectral;
else if (!infile)
infile = argv[i];
else
std::cerr <<" ** Unknown option ignored: "<< argv[i] << std::endl;
if (!infile)
{
std::cout <<"usage: "<< argv[0]
<<" <inputfile> [-dense|-spr|-superlu[<nt>]|-samg|-petsc]\n "
<<" [-free] [-lag] [-spec] [-2D[pstrain|axisymm]] [-nGauss <n>]\n"
<<" [-vtf <format> [-nviz <nviz>]"
<<" [-nu <nu>] [-nv <nv>] [-nw <nw>]] [-hdf5]\n"
<<" [-eig <iop> [-nev <nev>] [-ncv <ncv] [-shift <shf>]]\n"
<<" [-ignore <p1> <p2> ...] [-fixDup]"
<<" [-checkRHS] [-check] [-dumpASC]\n";
return 0;
}
if (twoD) n[2] = 1;
// Load vector visualization is not available when using additional viz-points
if (n[0] > 2 || n[1] > 2 || n[2] > 2) vizRHS = false;
// Boundary conditions can be ignored only in generalized eigenvalue analysis
if (iop != 4 && iop != 6) SIMbase::ignoreDirichlet = false;
if (linalg.myPid == 0)
{
std::cout <<"\n >>> Spline FEM Linear Elasticity solver <<<"
<<"\n ===========================================\n"
<<"\nInput file: "<< infile
<<"\nEquation solver: "<< solver
<<"\nNumber of Gauss points: "<< nGauss;
if (format >= 0)
{
std::cout <<"\nVTF file format: "<< (format ? "BINARY":"ASCII")
<<"\nNumber of visualization points: "
<< n[0] <<" "<< n[1];
if (!twoD) std::cout <<" "<< n[2];
}
if (iop > 0 && iop < 100)
std::cout <<"\nEigenproblem solver: "<< iop
<<"\nNumber of eigenvalues: "<< nev
<<"\nNumber of Arnoldi vectors: "<< ncv
<<"\nShift value: "<< shf;
if (SIMbase::discretization == SIMbase::Lagrange)
std::cout <<"\nLagrangian basis functions are used";
else if (SIMbase::discretization == SIMbase::Spectral)
std::cout <<"\nSpectral basis functions are used";
if (SIMbase::ignoreDirichlet)
std::cout <<"\nSpecified boundary conditions are ignored";
if (fixDup)
std::cout <<"\nCo-located nodes will be merged";
if (checkRHS)
std::cout <<"\nCheck that each patch has a right-hand coordinate system";
if (!ignoredPatches.empty())
{
std::cout <<"\nIgnored patches:";
for (size_t i = 0; i < ignoredPatches.size(); i++)
std::cout <<" "<< ignoredPatches[i];
}
std::cout << std::endl;
}
utl::profiler->stop("Initialization");
utl::profiler->start("Model input");
// Read in model definitions and establish the FE data structures
SIMbase* model;
if (twoD)
model = new SIMLinEl2D();
else
model = new SIMLinEl3D(checkRHS);
if (!model->read(infile))
return 1;
utl::profiler->stop("Model input");
if (linalg.myPid == 0)
model->printProblem(std::cout);
if (!model->preprocess(ignoredPatches,fixDup))
return 1;
model->setQuadratureRule(nGauss);
Matrix eNorm;
Vector gNorm, load;
Vectors displ(1);
std::vector<Mode> modes;
std::vector<Mode>::const_iterator it;
switch (iop) {
case 0:
case 5:
// Static solution: Assemble [Km] and {R}
model->setMode(SIM::STATIC);
model->initSystem(solver,1,1);
model->setAssociatedRHS(0,0);
if (!model->assembleSystem())
return 2;
else if (vizRHS)
model->extractLoadVec(load);
// Solve the linear system of equations
if (!model->solveSystem(displ.front(),1))
return 3;
// Evaluate solution norms
model->setMode(SIM::RECOVERY);
if (!model->solutionNorms(displ,eNorm,gNorm))
return 4;
if (linalg.myPid == 0)
{
std::cout <<"Energy norm |u^h| = a(u^h,u^h)^0.5 : "<< gNorm(1);
std::cout <<"\nExternal energy ((f,u^h)+(t,u^h)^0.5 : "<< gNorm(2);
if (gNorm.size() > 2)
std::cout <<"\nExact norm |u| = a(u,u)^0.5 : "<< gNorm(3);
if (gNorm.size() > 3)
std::cout <<"\nExact error a(e,e)^0.5, e=u-u^h : "<< gNorm(4)
<<"\nExact relative error (%) : "<< gNorm(4)/gNorm(3)*100.0;
std::cout << std::endl;
}
if (iop == 0) break;
// Linearized buckling: Assemble [Km] and [Kg]
model->setMode(SIM::BUCKLING);
model->initSystem(solver,2,0);
if (!model->assembleSystem(displ))
return 5;
// Solve the generalized eigenvalue problem
if (!model->systemModes(modes,nev,ncv,iop,shf))
return 6;
break;
case 1:
case 2:
// Assemble and solve the regular eigenvalue problem
model->setMode(SIM::STIFF_ONLY);
model->initSystem(solver,1,0);
if (!model->assembleSystem())
return 5;
if (!model->systemModes(modes,nev,ncv,iop,shf))
return 6;
break;
case 100:
break; // Model check
default:
// Free vibration: Assemble [Km] and [M]
model->setMode(SIM::VIBRATION);
model->initSystem(solver,2,0);
if (!model->assembleSystem())
return 5;
if (!model->systemModes(modes,nev,ncv,iop,shf))
return 6;
}
utl::profiler->start("Postprocessing");
if (dumpHDF5 && !displ.front().empty())
{
strtok(infile,".");
if (linalg.myPid == 0)
std::cout <<"\nWriting HDF5 file "<< infile <<".hdf5"<< std::endl;
DataExporter exporter(true);
exporter.registerField("u","solution",DataExporter::SIM,-1);
exporter.setFieldValue("u",model,&displ.front());
exporter.registerWriter(new HDF5Writer(infile));
exporter.registerWriter(new XMLWriter(infile));
exporter.dumpTimeLevel();
}
if (format >= 0)
{
// Write VTF-file with model geometry
int iStep = 1, nBlock = 0;
if (!model->writeGlv(infile,n,format))
return 7;
// Write boundary tractions, if any
if (!model->writeGlvT(iStep,nBlock))
return 8;
// Write Dirichlet boundary conditions
if (!model->writeGlvBC(n,nBlock))
return 8;
// Write load vector to VTF-file
if (!model->writeGlvV(load,"Load vector",n,iStep,nBlock))
return 9;
// Write solution fields to VTF-file
if (!model->writeGlvS(displ.front(),n,iStep,nBlock))
return 10;
// Write eigenmodes
for (it = modes.begin(); it != modes.end(); it++)
if (!model->writeGlvM(*it, iop==3 || iop==4 || iop==6, n, nBlock))
return 11;
// Write element norms (when no additional visualization points are used)
if (n[0] == 2 && n[1] == 2 && n[2] <= 2)
if (!model->writeGlvN(eNorm,iStep,nBlock))
return 12;
model->closeGlv();
}
if (dumpASCII)
{
// Write (refined) model to g2-file
std::ofstream osg(strcat(strtok(infile,"."),".g2"));
std::cout <<"\nWriting updated g2-file "<< infile << std::endl;
model->dumpGeometry(osg);
if (!displ.front().empty())
{
// Write solution (control point values) to ASCII files
std::ofstream osd(strcat(strtok(infile,"."),".dis"));
std::cout <<"\nWriting deformation to file "<< infile << std::endl;
model->dumpPrimSol(displ.front(),osd,false);
std::ofstream oss(strcat(strtok(infile,"."),".sol"));
std::cout <<"\nWriting solution to file "<< infile << std::endl;
model->dumpSolution(displ.front(),oss);
}
if (!modes.empty())
{
// Write eigenvectors to ASCII files
std::ofstream ose(strcat(strtok(infile,"."),".eig"));
std::cout <<"\nWriting eigenvectors to file "<< infile << std::endl;
for (it = modes.begin(); it != modes.end(); it++)
{
ose <<"# Eigenvector_"<< it->eigNo <<" Eigenvalue="<< it->eigVal <<"\n";
model->dumpPrimSol(it->eigVec,ose,false);
}
}
}
utl::profiler->stop("Postprocessing");
delete model;
return 0;
}