OOFEM 3.0
Loading...
Searching...
No Matches
hemokunzelmat.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 program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (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
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 */
34
36#include "floatmatrixf.h"
37#include "gausspoint.h"
38#include "mathfem.h"
39#include "classfactory.h"
40
41namespace oofem {
43
44bool
45HeMoKunzelMaterial :: hasMaterialModeCapability(MaterialMode mode) const
46{
47 return mode == _2dHeMo || mode == _3dHeMo;
48}
49
50
51void
52HeMoKunzelMaterial :: initializeFrom(InputRecord &ir)
53{
54 Material :: initializeFrom(ir);
55
56 int type = 0;
58 this->Isotherm = ( isothermType ) type;
59
60 if ( this->Isotherm == Hansen ) {
64 } else if ( this->Isotherm == Kunzeliso ) {
67 } else {
68 OOFEM_ERROR("Unknown Isotherm type");
69 }
70
71
73
74 if ( type >= 3 ) {
75 OOFEM_ERROR("initializeFrom: isothermType must be equal to 0, 1, 2");
76 }
77
78 this->Permeability = ( permeabilityType ) type;
79
80 if ( this->Permeability == Multilin_h ) {
83
84 if ( !( perm_h.giveSize() == perm_Dwh.giveSize() ) ) {
85 OOFEM_ERROR("initializeFrom: the size of 'perm_h' and 'perm_dw(h)' must be the same");
86 }
87
88 for ( int i = 1; i < perm_h.giveSize(); i++ ) {
89 if ( ( perm_h.at(i) < 0. ) || ( perm_h.at(i) > 1. ) ) {
90 OOFEM_ERROR("initializeFrom: perm_h must be in the range <0; 1>");
91 }
92 }
93 } else if ( this->Permeability == Multilin_wV ) {
96
97 if ( !( perm_wV.giveSize() == perm_DwwV.giveSize() ) ) {
98 OOFEM_ERROR("initializeFrom: the size of 'perm_h' and 'perm_dw(h)' must be the same");
99 }
100
101 for ( int i = 1; i < perm_wV.giveSize(); i++ ) {
102 if ( ( perm_wV.at(i) < 0. ) || ( perm_wV.at(i) > 1. ) ) {
103 OOFEM_ERROR("initializeFrom: perm_wv must be in the range <0; 1>");
104 }
105 }
106 } else if ( this->Permeability == Kunzelperm ) {
108 } else {
109 OOFEM_ERROR("initializeFrom: permeabilityType must be equal to 0, 1 or 2");
110 }
111
113
114 PL = 101325.;
116
117 rhoH2O = 1000.;
119
123
124 // cw = 4.1813e3;
125 cw = 4183.;
127
128 hv = 2.5e6;
130}
131
132
133double
134HeMoKunzelMaterial :: give(int aProperty, GaussPoint *gp) const
135{
136 return Material :: give(aProperty, gp);
137}
138
139
140std::pair<FloatArrayF<3>, FloatArrayF<3>>
141HeMoKunzelMaterial :: computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const
142{
143 auto ms = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) );
144
145 ms->setTempTemperature(t);
146 ms->setTempHumidity(h);
147
148 ms->setTempTemperatureGradient(grad_t);
149 ms->setTempHumidityGradient(grad_w);
150
151 auto ans_t = -perm_hm(h, t) * grad_w - perm_hh(h, t) * grad_t;
152 auto ans_w = -perm_mm(h, t) * grad_w - perm_mh(h, t) * grad_t;
153
154 ms->setTempHeatFlux(ans_t);
155 ms->setTempHumidityFlux(ans_w);
156
157 return {ans_t, ans_w};
158}
159
160
162HeMoKunzelMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
163{
164 auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) );
165
166 double t = status->giveTempTemperature();
167 double h = status->giveTempHumidity();
168
169 double k = 0.0;
170 if ( mode == Conductivity_ww ) {
171 k = perm_mm(h, t);
172 } else if ( mode == Conductivity_wh ) {
173 k = perm_mh(h, t);
174 } else if ( mode == Conductivity_hw ) {
175 k = perm_hm(h, t);
176 } else if ( mode == Conductivity_hh ) {
177 k = perm_hh(h, t);
178 } else {
179 OOFEM_ERROR("Unknown MatResponseMode");
180 }
181
182 return k * eye<3>();
183}
184
185
186double
187HeMoKunzelMaterial :: giveCharacteristicValue(MatResponseMode mode,
188 GaussPoint *gp,
189 TimeStep *tStep) const
190{
191 return this->computeCapacityCoeff(mode, gp, tStep);
192}
193
194
195double HeMoKunzelMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
196{
197 // if (gp->giveElement()->giveNumber() == 4)
198 // double bzzz = 20;
199
200 if ( mode == Capacity_ww ) {
201 auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) );
202
203 double h = status->giveTempHumidity();
204 return this->giveMoistureContentDerivative(h);
205 } else if ( mode == Capacity_wh ) {
206 return 0.0;
207 } else if ( mode == Capacity_hw ) {
208 return 0.0;
209 } else if ( mode == Capacity_hh ) {
210 auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) );
211
212 double h = status->giveTempHumidity();
213 double w = this->giveMoistureContent(h);
214
215 double dHs_dT = cs * give('d', nullptr);
216 double dHw_dT = cw * w;
217
218 return dHs_dT + dHw_dT;
219
220 // CONSTANT return 1.7e6;
221 } else {
222 OOFEM_ERROR("Unknown MatResponseMode");
223 }
224
225 // return 0.0; // to make compiler happy
226}
227
228
229double
230HeMoKunzelMaterial :: giveMoistureContent(double h) const
231{
232 if ( h < 0.0 || h > 1.00 ) {
233 OOFEM_ERROR("HeMoKunzelMaterial :: giveMoistureContent : Relative humidity %.3f is out of range", h);
234 }
235
236 if ( this->Isotherm == Hansen ) {
237 return iso_wh * pow( ( 1.0 - log(h) / iso_a ), ( -1.0 / iso_n ) );
238 } else if ( this->Isotherm == Kunzeliso ) {
239 return iso_wh * ( iso_b - 1. ) * h / ( iso_b - h );
240 } else {
241 OOFEM_ERROR("Unknown Isotherm type");
242 }
243}
244
245double
246HeMoKunzelMaterial :: giveMoistureContentDerivative(double h) const
247{
248 if ( h < 0.0 || h > 1.00 ) {
249 OOFEM_ERROR("HeMoKunzelMaterial :: giveMoistureContentDerivative : Relative humidity %.3f is out of range", h);
250 }
251
252 if ( this->Isotherm == Hansen ) {
253 return iso_wh / ( iso_n * iso_a * h ) * pow( ( 1.0 - log(h) / iso_a ), ( -( 1.0 + iso_n ) / iso_n ) );
254 } else if ( this->Isotherm == Kunzeliso ) {
255 return iso_wh * ( iso_b - 1. ) * iso_b / ( ( iso_b - h ) * ( iso_b - h ) );
256 } else {
257 OOFEM_ERROR("Unknown Isotherm type");
258 }
259}
260
261
262double
263HeMoKunzelMaterial :: computeWaterVaporPerm(double T) const
264{
265 // vapor diffusion coefficient in air [kg m^-1 s^-1 Pa^-1]
266 double delta = 2.0 * 1.e-7 * pow(T, 0.81) / PL;
267 return delta / mu;
268}
269
270double
271HeMoKunzelMaterial :: computeSatVaporPressure(double T) const
272{
273 double T_C = T - 273.15;
274
275 double T0, a;
276 if ( T_C < 0. ) {
277 a = 22.44;
278 T0 = 272.44;
279 } else {
280 a = 17.08;
281 T0 = 234.18;
282 }
283
284 return 611. * exp( a * T_C / ( T0 + T_C ) );
285}
286
287double
288HeMoKunzelMaterial :: computeSatVaporPressureDerivative(double T) const
289{
290 double T_C = T - 273.15;
291
292 double T0, a;
293 if ( T_C < 0. ) {
294 a = 22.44;
295 T0 = 272.44;
296 } else {
297 a = 17.08;
298 T0 = 234.18;
299 }
300
301 return 611. *a *T0 *exp( a *T_C / ( T0 + T_C ) ) / ( ( T0 + T_C ) * ( T0 + T_C ) );
302}
303
304
305double
306HeMoKunzelMaterial :: computeDw(double h) const
307{
308 if ( this->Permeability == Multilin_h ) {
309 double tol = 1.e-10;
310 for ( int i = 1; i <= perm_h.giveSize(); i++ ) {
311 if ( ( h - perm_h.at(i) ) < tol ) {
312 return perm_Dwh.at(i - 1) + ( perm_Dwh.at(i) - perm_Dwh.at(i - 1) ) * ( h - perm_h.at(i - 1) ) / ( perm_h.at(i) - perm_h.at(i - 1) );
313 }
314 }
315 } else if ( this->Permeability == Multilin_wV ) {
316 double wV = this->giveMoistureContent(h) / rhoH2O;
317 double tol = 1.e-10;
318 for ( int i = 1; i <= perm_wV.giveSize(); i++ ) {
319 if ( ( wV - perm_wV.at(i) ) < tol ) {
320 return perm_DwwV.at(i - 1) + ( perm_DwwV.at(i) - perm_DwwV.at(i - 1) ) * ( wV - perm_wV.at(i - 1) ) / ( perm_wV.at(i) - perm_wV.at(i - 1) );
321 }
322 }
323 } else if ( this->Permeability == Kunzelperm ) {
324 double w;
325 w = this->giveMoistureContent(h);
326 return 3.8 * ( A / iso_wh ) * ( A / iso_wh ) * pow(1000., w / iso_wh - 1.);
327 } else {
328 OOFEM_ERROR("initializeFrom: permeabilityType must be equal to 0, 1 or 2");
329 }
330
331 return 0.;
332}
333
334
335double
336HeMoKunzelMaterial :: perm_mm(double h, double T) const
337{
338 // Function calculates permability relative humidity - relative humidity (k_mm)
339 // h ... relative humidity
340 // Dw ... capillary transport coefficient [m^2/s]
341 // dw_dh ... derivative of moisture storage function [kg/m^3]
342 // p_sat ... saturation water vapor pressure
343
344 double dw_dh = this->giveMoistureContentDerivative(h);
345
346 double Dw = this->computeDw(h);
347
348 double deltap = this->computeWaterVaporPerm(T);
349 double p_sat = this->computeSatVaporPressure(T);
350
351 return Dw * dw_dh + deltap * p_sat;
352}
353
354double
355HeMoKunzelMaterial :: perm_mh(double h, double T) const
356{
357 // Function calculates permeability relative humidity-temperature (k_mh)
358 // deltap ... water vapor permeability
359 // dpsat_dt ... differentiation of saturation water vapor presssure with respect to temperature
360 double delta_p = computeWaterVaporPerm(T);
361 double dpsat_dT = computeSatVaporPressureDerivative(T);
362
363 return delta_p * h * dpsat_dT;
364}
365
366
367double
368HeMoKunzelMaterial :: perm_hm(double h, double T) const
369{
370 // Function calculates permability temperature-relative humidity (k_hm)
371 double deltap = this->computeWaterVaporPerm(T);
372 double p_sat = this->computeSatVaporPressure(T);
373 return hv * deltap * p_sat;
374}
375
376double
377HeMoKunzelMaterial :: perm_hh(double h, double T) const
378{
379 // Function calculates permability water temperature-temperature (k_hh)
380
381 double w = this->giveMoistureContent(h);
382 double lambda = lambda0 * ( 1. + b * w / give('d', nullptr) );
383 double deltap = this->computeWaterVaporPerm(T);
384 double dpsat_dT = computeSatVaporPressureDerivative(T);
385
386 return lambda + hv * deltap * h * dpsat_dT;
387}
388
389bool
390HeMoKunzelMaterial :: isCharacteristicMtrxSymmetric(MatResponseMode mode) const
391{
392 if ( mode == Conductivity_ww || mode == Conductivity_hh || mode == Conductivity_hw || mode == Conductivity_wh ) {
393 return false;
394 } else {
395 OOFEM_ERROR( "isCharacteristicMtrxSymmetric : unknown mode (%s)", __MatResponseModeToString(mode) );
396 }
397
398 // return false; // to make compiler happy
399}
400
401int
402HeMoKunzelMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
403// IST_Humidity overriden to use inverse_sorption_isotherm
404{
405 double humidity = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) )->giveHumidity();
406 if ( type == IST_Humidity ) {
407 answer.resize(1);
408 answer.at(1) = humidity;
409 return 1;
410 } else if ( type == IST_MoistureContent ) {
411 answer.resize(1);
412 answer.at(1) = giveMoistureContent(humidity);
413 return 1;
414 } else {
415 return TransportMaterial :: giveIPValue(answer, gp, type, tStep);
416 }
417}
418
419} // end namespace oofem
#define REGISTER_Material(class)
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double computeWaterVaporPerm(double T) const
double perm_mh(double h, double T) const
double iso_a
Parameter of Hansen's isotherm.
double hv
latent heat of phase change/evaporation enthalpy of pure water [J/kg]
double giveMoistureContent(double h) const
returns water content (in kg/m^3)
double computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) const
double computeDw(double h) const
double b
thermal conductivity supplement [-]
enum oofem::HeMoKunzelMaterial::permeabilityType Permeability
double cw
specific heat capacity of liquid water [J kg^-1 K^-1]
double perm_mm(double h, double T) const
double mu
water vapor diffusion resistance [-]
double iso_b
Parameter of Kunzel's isotherm.
double iso_wh
Parameter of Hansen's/Kunzel's isotherm - max. adsorbed water content [kg/m^3].
double iso_n
Parameter of Hansen's isotherm - exponent.
double perm_hm(double h, double T) const
enum oofem::HeMoKunzelMaterial::isothermType Isotherm
double giveMoistureContentDerivative(double h) const
computes derivative of the moisture storage function (sorption isotherm) with respect to relative hum...
double computeSatVaporPressure(double T) const
double perm_hh(double h, double T) const
double give(int aProperty, GaussPoint *gp) const override
FloatArray perm_h
values of the multilinear permeability
double rhoH2O
water density [kg m^-3]
double lambda0
thermal conductivity [W m^-1 K^-1]
double cs
specific heat capacity of the building material [J kg^-1 K^-1]
double A
water absorption coefficient [kg m^-2 s^-0.5]
double PL
ambient atmospheric pressure [Pa]
double computeSatVaporPressureDerivative(double T) const
double giveTempHumidity() const
Return last field.
void setTempTemperature(double newField)
Set field.
double giveTempTemperature() const
Return last field.
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
virtual double giveHumidity(GaussPoint *gp, ValueModeType mode) const
#define OOFEM_ERROR(...)
Definition error.h:79
#define _IFT_HeMoKunzelMaterial_a
#define _IFT_HeMoKunzelMaterial_iso_b
#define _IFT_HeMoKunzelMaterial_rhoh2o
#define _IFT_HeMoKunzelMaterial_perm_h
#define _IFT_HeMoKunzelMaterial_permeability_type
#define _IFT_HeMoKunzelMaterial_perm_dwwv
#define _IFT_HeMoKunzelMaterial_cs
#define _IFT_HeMoKunzelMaterial_iso_type
#define _IFT_HeMoKunzelMaterial_pl
#define _IFT_HeMoKunzelMaterial_perm_dwh
#define _IFT_HeMoKunzelMaterial_perm_wv
#define _IFT_HeMoKunzelMaterial_hv
#define _IFT_HeMoKunzelMaterial_iso_a
#define _IFT_HeMoKunzelMaterial_iso_wh
#define _IFT_HeMoKunzelMaterial_cw
#define _IFT_HeMoKunzelMaterial_lambda0
#define _IFT_HeMoKunzelMaterial_b
#define _IFT_HeMoKunzelMaterial_iso_n
#define _IFT_HeMoKunzelMaterial_mu
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
FloatMatrixF< N, N > eye()
Constructs an identity matrix.

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