OOFEM 3.0
Loading...
Searching...
No Matches
fe2fluidmaterial.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 "stokesflow.h"
37#include "oofemtxtdatareader.h"
38#include "domain.h"
39#include "gausspoint.h"
40#include "contextioerr.h"
41#include "util.h"
42#include "classfactory.h"
43#include "dynamicinputrecord.h"
44#include "mathfem.h"
45
46#include <sstream>
47
48//#define DEBUG_TANGENT
49#define DEBUG_ERR ( 1e-6 )
50
51namespace oofem {
53
54int FE2FluidMaterial :: n = 1;
55
56void FE2FluidMaterialStatus :: setTimeStep(TimeStep *tStep)
57{
58 TimeStep *rveTStep = this->rve->giveCurrentStep(); // Should i create a new one if it is empty?
59 rveTStep->setNumber( tStep->giveNumber() );
60 rveTStep->setTime( tStep->giveTargetTime() );
61 rveTStep->setTimeIncrement( tStep->giveTimeIncrement() );
62}
63
64FloatArrayF<6> FE2FluidMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const
65{
66 auto val = this->computeDeviatoricStress3D(eps, 0.0, gp, tStep);
67 double r_vol = val.second + eps.at(1) + eps.at(2) + eps.at(3);
68 if ( r_vol > 1e-9 ) {
69 OOFEM_ERROR("RVE seems to be compressible;"
70 " extended macro-formulation which doesn't assume incompressibility is required");
71 }
72 return val.first;
73}
74
75std::pair<FloatArrayF<6>, double> FE2FluidMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const
76{
77 FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) );
78
79 ms->setTimeStep(tStep);
80
82
83 // Set input
85 bc->setPrescribedPressure(pressure);
86 // Solve subscale problem
88
89 FloatArray stress_dev;
90 double r_vol;
91 bc->computeFields(stress_dev, r_vol, tStep);
92
93 ms->letDeviatoricStressVectorBe(stress_dev);
95 ms->letPressureBe(pressure);
96 ms->markOldTangents(); // Mark this so that tangents are reevaluated if they are needed.
97 // One could also just compute them here, but you don't actually need them if the problem has converged, so this method saves on that iteration.
98 // Computing the tangents are often *more* expensive than computeFields, so this is well worth the time it saves
99 return {stress_dev, r_vol};
100}
101
102FloatMatrixF<6,6> FE2FluidMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
103{
104 FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) );
105 ms->computeTangents(tStep);
106 if ( mode != TangentStiffness ) {
107 OOFEM_ERROR("Mode not implemented");
108 }
110 return x; //ms->giveDeviatoricTangent();
111}
112
114FE2FluidMaterial :: computeTangents3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
115{
116 //FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp,
117 FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) );
118 ms->computeTangents(tStep);
119 if ( mode != TangentStiffness ) {
120 OOFEM_ERROR("Mode not implemented");
121 }
122#if 0
123 // Numerical ATS for debugging
124 FloatMatrix numericalATS(6, 6);
125 FloatArray dsig;
126 FloatArray tempStrain(6);
127
128 tempStrain.zero();
129 FloatArray sig, strain, sigPert;
130 double epspvol;
131 computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep);
132 double h = 0.001; // Linear problem, size of this doesn't matter.
133 for ( int k = 1; k <= 6; ++k ) {
134 strain = tempStrain;
135 strain.at(k) += h;
136 double tmp = strain.at(1) + strain.at(2) + strain.at(3);
137 strain.at(1) -= tmp/3.0;
138 strain.at(2) -= tmp/3.0;
139 strain.at(3) -= tmp/3.0;
140 strain.printYourself();
141 computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep);
142 sigPert.printYourself();
143 dsig.beDifferenceOf(sigPert, sig);
144 numericalATS.setColumn(dsig, k);
145 }
146 numericalATS.times(1. / h);
147
148 printf("Analytical deviatoric tangent = ");
149 dsdd.printYourself();
150 printf("Numerical deviatoric tangent = ");
151 numericalATS.printYourself();
152 numericalATS.subtract(dsdd);
153 double norm = numericalATS.computeFrobeniusNorm();
154 if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) {
155 OOFEM_ERROR("Error in deviatoric tangent");
156 }
157#endif
158#if 0
159 // Numerical ATS for debugging
160 FloatArray strain(3);
161 strain.zero();
162 FloatArray sig, sigh;
163 double epspvol, pressure = 0.0;
164 double h = 1.00; // Linear problem, size of this doesn't matter.
165 computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep);
166 computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep);
167
168 FloatArray dsigh;
169 dsigh.beDifferenceOf(sigh, sig);
170 dsigh.times(1 / h);
171
172 printf("Analytical deviatoric pressure tangent = ");
173 dsdp.printYourself();
174 printf("Numerical deviatoric pressure tangent = ");
175 dsigh.printYourself();
176 dsigh.subtract(dsdp);
177 double norm = dsigh.computeNorm();
178 if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) {
179 OOFEM_ERROR("Error in deviatoric pressure tangent");
180 }
181#endif
182#if 0
183 // Numerical ATS for debugging
184 FloatArray tempStrain(3);
185 tempStrain.zero();
186 FloatArray sig, strain;
187 double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0;
188 double h = 1.0; // Linear problem, size of this doesn't matter.
189
190 computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep);
191 strain = tempStrain;
192 strain.at(1) += h;
193 computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep);
194 strain = tempStrain;
195 strain.at(2) += h;
196 computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep);
197 strain = tempStrain;
198 strain.at(3) += h;
199 computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep);
200
201 FloatArray dvol(3);
202 dvol.at(1) = ( epspvol11 - epspvol ) / h;
203 dvol.at(2) = ( epspvol22 - epspvol ) / h;
204 dvol.at(3) = ( epspvol12 - epspvol ) / h;
205 dvol.at(1) += 1.0;
206 dvol.at(2) += 1.0;
207
208 printf("Analytical volumetric deviatoric tangent = ");
209 dedd.printYourself();
210 printf("Numerical volumetric deviatoric tangent = ");
211 dvol.printYourself();
212 dvol.subtract(dedd);
213 double norm = dvol.computeNorm();
214 if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) {
215 OOFEM_ERROR("Error in volumetric deviatoric tangent");
216 }
217#endif
218#if 0
219 // Numerical ATS for debugging
220 FloatArray strain(3);
221 strain.zero();
222 FloatArray sig;
223 double epspvol, epspvolh, pressure = 0.0;
224 double h = 1.0; // Linear problem, size of this doesn't matter.
225
226 computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep);
227 computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep);
228
229 double dvol = -( epspvolh - epspvol ) / h;
230
231 printf("Analytical volumetric pressure tangent = %e\n", dedp);
232 printf("Numerical volumetric pressure tangent = %e\n", dvol);
233
234 double norm = fabs(dvol - dedp);
235 if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) {
236 OOFEM_ERROR("Error in volumetric pressure tangent");
237 }
238#endif
239 return {
244 };
245}
246
247void FE2FluidMaterial :: initializeFrom(InputRecord &ir)
248{
249 FluidDynamicMaterial :: initializeFrom(ir);
251}
252
253void FE2FluidMaterial :: giveInputRecord(DynamicInputRecord &input)
254{
255 FluidDynamicMaterial :: giveInputRecord(input);
257}
258
259
260int FE2FluidMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
261{
262 FE2FluidMaterialStatus *status = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) );
263 if ( type == IST_VOFFraction ) {
264 answer = FloatArray{status->giveVOFFraction()};
265 return true;
266 } else if ( type == IST_Pressure ) {
267 answer = FloatArray{status->givePressure()};
268 return true;
269 } else if ( type == IST_Undefined ) {
270#if 0
271 // Numerical ATS for debugging
272 FloatArray strain(3);
273 strain.zero();
274 FloatArray sig;
275 double epspvol, epspvolh, pressure = 0.0;
276 double h = 1.0; // Linear problem, size of this doesn't matter.
277
278 computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep);
279 computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep);
280
281 double dvol = - ( epspvolh - epspvol ) / h;
282
283
284 printf("Analytical volumetric pressure tangent = %f\n", status->giveVolumetricPressureTangent());
285 printf("Numerical volumetric pressure tangent = %f\n", dvol);
286
287 double norm = fabs(dvol - status->giveVolumetricPressureTangent());
288 if ( norm > fabs(status->giveVolumetricPressureTangent()) * DEBUG_ERR && norm > 0.0 ) {
289 OOFEM_ERROR("Error in volumetric pressure tangent");
290 }
291#endif
292 answer = FloatArray{status->giveVolumetricPressureTangent()};
293 return true;
294 } else {
295 return FluidDynamicMaterial :: giveIPValue(answer, gp, type, tStep);
296 }
297}
298
299
300std::unique_ptr<MaterialStatus> FE2FluidMaterial :: CreateStatus(GaussPoint *gp) const
301{
302 int rank = -1;
303 if ( this->domain->giveEngngModel()->isParallel() && this->domain->giveEngngModel()->giveNumberOfProcesses() > 1 ) {
304 rank = this->domain->giveEngngModel()->giveRank();
305 }
306 return std::make_unique<FE2FluidMaterialStatus>(n++, rank, gp, this->inputfile);
307}
308
309int FE2FluidMaterial :: checkConsistency()
310{
311 return true;
312}
313
314FE2FluidMaterialStatus :: FE2FluidMaterialStatus(int n, int rank, GaussPoint *gp, const std :: string &inputfile) :
316 voffraction(0.0),
317 oldTangents(true)
318{
319 if ( !this->createRVE(n, rank ,gp, inputfile) ) {
320 OOFEM_ERROR("Couldn't create RVE");
321 }
322}
323
324// Uses an input file for now, should eventually create the RVE itself.
325bool FE2FluidMaterialStatus :: createRVE(int n, int rank, GaussPoint *gp, const std :: string &inputfile)
326{
327 OOFEMTXTDataReader dr( inputfile.c_str() );
328 this->rve = InstanciateProblem(dr, _processor, 0); // Everything but nrsolver is updated.
329 dr.finish();
330 this->rve->setProblemScale(microScale);
331 this->rve->checkProblemConsistency();
332 this->rve->initMetaStepAttributes( this->rve->giveMetaStep(1) );
333 this->rve->giveNextStep(); // Makes sure there is a timestep (which we will modify before solving a step)
334 this->rve->init();
335
336 std :: ostringstream name;
337 name << this->rve->giveOutputBaseFileName() << "-gp" << n;
338 if ( rank >= 0 ) {
339 name << "." << rank;
340 }
341
342 this->rve->letOutputBaseFileNameBe( name.str() );
343
344 this->bc = dynamic_cast< MixedGradientPressureBC * >( this->rve->giveDomain(1)->giveBc(1) );
345 if ( !this->bc ) {
346 OOFEM_ERROR("RVE doesn't have necessary boundary condition; should have MixedGradientPressure as first b.c. (in first domain)");
347 }
348
349 return true;
350}
351
352void FE2FluidMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const
353{
354 FluidDynamicMaterialStatus :: printOutputAt(file, tStep);
355}
356
357void FE2FluidMaterialStatus :: updateYourself(TimeStep *tStep)
358{
359 double fluid_area = this->rve->giveDomain(1)->giveSize();
360 double total_area = this->bc->domainSize();
361 this->voffraction = fluid_area / total_area;
362 FluidDynamicMaterialStatus :: updateYourself(tStep);
363
364 this->rve->updateYourself(tStep);
365 this->rve->terminate(tStep);
366}
367
368void FE2FluidMaterialStatus :: initTempStatus()
369{
370 FluidDynamicMaterialStatus :: initTempStatus();
371}
372
373void FE2FluidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode)
374{
375 FluidDynamicMaterialStatus :: saveContext(stream, mode);
376 this->rve->saveContext(stream, mode);
377}
378
379void FE2FluidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode)
380{
381 FluidDynamicMaterialStatus :: restoreContext(stream, mode);
382 this->markOldTangents();
383 this->rve->restoreContext(stream, mode);
384}
385
386void FE2FluidMaterialStatus :: markOldTangents() { this->oldTangents = true; }
387
388void FE2FluidMaterialStatus :: computeTangents(TimeStep *tStep)
389{
390 if ( !tStep->isTheCurrentTimeStep() ) {
391 OOFEM_ERROR("Only current timestep supported.");
392 }
393
394 if ( this->oldTangents ) {
395 bc->computeTangents(this->giveDeviatoricTangent(),
399 tStep);
400 }
401
402 this->oldTangents = false;
403}
404
405double FE2FluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const
406{
407 FE2FluidMaterialStatus *status = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) );
408 status->computeTangents(tStep);
409 const auto &t = status->giveDeviatoricTangent();
410 // Project against the normalized I_dev
411 double v;
412 if ( gp->giveMaterialMode() == _3dFlow ) {
413 v = ( t.at(1, 1) * 2. - t.at(1, 2) - t.at(1, 3) ) / 3. +
414 ( -t.at(2, 1) + t.at(2, 2) * 2. - t.at(2, 3) ) / 3. +
415 ( -t.at(3, 1) - t.at(3, 2) + t.at(3, 3) * 2. ) / 3. +
416 4. * ( t.at(4, 4) + t.at(5, 5) + t.at(6, 6) );
417 v /= 16.;
418 } else {
419 v = ( t.at(1, 1) * 2. - t.at(1, 2) ) / 3. +
420 ( -t.at(2, 1) + t.at(2, 2) * 2. ) / 3. +
421 4. * t.at(3, 3);
422 v *= 9. / 56.;
423 }
424
425 return v;
426}
427} // end namespace oofem
#define REGISTER_Material(class)
void setField(int item, InputFieldType id)
virtual TimeStep * giveCurrentStep(bool force=false)
Definition engngm.h:717
virtual void solveYourselfAt(TimeStep *tStep)
Definition engngm.h:484
void computeTangents(TimeStep *tStep)
std ::unique_ptr< EngngModel > rve
The subscale flow.
FloatArray & giveVolumetricDeviatoricTangent()
MixedGradientPressureBC * giveBC()
MixedGradientPressureBC * bc
Boundary condition in RVE that performs the computational homogenization.
void setTimeStep(TimeStep *tStep)
Copies time step data to RVE.
FloatArray & giveDeviatoricPressureTangent()
bool createRVE(int n, int rank, GaussPoint *gp, const std ::string &inputfile)
Creates/Initiates the RVE problem.
std::pair< FloatArrayF< 6 >, double > computeDeviatoricStress3D(const FloatArrayF< 6 > &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const override
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
double & at(std::size_t i)
double computeNorm() const
Definition floatarray.C:861
double & at(Index i)
Definition floatarray.h:202
virtual void printYourself() const
Definition floatarray.C:762
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Definition floatarray.C:403
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void subtract(const FloatArray &src)
Definition floatarray.C:320
void times(double s)
Definition floatarray.C:834
void times(double f)
void setColumn(const FloatArray &src, int c)
*Prints matrix to stdout Useful for debugging void printYourself() const
double computeFrobeniusNorm() const
void subtract(const FloatMatrix &a)
FluidDynamicMaterialStatus(GaussPoint *g)
Constructor - creates new TransportMaterialStatus with number n, belonging to domain d and integratio...
void letDeviatoricStrainRateVectorBe(const FloatArrayF< 6 > &v)
void letDeviatoricStressVectorBe(const FloatArrayF< 6 > &v)
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
GaussPoint * gp
Associated integration point.
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
virtual void setPrescribedDeviatoricGradientFromVoigt(const FloatArray &ddev)=0
virtual void computeFields(FloatArray &stressDev, double &vol, TimeStep *tStep)=0
virtual void setPrescribedPressure(double p)=0
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
void setNumber(int i)
Set receiver's number.
Definition timestep.h:146
double giveTargetTime()
Returns target time.
Definition timestep.h:164
void setTimeIncrement(double newDt)
Sets solution step time increment.
Definition timestep.h:170
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
bool isTheCurrentTimeStep()
Definition timestep.C:164
void setTime(double newt)
Sets target and intrinsic time to be equal.
Definition timestep.h:172
#define OOFEM_ERROR(...)
Definition error.h:79
#define DEBUG_ERR
#define _IFT_FE2FluidMaterial_fileName
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
long ContextMode
Definition contextmode.h:43
double norm(const FloatArray &x)
std::unique_ptr< EngngModel > InstanciateProblem(DataReader &dr, problemMode mode, int contextFlag, EngngModel *_master, bool parallelFlag)
Definition util.C:153
@ _processor
Definition problemmode.h:40
@ microScale
Definition problemmode.h:47

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