Files
IFEM/Apps/main_LinElStep.C
2015-07-09 08:50:41 +02:00

252 lines
8.4 KiB
C

// $Id: main_LinElStep.C,v 1.7 2011-02-05 18:32:25 kmo Exp $
//==============================================================================
//!
//! \file main_LinElStep.C
//!
//! \date Jun 1 2010
//!
//! \author Knut Morten Okstad / SINTEF
//!
//! \brief Main program for the isogeometric linear elasticity solver.
//!
//==============================================================================
#include "SIMLinEl3D.h"
#include "LinAlgInit.h"
#include "TimeDomain.h"
#include "Profiler.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*!
\brief Main program for the NURBS-based isogeometric linear elasticity solver.
This program is basicly the same as main_LinEl3D.C, except that this one runs
in a loop over a specified number of load steps to compute the linear solution
for each step, when the load function is assumed to vary with time.
This version is for 3D patches only, and no eigenvalue solution is included.
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 (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 -ignore \a p1, \a p2, ... : Ignore these patches in the analysis
\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 -lag : Use Lagrangian basis functions instead of splines/NURBS
\arg -spec : Use Spectral basis functions instead of splines/NURBS
\arg -nstep \a n : Number of time steps
\arg -dt \a dt : Time increment size
*/
int main (int argc, char** argv)
{
Profiler prof(argv[0]);
utl::profiler->start("Initialization");
SystemMatrix::Type solver = SystemMatrix::SPARSE;
int nGauss = 4;
int format = 0;
int n[3] = { 2, 2, 2 };
std::vector<int> ignoredPatches;
bool checkRHS = false;
bool vizRHS = false;
bool fixDup = false;
char* infile = 0;
TimeDomain time;
int nStep = 1;
LinAlgInit linalg(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 (!strcmp(argv[i],"-superlu"))
solver = SystemMatrix::SPARSE;
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],"-ignore"))
while (i < argc-1 && isdigit(argv[i+1][0]))
{
char* endp = 0;
int endVal = 0;
ignoredPatches.push_back(strtol(argv[++i],&endp,10));
if (endp && *endp == ':')
endVal = strtol(endp+1,&endp,10);
while (ignoredPatches.back() < endVal)
ignoredPatches.push_back(ignoredPatches.back()+1);
}
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],"-lag",4))
SIMbase::discretization = SIMbase::Lagrange;
else if (!strncmp(argv[i],"-spec",5))
SIMbase::discretization = SIMbase::Spectral;
else if (!strcmp(argv[i],"-nstep") && i < argc-1)
nStep = atoi(argv[++i]);
else if (!strcmp(argv[i],"-dt") && i < argc-1)
time.dt = atof(argv[++i]);
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|-samg|-petsc]\n"
<<" [-lag] [-spec] [-nGauss <n>] [-nstep <n>] [-dt <dt>]\n"
<<" [-vtf <format>] [-nviz <nviz>]"
<<" [-nu <nu>] [-nv <nv>] [-nw <nw>]\n"
<<" [-ignore <p1> <p2> ...] [-fixDup] [-checkRHS]\n";
return 0;
}
// Load vector visualization is not available when using additional viz-points
if (n[0] > 2 || n[1] > 2 || n[2] > 2) vizRHS = false;
std::cout <<"\n >>> Spline FEM Linear Elasticity solver <<<"
<<"\n ===========================================\n"
<<"\nInput file: "<< infile
<<"\nEquation solver: "<< solver
<<"\nNumber of Gauss points: "<< nGauss
<<"\nVTF file format: "<< (format ? "BINARY":"ASCII")
<<"\nNumber of visualization points: "
<< n[0] <<" "<< n[1] <<" "<< n[2];
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 (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 structures
SIMbase* model = new SIMLinEl3D(checkRHS);
if (!model->read(infile) || !model->preprocess(ignoredPatches,fixDup))
return 1;
model->setQuadratureRule(nGauss);
utl::profiler->stop("Model input");
// Write VTF-file with model geometry
int nBlock = 0;
if (!model->writeGlv(infile,n,format))
return 2;
// Write Dirichlet boundary conditions
if (!model->writeGlvBC(n,nBlock))
return 3;
Matrix eNorm;
Vector gNorm, displ, load;
model->initSystem(solver,1,1);
model->setAssociatedRHS(0,0);
for (int iStep = 1; iStep <= nStep; iStep++)
{
time.t += time.dt;
std::cout <<"\n\nStep "<< iStep <<", time = "<< time.t << std::endl;
model->setMode(SIM::STATIC);
if (!model->assembleSystem(time))
return 4;
else if (vizRHS)
model->extractLoadVec(load);
// Solve the linear system of equations
if (!model->solveSystem(displ,1))
return 5;
// Evaluate solution norms
model->setMode(SIM::RECOVERY);
if (!model->solutionNorms(Vectors(1,displ),eNorm,gNorm))
return 6;
std::cout <<"Energy norm |u^h| = a(u^h,u^h)^0.5 : "<< gNorm(1);
if (gNorm.size() > 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;
utl::profiler->start("Postprocessing");
// Write boundary tractions, if any
if (!model->writeGlvT(iStep,nBlock))
return 7;
// Write load vector to VTF-file
if (!model->writeGlvV(load,"Load vector",n,iStep,nBlock))
return 8;
// Write solution fields to VTF-file
if (!model->writeGlvS(displ,n,iStep,nBlock))
return 9;
// Write element norms, if feasable
if (n[0] == 2 && n[1] == 2 && n[2] == 2)
if (!model->writeGlvN(eNorm,iStep,nBlock))
return 10;
// Write step information to VTF-file
if (!model->writeGlvStep(iStep,time.t))
return 11;
utl::profiler->stop("Postprocessing");
}
model->closeGlv();
delete model;
return 0;
}