OOFEM 3.0
Loading...
Searching...
No Matches
nltransienttransportproblem.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
36#include "timestep.h"
37#include "element.h"
38#include "dofmanager.h"
39#include "dof.h"
40#include "verbose.h"
42#include "classfactory.h"
43#include "mathfem.h"
44#include "assemblercallback.h"
46
47namespace oofem {
49
50NLTransientTransportProblem :: NLTransientTransportProblem(int i, EngngModel *_master = nullptr) : NonStationaryTransportProblem(i, _master)
51{
52}
53
54void
55NLTransientTransportProblem :: initializeFrom(InputRecord &ir)
56{
57 NonStationaryTransportProblem :: initializeFrom(ir);
58
59 int val = 30;
61 nsmax = val;
62
64
66 MANRMSteps = 0;
68 if ( MANRMSteps > 0 ) {
70 } else {
72 }
73}
74
76NLTransientTransportProblem :: giveNextStep()
77{
78 double intrinsicTime;
79 NonStationaryTransportProblem :: giveNextStep();
80 intrinsicTime = previousStep->giveTargetTime() + this->alpha*(currentStep->giveTargetTime()-previousStep->giveTargetTime());
81 currentStep->setIntrinsicTime(intrinsicTime);
82 return currentStep.get();
83}
84
85
86void NLTransientTransportProblem :: solveYourselfAt(TimeStep *tStep)
87{
88 // creates system of governing eq's and solves them at given time step
89 // first assemble problem at current time step
90
91 // Right hand side
92 FloatArray rhs;
93 double solutionErr, incrementErr;
95
96#ifdef VERBOSE
97 OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() );
98#endif
99 //Delete lhs matrix and create a new one. This is necessary due to growing/decreasing number of equations.
100 if ( tStep->isTheFirstStep() || this->changingProblemSize ) {
101
103 if ( !conductivityMatrix ) {
104 OOFEM_ERROR("sparse matrix creation failed");
105 }
106
107 conductivityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() );
108#ifdef VERBOSE
109 OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n");
110#endif
111 }
112
113 //create previous solution from IC or from previous tStep
114 if ( tStep->isTheFirstStep() ) {
115 if ( !stepWhenIcApply ) {
116 stepWhenIcApply = std::make_unique<TimeStep>( *tStep->givePreviousStep() );
117 }
118 this->applyIC(stepWhenIcApply.get()); //insert solution to hash=1(previous), if changes in equation numbering
119 }
120
121 double dTTau = tStep->giveTimeIncrement();
122 double Tau = tStep->giveTargetTime() - ( 1. - alpha ) * tStep->giveTimeIncrement();
123 //Time step in which material laws are taken into account
124 TimeStep TauStep(tStep->giveNumber(), this, tStep->giveMetaStepNumber(), Tau, dTTau, tStep->giveSolutionStateCounter() + 1);
125
126 //Predictor
127 FloatArray *solutionVector;
128 UnknownsField->advanceSolution(tStep);
129 solutionVector = UnknownsField->giveSolutionVector(tStep);
130
131 //Initialize and give solutionVector from previous solution
132 if ( changingProblemSize ) {
133 if ( !tStep->isTheFirstStep() ) {
134 //copy recent solution to previous position, copy from hash=0 to hash=1(previous)
135 copyUnknownsInDictionary( VM_Total, tStep, tStep->givePreviousStep() );
136 }
137
138 UnknownsField->initialize( VM_Total, tStep->givePreviousStep(), *solutionVector, EModelDefaultEquationNumbering() );
139 } else {
140 //copy previous solution vector to actual
141 *solutionVector = *UnknownsField->giveSolutionVector( tStep->givePreviousStep() );
142 }
143
144 this->updateInternalState(& TauStep); //insert to hash=0(current), if changes in equation numbering
145
146 FloatArray solutionVectorIncrement(neq);
147 int nite = 0;
148
149 OOFEM_LOG_INFO("Time Iter ResidNorm IncrNorm\n__________________________________________________________\n");
150
151
152 do {
153 nite++;
154
155 // Corrector
156#ifdef VERBOSE
157 // printf("\nAssembling conductivity and capacity matrices");
158#endif
159
160 if ( ( nite == 1 ) || ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) {
161 conductivityMatrix->zero();
162 //Assembling left hand side - start with conductivity matrix
166 //Add capacity matrix
169 }
170
171 rhs.resize(neq);
172 rhs.zero();
173 //edge or surface load on element
174 //add internal source vector on elements
175 this->assembleVectorFromElements( rhs, tStep, TransportExternalForceAssembler(), VM_Total,
177 //add nodal load
178 this->assembleVectorFromDofManagers( rhs, tStep, ExternalForceAssembler(), VM_Total,
180
181 // subtract the rhs part depending on previous solution
183 // set-up numerical model
185
186 // call numerical model to solve arised problem
187#ifdef VERBOSE
188 //OOFEM_LOG_INFO("Solving ...\n");
189#endif
190
191 // compute norm of residuals from balance equations
192 solutionErr = rhs.computeNorm();
193
194 linSolver->solve(*conductivityMatrix, rhs, solutionVectorIncrement);
195 solutionVector->add(solutionVectorIncrement);
196 this->updateInternalState(tStep); //insert to hash=0(current), if changes in equation numbering
197 // compute error in the solutionvector increment
198 incrementErr = solutionVectorIncrement.computeNorm();
199
200 // update solution state counter
201 TauStep.incrementStateCounter();
202 tStep->incrementStateCounter();
203
204 OOFEM_LOG_INFO("%-15e %-10d %-15e %-15e\n", tStep->giveTargetTime(), nite, solutionErr, incrementErr);
205
206 currentIterations = nite;
207
208 if ( nite >= nsmax ) {
209 OOFEM_ERROR("convergence not reached after %d iterations", nsmax);
210 }
211 } while ( ( fabs(solutionErr) > rtol ) || ( fabs(incrementErr) > rtol ) );
212}
213
214
215double NLTransientTransportProblem :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof)
216// returns unknown quantity like displacement, velocity of equation
217// This function translates this request to numerical method language
218{
219 if ( this->requiresUnknownsDictionaryUpdate() ) {
220 if ( mode == VM_Incremental ) { //get difference between current and previous time variable
221 return dof->giveUnknowns()->at(0) - dof->giveUnknowns()->at(1);
222 } else if ( mode == VM_TotalIntrinsic ) { // intrinsic value only for current step
223 return this->alpha * dof->giveUnknowns()->at(0) + (1.-this->alpha) * dof->giveUnknowns()->at(1);
224 }
225 int hash = this->giveUnknownDictHashIndx(mode, tStep);
226 if ( dof->giveUnknowns()->includes(hash) ) {
227 return dof->giveUnknowns()->at(hash);
228 } else {
229 OOFEM_ERROR("Dof unknowns dictionary does not contain unknown of value mode (%s)", __ValueModeTypeToString(mode) );
230 }
231 }
232
233 double t = tStep->giveTargetTime();
234 TimeStep *pStep = this->givePreviousStep(), *cStep = this->giveCurrentStep();
235
236 if ( dof->__giveEquationNumber() == 0 ) {
237 OOFEM_ERROR("invalid equation number on DoF %d", dof->giveDofID() );
238 }
239
240 if ( ( t >= pStep->giveTargetTime() ) && ( t <= cStep->giveTargetTime() ) ) {
242 //UnknownsField->giveUnknownValue(dof, mode, cStep);
243 double rtdt = UnknownsField->giveUnknownValue(dof, VM_Total, cStep);
244 double rt = UnknownsField->giveUnknownValue(dof, VM_Total, pStep);
245 double psi = ( t - pStep->giveTargetTime() ) / cStep->giveTimeIncrement();
246 if ( mode == VM_Velocity ) {
247 return ( rtdt - rt ) / cStep->giveTimeIncrement();
248 } else if ( mode == VM_TotalIntrinsic ) {
249 // only supported for current step
250 return this->alpha * rtdt + ( 1. - this->alpha ) * rt;
251 } else if ( mode == VM_Total ) {
252 return psi * rtdt + ( 1. - psi ) * rt;
253 } else if ( mode == VM_Incremental ) {
254 if ( pStep->isIcApply() ) {
255 return 0;
256 } else {
257 return ( rtdt - rt );
258 }
259 } else {
260 OOFEM_ERROR("Unknown mode %s is undefined for this problem", __ValueModeTypeToString(mode) );
261 }
262 } else {
263 OOFEM_ERROR("time value %f not within bounds %f and %f", t, pStep->giveTargetTime(), cStep->giveTargetTime() );
264 }
265
266 return 0.; // to make compiler happy;
267}
268
269
270void
271NLTransientTransportProblem :: applyIC(TimeStep *_stepWhenIcApply)
272{
273 Domain *domain = this->giveDomain(1);
274
275 NonStationaryTransportProblem :: applyIC(_stepWhenIcApply);
276
277 // update element state according to given ic
278 for ( auto &elem : domain->giveElements() ) {
279 TransportElement *element = static_cast< TransportElement * >( elem.get() );
280 element->updateInternalState(_stepWhenIcApply);
281 element->updateYourself(_stepWhenIcApply);
282 }
283}
284
285void
286NLTransientTransportProblem :: createPreviousSolutionInDofUnknownsDictionary(TimeStep *tStep)
287{
288 //Copy the last known temperature to be a previous solution
289 for ( auto &domain: domainList ) {
291 for ( auto &node : domain->giveDofManagers() ) {
292 for ( Dof *dof: *node ) {
293 double val = dof->giveUnknown(VM_Total, tStep); //get number on hash=0(current)
294 dof->updateUnknownsDictionary(tStep->givePreviousStep(), VM_Total, val);
295 }
296 }
297 }
298 }
299}
300
301
302void
303NLTransientTransportProblem :: updateYourself(TimeStep *tStep)
304{
305 //this->updateInternalState(tStep);
306 //Set intrinsic time for a staggered problem here. This is important for materials such as hydratingconcretemat, who keep history of intrinsic times.
307 double intrinsicTime = tStep->giveIntrinsicTime();
308 double Tau = tStep->giveTargetTime() - ( 1. - alpha ) * tStep->giveTimeIncrement();
309 tStep->setIntrinsicTime(Tau);
310 NonStationaryTransportProblem :: updateYourself(tStep);
311 //return back to original intrinsic time
312 tStep->setIntrinsicTime(intrinsicTime);
313}
314
315int
316NLTransientTransportProblem :: giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep)
317{
318 if ( mode == VM_Total ) { //Nodal temperature
319 if ( tStep->giveNumber() == this->giveCurrentStep()->giveNumber() ) { //current time
320 return 0;
321 } else if ( tStep->giveNumber() == this->giveCurrentStep()->giveNumber() - 1 ) { //previous time
322 return 1;
323 } else {
324 OOFEM_ERROR("No history available at TimeStep %d = %f, called from TimeStep %d = %f", tStep->giveNumber(), tStep->giveTargetTime(), this->giveCurrentStep()->giveNumber(), this->giveCurrentStep()->giveTargetTime() );
325 }
326 } else {
327 OOFEM_ERROR("ValueModeType %s undefined", __ValueModeTypeToString(mode));
328 }
329}
330
331void
332NLTransientTransportProblem :: updateDofUnknownsDictionary(DofManager *inode, TimeStep *tStep)
333{
334 // update DoF unknowns dictionary. Store the last and previous temperature only, see giveUnknownDictHashIndx
335 for ( Dof *dof: *inode ) {
336 int eqNum = dof->__giveEquationNumber();
337 double val;
338 if ( dof->hasBc(tStep) ) { // boundary condition
339 val = dof->giveBcValue(VM_Total, tStep);
340 } else {
341 FloatArray *vect = this->UnknownsField->giveSolutionVector(tStep);
342 val = vect->at(eqNum);
343 }
344
345 //update temperature, which is present in every node
346 dof->updateUnknownsDictionary(tStep, VM_Total, val);
347 }
348}
349
350
351void
352NLTransientTransportProblem :: updateInternalState(TimeStep *tStep)
353{
354 for ( auto &domain: domainList ) {
356 for ( auto &dman : domain->giveDofManagers() ) {
357 //update dictionary entry or add a new pair if the position is missing
358 this->updateDofUnknownsDictionary(dman.get(), tStep);
359 }
360 }
361
362 for ( auto &elem : domain->giveElements() ) {
363 elem->updateInternalState(tStep);
364 }
365 }
366}
367
368void
369NLTransientTransportProblem :: assembleAlgorithmicPartOfRhs(FloatArray &answer,
370 const UnknownNumberingScheme &ns, TimeStep *tStep)
371{
372 //
373 // Computes right hand side on all nodes
374 //
375 double t = tStep->giveTargetTime();
376 IntArray loc;
377 FloatMatrix charMtrxCond, charMtrxCap;
378 FloatArray r, drdt, contrib, help;
379 Element *element;
380 TimeStep *pStep = this->givePreviousStep(); //r_t
381 TimeStep *cStep = this->giveCurrentStep(); //r_{t+\Delta t}. Note that *tStep is a Tau step between r_t and r_{t+\Delta t}
382
383 Domain *domain = this->giveDomain(1);
384 int nelem = domain->giveNumberOfElements();
385
386 for ( int i = 1; i <= nelem; i++ ) {
387 element = domain->giveElement(i);
388 // skip remote elements (these are used as mirrors of remote elements on other domains
389 // when nonlocal constitutive models are used. They introduction is necessary to
390 // allow local averaging on domains without fine grain communication between domains).
391 if ( element->giveParallelMode() == Element_remote ) {
392 continue;
393 }
394
395 if ( !element->isActivated(tStep) ) {
396 continue;
397 }
398
399 element->giveLocationArray(loc, ns);
400
401 element->giveCharacteristicMatrix(charMtrxCond, TangentStiffnessMatrix, tStep);
402 element->giveCharacteristicMatrix(charMtrxCap, CapacityMatrix, tStep);
403
404
405 /*
406 * element -> computeVectorOf (VM_Total, tStep, r);
407 * element -> computeVectorOf (VM_Velocity, tStep, drdt);
408 */
409
410 if ( ( t >= pStep->giveTargetTime() ) && ( t <= cStep->giveTargetTime() ) ) {
411 FloatArray rp, rc;
412 element->computeVectorOf(VM_Total, cStep, rc);
413 element->computeVectorOf(VM_Total, pStep, rp);
414
415 //approximate derivative with a difference
416 drdt.beDifferenceOf(rc, rp);
417 drdt.times( 1. / cStep->giveTimeIncrement() );
418 //approximate current solution from linear interpolation
419 rp.times(1 - alpha);
420 rc.times(alpha);
421 r = rc;
422 r.add(rp);
423 } else {
424 OOFEM_ERROR("unsupported time value");
425 }
426 // bp: r can be computed simply as element->computeVectorOf(VM_TotalIntrinsic, currentStep, r);
427
428 if ( lumpedCapacityStab ) {
429 int size = charMtrxCap.giveNumberOfRows();
430 double s;
431 for ( int j = 1; j <= size; j++ ) {
432 s = 0.0;
433 for ( int k = 1; k <= size; k++ ) {
434 s += charMtrxCap.at(j, k);
435 charMtrxCap.at(j, k) = 0.0;
436 }
437
438 charMtrxCap.at(j, j) = s;
439 }
440 }
441
442 help.beProductOf(charMtrxCap, drdt);
443
444 contrib.beProductOf(charMtrxCond, r);
445 contrib.add(help);
446 contrib.negated();
447
448 answer.assemble(contrib, loc);
449 }
450}
451} // end namespace oofem
#define REGISTER_EngngModel(class)
DofIDItem giveDofID() const
Definition dof.h:276
virtual int __giveEquationNumber() const =0
virtual void giveUnknowns(FloatArray &masterUnknowns, ValueModeType mode, TimeStep *tStep)
Definition dof.C:159
int giveNumberOfElements() const
Returns number of elements in domain.
Definition domain.h:463
Element * giveElement(int n)
Definition domain.C:165
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep)
Definition element.C:620
virtual bool isActivated(TimeStep *tStep)
Definition element.C:838
virtual void updateYourself(TimeStep *tStep)
Definition element.C:824
void giveLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, IntArray *dofIds=NULL) const
Definition element.C:429
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
elementParallelMode giveParallelMode() const
Definition element.h:1139
void assembleVectorFromDofManagers(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1136
std ::vector< std ::unique_ptr< Domain > > domainList
List of problem domains.
Definition engngm.h:217
virtual TimeStep * giveCurrentStep(bool force=false)
Definition engngm.h:717
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Definition engngm.C:452
void assembleVectorFromElements(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1351
std ::unique_ptr< TimeStep > previousStep
Previous time step.
Definition engngm.h:243
MetaStep * giveCurrentMetaStep()
Returns current meta step.
Definition engngm.C:1900
Domain * giveDomain(int n)
Definition engngm.C:1936
std ::unique_ptr< TimeStep > currentStep
Current time step.
Definition engngm.h:241
virtual TimeStep * givePreviousStep(bool force=false)
Definition engngm.h:738
std ::unique_ptr< TimeStep > stepWhenIcApply
Solution step when IC (initial conditions) apply.
Definition engngm.h:239
double computeNorm() const
Definition floatarray.C:861
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Definition floatarray.C:403
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void add(const FloatArray &src)
Definition floatarray.C:218
void times(double s)
Definition floatarray.C:834
int giveNumberOfRows() const
Returns number of rows of receiver.
double at(std::size_t i, std::size_t j) const
void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep) override
void updateInternalState(TimeStep *tStep) override
int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override
void assembleAlgorithmicPartOfRhs(FloatArray &rhs, const UnknownNumberingScheme &s, TimeStep *tStep) override
int requiresUnknownsDictionaryUpdate() override
Allows to change number of equations during solution.
NonStationaryTransportProblem(int i, EngngModel *_master)
std ::unique_ptr< SparseLinearSystemNM > linSolver
int lumpedCapacityStab
If set then stabilization using lumped capacity will be used.
NumericalMethod * giveNumericalMethod(MetaStep *mStep) override
Returns reference to receiver's numerical method.
virtual void copyUnknownsInDictionary(ValueModeType mode, TimeStep *fromTime, TimeStep *toTime)
bool changingProblemSize
Determines if there are change in the problem size (no application/removal of Dirichlet boundary cond...
std ::unique_ptr< PrimaryField > UnknownsField
This field stores solution vector. For fixed size of problem, the PrimaryField is used,...
std ::unique_ptr< SparseMtrx > conductivityMatrix
void setIntrinsicTime(double newt)
Sets only intrinsic time.
Definition timestep.h:179
int giveMetaStepNumber()
Returns receiver's meta step number.
Definition timestep.h:150
void incrementStateCounter()
Updates solution state counter.
Definition timestep.h:213
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
double giveTargetTime()
Returns target time.
Definition timestep.h:164
bool isIcApply()
Definition timestep.C:154
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition timestep.C:132
bool isTheFirstStep()
Definition timestep.C:148
double giveIntrinsicTime()
Returns intrinsic time, e.g. time in which constitutive model is evaluated.
Definition timestep.h:166
StateCounterType giveSolutionStateCounter()
Definition timestep.h:211
void updateInternalState(TimeStep *tStep) override
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_RELEVANT(...)
Definition logger.h:142
@ Element_remote
Element in active domain is only mirror of some remote element.
Definition element.h:89
FloatArrayF< N > assemble(const FloatArrayF< M > &x, int const (&c)[M])
Assemble components into zero matrix.
ClassFactory & classFactory
#define _IFT_NLTransientTransportProblem_rtol
#define _IFT_NLTransientTransportProblem_manrmsteps
#define _IFT_NLTransientTransportProblem_nsmax

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011