OOFEM 3.0
Loading...
Searching...
No Matches
stationarytransportproblem.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 "nummet.h"
37#include "timestep.h"
38#include "element.h"
39#include "dof.h"
40#include "maskedprimaryfield.h"
41#include "verbose.h"
43#include "classfactory.h"
44#include "datastream.h"
45#include "contextioerr.h"
46#include "nrsolver.h"
49
50namespace oofem {
52
53StationaryTransportProblem :: StationaryTransportProblem(int i, EngngModel *_master = nullptr) : EngngModel(i, _master),
54 nMethod(nullptr)
55{
56 ndomains = 1;
57}
58
59
60NumericalMethod *StationaryTransportProblem :: giveNumericalMethod(MetaStep *mStep)
61{
62 if ( !nMethod ) {
63 nMethod = std::make_unique<NRSolver>(this->giveDomain(1), this);
64 }
65 return nMethod.get();
66}
67
68
69void
70StationaryTransportProblem :: initializeFrom(InputRecord &ir)
71{
72 EngngModel :: initializeFrom(ir);
73
74 int val = SMT_Skyline;
76 this->sparseMtrxType = ( SparseMtrxType ) val;
77
80
81 // read field export flag
82 IntArray exportFields;
84 if ( exportFields.giveSize() ) {
85 FieldManager *fm = this->giveContext()->giveFieldManager();
86 for ( int i = 1; i <= exportFields.giveSize(); i++ ) {
87 if ( exportFields.at(i) == FT_Temperature ) {
88 FieldPtr _temperatureField( new MaskedPrimaryField ( ( FieldType ) exportFields.at(i), this->UnknownsField.get(), {T_f} ) );
89 fm->registerField( _temperatureField, ( FieldType ) exportFields.at(i) );
90 } else if ( exportFields.at(i) == FT_HumidityConcentration ) {
91 FieldPtr _concentrationField( new MaskedPrimaryField ( ( FieldType ) exportFields.at(i), this->UnknownsField.get(), {C_1} ) );
92 fm->registerField( _concentrationField, ( FieldType ) exportFields.at(i) );
93 }
94 }
95 }
96
97 if ( !UnknownsField ) { // can exist from nonstationary transport problem
98 //UnknownsField = std::make_unique<DofDistributedPrimaryField>(this, 1, FT_TransportProblemUnknowns, 0);
99 UnknownsField = std::make_unique<PrimaryField>(this, 1, FT_TransportProblemUnknowns, 0);
100 }
101}
102
103
104
105double StationaryTransportProblem :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof)
106{
107#ifdef DEBUG
108 if ( dof->__giveEquationNumber() == 0 ) {
109 OOFEM_ERROR("invalid equation number");
110 }
111#endif
112 if (mode == VM_TotalIntrinsic) mode = VM_Total;
113 return UnknownsField->giveUnknownValue(dof, mode, tStep);
114}
115
116
118{
119 /* Note: the current implementation uses MaskedPrimaryField, that is automatically updated with the model progress,
120 so the returned field always refers to active solution step.
121 */
122
123 if ( tStep != this->giveCurrentStep() ) {
124 OOFEM_ERROR("Unable to return field representation for non-current time step");
125 }
126 if ( key == FT_Temperature ) {
127 FieldPtr _ptr ( new MaskedPrimaryField ( key, this->UnknownsField.get(), {T_f} ) );
128 return _ptr;
129 } else if ( key == FT_HumidityConcentration ) {
130 FieldPtr _ptr ( new MaskedPrimaryField ( key, this->UnknownsField.get(), {C_1} ) );
131 return _ptr;
132 } else {
133 return FieldPtr();
134 }
135}
136
137
138
139TimeStep *StationaryTransportProblem :: giveNextStep()
140{
141 int istep = this->giveNumberOfFirstStep();
142 StateCounterType counter = 1;
143
144 if ( currentStep ) {
145 istep = currentStep->giveNumber() + 1;
146 counter = currentStep->giveSolutionStateCounter() + 1;
147 }
148
149 previousStep = std :: move(currentStep);
150 currentStep = std::make_unique<TimeStep>(istep, this, 1, ( double ) istep, 0., counter);
151 return currentStep.get();
152}
153
154
155void StationaryTransportProblem :: solveYourselfAt(TimeStep *tStep)
156{
157
158
159 //
160 // creates system of governing eq's and solves them at given time step
161 //
162 // first assemble problem at current time step
163 UnknownsField->advanceSolution(tStep);
165
166 if ( tStep->giveNumber() == 1 ) {
167 // allocate space for solution vector
168 FloatArray *solutionVector = UnknownsField->giveSolutionVector(tStep);
169 solutionVector->resize(neq);
170 solutionVector->zero();
171
173 if ( !conductivityMatrix ) {
174 OOFEM_ERROR("sparse matrix creation failed");
175 }
176
177 conductivityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() );
178 if ( this->keepTangent ) {
179 this->conductivityMatrix->zero();
180 this->assemble( *conductivityMatrix, tStep, TangentAssembler(TangentStiffness),
182 }
183 }
184
185 Domain *domain = this->giveDomain(1);
186 if ( tStep->isTheFirstStep() ) {
187 // update element state according to given ic
188 for ( auto &elem : domain->giveElements() ) {
189 TransportElement *element = static_cast< TransportElement * >( elem.get() );
190 element->updateInternalState(tStep);
191 element->updateYourself(tStep);
192 }
193 }
194
195 internalForces.resize(neq);
196
197#ifdef VERBOSE
198 OOFEM_LOG_INFO("Assembling external forces\n");
199#endif
200 FloatArray externalForces(neq);
201 externalForces.zero();
202 this->assembleVector( externalForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) );
204
205 // set-up numerical method
207#ifdef VERBOSE
208 OOFEM_LOG_INFO("Solving for %d unknowns\n", neq);
209#endif
210
211 FloatArray incrementOfSolution;
212 double loadLevel;
213 int currentIterations;
214 this->nMethod->solve(*this->conductivityMatrix,
215 externalForces,
216 NULL,
217 *UnknownsField->giveSolutionVector(tStep),
218 incrementOfSolution,
219 this->internalForces,
220 this->eNorm,
221 loadLevel, // Only relevant for incrementalBCLoadVector
222 SparseNonLinearSystemNM :: rlm_total,
223 currentIterations,
224 tStep);
225
226 //nMethod->solve( *conductivityMatrix, rhsVector, *UnknownsField->giveSolutionVector(tStep) );
227}
228
229
230void
231StationaryTransportProblem :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d)
232{
233 // No-op: currently uses "PrimaryField" and passes along the reference
235}
236
237
238void
239StationaryTransportProblem :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *enorm)
240{
241 answer.zero();
242 this->assembleVector(answer, tStep, InternalForceAssembler(), VM_Total,
243 EModelDefaultEquationNumbering(), this->giveDomain(1), enorm);
245}
246
247
248void
249StationaryTransportProblem :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d)
250{
251 mat.zero();
252 this->assemble(mat, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), this->giveDomain(1) );
253}
254
255
256void
257StationaryTransportProblem :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d)
258{
259 if ( cmpn == InternalRhs ) {
260 this->internalForces.zero();
261 this->assembleVector(this->internalForces, tStep, InternalForceAssembler(), VM_Total,
262 EModelDefaultEquationNumbering(), this->giveDomain(1), & this->eNorm);
264 return;
265 } else if ( cmpn == NonLinearLhs ) {
266 if ( !this->keepTangent ) {
267 // Optimization for linear problems, we can keep the old matrix (which could save its factorization)
268 this->conductivityMatrix->zero();
269 this->assemble( *conductivityMatrix, tStep, TangentAssembler(TangentStiffness),
271 }
272 return;
273 } else {
274 OOFEM_ERROR("Unknown component");
275 }
276}
277
278void
279StationaryTransportProblem :: saveContext(DataStream &stream, ContextMode mode)
280{
281 EngngModel :: saveContext(stream, mode);
282 UnknownsField->saveContext(stream);
283}
284
285
286void
287StationaryTransportProblem :: restoreContext(DataStream &stream, ContextMode mode)
288{
289 EngngModel :: restoreContext(stream, mode);
290 UnknownsField->restoreContext(stream);
291}
292
293
294int
295StationaryTransportProblem :: checkConsistency()
296{
297 Domain *domain = this->giveDomain(1);
298
299 // check for proper element type
300 for ( auto &elem : domain->giveElements() ) {
301 if ( !dynamic_cast< TransportElement * >( elem.get() ) ) {
302 OOFEM_WARNING("Element %d has no TransportElement base", elem->giveLabel());
303 return 0;
304 }
305 }
306
307 return EngngModel :: checkConsistency();
308}
309
310
311void
312StationaryTransportProblem :: updateDomainLinks()
313{
314 EngngModel :: updateDomainLinks();
315 this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) );
316}
317
318} // end namespace oofem
#define REGISTER_EngngModel(class)
virtual int __giveEquationNumber() const =0
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
virtual void updateYourself(TimeStep *tStep)
Definition element.C:824
virtual TimeStep * giveCurrentStep(bool force=false)
Definition engngm.h:717
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Definition engngm.C:452
EngngModelContext * giveContext()
Context requesting service.
Definition engngm.h:1174
EngngModel(int i, EngngModel *_master=NULL)
Definition engngm.C:99
std ::unique_ptr< TimeStep > previousStep
Previous time step.
Definition engngm.h:243
MetaStep * giveCurrentMetaStep()
Returns current meta step.
Definition engngm.C:1900
int ndomains
Number of receiver domains.
Definition engngm.h:215
Domain * giveDomain(int n)
Definition engngm.C:1936
std ::unique_ptr< TimeStep > currentStep
Current time step.
Definition engngm.h:241
@ InternalForcesExchangeTag
Definition engngm.h:321
virtual int giveNumberOfFirstStep(bool force=false)
Definition engngm.h:763
int updateSharedDofManagers(FloatArray &answer, const UnknownNumberingScheme &s, int ExchangeTag)
Definition engngm.C:2162
void assembleVector(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1106
void registerField(FieldPtr eField, FieldType key)
void resize(Index s)
Definition floatarray.C:94
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
virtual void zero()=0
Zeroes the receiver.
std::unique_ptr< SparseNonLinearSystemNM > nMethod
Numerical method used to solve the problem.
NumericalMethod * giveNumericalMethod(MetaStep *mStep) override
Returns reference to receiver's numerical method.
FieldPtr giveField(FieldType key, TimeStep *) override
std ::unique_ptr< PrimaryField > UnknownsField
This field stores solution vector. For fixed size of problem, the PrimaryField is used,...
std ::unique_ptr< SparseMtrx > conductivityMatrix
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
bool isTheFirstStep()
Definition timestep.C:148
void updateInternalState(TimeStep *tStep) override
#define _IFT_EngngModel_smtype
Definition engngm.h:92
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
long ContextMode
Definition contextmode.h:43
FieldType
Physical type of field.
Definition field.h:64
FloatArrayF< N > assemble(const FloatArrayF< M > &x, int const (&c)[M])
Assemble components into zero matrix.
long StateCounterType
StateCounterType type used to indicate solution state.
@ SMT_Skyline
Symmetric skyline.
ClassFactory & classFactory
std::shared_ptr< Field > FieldPtr
Definition field.h:78
@ NonLinearLhs
@ InternalRhs
#define _IFT_StationaryTransportProblem_exportfields
#define _IFT_StationaryTransportProblem_keepTangent

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