The solution step may represent either a time step, a load increment, or a load case. The solution steps are grouped together into so called meta steps. The meta step can be thought as a sequence of solution steps, with the same set of attributes used to drive the behavior of engng model. For each meta step, the engng model typically updates certain attribute values according to meta step model attributes (see updateAttributes service) and creates the solution steps accordingly. This allows to switch to a different time increment, a different solution control, etc. If no meta step is specified, the engng model creates a default one for all required solution steps. There are two services, where engng model attributes are set or updated. The first one, used for those attributes which do not vary during the solution of the problem, are initialized in instanciateYourself service. The second service is updateAttributes, where the attributes (with meta step validity) are updated according to a values valid for the given meta step. If no meta step is introduced, a default one is created (with the attributes set to the engng model attributes). Then there is no difference, whether the attributes are initialized in instanciateYourself or in updateAttributes, but the preferred scheme is to read all attributes in instanciateYourself and to left updateAttributes service empty.
The basic EngngModel tasks are following:
The complete listing of EngngModel class declaration folows.
/* $Header: /home/cvs/bp/oofem/doc/usrman/usrman.tex,v 1.7 2003/04/23 14:19:27 bp Exp $ */
// ************************
// *** CLASS ENGNGMODEL ***
// ************************
class EngngModel
{
protected:
/// number of receiver domains
int ndomains;
/// List of problem domains
AList<Domain>* domainList;
/// Total number of time steps
int numberOfSteps;
/// total number of equation in cuurent time step
int numberOfEquations;
/// total number or prescribed equations in current time step
int numberOfPrescribedEquations;
/// number of equations per domain
IntArray domainNeqs;
/// number of prescribed equations per domain
IntArray domainPrescribedNeqs;
/// renumbering flag
int renumberFlag;
/// equation numbering completed flag
int equationNumberingCompleted;
/// number of meta steps
int nMetaSteps;
/// List of problem metasteps
AList<MetaStep>* metaStepList;
/// Solution step when IC (initial conditions) apply
TimeStep* stepWhenIcApply;
/// Currnet time step
TimeStep* currentStep ;
/// Previous time step
TimeStep* previousStep;
/// receivers id
int number ;
/// Path to input stream
//char* dataInputFileName ;
/// Path to output stream
char* dataOutputFileName ;
/// Output stream
FILE* outputStream;
/// Input stream
//FILE* inputStream;
/// Domain context output mode
ContextOutputMode contextOutputMode;
int contextOutputStep;
///Export module manager
ExportModuleManager* exportModuleManager;
/// Domain mode
problemMode pMode ;
/// solution start time
time_t startTime;
// initial value of processor time used by program
// clock_t startClock;
/// master e-model; if defined receiver is in maintained (slave) mode
EngngModel* master;
/// context
EngngModelContext* context;
/**
flag indicating that the receiver runs in parallel.
*/
int parallelFlag;
public:
/**
Constructor. Creates Engng model with number i belonging to domain d.
*/
EngngModel (int i, EngngModel* _master = NULL) ; // constructor
/**
Constructor. Creates Engng model with number i and input file given by path.
*/
EngngModel (int i, char* s, EngngModel* _master = NULL);
/// Destructor.
virtual ~EngngModel () ; // destructor
/**
Service for accessing particular problem domain.
Generates error if no such domain is defined.
@param: n pointer to n-th domain is returned
*/
Domain* giveDomain (int n);
/// Returns number of domains in problem.
int giveNumberOfDomains () {return ndomains;}
/** Service for accessing ErrorEstimator corresponding to particular domain */
virtual ErrorEstimator* giveDomainErrorEstimator (int n) {return NULL;}
// input / output
/// Returns input file path.
//char* giveInputDataFileName () ;
/// Returns file descriptor of output file
FILE* giveOutputStream () ;
/** Returns base output file name
to which extensions, like .out .vtk .osf should be added.
In current implementation, output file name is simply returned.
@param path and base file name will be copied into the array pointed to by dest
@param not more than n bytes of src are copied
*/
char * giveOutputBaseFileName(char *dest, size_t n)
{return strncpy (dest, dataOutputFileName, n);}
//FILE* giveInputStream () ;
/*
Returns current time in seconds as returned by time call.
@return current time in time_t structure.
*/
//time_t getTime ();
/*
Returns an approximation of processor time used by the program.
The value returned is the CPU time used so far as a
clock_t; to get the number of seconds used, divide by
CLOCKS_PER_SEC. Calls clock ANSI C function.
The C standard allows for arbitrary values at the start of
the program; take the difference between the value
returned from a call to this method at the start of the pro-
gram and the end to get maximum portability.
*/
//clock_t getClock ();
/**
Returns domain context output mode.
*/
ContextOutputMode giveContextOutputMode () {return contextOutputMode;}
/**
Returns domain context output step.
*/
int giveContextOutputStep () {return contextOutputStep;}
/**
Sets context output mode of receiver.
@param contextMode domain context mode.
*/
void setContextOutputMode (ContextOutputMode contextMode)
{contextOutputMode=contextMode;}
/**
Sets user defined context output mode (it sets contextOutputMode to contextOutputMode),
setting contextOutputStep to given value.
@param cStep new context output step
*/
void setUDContextOutputMode (int cStep)
{contextOutputMode=USERDEFINED; contextOutputStep = cStep;}
/**
Sets domain mode to given mode.
@param mode domain mode.
*/
void setProblemMode (problemMode mode) {pMode = mode;}
/// Returns domain mode.
problemMode giveProblemMode () {return pMode;}
/// Sets the renumber flag to TRUE
virtual void setRenumberFlag() {this->renumberFlag = 1;}
/// Sets the renumber flag to FALSE
virtual void resetRenumberFlag() {this->renumberFlag = 0;}
/**
Performs analysis termination after finishing analysis.
*/
void terminateAnalysis () ;
// solving
/** Starts solution process. Implementation should invoke for each
time step solveYourselfAt function with time step as parameter. Time
steps are created using giveNextStep function (this will set current
time step to newly created, and updates previous step).
*/
virtual void solveYourself ();
/** Solves problem for given time step. Should assemble
characteristic matrices and vectors if necessary and solve problem
using appropriate numerical method. After finishing solution,
this->updateYourself function for updating solution state and then
this->terminate function (for updating nodal and element values)
should be called.
*/
virtual void solveYourselfAt (TimeStep*) {}
//virtual int requiresNewLhs () {return 1;}
/** Terminates the solution of time step. Default implementation
calls prinOutput() service and if specified, context of whole domain
is stored and output for given time step is printed.
*/
virtual void terminate (TimeStep*);
/** Prints the ouput of the solution step (using virtual
this->printOutputAtservice) to the stream detemined using
this->giveOutputStream() method and calls exportModuleManager to do
output. */
virtual void doStepOutput(TimeStep*);
/** Saves context of given solution step, if required (determined
using this->giveContextOutputMode() method).
*/
void saveStepContext(TimeStep*);
/** Updates internal state after finishing time step. (for example
total values may be updated according to previously solved
increments). Then element values are also updated (together with
related integration points and material statuses). */
virtual void updateYourself (TimeStep* stepN);
/** Provides the oportunity to initialize state variables stored in
element integration points acording to initial conditions using
function initializeYourself() on element level. Should be called
when curent time step is time step when IC will aply (see
EngngModel::giveNumberOfTimeStepWhenIcApply) somewhere from
solveYourselfAt function). Implementation must be provided. Default
implementation is empty. */
virtual void initializeYourself (TimeStep*) {}
/** Initializes the newly generated discretization state acording to
previous solution. This process should typically include restoring
old solution, instanciating newly generated domain(s) and by mapping
procedure. */
virtual int initializeAdaptive (int stepNumber) {return 0;}
/** Returns total number of equations in active (current time steep)
time step. The UnknownType parameter allows to distinguis between
several possible governing equations, that can be numbered
separately. */
virtual int giveNumberOfEquations (EquationID);
/** Returns total number of prescribed equations in active (current
time steep) time step. The UnknownType parameter allows to
distinguis between several possible governing equations, that can be
numbered separately. */
virtual int giveNumberOfPrescribedEquations (EquationID);
/** Returns number of equations for given domain in active (current
time steep) time step. The UnknownType parameter allows to
distinguis between several possible governing equations, that can be
numbered separately. */
virtual int giveNumberOfDomainEquations (int, EquationID);
/** Returns number of prescribed equations for given domain in active
(current time steep) time step. The UnknownType parameter allows to
distinguis between several possible governing equations, that can be
numbered separately. */
virtual int giveNumberOfPrescribedDomainEquations (int, EquationID);
//virtual IntArray* GiveBanWidthVector ();
// management components
/** Provides backward mapping between numerical component and
characteristic component on EngngModel level. */
virtual CharType giveTypeOfComponent (NumericalCmpn) {return UnknownCharType;}
/** Returns requested unknown. Unknown at give time step is
characterized by its type and mode and by its equation number. This
function is used by Dofs, when they are requsted for their associated
unknowns. @see Dof::giveUnknown method */
virtual double giveUnknownComponent (EquationID, ValueModeType, TimeStep*, Domain*, Dof*)
{return 0.0;}
virtual double giveUnknownComponent (UnknownType, ValueModeType, TimeStep*, Domain*, Dof*)
{return 0.0;}
/** Initializes whole problem acording to its description stored in
inputStream. Prints header, opens the outFileName, instanciate
itself the receicer using using virtual initializeFrom service and
instancites all problem domains. */
virtual int instanciateYourself (DataReader* dr, InputRecord* ir,
char* outFileName, char* desc) ;
/** Initializes receiver acording to object description in input
reader. InitString can be imagined as data record in component
database belonging to receiver. Receiver may use value-name
extracting functions to extract particular field from record.*/
virtual IRResultType initializeFrom (InputRecord* ir);
/// Instanciate problem domains by calling their instanciateYourself() service
int instanciateDomains (DataReader* dr);
/// Instanciate problem meta steps by calling their instanciateYourself() service
int instanciateMetaSteps (DataReader *dr);
/// Instanciate default metastep, if nmsteps is zero
int instanciateDefaultMetaStep (InputRecord* ir);
/** Update receiver attributes according to step metaStep
attributes. Allows the certain parameters or attributes to be
updated for particular metastep. The metastep provides the
attributes record, from which the corresponding attributes can be
read. The service takes TimeStep as parameter, from which
corresponding MetaStep is requested. It is recomended, to implement
this service in such way, that multiple calls for steps belonging to
same MetaStep does not change response. The default implementation
updates the numerical method attributes. @param TimeStep time step.
*/
virtual void updateAttributes (TimeStep*);
/** Update e-model attributes attributes according to step metaStep
attributes. Calls updateAttributes. At the end the meta step input
reader finish() service is called in order to allow for unread
attribute check. */
void initMetaStepAttributes (TimeStep* tStep);
/** Stores the state of model to output stream. Stores not only the
receiver state, but also same function is invoked for all DofManagers
and Elements in associated domain. Note that by storing element
context also contexts of all associated integration points (and
material statuses) are stored. Stored context is associated with
current time step. One time step can have only one associated
context. Multiple call to saveContext within same time step owerride
previously saved context for this step. By default the stream
paprameter is used to store data and is not closed. If stream is
NULL, new file descriptor is created and this must be also closed at
the end.
@param stream - context stream. If NULL then new file
descriptor will be openned and closed at the end else the stream
given as parameter will be used and not closed at the end.
@return contextIOResultType.
@exception throws an ContextIOERR exception if error encountered */
virtual contextIOResultType saveContext (FILE *stream, void *obj = NULL) ;
/** Restores the state of model from output stream. Restores not only
the receiver state, but also same function is invoked for all
DofManagers and Elements in associated domain. Note that by restoring
element context also contexts of all associated integration points
(and material statuses) are restored. Each context is associated
with unique time step. Only one context per time step is
allowed. Restore context function will restore such contex, which is
related (through its step number) to time step number and version
given in obj parameter. Restoring context will change current time
step in order to correspond to newly restored context.
@param stream context file
@param obj is a void pointer to an int array containing two values:time step number and
version of a context file to be restored.
@return contextIOResultType.
@exception throws an ContextIOERR exception if error encountered.
*/
virtual contextIOResultType restoreContext (FILE* stream, void* obj = NULL) ;
/** Updates domain links after the domains of receiver have
changed. Used mainly after restoring context - the domains may change
and this service is then used to update domain variables in all
components belonging to receiver like errorestimators, solvers, etc,
having domains as attributes. */
virtual void updateDomainLinks() {};
void resolveCorrespondingStepNumber (int&, int&, void* obj);
/// Returns current time step.
TimeStep* giveCurrentStep () {if (master) return master->giveCurrentStep();
else return currentStep;}
/// Returns previous time step.
TimeStep* givePreviousStep() {if (master) return master->givePreviousStep();
else return previousStep;}
/// Returns next time step (next to current step) of receiver.
virtual TimeStep* giveNextStep() {return NULL;}
/// Returns the solution step when Initial Conditions (IC) apply
virtual TimeStep* giveSolutionStepWhenIcApply()
{if (master) return master->giveCurrentStep();
else return stepWhenIcApply;}
/// Returns number of first time step used by receiver.
virtual int giveNumberOfFirstStep ()
{if (master) return master->giveNumberOfFirstStep();
else return 1;}
/// Return number of meta steps
int giveNumberOfMetaSteps () {return nMetaSteps;}
/// Returns the i-th meta step
MetaStep* giveMetaStep (int i);
/// Returns total number of steps.
int giveNumberOfSteps()
{if (master) return master->giveNumberOfSteps();
else return numberOfSteps ;}
/// Returns end of time interest (time corresponding to end of time integration).
virtual double giveEndOfTimeOfInterest () {return 0.;}
/// Returns the time step number, when initial conditions should apply.
virtual int giveNumberOfTimeStepWhenIcApply()
{if (master) return master->giveNumberOfTimeStepWhenIcApply();
else return 0;}
/// Returns reference to receiver's numerical method
virtual NumericalMethod* giveNumericalMethod (TimeStep*) {return NULL;}
/// Returns receiver's export mudule manager
ExportModuleManager* giveExportModuleManager() {return exportModuleManager;}
/** Increases number of equations of receiver's domain and returns
newly created equation number. Used mainly by DofManagers to
allocate their corresponding equation number if it is not currently
allocated. The DofIDItem parameter allows to distinguis between
several possible governing equations, that can be numbered
separately. */
virtual int giveNewEquationNumber (int domain, DofIDItem)
{return ++domainNeqs.at(domain);}
/** Increases number of prescribed equations of receiver's domain and
returns newly created equation number. Used mainly by DofManagers to
allocate their corresponding equation number if it is not currently
allocated. The DofIDItem parameter allows to distinguis between
several possible governing equations, that can be numbered
separately. */
virtual int giveNewPrescribedEquationNumber (int domain, DofIDItem)
{return ++domainPrescribedNeqs.at(domain);}
/**
Assigns context file-descriptor for given step number to stream.
Returns nonzero on success.
@param stepNumber solution step number to store/restore
@param stepVersion version of step
@param cmode determines the i/o mode of context file
@param errLevel determines the amout of warning messages if
errors are encountered, level 0 no warnings reported.
*/
int giveContextFile (FILE** contextFile, int stepNumber, int stepVersion,
ContextFileMode cmode, int errLevel = 1) ;
/** Returns true if context file for given step and version is available */
bool testContextFile (int stepNumber, int stepVersion);
/**
Creates new DataReader for given domain.
Returns nonzero on success.
@param domainNum domain number
@param domainSerNum domain seerial number
@param cmode determines the i/o mode of context file
*/
DataReader* GiveDomainDataReader (int domainNum, int domainSerNum,
ContextFileMode cmode) ;
/**
Updates components mapped to numerical method if necessary during solution process.
Some numerical methods may require updating
mapped components during solution process (e.g., updating of tanget stiffness
when using updated Newton-Raphson method).
@param tStep time when component is updated.
@param cmpn Numerical component to update.
*/
virtual void updateComponent (TimeStep* tStep, NumericalCmpn cmpn);
/**
Initializes solution of new time step. Default implementation
resets all internal history variables (in integration points of elements)
to previously reached equilibrium values.
Can be used for time step restart.
*/
virtual void initStepIncrements();
/** Forces equation renumbering on given domain. All equation numbers
in all dofManagers are invalidated, and new equation numbers are
generated starting from domainNeqs entry corresponding to given
domain. It will update numberOfEquations variable accordingly.
Should be used at startup to force equation numbering and therefore
sets numberOfEquations. Must be used if model supports changes of
static system to assign new valid equation numbers to dofManagers.
*/
virtual int forceEquationNumbering (int i);
/** Forces equation renumbering on all domains associated to engng
model. All equation numbers in all domains for all dofManagers are
invalidated, and new equation numbers are generated starting from 1
on each domain. It will update numberOfEquations variable
accordingly. Should be used at startup to force equation numbering
and therefore sets numberOfEquations. Must be used if model supports
changes of static system to assign new valid equation numbers to
dofManagers. */
virtual int forceEquationNumbering ();
/** Indicates if Engngmodel requires Dofs dictionaries to be updated.
If EngngModel does not support changes of static system, the dof
frowards the requests for its unknowns to EngngModel, where unknowns
are naturaly kept. This is posible, because dof equation number is
same during whole solution. But when changes of static system are
allowed, several problem arise. For example by solving simple
incremental static with allowed static changes, the incremetal
displacement vector of structure can not be added to total
displacement vector of structure, because equation numbers may have
changed, and one can not simply add these vector to obtain new total
displacement vector, because uncompatible displacement will be added.
To solve this problem, uknown dictionary at dof level has been
assumed. Dof then keeps its unknowns in its onw private dictionary.
After computing increment of solution, engngModel updates for each
dof its unknowns in its dictionary (using updateUnknownsDictionary
function). For aforementioned example engngModel updates incremental
values but also total value by asking dof for previous total value
(dof will use its dictionary, does not asks back EngngModel) adds
corresponding increment and updates total value in dictionary.
*/
virtual int requiresUnknowsDictionaryUpdate () {return 0;}
/** Returns true if equation renumbering is required for given
solution step. This may of course change the number of equation and
in general there is no gauarantee that for a certain dof the same
eautiaon will be assigned. So the use of DOF unknowns dictionaries
is generally recomended. */
virtual bool requiresEquationRenumbering(TimeStep*) {return false;}
//virtual int supportsBoundaryConditionChange () {return 0;}
/**
Updates necessary values in Dofs unknown dictionaries.
@see EngngModel::requiresUnknowsDictionaryUpdate
@see Dof::updateUnknownsDictionary
*/
virtual void updateDofUnknownsDictionary (DofManager*, TimeStep*) {}
/** This method is responsible for computing unique dictionary id
(ie hash value) from given equationId, valueModeType and
timestep. This function is used by particular dofs to access unknown
identified by given params from its dictionary using computed index.
Usually the hash algorithm shoud produce index that depend on
timestep relativelly to actual one to avoid storage of complete
history.
*/
virtual int giveUnknownDictHashIndx (EquationID type, ValueModeType mode,
TimeStep* stepN) {return 0;}
// we don't directlt call element ->GiveCharacteristicMatrix() function, because some
// engngm classes may require special modification of base types supported on
// element class level
/** Returns characteristic matrix of element. The
Element::GiveCharacteristicMatrix function should not be called
directly, because EngngModel may require some special modification of
characteristic matrices supported on element level. But default
implementation does the direct call to element level.
@param answer characteristic matrix
@param num element number
@param type type of CharMatrix requsted
@param tStep time step when response is computed
@param domain source domain
*/
virtual void giveElementCharacteristicMatrix (FloatMatrix& answer, int num,
CharType type, TimeStep* tStep, Domain* domain)
{ domain->giveElement(num)->giveCharacteristicMatrix (answer, type, tStep);}
/** Returns characteristic vector of element. The
Element::GiveCharacteristicVector function should not be called
directly, because EngngModel may require some special modification of
characteristic vectors supported on element level. But default
implementation does the direct call to element level.
@param answer characteristic vector
@param num element number
@param type type of vector requsted
@param tStep time step when response is computed
@param domain source domain
*/
virtual void giveElementCharacteristicVector (FloatArray& answer, int num,
CharType type, ValueModeType mode, TimeStep* tStep, Domain* domain)
{ domain->giveElement(num)->giveCharacteristicVector (answer, type, mode, tStep);}
protected:
/**
Assembles characteristic matrix of required type into given sparse matrix.
@param answer assembled matrix
@param tStep time step, when answer is assembled.
@param ut determines type of equation and corresponding element code numbers
@param type characterisctic components of type type are requsted from elements and assembled.
@param domain source domain
*/
virtual void assemble (SparseMtrx *answer, TimeStep* tStep, EquationID ut,
CharType type, Domain* domain) ;
/**
Assembles characteristic matrix of required type into given sparse matrix.
@param answer assembled matrix
@param tStep time step, when answer is assembled.
@param r_id determines type of equation and corresponding element code numbers for matrix rows
@param c_id determines type of equation and corresponding element code numbers for matrix columns
@param type characterisctic components of type type are requsted from elements and assembled.
@param domain source domain
*/
virtual void assemble (SparseMtrx *answer, TimeStep* tStep, EquationID r_id,
EquationID c_id, CharType type, Domain* domain) ;
/**
Assembles characteristic vector of required type into given vector.
@param answer assembled vector
@param tStep time step, when answer is assembled.
@param type characterisctic components of type type are requsted
from dofManagers/elements and assembled.
*/
//virtual void assemble (FloatArray&, TimeStep*, CharType type,
Domain* domain) ;
/**
Assembles characteristic vector of required type from dofManagers into given vector.
@param answer assembled vector
@param tStep time step, when answer is assembled.
@param type characterisctic components of type type are requsted
from dofManagers and assembled using code numbers.
*/
virtual void assembleVectorFromDofManagers (FloatArray&, TimeStep*, EquationID ut,
CharType type, ValueModeType mode,
Domain* domain) ;
/** Assembles prescribed characteristic vector of required type
from dofManagers into given vector.
@param answer assembled vector
@param tStep time step, when answer is assembled.
@param type characterisctic components of type type are requsted
from dofManagers and assembled using prescribed eqn numbers.
*/
void assemblePrescribedVectorFromDofManagers (FloatArray&, TimeStep*, EquationID,
CharType type, ValueModeType mode,
Domain* domain) ;
/**
Assembles characteristic vector of required type from elements into given vector.
@param answer assembled vector
@param tStep time step, when answer is assembled.
@param type characterisctic components of type type are requsted
from elements and assembled using using code numbers.
*/
void assembleVectorFromElements (FloatArray&, TimeStep*, EquationID,
CharType type, ValueModeType mode,
Domain* domain) ;
/**
Assembles prescribed characteristic vector of required type from
elements into given vector.
@param answer assembled vector
@param tStep time step, when answer is assembled.
@param type characterisctic components of type type are requsted
from elements and assembled using prescribed eqn numbers.
*/
void assemblePrescribedVectorFromElements (FloatArray&, TimeStep*, EquationID,
CharType type, ValueModeType mode, Domain* domain) ;
public:
// consistency check
/** Allows programmer to test some receiver's internal data, before
computation begins.
@return nonzero if receiver check is o.k. */
virtual int checkConsistency () {return 1;} // returns nonzero if o.k.
/** Allows programmer to test problem its internal data, before computation begins.
@return nonzero if receiver check is o.k. */
int checkProblemConsistency (); // returns nonzero if o.k.
/**
Prints output of receiver to ouput domain stream, for given time step.
Corresponding function for element gauss points is invoked
(gaussPoint::printOutputAt).
*/
virtual void printOutputAt (FILE *, TimeStep*) ;
// input / output
/// Prints stete of receiver. Usefull for debugging.
void printYourself () ;
/** DOF printing routine. Called by DofManagers to print Dof specific part.
Dof class provides component printing routines, but emodel is responsible
for what will be printed at DOF level.
@param stream output stream
@param iDof dof to be processed
@param atTime solution step
*/
virtual void printDofOutputAt (FILE* stream, Dof* iDof, TimeStep* atTime) = 0;
// identification
/// Returns class name of the receiver.
virtual const char* giveClassName () const { return "EngngModel" ;}
/// Returns classType id of receiver.
virtual classType giveClassID () const { return EngngModelClass ;}
/// Returns nonzero if receiver does incremental analysis.
virtual int isIncremental () {return 0;}
/// Returns nonzero if nonlocal stiffness option activated.
virtual int useNonlocalStiffnessOption () {return 0;}
/// retun true if receiver in parallel mode
bool isParallel () {return (parallelFlag != 0);}
/**
Indicates type of non linear computation (total or updated formulation).
This is used for example on Nodal level to update coordinates
if updated formulation
is done, or on element level, when non linear contributions are computed.
*/
virtual fMode giveFormulation () {return UNKNOWN;} // for non-linear computation
/*
Returns Load Response Mode of receiver.
This value indicates, whether nodes and elements should assemble
total or incremental load vectors.
virtual LoadResponseMode giveLoadResponseMode () {return TotalLoad;}
*/
/// Context requesting service
EngngModelContext* giveContext () {return this->context;}
/**
Returns number of slave problems */
virtual int giveNumberOfSlaveProblems() {return 0;}
/**Returns i-th slave problem */
virtual EngngModel* giveSlaveProblem (int i) {return NULL;}
/** Returns the Equation scaling flag, which is used to indicate
that governing equation(s) are scaled, or non-dimensionalized */
virtual bool giveEquationScalingFlag () {return false;}
/// Returns the scale factor for given variable type
virtual double giveVariableScale (VarScaleType varId) {return 1.0;}
/**@name error and warning reporting methods These methods will
print error (or warning) message using oofem default loggers. Do
not use these methods directly, to avoid specify file and line
parameters. More preferably, use these methods via corresponding
OOFEM_CLASS_ERROR and OOFEM_CLASS_WARNING macros, that will include
file and line parameters automatically. Uses variable number of
arguments, so a format string followed by optional argumens is
expected (according to printf conventions).
@param file source file name, where error encountered (where error* function called)
@param line source file line number, where error encountered
*/
//@{
/// prints error message and exits
void error (char* file, int line, char *format, ...) const ;
/// prints warning message
void warning (char* file, int line, char *format, ...) const ;
//@}
};
typedef EngngModel Problem;
The key method declared by EngngModel is solveYourself, which starts the solution. It loops over all metasteps. For each metastep, the loop over corresponding solution steps is performed. For each solution step, the value of currentStep attribute is updated by invoking giveNextStep() service, and the solveYourselfAt is called, performing the solution for given step. The currentStep is an attribute of EngngModel class. At the very beginning, it is set to NULL or is initialized to the step from which analysis is restarted.
void
EngngModel :: solveYourself ()
{
int imstep, jstep;
int smstep=1, sjstep=1;
MetaStep* activeMStep;
#ifdef TIME_REPORT
oofem_timeval tstart;
#endif
// restart support - if currentStep is set already, start from the
// next one
if (this->currentStep) {
smstep = this->currentStep->giveMetaStepNumber();
sjstep = this->giveMetaStep(smstep)->
giveStepRelativeNumber(this->currentStep->giveNumber()) + 1;
}
for (imstep = smstep; imstep<= nMetaSteps; imstep++) {
activeMStep = this->giveMetaStep(imstep);
for (jstep = sjstep; jstep <= activeMStep->giveNumberOfSteps(); jstep++)
{
#ifdef TIME_REPORT
::getUtime(tstart);
#endif
this->giveNextStep();
// update attributes according to new meta step attributes
if (jstep == sjstep) this->updateAttributes (this->giveCurrentStep());
this->solveYourselfAt(this->giveCurrentStep());
#ifdef TIME_REPORT
oofem_timeval ut;
::getRelativeUtime (ut, tstart);
printf ("\nEngngModel info: user time consumed by solution step %d: %.2fs\n",
jstep, (double)(ut.tv_sec+ut.tv_usec/(double)OOFEM_USEC_LIM));
#endif
}
}
}
The solveYourselfAt typically assembles characteristic matrices and vectors and solve the problem using the suitable numerical method. After finishing the solution, the updateYourself service for updating solution state and then terminate method (for updating nodal and element values) should be called to consistently update the state of all components. The implementation should be provided by derived classes (see section 3.4 for an example).
The implementation of updateYourself service loops over all problem domains and calls corresponding update service for all DOF managers and elements. The terminate service prints the required outputs and optionally saves the context file (if required), so the solution can be restarted from this saved state later. Both services are virtual, so they can be easily tailored to specific needs.
void
EngngModel :: updateYourself (TimeStep* stepN)
{
int idomain, ndomains = this->giveNumberOfDomains();
int j, nnodes;
Domain* domain;
for (idomain = 1; idomain <= ndomains; idomain++) {
domain= this->giveDomain(idomain);
# ifdef VERBOSE
VERBOSE_PRINT0("Updating domain ",domain->giveNumber())
# endif
nnodes = domain->giveNumberOfDofManagers ();
for( j=1;j<=nnodes;j++) {
domain->giveDofManager(j)->updateYourself(stepN) ;
}
# ifdef VERBOSE
VERBOSE_PRINT0("Updated nodes & sides ",nnodes)
# endif
Element* elem;
int nelem = domain->giveNumberOfElements ();
for (j=1 ; j<=nelem ; j++) {
elem = domain -> giveElement(j) ;
#ifdef __PARALLEL_MODE
// skip remote elements (these are used as mirrors
// of remote elements on other domains, when nonlocal
// constitutive models are used.
// Their introduction is necessary to allow local
// averaging on domains without fine grain
// communication between domains)
if (elem->giveParallelMode () == Element_remote) continue;
#endif
elem -> updateYourself(stepN);
}
# ifdef VERBOSE
VERBOSE_PRINT0("Updated Elements ",nelem)
# endif
}
}
void
EngngModel :: terminate (TimeStep* stepN)
{
FILE* File = this->giveOutputStream();
// print output
this->printOutputAt (File, stepN);
// save context if required
// default - save only if ALWAYS is set ( see cltypes.h )
if ((this->giveContextOutputMode() == ALWAYS) ||
(this->giveContextOutputMode() == REQUIRED)) {
this->saveContext(NULL);
} else if (this->giveContextOutputMode() == USERDEFINED) {
if (stepN->giveNumber()%this->giveContextOutputStep() == 0)
this->saveContext(NULL);
}
}
The implementations of services for characteristic components assembly are provided. They simply loop over nodes or elements (depending on the character of the requested component) of the given domain, requesting the corresponding component contributions and corresponding code numbers. The component contributions are assembled (using code numbers) into a target array or matrix. The implementation of assemble for characteristic vectors has to determine whether the contribution comes from node or element. The implementation presented here uses the hard-wired decision rules (adapted for structural analysis), which in other cases leads the overloading of basic implementation. The better solution will be probably to call some virtual service, which returns the source of contribution (nodal or element contribution) and then to perform corresponding loop.
void EngngModel :: assemble (SparseMtrx* answer, TimeStep* tStep, EquationID ut,
CharType type, Domain* domain)
//
// assembles matrix answer by calling
// element(i) -> giveCharacteristicMatrix ( type, tStep );
// for each element in domain
// and assembling every contribution to answer
//
//
{
int ielem;
IntArray loc ;
FloatMatrix mat;
Element *element;
if (answer == NULL) _error("assemble: NULL pointer encountered.");
int nelem = domain -> giveNumberOfElements ();
for ( ielem = 1; ielem <= nelem ; ielem++ ) {
element = domain -> giveElement(ielem);
#ifdef __PARALLEL_MODE
// skip remote elements (these are used as mirrors of remote eleemnts on other domains
// when nonlocal constitutive models are used. They introduction is necessary to
// allow local averaging on domains without fine grain communication between domains).
if (element->giveParallelMode () == Element_remote) continue;
#endif
element -> giveLocationArray (loc, ut);
this->giveElementCharacteristicMatrix(mat, ielem, type, tStep, domain );
if (mat.isNotEmpty()) {
if (answer -> assemble (loc, mat) == 0)
_error("assemble: sparse matrix assemble error");
}
}
answer->assembleBegin();
answer->assembleEnd();
}
void EngngModel :: assembleVectorFromDofManagers
(FloatArray& answer, TimeStep* tStep, EquationID ut,
CharType type, ValueModeType mode, Domain* domain)
//
// assembles matrix answer by calling
// node(i) -> computeLoadVectorAt (tStep);
// for each element in domain
// and assembling every contribution to answer
//
//
{
int i ;
IntArray loc ;
FloatArray charVec ;
DofManager *node ;
int nnode = domain -> giveNumberOfDofManagers();
for (i = 1; i <= nnode ; i++ ) {
node = domain -> giveDofManager(i);
node -> computeLoadVectorAt (charVec, tStep, mode);
if(charVec.giveSize()) {
node -> giveCompleteLocationArray (loc);
answer.assemble (charVec, loc) ;
}
}
}
void EngngModel :: assembleVectorFromElements
(FloatArray& answer, TimeStep* tStep, EquationID ut,
CharType type, ValueModeType mode, Domain* domain)
//
// assembles matrix answer by calling
// element(i) -> giveCharacteristicMatrix ( type, tStep );
// for each element in domain
// and assembling every contribution to answer
//
//
{
int i ;
IntArray loc ;
FloatArray charVec ;
Element *element ;
int nelem = domain -> giveNumberOfElements ();
for (i = 1; i <= nelem ; i++ ) {
element = domain -> giveElement(i);
#ifdef __PARALLEL_MODE
// skip remote elements (these are used as mirrors of remote eleemnts on other domains
// when nonlocal constitutive models are used. They introduction is necessary to
// allow local averaging on domains without fine grain communication between domains).
if (element->giveParallelMode () == Element_remote) continue;
#endif
element -> giveLocationArray (loc, ut);
this -> giveElementCharacteristicVector (charVec, i, type, mode, tStep, domain);
if(charVec.giveSize()) answer.assemble (charVec, loc) ;
}
}
void EngngModel :: assemblePrescribedVectorFromDofManagers
(FloatArray& answer, TimeStep* tStep, EquationID ut,
CharType type, ValueModeType mode, Domain* domain)
//
// assembles matrix answer by calling
// node(i) -> computeLoadVectorAt (tStep);
// for each element in domain
// and assembling every contribution to answer
//
//
{
int i ;
IntArray loc ;
FloatArray charVec ;
DofManager *node ;
int nnode = domain -> giveNumberOfDofManagers();
for (i = 1; i <= nnode ; i++ ) {
node = domain -> giveDofManager(i);
node -> computeLoadVectorAt (charVec, tStep, mode);
if(charVec.giveSize()) {
node -> giveCompletePrescribedLocationArray (loc);
answer.assemble (charVec, loc) ;
}
}
}
void EngngModel :: assemblePrescribedVectorFromElements
(FloatArray& answer, TimeStep* tStep, EquationID ut,
CharType type, ValueModeType mode, Domain* domain)
//
// assembles matrix answer by calling
// element(i) -> giveCharacteristicMatrix ( type, tStep );
// for each element in domain
// and assembling every contribution to answer
//
//
{
int i ;
IntArray loc ;
FloatArray charVec ;
Element *element ;
int nelem = domain -> giveNumberOfElements ();
for (i = 1; i <= nelem ; i++ ) {
element = domain -> giveElement(i);
#ifdef __PARALLEL_MODE
// skip remote elements (these are used as mirrors of remote eleemnts on other domains
// when nonlocal constitutive models are used. They introduction is necessary to
// allow local averaging on domains without fine grain communication between domains).
if (element->giveParallelMode () == Element_remote) continue;
#endif
element -> givePrescribedLocationArray (loc, ut);
if (loc.containsOnlyZeroes()) continue;
this -> giveElementCharacteristicVector (charVec, i, type, mode, tStep, domain);
if(charVec.giveSize()) answer.assemble (charVec, loc) ;
}
}
Borek Patzak 2018-01-02