OOFEM 3.0
Loading...
Searching...
No Matches
cemhydmat.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
35/* Majority of this file was developed at the National Institute of
36 * Standards and Technology by employees of the Federal
37 * Government in the course of their official duties. Pursuant
38 * to title 17 Section 105 of the United States Code this
39 * software is not subject to copyright protection and is in
40 * the public domain. CEMHYD3D is an experimental system. NIST
41 * assumes no responsibility whatsoever for its use by other
42 * parties, and makes no guarantees, expressed or implied,
43 * about its quality, reliability, or any other characteristic.
44 * We would appreciate acknowledgement if the software is used.
45 * This software can be redistributed and/or modified freely
46 * provided that any derivative works bear some notice that
47 * they are derived from it, and any modified versions bear
48 * some notice that they have been modified.
49 */
50
51#include <cstdio>
52#include <cstdlib>
53
54//#include "tm/Materials/cemhyd/cemhydmat.h"
55#include "cemhydmat.h"
56#include "homogenize.h"
57#include "mathfem.h"
58
59#ifdef __TM_MODULE //OOFEM transport module
60 #include "classfactory.h"
61 #include "domain.h"
62 #include "floatmatrix.h"
63 #include "gausspoint.h"
64#endif
65
66namespace oofem {
67/* This software was developed at the National Institute of */
68/* Standards and Technology by employees of the Federal */
69/* Government in the course of their official duties. Pursuant */
70/* to title 17 Section 105 of the United States Code this */
71/* software is not subject to copyright protection and is in */
72/* the public domain. CEMHYD3D is an experimental system. NIST */
73/* assumes no responsibility whatsoever for its use by other */
74/* parties, and makes no guarantees, expressed or implied, */
75/* about its quality, reliability, or any other characteristic. */
76/* We would appreciate acknowledgement if the software is used. */
77/* This software can be redistributed and/or modified freely */
78/* provided that any derivative works bear some notice that */
79/* they are derived from it, and any modified versions bear */
80/* some notice that they have been modified. */
81/* Modified 3/97 to allow placement of pozzolanic, inert and fly ash particles */
82/* Modified 9/98 to allow placement of various forms of gypsum */
83/* Documented version produced 1/00 */
84/* Modified by smilauer@cml.fsv.cvut.cz to include 1 voxel particles 16.6.2005
85 * Dynamical allocation of memory arrays (possible in input file)
86 */
87
88//#define OUTFILES //if defined, output files are generated
89//#define IMAGEFILES //if defined, output percolated and unpercolated images in each cycle (directories perc/ and unperc/)
90//#define PRINTF //if defined, printf results simultaneously on screen
91
92#ifdef __TM_MODULE //OOFEM transport module
93
95
96CemhydMat :: CemhydMat(int n, Domain *d) : IsotropicHeatTransferMaterial(n, d)
97{
98 MasterCemhydMatStatus = nullptr;
99}
100
101//returns hydration power [W/m3 of concrete]
102void
103CemhydMat :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const
104{
105 double averageTemperature;
106 CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
107 val.resize(1);
108
109 if ( eachGP || ms == MasterCemhydMatStatus ) {
111 if ( mode == VM_Total || mode == VM_TotalIntrinsic ) {
112 //for nonlinear solver, return the last value even no time has elapsed
113 if ( tStep->giveTargetTime() != ms->LastCallTime ) {
114 val.at(1) = ms->GivePower( averageTemperature, tStep->giveTargetTime() );
115 } else {
116 val.at(1) = ms->PartHeat;
117 }
118 } else {
119 OOFEM_ERROR( "Undefined mode %s\n", __ValueModeTypeToString(mode) );
120 }
121 } else { //return released heat from the master
122 if ( mode == VM_Total || mode == VM_TotalIntrinsic ) {
123 val.at(1) = MasterCemhydMatStatus->PartHeat;
124 } else {
125 OOFEM_ERROR( "Undefined mode %s\n", __ValueModeTypeToString(mode) );
126 }
127 }
128
129 //val.at(1) = 1500;//constant source
130}
131
132
133int CemhydMat :: giveCycleNumber(GaussPoint *gp)
134{
135 auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
136 if ( MasterCemhydMatStatus ) {
138 }
139
140 return ms->GiveCycNum();
141}
142
143double CemhydMat :: giveTimeOfCycle(GaussPoint *gp)
144{
145 auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
146 if ( MasterCemhydMatStatus ) {
148 }
149
150 return ms->GiveCycTime();
151}
152
153
154
155double CemhydMat :: giveDoHActual(GaussPoint *gp)
156{
157 auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
158 if ( MasterCemhydMatStatus ) {
160 }
161
162 return ms->GiveDoHActual();
163}
164
165//standard units are [Wm-1K-1]
166double CemhydMat :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const
167{
168 auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
169 double conduct = 0.0;
170
171 if ( MasterCemhydMatStatus ) {
173 }
174
175 if ( conductivityType == 0 ) { //given from OOFEM input file
176 conduct = IsotropicHeatTransferMaterial :: give('k', gp, tStep);
177 } else if ( conductivityType == 1 ) { //compute according to Ruiz, Schindler, Rasmussen. Kim, Chang: Concrete temperature modeling and strength prediction using maturity concepts in the FHWA HIPERPAV software, 7th international conference on concrete pavements, Orlando (FL), USA, 2001
178 conduct = IsotropicHeatTransferMaterial :: give('k', gp, tStep) * ( 1.33 - 0.33 * ms->GiveDoHActual() );
179 } else {
180 OOFEM_ERROR("Unknown conductivityType %d\n", conductivityType);
181 }
182
183
184 //Parallel Voigt model, 20 W/m/K for steel
185 conduct = conduct * ( 1. - this->reinforcementDegree ) + 20. * this->reinforcementDegree;
186
187 if ( !this->nowarnings.at(2) && ( conduct < 0.3 || conduct > 5 ) ) {
188 OOFEM_WARNING("Weird concrete thermal conductivity %f W/m/K\n", conduct);
189 }
190
191 conduct *= this->scaling.at(2);
192
193 return conduct;
194}
195
196//normally it returns J/kg/K of concrete
197double CemhydMat :: giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) const
198{
199 auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
200 double capacityConcrete = 0.0;
201
202 if ( MasterCemhydMatStatus ) {
204 }
205
206 if ( capacityType == 0 ) { //given from OOFEM input file
207 capacityConcrete = IsotropicHeatTransferMaterial :: give('c', gp, tStep);
208 } else if ( capacityType == 1 ) { //compute from CEMHYD3D according to Bentz
209 capacityConcrete = ms->computeConcreteCapacityBentz();
210 } else if ( capacityType == 2 ) { //compute from CEMHYD3D directly
211 capacityConcrete = 1000 * ms->GiveCp();
212 } else {
213 OOFEM_ERROR("Unknown capacityType %d\n", capacityType);
214 }
215
216 //Parallel Voigt model, 500 J/kg/K for steel
217 capacityConcrete = capacityConcrete * ( 1. - this->reinforcementDegree ) + 500. * this->reinforcementDegree;
218
219 if ( !this->nowarnings.at(3) && ( capacityConcrete < 500 || capacityConcrete > 2000 ) ) {
220 OOFEM_WARNING("Weird concrete heat capacity %f J/kg/K\n", capacityConcrete);
221 }
222
223 capacityConcrete *= this->scaling.at(3);
224
225 return capacityConcrete;
226}
227
228double CemhydMat :: giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) const
229{
230 auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
231 double concreteBulkDensity = 0.0;
232
233 if ( MasterCemhydMatStatus ) {
235 }
236
237 if ( densityType == 0 ) { //get from OOFEM input file
238 concreteBulkDensity = IsotropicHeatTransferMaterial :: give('d', gp, tStep);
239 } else if ( densityType == 1 ) { //get from XML input file
240 concreteBulkDensity = ms->GiveDensity();
241 } else {
242 OOFEM_ERROR("Unknown densityType %d\n", densityType);
243 }
244
245 //Parallel Voigt model, 7850 kg/m3 for steel
246 concreteBulkDensity = concreteBulkDensity * ( 1. - this->reinforcementDegree ) + 7850. * this->reinforcementDegree;
247
248 if ( !this->nowarnings.at(1) && ( concreteBulkDensity < 1000 || concreteBulkDensity > 4000 ) ) {
249 OOFEM_WARNING("Weird concrete density %f kg/m3\n", concreteBulkDensity);
250 }
251
252 concreteBulkDensity *= this->scaling.at(1);
253
254 return concreteBulkDensity;
255}
256
257double
258CemhydMat :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
259{
260 if ( mode == Capacity ) {
261 return ( giveConcreteCapacity(gp, tStep) * giveConcreteDensity(gp, tStep) );
262 } else if ( mode == IntSource ) { //for nonlinear solver, return dHeat/dTemperature
263 auto status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) );
264 //it suffices to compute derivative of Arrhenius equation
265 //double actualTemperature = status->giveTempField().at(1);
266 double lastEquilibratedTemperature = status->giveField();
267 //double dt = tStep->giveTimeIncrement();
268 double krate, EaOverR, val;
269 CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
270 if ( MasterCemhydMatStatus ) {
272 }
273
274 EaOverR = 1000. * ms->E_act / 8.314;
275
276 if ( ms->icyc > 1 ) {
277 krate = exp( -EaOverR * ( 1. / ( ms->temp_cur + 273.15 ) - 1. / ( lastEquilibratedTemperature + 273.15 ) ) );
278 //use PartHeat from the last cycle as a corrector tangent, at least one cycle has elapsed
279 // if( fabs(3600*ms->time_cur - ms->PrevHydrTime) > 1.e-3 ){
280 // power = ms->heat_new-ms->PrevCycHeat / (3600*ms->time_cur - ms->PrevHydrTime);//[J/s = W] per gram of cement
281 // power *= 1000 * ms->Mass_cement_concrete;//W/m3/s
282 // } else {
283 // power = 1.e-6;
284 // }
285 } else {
286 krate = 1.;
287 }
288
289 val = EaOverR * krate / ( ms->temp_cur + 273.15 ) / ( ms->temp_cur + 273.15 );
290
291 return val;
292 } else {
293 OOFEM_ERROR("unknown mode (%s)\n", __MatResponseModeToString(mode) );
294 }
295
296 return 0.;
297}
298
299
300int
301CemhydMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
302{
303 CemhydMatStatus *ms;
304 if ( MasterCemhydMatStatus ) {
306 } else {
307 ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
308 }
309
310 if ( type == IST_HydrationDegree ) {
311 answer.resize(1);
312 answer.at(1) = this->giveDoHActual(gp);
313 return 1;
314 } else if ( type == IST_Density ) {
315 answer.resize(1);
316 answer.at(1) = this->giveConcreteDensity(gp,tStep);
317 return 1;
318 } else if ( type == IST_ThermalConductivityIsotropic ) {
319 answer.resize(1);
320 answer.at(1) = this->giveIsotropicConductivity(gp, tStep);
321 return 1;
322 } else if ( type == IST_HeatCapacity ) {
323 answer.resize(1);
324 answer.at(1) = this->giveConcreteCapacity(gp,tStep);
325 return 1;
326 } else if ( type == IST_AverageTemperature ) {
327 answer.resize(1);
328 answer.at(1) = ms->giveAverageTemperature();
329 return 1;
330 } else if ( type == IST_YoungModulusVirginPaste ) {
331 answer.resize(1);
332 answer.at(1) = ms->last_values [ 2 ];
333 return 1;
334 } else if ( type == IST_PoissonRatioVirginPaste ) {
335 answer.resize(1);
336 answer.at(1) = ms->last_values [ 3 ];
337 return 1;
338 } else if ( type == IST_YoungModulusConcrete ) {
339 answer.resize(1);
340 answer.at(1) = ms->last_values [ 4 ];
341 return 1;
342 } else if ( type == IST_PoissonRatioConcrete ) {
343 answer.resize(1);
344 answer.at(1) = ms->last_values [ 5 ];
345 return 1;
346 } else {
347 return TransportMaterial :: giveIPValue(answer, gp, type, tStep);
348 }
349}
350
351int
352CemhydMat :: initMaterial(Element *element)
353{
354 for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) {
355 CemhydMatStatus *ms;
356 if ( !MasterCemhydMatStatus && !eachGP ) {
357 ms = new CemhydMatStatus(gp, NULL, this, 1);
359 } else if ( eachGP ) {
360 ms = new CemhydMatStatus(gp, MasterCemhydMatStatus, this, 1);
361 } else {
362 ms = new CemhydMatStatus(gp, nullptr, this, 0);
363 }
364
365// if(!gp->giveMaterialStatus()){
366 gp->setMaterialStatus( ms );
367// }
368 }
369
370 return 1;
371}
372
373void CemhydMat :: clearWeightTemperatureProductVolume(Element *element)
374{
375 CemhydMatStatus *ms;
376
377 for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) {
378 ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
379 ms->setAverageTemperatureVolume(0.0, 0.0);
380 }
381}
382
383void CemhydMat :: storeWeightTemperatureProductVolume(Element *element, TimeStep *tStep)
384{
385 FloatArray vecTemperature;
386
387 if ( !eachGP ) {
388 for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) {
389 //when more GPs are lumped to a master GP
390 double dV = element->computeVolumeAround(gp);
391 element->giveIPValue(vecTemperature, gp, IST_Temperature, tStep);
392 MasterCemhydMatStatus->setAverageTemperatureVolume(MasterCemhydMatStatus->giveAverageTemperature() + dV * vecTemperature.at(1), MasterCemhydMatStatus->giveTotalVolume() + dV);
393 }
394 }
395}
396
397void CemhydMat :: averageTemperature()
398{
399 //printf("%f ", MasterCemhydMatStatus->giveAverageTemperature());
400 if ( !eachGP ) {
401 MasterCemhydMatStatus->setAverageTemperatureVolume( MasterCemhydMatStatus->giveAverageTemperature() / MasterCemhydMatStatus->giveTotalVolume(), MasterCemhydMatStatus->giveTotalVolume() );
402 }
403}
404
405void CemhydMat :: initializeFrom(InputRecord &ir)
406{
407 castingTime = 0.;
408
409 IsotropicHeatTransferMaterial :: initializeFrom(ir); //read d,k,c
410
412 capacityType = 0;
413 densityType = 0;
414 eachGP = 0;
415 nowarnings.resize(4);
416 nowarnings.zero();
417 scaling.resize(3);
418 for ( int i = 1; i <= scaling.giveSize(); i++ ) {
419 scaling.at(i) = 1.;
420 }
421
423 //if you want computation of material properties directly from CEMHYD3D, sum up 1 for density, 2 for conductivity, 4 for capacity
429 if ( nowarnings.giveSize() != 4 ) {
430 OOFEM_ERROR("Incorrect size %d of nowarnings", nowarnings.giveSize() );
431 }
432
434 if ( scaling.giveSize() != 3 ) {
435 OOFEM_ERROR("Incorrect size %d of scaling", nowarnings.giveSize() );
436 }
437
440}
441
442
444CemhydMat :: CreateStatus(GaussPoint *gp) const
445{
446 OOFEM_ERROR("Use function CemhydMat :: initMaterial instead");
447 return NULL;
448}
449
450
451//constructor allowing to copy a microstructure from another CemhydMatStatus
452//particular instance of CemhydMat in an integration point
453CemhydMatStatus :: CemhydMatStatus(GaussPoint *gp, CemhydMatStatus *CemStat, CemhydMat *cemhydmat, bool withMicrostructure) :
455{
456 int i, j, k;
457 PartHeat = 0.;
458 //to be sure, set all pointers to NULL
459 mic = NULL;
460 mic_CSH = NULL;
461 micorig = NULL;
462 micpart = NULL;
463 mask = NULL;
464 ArrPerc = NULL;
465 ConnNumbers = NULL;
466 cshage = NULL;
467 faces = NULL;
468 PhaseFrac = NULL;
469 last_values = NULL;
470 phase = NULL;
471
472 adiafile = NULL;
473 thfile = NULL;
474 elasfile = NULL;
475 heatfile = NULL;
476 chsfile = NULL;
477 ptmpfile = NULL;
478 movfile = NULL;
479 pHfile = NULL;
480 micfile = NULL;
481 fileperc = NULL;
482 percfile = NULL;
483 disprobfile = NULL;
484 phasfile = NULL;
485 perc_phases = NULL;
486 CSHfile = NULL;
487 infoperc = NULL;
488 infoUnperc = NULL;
489
490 mic = NULL;
491 micorig = NULL;
492 micpart = NULL;
493 cement = NULL;
494 cemreal = NULL;
495 clust = NULL;
496 mask = NULL;
497 curvature = NULL;
498 mic_CSH = NULL;
499 ArrPerc = NULL;
500 ConnNumbers = NULL;
501 faces = NULL;
502
503 #ifdef TINYXML
504 xmlFile = NULL;
505 #endif
506
507 headant = NULL;
508 tailant = NULL;
509 soluble = NULL;
510 creates = NULL;
511 CSH_vicinity = NULL;
512 molarvcsh = NULL;
513 watercsh = NULL;
514 xsph = NULL;
515 ysph = NULL;
516 zsph = NULL;
517 iv = NULL;
518 discount = NULL;
519 count = NULL;
520 disprob = NULL;
521 disbase = NULL;
522 specgrav = NULL;
523 molarv = NULL;
524 heatf = NULL;
525 waterc = NULL;
526 pHeffect = NULL;
527 soluble = NULL;
528 creates = NULL;
529
530
531 //set common variables in constructor
532 #ifdef PRINTF
533 printf("Constructor of CemhydMatStatus on GP %p, withMicrostructure %d, copy from CemhydMatStatus %p\n", gp, withMicrostructure, CemStat);
534 fflush(stdout);
535 #endif
536 this->gp = gp;
537 if ( withMicrostructure ) {
539 if ( !CemStat ) {
540 this->readInputFileAndInitialize(cemhydmat->XMLfileName.c_str(), 1);
541 } else { //copy 3D microstructure
542 this->readInputFileAndInitialize(cemhydmat->XMLfileName.c_str(), 0); //read input but do not reconstruct 3D microstructure
543 for ( k = 0; k < SYSIZE; k++ ) {
544 for ( j = 0; j < SYSIZE; j++ ) {
545 for ( i = 0; i < SYSIZE; i++ ) {
546 micpart [ i ] [ j ] [ k ] = CemStat->micpart [ i ] [ j ] [ k ];
547 micorig [ i ] [ j ] [ k ] = CemStat->micorig [ i ] [ j ] [ k ];
548 mic [ i ] [ j ] [ k ] = micorig [ i ] [ j ] [ k ];
549 }
550 }
551 }
552 }
553 }
554}
555#endif //__TM_MODULE
556
557
558void CemhydMatStatus :: initializeMicrostructure()
559{
560 icyc = 1; //set the cycle counter
561 time_cur = 0.; //hydration time [h]
562 heat_new = 0.;
563 heat_cf = 0.;
564 Cp_now = 0.900; //initial guess [J/g of concrete], which is later updated
565
567 IPVolume = 0.;
569
570 xoff [ 0 ] = 1;
571 xoff [ 1 ] = 0;
572 xoff [ 2 ] = 0;
573 xoff [ 3 ] = -1;
574 xoff [ 4 ] = 0;
575 xoff [ 5 ] = 0;
576 xoff [ 6 ] = 1;
577 xoff [ 7 ] = 1;
578 xoff [ 8 ] = -1;
579 xoff [ 9 ] = -1;
580 xoff [ 10 ] = 0;
581 xoff [ 11 ] = 0;
582 xoff [ 12 ] = 0;
583 xoff [ 13 ] = 0;
584 xoff [ 14 ] = 1;
585 xoff [ 15 ] = 1;
586 xoff [ 16 ] = -1;
587 xoff [ 17 ] = -1;
588 xoff [ 18 ] = 1;
589 xoff [ 19 ] = 1;
590 xoff [ 20 ] = 1;
591 xoff [ 21 ] = 1;
592 xoff [ 22 ] = -1;
593 xoff [ 23 ] = -1;
594 xoff [ 24 ] = -1;
595 xoff [ 25 ] = -1;
596 xoff [ 26 ] = 0;
597
598 yoff [ 0 ] = 0;
599 yoff [ 1 ] = 1;
600 yoff [ 2 ] = 0;
601 yoff [ 3 ] = 0;
602 yoff [ 4 ] = -1;
603 yoff [ 5 ] = 0;
604 yoff [ 6 ] = 1;
605 yoff [ 7 ] = -1;
606 yoff [ 8 ] = 1;
607 yoff [ 9 ] = -1;
608 yoff [ 10 ] = 1;
609 yoff [ 11 ] = -1;
610 yoff [ 12 ] = 1;
611 yoff [ 13 ] = -1;
612 yoff [ 14 ] = 0;
613 yoff [ 15 ] = 0;
614 yoff [ 16 ] = 0;
615 yoff [ 17 ] = 0;
616 yoff [ 18 ] = 1;
617 yoff [ 19 ] = -1;
618 yoff [ 20 ] = 1;
619 yoff [ 21 ] = -1;
620 yoff [ 22 ] = 1;
621 yoff [ 23 ] = 1;
622 yoff [ 24 ] = -1;
623 yoff [ 25 ] = -1;
624 yoff [ 26 ] = 0;
625
626 zoff [ 0 ] = 0;
627 zoff [ 1 ] = 0;
628 zoff [ 2 ] = 1;
629 zoff [ 3 ] = 0;
630 zoff [ 4 ] = 0;
631 zoff [ 5 ] = -1;
632 zoff [ 6 ] = 0;
633 zoff [ 7 ] = 0;
634 zoff [ 8 ] = 0;
635 zoff [ 9 ] = 0;
636 zoff [ 10 ] = 1;
637 zoff [ 11 ] = 1;
638 zoff [ 12 ] = -1;
639 zoff [ 13 ] = -1;
640 zoff [ 14 ] = 1;
641 zoff [ 15 ] = -1;
642 zoff [ 16 ] = 1;
643 zoff [ 17 ] = -1;
644 zoff [ 18 ] = 1;
645 zoff [ 19 ] = 1;
646 zoff [ 20 ] = -1;
647 zoff [ 21 ] = -1;
648 zoff [ 22 ] = 1;
649 zoff [ 23 ] = -1;
650 zoff [ 24 ] = 1;
651 zoff [ 25 ] = -1;
652 zoff [ 26 ] = 0;
653
654 iy = 0; //random generator ran1()
655 LastCallTime = -1.e6; //start from begining (the LastCall in the beginning is -1.e6)
656 alpha_cur = 0.0;
657 alpha_last = 0.; //last degree of hydration
658 LastTargTime = 0.; //stores last call of TargTime
659 TargDoHelas = 0.; //stores DoH at which to perform analytic homogenization
660 //definitions originally from CemhydMat.h
661
662 //for generation of microstructures
663 CEM = 100; /* and greater */
664 CEMID = 1; /* phase identifier for cement */
665 C2SID = 2; /* phase identified for C2S cement */
666 GYPID = 5; /* phase identifier for gypsum */
667 HEMIHYDRATE = 6; /* phase identifier for hemihydrate */
668 POZZID = 8; /* phase identifier for pozzolanic material - REACTIVE */
669 INERTID = 9; /* phase identifier for inert material - UNREACTIVE */
670 SLAGID = 10; /* phase identifier for slag - REACTIVE */
671 AGG = 28; /* phase identifier for flat aggregate - UNREACTIVE */
672 FLYASH = 30; /* phase identifier for all fly ash components - UNREACTIVE*/
673
674 //for hydration part
675 POROSITY = 0;
676 C3S = 1;
677 C2S = 2;
678 C3A = 3;
679 C4AF = 4;
680 GYPSUM = 5;
681 HEMIHYD = 6;
682 ANHYDRITE = 7;
683 POZZ = 8;
684 INERT = 9;
685 SLAG = 10;
686 ASG = 11; /* aluminosilicate glass */
687 CAS2 = 12;
688 CH = 13;
689 CSH = 14;
690 C3AH6 = 15;
691 ETTR = 16;
692 ETTRC4AF = 17; /* Iron-rich stable ettringite phase */
693 AFM = 18;
694 FH3 = 19;
695 POZZCSH = 20;
696 SLAGCSH = 21; /* Slag gel-hydration product */
697 CACL2 = 22;
698 FREIDEL = 23; /* Freidel's salt */
699 STRAT = 24; /* stratlingite (C2ASH8) */
700 GYPSUMS = 25; /* Gypsum formed from hemihydrate and anhydrite */
701 CACO3 = 26;
702 AFMC = 27;
703 INERTAGG = 28;
704 ABSGYP = 29;
705 DIFFCSH = 30;
706 DIFFCH = 31;
707 DIFFGYP = 32;
708 DIFFC3A = 33;
709 DIFFC4A = 34;
710 DIFFFH3 = 35;
711 DIFFETTR = 36;
712 DIFFCACO3 = 37;
713 DIFFAS = 38;
714 DIFFANH = 39;
715 DIFFHEM = 40;
716 DIFFCAS2 = 41;
717 DIFFCACL2 = 42;
718 EMPTYP = 45; /*Empty porosity due to self desiccation*/
719 HDCSH = 46;
720 OFFSET = 50; /*Offset for highlighted potentially soluble pixel*/
721
722 NEIGHBORS = 26; /* number of neighbors to consider (6, 18, or 26) in dissolution */
723 BoxSize = 1; /*int describing vicinity of CSH*/
724 SolidLimit = 27; /*how many solid phase voxels must be in a box (max. <=(2*BoxSize+1)^3)*/
725 MAXTRIES = 150000; /* maximum number of random tries for sphere placement */
726 MAXCYC_SEAL = 30000; /* Maximum number of cycles of sealed hydration (originally MAXCYC in disrealnew.c */
727 NUMSIZES = 100; /* maximum number of different particle sizes */
728 MAXSPH = 10000; /* maximum number of elements in a spherical template */
729
730 Cp_pozz = 0.75;
731 Cp_CH = 0.75;
732 Cp_h2o = 4.18; /* Cp for free water */
733 Cp_bh2o = 2.2; /* Cp for bound water */
734 WN = 0.23; /* water bound per gram of cement during hydration */
735 WCHSH = 0.06; /* water imbibed per gram of cement during chemical shrinkage (estimate) */
736 CUBEMIN = 3; /* Minimum cube size for checking pore size */
737
738 DISBIAS = 30.0; /* Dissolution bias- to change all dissolution rates */
739 DISMIN = 0.001; /* Minimum dissolution for C3S dissolution */
740 DISMIN2 = 0.00025; /* Minimum dissolution for C2S dissolution */
741 DISMINSLAG = 0.0001; /* Minimum dissolution for SLAG dissolution */
742 DISMINASG = 0.0005; /* Minimum dissolution for ASG dissolution */
743 DISMINCAS2 = 0.0005; /* Minimum dissolution for CAS2 dissolution */
744 DISMIN_C3A_0 = 0.002; /* Minimum dissolution for C3A dissolution */
745 DISMIN_C4AF_0 = 0.0005; /* Minimum dissolution for C4AF dissolution */
746
747 C3AH6GROW = 0.01; /* Probability for C3AH6 growth */
748 CHGROW = 1.0; /* Probability for CH growth */
749 CHGROWAGG = 1.0; /* Probability for CH growth on aggregate surface */
750 ETTRGROW = 0.002; /* Probability for ettringite growth */
751 C3AETTR = 0.001; /* Probability for reaction of diffusing C3A with ettringite */
752 C3AGYP = 0.001; /* Probability for diffusing C3A to react with diffusing gypsum */
753 SOLIDC3AGYP = 0.5; /* Probability of solid C3A to react with diffusing sulfate */
754 SOLIDC4AFGYP = 0.1; /* Probability of solid C4AF to react with diffusing sulfate */
755 PPOZZ = 0.05; /* base probability for pozzolanic reaction */
756 PCSH2CSH = 0.002; /* probability for CSH dissolution */
757 A0_CHSOL = 1.325; /* Parameters for variation of CH solubility with */
758 A1_CHSOL = 0.008162; /* temperature (data from Taylor- Cement Chemistry) */
759
760 BURNT = 70; /* label for a burnt pixel <255 (in char type arrays) */
761 SIZE2D = 49000; /* size of matrices for holding burning locations */
762
763 SIZESET = 100000;
764 AGRATE = 0.25; /* Probability of gypsum absorption by CSH */
765 VOLFACTOR = 0.00001; /* dm per pixel Note- dm*dm*dm = Liters */
766 MASSFACTOR = 0.0001; /* cm per pixel - specific gravities in g/cm^3 */
767 MMNa = 22.9898;
768 MMK = 39.102;
769 MMNa2O = 61.979;
770 MMK2O = 94.203;
771 BNa = 0.00031; /* From Taylor paper in liters (31 mL/1000/ 100 g) */
772 BK = 0.00020; /* From Taylor paper in liters (20 mL/1000/ 100 g) */
773 BprimeNa = 0.0030; /* From Taylor paper in liters (3 mL/1000/ 1 g POZZ) */
774 BprimeK = 0.0033; /* From Taylor paper in liters (3.3 mL/1000/ 1 g POZZ) */
775 KspCH25C = 0.00000646;
776 KspGypsum = 0.0000263;
777 KspSyngenite = 0.00000010;
778 SpecgravSyngenite = 2.607; /* Source Taylor, H.F.W., Cement Chemistry */
779 KperSyn = 2.0; /* moles of K+ per mole of syngenite */
780 activeA0 = 0.0366; /* A at 295 K (from Ken) */
781 activeB0 = 0.01035; /* B at 295 K (from Ken) */
782 zCa = 2.;
783 zSO4 = 2.;
784 zOH = 1.;
785 zNa = 1.;
786 zK = 1.;
787 aK = 1.33;
788 aCa = 1.;
789 aOH = 3.;
790 aNa = 3.;
791 aSO4 = 4.5; /* Estimate as S ionic radii + O ionic diameter */
792 lambdaOH_0 = 198.0; /* Units: S cm-cm eq.^(-1) */
793 lambdaNa_0 = 50.1;
794 lambdaK_0 = 73.5;
795 lambdaSO4_0 = 39.5;
796 lambdaCa_0 = 29.5; /* Note that CRC has 60./2 for this */
797 GOH = 0.353; /* Units: (eq.^2 mol/L)^(-0.5) */
798 GK = 0.548;
799 GNa = 0.733;
800 GCa = 0.771;
801 GSO4 = 0.877;
802 cm2perL2m = 0.1; /* Conversion from cm2/Liter to 1/m */
803 EPSS = 6.e-8;
804 MAXIT = 100;
805 EPSP = 2.0e-6;
806 MAXM = 100;
807
808 /*random generator*/
809 IA = 16807;
810 IM = 2147483647;
811 IQ = 127773;
812 IR = 2836;
813 NTAB = 32;
814 EPS = 1.2E-07;
815
816 PhaseFrac = new double [ 34 ];
817 last_values = new double [ 6 ];
818 last_values [ 2 ] = 0.001; //Young's modulus of virgin paste
819 last_values [ 3 ] = 0.499924; //Poisson's ratio of virgin paste
820 last_values [ 4 ] = 0.001; //Young's modulus of concrete
821 last_values [ 5 ] = 0.499924; //Poisson's ratio of concrete
822 phase = new long int [ 51 ];
823
824 CSH_vicinity = new unsigned int [ ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) + 1 ];
825 molarvcsh = new float [ MAXCYC_SEAL ];
826 watercsh = new float [ MAXCYC_SEAL ];
827 xsph = new int [ MAXSPH ];
828 ysph = new int [ MAXSPH ];
829 zsph = new int [ MAXSPH ];
830
831 iv = new int [ NTAB ];
832
833 discount = new long int [ EMPTYP + 1 ];
834 count = new long int [ HDCSH + 1 ];
835 disprob = new float [ HDCSH + 1 ];
836 disbase = new float [ EMPTYP + 1 ];
837 specgrav = new float [ EMPTYP + 1 ];
838 molarv = new float [ EMPTYP + 1 ];
839 heatf = new float [ EMPTYP + 1 ];
840 waterc = new float [ EMPTYP + 1 ];
841 pHeffect = new float [ EMPTYP + 1 ];
842
843 //set zero to arrays
844 for ( int i = 0; i <= EMPTYP; i++ ) {
845 heatf [ i ] = 0.;
846 waterc [ i ] = 0.;
847 }
848
849 for ( int i = 0; i <= HDCSH; i++ ) {
850 disprob [ i ] = 0.;
851 }
852
853 soluble = new int [ EMPTYP + 1 ];
854 creates = new int [ EMPTYP + 1 ];
855}
856
857
858
859// destructor
860CemhydMatStatus :: ~CemhydMatStatus()
861{
862#ifdef OUTFILES
863 if ( fileperc != NULL ) {
864 fclose(fileperc);
865 }
866
867 if ( disprobfile != NULL ) {
868 fclose(disprobfile);
869 }
870
871 //fclose(percfile);
872 if ( heatfile != NULL ) {
873 fclose(heatfile);
874 }
875
876 if ( pHfile != NULL ) {
877 fclose(pHfile);
878 }
879
880 if ( phasfile != NULL ) {
881 fclose(phasfile);
882 }
883
884 if ( perc_phases != NULL ) {
885 fclose(perc_phases);
886 }
887
888 if ( adiafile != NULL ) {
889 fclose(adiafile);
890 }
891
892 if ( elasfile != NULL ) {
893 fclose(elasfile);
894 }
895
896 if ( CSHfile != NULL ) {
897 fclose(CSHfile);
898 }
899
900 if ( infoperc != NULL ) {
901 fclose(infoperc);
902 }
903
904 if ( infoUnperc != NULL ) {
905 fclose(infoUnperc);
906 }
907
908#endif
909 delete [] PhaseFrac;
910 delete [] last_values;
911 delete [] phase;
912
913#ifdef CMLFILE
914 delete F; //delete cmlfile
915#endif
916#ifdef TINYXML
917 if ( xmlFile != NULL ) {
918 delete xmlFile;
919 }
920#endif
921
922 delete [] CSH_vicinity;
923 delete [] molarvcsh;
924 delete [] watercsh;
925
926 delete [] xsph;
927 delete [] ysph;
928 delete [] zsph;
929 delete [] iv;
930 delete [] discount;
931 delete [] count;
932 delete [] disprob;
933 delete [] disbase;
934 delete [] specgrav;
935 delete [] molarv;
936 delete [] heatf;
937 delete [] waterc;
938 delete [] pHeffect;
939 delete [] soluble;
940 delete [] creates;
941
942 /* Eliminate the whole list */
943 struct ants *curant;
944
945 if ( headant != NULL ) { //if hydration did not start sucessfully
946 while ( headant->nextant != NULL ) {
947 curant = headant->nextant;
948 free(headant);
949 headant = curant;
950#ifdef PRINTF
951 printf("Deallocating headant\n");
952#endif
953 }
954 }
955
956 if ( tailant != NULL ) { //if hydration did not start sucessfully
957 free(tailant);
958 }
959
960#ifdef PRINTF
961 printf("Deallocating arrays\n");
962 fflush(stdout);
963#endif
964
974}
975
976void CemhydMatStatus :: alloc_char_3D(char ***( &mic ), long SYSIZE)
977{
978 mic = new char ** [ SYSIZE ];
979 for ( int x = 0; x < SYSIZE; x++ ) {
980 mic [ x ] = new char * [ SYSIZE ];
981 for ( int y = 0; y < SYSIZE; y++ ) {
982 mic [ x ] [ y ] = new char [ SYSIZE ];
983 if ( mic [ x ] [ y ] == NULL ) {
984 printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
985 }
986 }
987 }
988}
989
990void CemhydMatStatus :: dealloc_char_3D(char ***( &mic ), long SYSIZE)
991{
992 if ( mic != NULL ) {
993 for ( int x = 0; x < SYSIZE; x++ ) {
994 for ( int y = 0; y < SYSIZE; y++ ) {
995 delete [] mic [ x ] [ y ];
996 }
997
998 delete [] mic [ x ];
999 }
1000
1001 delete [] mic;
1002 }
1003}
1004
1005void CemhydMatStatus :: alloc_long_3D(long ***( &mic ), long SYSIZE)
1006{
1007 mic = new long ** [ SYSIZE ];
1008 for ( int x = 0; x < SYSIZE; x++ ) {
1009 mic [ x ] = new long * [ SYSIZE ];
1010 for ( int y = 0; y < SYSIZE; y++ ) {
1011 mic [ x ] [ y ] = new long [ SYSIZE ];
1012 if ( mic [ x ] [ y ] == NULL ) {
1013 printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1014 }
1015 }
1016 }
1017}
1018
1019
1020void CemhydMatStatus :: dealloc_long_3D(long ***( &mic ), long SYSIZE)
1021{
1022 if ( mic != NULL ) {
1023 for ( int x = 0; x < SYSIZE; x++ ) {
1024 for ( int y = 0; y < SYSIZE; y++ ) {
1025 delete [] mic [ x ] [ y ];
1026 }
1027
1028 delete [] mic [ x ];
1029 }
1030
1031 delete [] mic;
1032 }
1033}
1034
1035void CemhydMatStatus :: alloc_int_3D(int ***( &mic ), long SYSIZE)
1036{
1037 mic = new int ** [ SYSIZE ];
1038 for ( int x = 0; x < SYSIZE; x++ ) {
1039 mic [ x ] = new int * [ SYSIZE ];
1040 for ( int y = 0; y < SYSIZE; y++ ) {
1041 mic [ x ] [ y ] = new int [ SYSIZE ];
1042 if ( mic [ x ] [ y ] == NULL ) {
1043 printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1044 }
1045 }
1046 }
1047}
1048
1049
1050void CemhydMatStatus :: dealloc_int_3D(int ***( &mic ), long SYSIZE)
1051{
1052 if ( mic != NULL ) {
1053 for ( int x = 0; x < SYSIZE; x++ ) {
1054 for ( int y = 0; y < SYSIZE; y++ ) {
1055 delete [] mic [ x ] [ y ];
1056 }
1057
1058 delete [] mic [ x ];
1059 }
1060
1061 delete [] mic;
1062 }
1063}
1064
1065void CemhydMatStatus :: alloc_shortint_3D(short int ***( &mic ), long SYSIZE)
1066{
1067 mic = new short int ** [ SYSIZE ];
1068 for ( int x = 0; x < SYSIZE; x++ ) {
1069 mic [ x ] = new short int * [ SYSIZE ];
1070 for ( int y = 0; y < SYSIZE; y++ ) {
1071 mic [ x ] [ y ] = new short int [ SYSIZE ];
1072 if ( mic [ x ] [ y ] == NULL ) {
1073 printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1074 }
1075 }
1076 }
1077}
1078
1079
1080void CemhydMatStatus :: dealloc_shortint_3D(short int ***( &mic ), long SYSIZE)
1081{
1082 if ( mic != NULL ) {
1083 for ( int x = 0; x < SYSIZE; x++ ) {
1084 for ( int y = 0; y < SYSIZE; y++ ) {
1085 delete [] mic [ x ] [ y ];
1086 }
1087
1088 delete [] mic [ x ];
1089 }
1090
1091 delete [] mic;
1092 }
1093}
1094
1095void CemhydMatStatus :: alloc_double_3D(double ***( &mic ), long SYSIZE)
1096{
1097 mic = new double ** [ SYSIZE ];
1098 for ( int x = 0; x < SYSIZE; x++ ) {
1099 mic [ x ] = new double * [ SYSIZE ];
1100 for ( int y = 0; y < SYSIZE; y++ ) {
1101 mic [ x ] [ y ] = new double [ SYSIZE ];
1102 if ( mic [ x ] [ y ] == NULL ) {
1103 printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1104 }
1105 }
1106 }
1107}
1108
1109
1110void CemhydMatStatus :: dealloc_double_3D(double ***( &mic ), long SYSIZE)
1111{
1112 if ( mic != NULL ) {
1113 for ( int x = 0; x < SYSIZE; x++ ) {
1114 for ( int y = 0; y < SYSIZE; y++ ) {
1115 delete [] mic [ x ] [ y ];
1116 }
1117
1118 delete [] mic [ x ];
1119 }
1120
1121 delete [] mic;
1122 }
1123}
1124
1125#ifdef TINYXML
1126//functions to read int, double and string with error checking
1127void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, int &val)
1128{
1129 int success;
1130 char key [ 256 ];
1131 XMLHandle docHandle = XMLHandle(xmlFile);
1132 XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1133 if ( elemSelected == NULL ) {
1134 printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1135 exit(0);
1136 }
1137
1138 sprintf(key, "key%d", position);
1139 success = elemSelected->QueryIntAttribute(key, & val);
1140 if ( success != XML_SUCCESS ) {
1141 printf("Cannot read int value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1142 exit(0);
1143 }
1144}
1145
1146void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, long int &val)
1147{
1148 int temp;
1149 QueryNumAttributeExt(xmlFile, elementName, position, temp);
1150 val = static_cast< long int >(temp);
1151}
1152
1153void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, const char *key, int &val)
1154{
1155 int success;
1156 XMLHandle docHandle = XMLHandle(xmlFile);
1157 XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1158 if ( elemSelected == NULL ) {
1159 printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1160 exit(0);
1161 }
1162
1163 success = elemSelected->QueryIntAttribute(key, & val);
1164 if ( success != XML_SUCCESS ) {
1165 printf("Cannot read int value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1166 exit(0);
1167 }
1168}
1169
1170
1171void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, double &val)
1172{
1173 int success;
1174 char key [ 256 ];
1175 XMLHandle docHandle = XMLHandle(xmlFile);
1176 XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1177 if ( elemSelected == NULL ) {
1178 printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1179 exit(0);
1180 }
1181
1182 sprintf(key, "key%d", position);
1183 success = elemSelected->QueryDoubleAttribute(key, & val);
1184 if ( success != XML_SUCCESS ) {
1185 printf("Cannot read double value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1186 exit(0);
1187 }
1188}
1189
1190void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, const char *key, double &val)
1191{
1192 int success;
1193 XMLHandle docHandle = XMLHandle(xmlFile);
1194 XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1195 if ( elemSelected == NULL ) {
1196 printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1197 exit(0);
1198 }
1199
1200 success = elemSelected->QueryDoubleAttribute(key, & val);
1201 if ( success != XML_SUCCESS ) {
1202 printf("Cannot read double value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1203 exit(0);
1204 }
1205}
1206
1207void CemhydMatStatus :: QueryStringAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, char *chars)
1208{
1209 int success;
1210 char key [ 256 ];
1211 XMLHandle docHandle = XMLHandle(xmlFile);
1212 std :: string str1;
1213 XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1214 if ( elemSelected == NULL ) {
1215 printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1216 exit(0);
1217 }
1218
1219 sprintf(key, "key%d", position);
1220 //success = elemSelected->QueryStringAttribute(key, & str1);
1221 // Since ubuntu/debian is still stuck at 2.5.3, lacking QueryStringAttribute.
1222 // Change with above whenever packages are updated.
1223 const char *cstr = elemSelected->Attribute(key);
1224 if ( cstr ) {
1225 success = XML_SUCCESS;
1226 } else {
1227 success = XML_NO_ATTRIBUTE;
1228 }
1229 if ( success != XML_SUCCESS ) {
1230 printf("Cannot read string value or key %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1231 exit(0);
1232 }
1233 str1 = std :: string(cstr);
1234
1235 strcpy( chars, str1.c_str() );
1236}
1237#endif
1238
1239/* read input parameters in file, use XML or cmlfile construction
1240 * allocate necessary arrays (especially those dependent on SYSIZE)
1241 * returns (1) if generation of particles in the Representative Volume Element (RVE) was unsuccessful
1242 */
1243int CemhydMatStatus :: readInputFileAndInitialize(const char *inp, bool generateMicrostructure)
1244{
1245 int read_micr;
1246#ifdef CMLFILE
1247 F = new cmlfile(inp);
1248 // set number of keywords
1249 F->set_labels(54);
1250 F->set_label_string(0, "Rand_seed_num");
1251 F->set_label_string(1, "Input_img_file");
1252 F->set_label_string(2, "Input_id_file");
1253 F->set_label_string(3, "Saturated_sealed");
1254 F->set_label_string(4, "Induction_time");
1255 F->set_label_string(5, "Ea_cement");
1256 F->set_label_string(6, "Ea_pozz");
1257 F->set_label_string(7, "Ea_slag");
1258 F->set_label_string(8, "Beta");
1259 F->set_label_string(9, "Mass_SCM_FA_CA_inert_frac");
1260 F->set_label_string(10, "Mass_cem");
1261 F->set_label_string(11, "Cp_SCM_FA_CA_inert");
1262 F->set_label_string(12, "Cp_cem");
1263 F->set_label_string(13, "Given_microstructure");
1264 F->set_label_string(14, "Output_initial_microstructure");
1265 F->set_label_string(15, "Output_initial_microstructure_img_file");
1266 F->set_label_string(16, "Output_initial_microstructure_id_file");
1267 F->set_label_string(17, "Cycle_freq_perc_pore");
1268 F->set_label_string(18, "Cycle_freq_perc_sol");
1269 F->set_label_string(19, "Total_sodium");
1270 F->set_label_string(20, "Total_potassium");
1271 F->set_label_string(21, "Readily_soluble_sodium");
1272 F->set_label_string(22, "Readily_soluble_potassium");
1273 F->set_label_string(23, "Diffusion_steps_per_cycle");
1274 F->set_label_string(24, "CH_nucleation_probability");
1275 F->set_label_string(25, "CH_scale_factor");
1276 F->set_label_string(26, "Gypsum_nucleation_probability");
1277 F->set_label_string(27, "Gypsum_scale_factor");
1278 F->set_label_string(28, "C3AH6_nucleation_probability");
1279 F->set_label_string(29, "C3AH6_scale_factor");
1280 F->set_label_string(30, "FH3_nucleation_probability");
1281 F->set_label_string(31, "FH3_scale_factor");
1282 F->set_label_string(32, "Microstructure_size");
1283 F->set_label_string(33, "Adiabatic_conditions");
1284 F->set_label_string(34, "Vol_cement_clinker_gypsum");
1285 F->set_label_string(35, "Vol_cement_SCM");
1286 F->set_label_string(36, "Vol_water");
1287 F->set_label_string(37, "Vol_FA");
1288 F->set_label_string(38, "Vol_CA");
1289 F->set_label_string(39, "Vol_inert_filler");
1290 F->set_label_string(40, "Vol_entrained_entrapped_air");
1291 F->set_label_string(41, "Grain_average_FA");
1292 F->set_label_string(42, "Grain_average_CA");
1293 F->set_label_string(43, "ITZ_thickness");
1294 F->set_label_string(44, "ITZ_Young_red");
1295 F->set_label_string(45, "Young_SCM");
1296 F->set_label_string(46, "Poisson_SCM");
1297 F->set_label_string(47, "Young_FA");
1298 F->set_label_string(48, "Poisson_FA");
1299 F->set_label_string(49, "Young_CA");
1300 F->set_label_string(50, "Poisson_CA");
1301 F->set_label_string(51, "Young_inert");
1302 F->set_label_string(52, "Poisson_inert");
1303 F->set_label_string(53, "Calculate_elastic_homogenization");
1304
1305 // these keywords with #id will be required
1306 F->require(0);
1307 //F->require( 1 ) ;
1308 //F->require( 2 ) ;
1309 F->require(3);
1310 F->require(4);
1311 F->require(5);
1312 F->require(6);
1313 F->require(7);
1314 F->require(8);
1315 F->require(9);
1316 F->require(10);
1317 F->require(11);
1318 F->require(12);
1319 F->require(13);
1320 F->require(14);
1321 F->require(17);
1322 F->require(18);
1323 F->require(19);
1324 F->require(20);
1325 F->require(21);
1326 F->require(22);
1327 F->require(23);
1328 F->require(24);
1329 F->require(27);
1330 F->require(28);
1331 F->require(29);
1332 F->require(30);
1333 F->require(31);
1334 F->require(32);
1335 F->require(33);
1336 F->require(34);
1337 F->require(35);
1338 F->require(36);
1339 F->require(37);
1340 F->require(38);
1341 F->require(39);
1342 F->require(40);
1343 F->require(41);
1344 F->require(42);
1345 F->require(43);
1346 F->require(44);
1347 F->require(45);
1348 F->require(46);
1349 F->require(47);
1350 F->require(48);
1351 F->require(49);
1352 F->require(50);
1353 F->require(51);
1354 F->require(52);
1355 F->require(53);
1356 // set number and names of sections
1357 F->set_sections(1);
1358 F->set_section_string(0, "CEMHYD_generate_particles");
1359
1360 F->check_requirements();
1361
1362 if ( F->error_in_requirements() ) {
1363 printf("Cemhyd input file %s is not complete (file %s, line %d)\n", inp, __FILE__, __LINE__);
1364 exit(0);
1365 }
1366
1367 F->get_value(0, ( long & )iseed);
1368#endif
1369#ifdef TINYXML
1370 xmlFile = new XMLDocument();
1371 countKey = 0;
1372 int errorId = xmlFile->LoadFile(inp);
1373 if ( errorId != XML_SUCCESS ) {
1374 printf("\nError reading XML file %s or nonletter symbols used, error id = %d\n", inp, errorId);
1375 exit(0);
1376 }
1377
1378 QueryNumAttributeExt(xmlFile, "Rand_seed_num", 0, iseed);
1379 QueryNumAttributeExt(xmlFile, "Microstructure_size", 0, SYSSIZE);
1380 QueryNumAttributeExt(xmlFile, "Given_microstructure", 0, read_micr);
1381#endif
1382
1383 nseed = iseed;
1384 seed = ( & nseed );
1385 //printf("iseed = %d", iseed);
1386
1387 //read SYSSIZE of microstructure and allocate arrays
1388#ifdef CMLFILE
1389 F->get_value(32, ( long & )SYSSIZE);
1390#endif
1391 if ( SYSSIZE < 10 ) {
1392 printf("Can not run small microstructure %d (< 10 voxels a side), file %s, line %d)\n", SYSSIZE, __FILE__, __LINE__);
1393 exit(0);
1394 }
1395
1396 SYSIZE = SYSSIZE;
1397 SYSIZEM1 = ( SYSIZE - 1 ); /* System size -1 */
1398 SYSIZE_POW3 = ( SYSIZE * SYSIZE * SYSIZE );
1399 NPARTC = ( long ) ( 700000 * ( double ) SYSIZE_POW3 / 1000000. );
1400 BURNTG = ( NPARTC > 100 ? NPARTC : 100 );
1401 CUBEMAX = ( SYSIZE > 6 ? 7 : 3 );
1402 DETTRMAX = ( 1200. * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of ettringite diffusing species */
1403 DGYPMAX = ( 2000. * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of gypsum diffusing species */
1404 DCACO3MAX = ( 1000 * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of CaCO3 diffusing species */
1405 DCACL2MAX = ( 2000 * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of CaCl2 diffusing species */
1406 DCAS2MAX = ( 2000 * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of CAS2 diffusing species */
1407 CHCRIT = ( 50. * SYSIZE_POW3 / 1000000. ); /* Scale parameter to adjust CH dissolution probability */
1408 C3AH6CRIT = ( 10. * SYSIZE_POW3 / 1000000. ); /* Scale par. to adjust C3AH6 dissolution prob. */
1409 CSHSCALE = ( 70000. * SYSIZE_POW3 / 1000000. ); /*scale factor for CSH controlling induction */
1410 C3AH6_SCALE = ( 2000. * SYSIZE_POW3 / 1000000. ); /*scale factor for C3AH6 controlling induction of aluminates */
1411
1416 alloc_int_3D(mask, SYSIZE + 1);
1421
1422#ifdef CMLFILE
1423 F->get_value(13, ( long & )read_micr);
1424#endif
1425
1426 if ( !read_micr && generateMicrostructure == 1 ) { //generate new microstructure
1427 if ( genpartnew() == 1 ) { //read input file for RVE generation, if unsuccessful microstructure generation, return
1428 return 1;
1429 }
1430
1431#ifdef PRINTF
1432 printf("MONOPHASE microstructure created\n");
1433#endif
1434 distrib3d(); //read autocorrelation functions and distribute clinker phases in RVE
1435 }
1436
1437 readhydrparam(); //read hydration parameters
1438
1439 return 0;
1440}
1441
1442
1443/* Random number generator ran1 from Computers in Physics */
1444/* Volume 6 No. 5, 1992, 522-524, Press and Teukolsky */
1445/* To generate real random numbers 0.0-1.0 */
1446/* Should be seeded with a negative integer */
1447double CemhydMatStatus :: ran1(int *idum)
1448/* Calls: no routines */
1449/* Called by: gsphere,makefloc */
1450{
1451 int j, k;
1452 NDIV = 1.0 / ( 1.0 + ( IM - 1.0 ) / NTAB );
1453 RNMX = ( 1.0 - EPS );
1454 AM = ( 1.0 / IM );
1455
1456 if ( ( * idum <= 0 ) || ( iy == 0 ) ) {
1457 * idum = ( -* idum > * idum ) ? -* idum : * idum; //MAX(-*idum>*idum);
1458 for ( j = NTAB + 7; j >= 0; j-- ) {
1459 k = * idum / IQ;
1460 * idum = IA * ( * idum - k * IQ ) - IR * k;
1461 if ( * idum < 0 ) {
1462 * idum += IM;
1463 }
1464
1465 if ( j < NTAB ) {
1466 iv [ j ] = * idum;
1467 }
1468 }
1469
1470 iy = iv [ 0 ];
1471 }
1472
1473 k = * idum / IQ;
1474 * idum = IA * ( * idum - k * IQ ) - IR * k;
1475 if ( * idum < 0 ) {
1476 * idum += IM;
1477 }
1478
1479 j = ( int ) ( iy * NDIV );
1480 iy = iv [ j ];
1481 iv [ j ] = * idum;
1482 return AM * iy < RNMX ? AM * iy : RNMX; //MIN(AM*iy,RNMX);
1483}
1484
1485
1486/* routine to add a flat plate aggregate in the microstructure */
1487void CemhydMatStatus :: addagg()
1488/* Calls: no other routines */
1489/* Called by: main program */
1490{
1491 int ix, iy, iz;
1492 int agglo, agghi;
1493
1494 /* Be sure aggregate size is an even integer */
1495 do {
1496 printf("Enter thickness of aggregate to place (an even integer) \n");
1497#ifdef CMLFILE
1498 F->get_next_line_in_section(0, ( long & )aggsize);
1499#endif
1500#ifdef TINYXML
1501 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, aggsize);
1502#endif
1503
1504 //fscanf(in, "%d",&aggsize);
1505#ifdef PRINTF
1506 printf("%d\n", aggsize);
1507#endif
1508 } while ( ( ( aggsize % 2 ) != 0 ) || ( aggsize > ( SYSSIZE - 2 ) ) );
1509
1510 if ( aggsize != 0 ) {
1511 agglo = ( SYSSIZE / 2 ) - ( ( aggsize - 2 ) / 2 );
1512 agghi = ( SYSSIZE / 2 ) + ( aggsize / 2 );
1513
1514 /* Aggregate is placed in yz plane */
1515 for ( ix = agglo; ix <= agghi; ix++ ) {
1516 for ( iy = 1; iy <= SYSSIZE; iy++ ) {
1517 for ( iz = 1; iz <= SYSSIZE; iz++ ) {
1518 /* Mark aggregate in both particle and microstructure images */
1519 cement [ ix ] [ iy ] [ iz ] = AGG;
1520 cemreal [ ix ] [ iy ] [ iz ] = AGG;
1521 }
1522 }
1523 }
1524 }
1525}
1526
1527
1528
1529/* routine to check or perform placement of sphere of ID phasein */
1530/* centered at location (xin,yin,zin) of radius radd */
1531/* wflg=1 check for fit of sphere */
1532/* wflg=2 place the sphere */
1533/* phasein and phase2 are phases to assign to cement and cemreal images resp. */
1534int CemhydMatStatus :: chksph(int xin, int yin, int zin, int radd, int wflg, int phasein, int phase2)
1535/* Calls: no other routines */
1536/* Called by: gsphere */
1537{
1538 int nofits, xp, yp, zp, i, j, k;
1539 float dist, xdist, ydist, zdist, ftmp;
1540
1541 nofits = 0; /* Flag indicating if placement is possible */
1542 /* Check all pixels within the digitized sphere volume */
1543 for ( i = xin - radd; ( ( i <= xin + radd ) && ( nofits == 0 ) ); i++ ) {
1544 xp = i;
1545 /* use periodic boundary conditions for sphere placement */
1546 if ( xp < 1 ) {
1547 xp += SYSSIZE;
1548 } else if ( xp > SYSSIZE ) {
1549 xp -= SYSSIZE;
1550 }
1551
1552 ftmp = ( float ) ( i - xin );
1553 xdist = ftmp * ftmp;
1554 for ( j = yin - radd; ( ( j <= yin + radd ) && ( nofits == 0 ) ); j++ ) {
1555 yp = j;
1556 /* use periodic boundary conditions for sphere placement */
1557 if ( yp < 1 ) {
1558 yp += SYSSIZE;
1559 } else if ( yp > SYSSIZE ) {
1560 yp -= SYSSIZE;
1561 }
1562
1563 ftmp = ( float ) ( j - yin );
1564 ydist = ftmp * ftmp;
1565 for ( k = zin - radd; ( ( k <= zin + radd ) && ( nofits == 0 ) ); k++ ) {
1566 zp = k;
1567 /* use periodic boundary conditions for sphere placement */
1568 if ( zp < 1 ) {
1569 zp += SYSSIZE;
1570 } else if ( zp > SYSSIZE ) {
1571 zp -= SYSSIZE;
1572 }
1573
1574 ftmp = ( float ) ( k - zin );
1575 zdist = ftmp * ftmp;
1576
1577 /* Compute distance from center of sphere to this pixel */
1578 dist = sqrt(xdist + ydist + zdist);
1579 if ( ( dist - 0.5 ) <= ( float ) radd ) {
1580 /* Perform placement */
1581 if ( wflg == 2 ) {
1582 cement [ xp ] [ yp ] [ zp ] = phasein;
1583 cemreal [ xp ] [ yp ] [ zp ] = phase2;
1584 }
1585 /* or check placement */
1586 else if ( ( wflg == 1 ) && ( cement [ xp ] [ yp ] [ zp ] != POROSITY ) ) {
1587 nofits = 1;
1588 }
1589 }
1590
1591 /* Check for overlap with aggregate */
1592 if ( ( wflg == 1 ) && ( ( fabs( xp - ( ( float ) ( SYSSIZE + 1 ) / 2.0 ) ) ) < ( ( float ) aggsize / 2.0 ) ) ) {
1593 nofits = 1;
1594 }
1595 }
1596 }
1597 }
1598
1599 /* return flag indicating if sphere will fit */
1600 return ( nofits );
1601}
1602
1603
1604
1605/* routine to place spheres of various sizes and phases at random */
1606/* locations in 3-D microstructure */
1607/* numgen is number of different size spheres to place */
1608/* numeach holds the number of each size class */
1609/* sizeeach holds the radius of each size class */
1610/* pheach holds the phase of each size class */
1611int CemhydMatStatus :: gsphere(int numgen, long int *numeach, int *sizeeach, int *pheach)
1612{
1613 /* Calls: makesph, ran1 */
1614 /* Called by: create */
1615 int count, x, y, z, radius, ig, tries, phnow;
1616 long int jg, i;
1617 float testgyp, typegyp;
1618
1619 /* Generate spheres of each size class in turn (largest first) */
1620 for ( ig = 0; ig < numgen; ig++ ) {
1621 phnow = pheach [ ig ]; /* phase for this class */
1622 radius = sizeeach [ ig ]; /* radius for this class */
1623 /* loop for each sphere in this size class */
1624 for ( jg = 1; jg <= numeach [ ig ]; jg++ ) {
1625 tries = 0;
1626 /* Stop after MAXTRIES random tries */
1627 do {
1628 tries += 1;
1629 /* generate a random center location for the sphere */
1630 x = ( int ) ( ( float ) SYSSIZE * ran1(seed) ) + 1;
1631 y = ( int ) ( ( float ) SYSSIZE * ran1(seed) ) + 1;
1632 z = ( int ) ( ( float ) SYSSIZE * ran1(seed) ) + 1;
1633 /* See if the sphere will fit at x,y,z */
1634 /* Include dispersion distance when checking */
1635 /* to insure requested separation between spheres */
1636 count = chksph(x, y, z, radius + dispdist, 1, npart + CEM, 0);
1637 if ( ( tries > MAXTRIES ) && ( dispdist == 2 ) ) {
1638 tries = 0;
1639 dispdist += 1;
1640 }
1641
1642 if ( tries > MAXTRIES ) {
1643 printf("Could not place sphere %d after %ld random attempts \n", npart, MAXTRIES);
1644 printf("Skipping this microstructure parameters\n");
1645 for ( i = 1; i <= npart; i++ ) {
1646 free(clust [ i ]);
1647 }
1648
1649 return ( 1 );
1650 }
1651 } while ( count != 0 );
1652
1653 /* place the sphere at x,y,z */
1654 npart += 1;
1655 if ( npart >= NPARTC ) {
1656 printf("Too many spheres being generated \n");
1657 printf("User needs to increase value of NPARTC at top of C-code\n");
1658 printf("Skipping this microstructure parameters\n");
1659 return ( 1 );
1660 }
1661
1662 /* Allocate space for new particle info */
1663 clust [ npart ] = ( struct cluster * ) malloc( sizeof( struct cluster ) );
1664 clust [ npart ]->partid = npart;
1665 clust [ npart ]->clustid = npart;
1666 /* Default to cement placement */
1667 clust [ npart ]->partphase = CEMID;
1668 clust [ npart ]->x = x;
1669 clust [ npart ]->y = y;
1670 clust [ npart ]->z = z;
1671 clust [ npart ]->r = radius;
1672 clusleft += 1;
1673 if ( phnow == 1 ) {
1674 testgyp = ran1(seed);
1675 /* Do not use dispersion distance when placing particle */
1676 if ( ( ( testgyp > probgyp ) && ( ( target_sulfate - n_sulfate ) < ( target_total - n_total ) ) ) || ( n_sulfate > target_sulfate ) || ( volpart [ radius ] > ( target_sulfate - n_sulfate ) ) || ( numeach [ ig ] <= 2 ) ) {
1677 count = chksph(x, y, z, radius, 2, npart + CEM - 1, CEMID);
1678 n_total += volpart [ radius ];
1679 } else {
1680 /* Place particle as gypsum */
1681 typegyp = ran1(seed);
1682 n_total += volpart [ radius ];
1683 n_sulfate += volpart [ radius ];
1684 if ( ( probanh >= 1.0 ) || ( ( typegyp < probanh ) && ( n_anhydrite < target_anhydrite ) && ( volpart [ radius ] <= ( target_anhydrite - n_anhydrite ) ) ) ) {
1685 /* Place particle as anhydrite */
1686 n_anhydrite += volpart [ radius ];
1687 count = chksph(x, y, z, radius, 2, npart + CEM - 1, ANHYDRITE);
1688 clust [ npart ]->partphase = ANHYDRITE;
1689 } else if ( ( ( probanh + probhem ) >= 1.0 ) || ( ( typegyp < ( probanh + probhem ) ) && ( n_hemi < target_hemi ) && ( volpart [ radius ] <= ( target_hemi - n_hemi ) ) ) ) {
1690 /* Place particle as hemihydrate */
1691 n_hemi += volpart [ radius ];
1692 count = chksph(x, y, z, radius, 2, npart + CEM - 1, HEMIHYDRATE);
1693 clust [ npart ]->partphase = HEMIHYDRATE;
1694 } else {
1695 count = chksph(x, y, z, radius, 2, npart + CEM - 1, GYPID);
1696 /* Correct phase ID of particle */
1697 clust [ npart ]->partphase = GYPID;
1698 }
1699 }
1700 }
1701 /* place as inert, CaCO3, C2S, slag, or pozzolanic material */
1702 else {
1703 count = chksph(x, y, z, radius, 2, npart + CEM - 1, phnow);
1704 /* Correct phase ID of particle */
1705 clust [ npart ]->partphase = phnow;
1706 }
1707
1708 clust [ npart ]->nextpart = NULL;
1709 }
1710 }
1711
1712 //deallocate
1713 for ( i = 1; i <= npart; i++ ) {
1714 free(clust [ i ]);
1715 //printf("Dealloc clust %ld of %d", i,npart);
1716 }
1717
1718 return ( 0 );
1719}
1720
1721
1722/* routine to obtain user input and create a starting microstructure */
1723int CemhydMatStatus :: create()
1724{
1725 /* Calls: gsphere */
1726 /* Called by: main program */
1727 int numsize;
1728 int *sphrad, *sphase;
1729 long int *sphnum;
1730 long int inval1;
1731 int isph, inval;
1732
1733 sphrad = new int [ NUMSIZES ];
1734 sphase = new int [ NUMSIZES ];
1735 sphnum = new long int [ NUMSIZES ];
1736
1737
1738 do {
1739#ifdef PRINTF
1740 printf("Enter number of different size spheres to use(max. is %d) \n", NUMSIZES);
1741#endif
1742#ifdef CMLFILE
1743 F->get_next_line_in_section(0, ( long & )numsize);
1744#endif
1745#ifdef TINYXML
1746 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, numsize);
1747#endif
1748 //fscanf(in, "%d",&numsize);
1749#ifdef PRINTF
1750 printf("%d \n", numsize);
1751#endif
1752 } while ( ( numsize > NUMSIZES ) || ( numsize < 0 ) );
1753
1754 do {
1755#ifdef PRINTF
1756 printf("Enter dispersion factor (separation distance in pixels) for spheres (0-2) \n");
1757 printf("0 corresponds to totally random placement \n");
1758#endif
1759#ifdef CMLFILE
1760 F->get_next_line_in_section(0, ( long & )dispdist);
1761#endif
1762#ifdef TINYXML
1763 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, dispdist);
1764#endif
1765 //fscanf(in, "%d",&dispdist);
1766#ifdef PRINTF
1767 printf("%d \n", dispdist);
1768#endif
1769 } while ( ( dispdist < 0 ) || ( dispdist > 2 ) );
1770
1771 do {
1772#ifdef PRINTF
1773 printf("Enter probability for gypsum particles on a random particle basis (0.0-1.0) \n");
1774#endif
1775#ifdef CMLFILE
1776 F->get_next_line_in_section(0, probgyp);
1777#endif
1778#ifdef TINYXML
1779 QueryNumAttributeExt(xmlFile, "Generate_microstructure", "dihydrate", probgyp);
1780#endif
1781 //fscanf(in, "%f",&probgyp);
1782#ifdef PRINTF
1783 printf("%f \n", probgyp);
1784#endif
1785 } while ( ( probgyp < 0.0 ) || ( probgyp > 1.0 ) );
1786
1787 do {
1788#ifdef PRINTF
1789 printf("Enter probabilities for hemihydrate and anhydrite forms of gypsum (0.0-1.0) \n");
1790#endif
1791#ifdef CMLFILE
1792 F->get_next_line_in_section(0, probhem);
1793 F->get_next_line_in_section(0, probanh);
1794#endif
1795#ifdef TINYXML
1796 QueryNumAttributeExt(xmlFile, "Generate_microstructure", "hemihydrate", probhem);
1797 QueryNumAttributeExt(xmlFile, "Generate_microstructure", "anhydrite", probanh);
1798#endif
1799 //fscanf(in, "%f %f",&probhem,&probanh);
1800#ifdef PRINTF
1801 printf("%f %f\n", probhem, probanh);
1802#endif
1803 } while ( ( probhem < 0.0 ) || ( probhem > 1.0 ) || ( probanh < 0.0 ) || ( probanh > 1.0 ) || ( ( probanh + probhem ) > 1.001 ) );
1804
1805 if ( ( numsize > 0 ) && ( numsize < ( NUMSIZES + 1 ) ) ) {
1806#ifdef PRINTF
1807 printf("Enter number, radius, and phase ID for each sphere class (largest radius 1st) \n");
1808 printf("Phases are %d- Cement and (random) calcium sulfate, %d- C2S, %d- Gypsum, %d- hemihydrate %d- anhydrite %d- Pozzolanic, %d- Inert, %d- Slag, %d- CaCO3 %d- Fly Ash \n", CEMID, C2SID, GYPID, HEMIHYDRATE, ANHYDRITE, POZZID, INERTID, SLAGID, CACO3, FLYASH);
1809#endif
1810 /* Obtain input for each size class of spheres */
1811 for ( isph = 0; isph < numsize; isph++ ) {
1812#ifdef PRINTF
1813 printf("Enter number of spheres of class %d \n", isph + 1);
1814#endif
1815#ifdef CMLFILE
1816 F->get_next_line_in_section(0, inval1);
1817#endif
1818#ifdef TINYXML
1819 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, inval1);
1820 //inval1 = static_cast<long int>(inval);
1821#endif
1822 //fscanf(in, "%ld",&inval1);
1823#ifdef PRINTF
1824 printf("%ld \n", inval1);
1825#endif
1826 sphnum [ isph ] = inval1;
1827
1828 // do{
1829#ifdef PRINTF
1830 printf("Enter radius of spheres of class %d \n", isph + 1);
1831 printf("(Integer <=%d please) \n", SYSSIZE / 3);
1832#endif
1833#ifdef CMLFILE
1834 F->get_next_line_in_section(0, ( long & )inval);
1835#endif
1836#ifdef TINYXML
1837 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, inval);
1838#endif
1839 //fscanf(in, "%d",&inval);
1840 if ( inval > ( SYSSIZE / 3 ) ) {
1841 printf("Given radius %d exceeded maximum radius of %d, terminating\n", inval, SYSSIZE / 3);
1842 exit(0);
1843 }
1844
1845#ifdef PRINTF
1846 printf("%d \n", inval);
1847#endif
1848 //} while ((inval<0)||(inval>(SYSSIZE/3)));
1849
1850 sphrad [ isph ] = inval;
1851 do {
1852#ifdef PRINTF
1853 printf("Enter phase of spheres of class %d \n", isph + 1);
1854#endif
1855#ifdef CMLFILE
1856 F->get_next_line_in_section(0, ( long & )inval);
1857#endif
1858#ifdef TINYXML
1859 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, inval);
1860#endif
1861 //fscanf(in, "%d",&inval);
1862#ifdef PRINTF
1863 printf("%d \n", inval);
1864#endif
1865 } while ( ( inval != CEMID ) && ( inval != C2SID ) && ( inval != GYPID ) && ( inval != HEMIHYDRATE ) && ( inval != ANHYDRITE ) && ( inval != POZZID ) && ( inval != INERTID ) && ( inval != SLAGID ) && ( inval != FLYASH ) && ( inval != CACO3 ) && ( inval != AGG ) && ( inval != ASG ) );
1866
1867 sphase [ isph ] = inval;
1868 if ( inval == CEMID ) {
1869 target_total += sphnum [ isph ] * volpart [ sphrad [ isph ] ];
1870 }
1871 }
1872
1873 /* Determine target pixel counts for calcium sulfate forms */
1874 target_sulfate = ( int ) ( ( float ) target_total * probgyp );
1875 target_anhydrite = ( int ) ( ( float ) target_total * probgyp * probanh );
1876 target_hemi = ( int ) ( ( float ) target_total * probgyp * probhem );
1877 if ( gsphere(numsize, sphnum, sphrad, sphase) == 1 ) { //unsuccessful generation of microstructure due to excessive amount of particles or too dense
1878 delete [] sphrad;
1879 delete [] sphase;
1880 delete [] sphnum;
1881 return ( 1 );
1882 }
1883 }
1884
1885 delete [] sphrad;
1886 delete [] sphase;
1887 delete [] sphnum;
1888
1889
1890 return ( 0 );
1891}
1892
1893
1894/* Routine to draw a particle during flocculation routine */
1895/* See routine chksph for definition of parameters */
1896void CemhydMatStatus :: drawfloc(int xin, int yin, int zin, int radd, int phasein, int phase2)
1897{
1898 /* Calls: no other routines */
1899 /* Called by: makefloc */
1900 int xp, yp, zp, i, j, k;
1901 float dist, xdist, ydist, zdist, ftmp;
1902
1903 /* Check all pixels within the digitized sphere volume */
1904 for ( i = xin - radd; ( i <= xin + radd ); i++ ) {
1905 xp = i;
1906 /* use periodic boundary conditions for sphere placement */
1907 if ( xp < 1 ) {
1908 xp += SYSSIZE;
1909 } else if ( xp > SYSSIZE ) {
1910 xp -= SYSSIZE;
1911 }
1912
1913 ftmp = ( float ) ( i - xin );
1914 xdist = ftmp * ftmp;
1915 for ( j = yin - radd; ( j <= yin + radd ); j++ ) {
1916 yp = j;
1917 /* use periodic boundary conditions for sphere placement */
1918 if ( yp < 1 ) {
1919 yp += SYSSIZE;
1920 } else if ( yp > SYSSIZE ) {
1921 yp -= SYSSIZE;
1922 }
1923
1924 ftmp = ( float ) ( j - yin );
1925 ydist = ftmp * ftmp;
1926 for ( k = zin - radd; ( k <= zin + radd ); k++ ) {
1927 zp = k;
1928 /* use periodic boundary conditions for sphere placement */
1929 if ( zp < 1 ) {
1930 zp += SYSSIZE;
1931 } else if ( zp > SYSSIZE ) {
1932 zp -= SYSSIZE;
1933 }
1934
1935 ftmp = ( float ) ( k - zin );
1936 zdist = ftmp * ftmp;
1937
1938 /* Compute distance from center of sphere to this pixel */
1939 dist = sqrt(xdist + ydist + zdist);
1940 if ( ( dist - 0.5 ) <= ( float ) radd ) {
1941 /* Update both cement and cemreal images */
1942 cement [ xp ] [ yp ] [ zp ] = phasein;
1943 cemreal [ xp ] [ yp ] [ zp ] = phase2;
1944 }
1945 }
1946 }
1947 }
1948}
1949
1950
1951/* Routine to check particle placement during flocculation */
1952/* for particle of size radd centered at (xin,yin,zin) */
1953/* Returns flag indicating if placement is possible */
1954int CemhydMatStatus :: chkfloc(int xin, int yin, int zin, int radd)
1955{
1956 /* Calls: no other routines */
1957 /* Called by: makefloc */
1958 int nofits, xp, yp, zp, i, j, k;
1959 float dist, xdist, ydist, zdist, ftmp;
1960
1961 nofits = 0; /* Flag indicating if placement is possible */
1962
1963 /* Check all pixels within the digitized sphere volume */
1964 for ( i = xin - radd; ( ( i <= xin + radd ) && ( nofits == 0 ) ); i++ ) {
1965 xp = i;
1966 /* use periodic boundary conditions for sphere placement */
1967 if ( xp < 1 ) {
1968 xp += SYSSIZE;
1969 } else if ( xp > SYSSIZE ) {
1970 xp -= SYSSIZE;
1971 }
1972
1973 ftmp = ( float ) ( i - xin );
1974 xdist = ftmp * ftmp;
1975 for ( j = yin - radd; ( ( j <= yin + radd ) && ( nofits == 0 ) ); j++ ) {
1976 yp = j;
1977 /* use periodic boundary conditions for sphere placement */
1978 if ( yp < 1 ) {
1979 yp += SYSSIZE;
1980 } else if ( yp > SYSSIZE ) {
1981 yp -= SYSSIZE;
1982 }
1983
1984 ftmp = ( float ) ( j - yin );
1985 ydist = ftmp * ftmp;
1986 for ( k = zin - radd; ( ( k <= zin + radd ) && ( nofits == 0 ) ); k++ ) {
1987 zp = k;
1988 /* use periodic boundary conditions for sphere placement */
1989 if ( zp < 1 ) {
1990 zp += SYSSIZE;
1991 } else if ( zp > SYSSIZE ) {
1992 zp -= SYSSIZE;
1993 }
1994
1995 ftmp = ( float ) ( k - zin );
1996 zdist = ftmp * ftmp;
1997
1998 /* Compute distance from center of sphere to this pixel */
1999 dist = sqrt(xdist + ydist + zdist);
2000 if ( ( dist - 0.5 ) <= ( float ) radd ) {
2001 if ( ( cement [ xp ] [ yp ] [ zp ] != POROSITY ) ) {
2002 /* Record ID of particle hit */
2003 nofits = cement [ xp ] [ yp ] [ zp ];
2004 }
2005 }
2006
2007 /* Check for overlap with aggregate */
2008 if ( ( fabs( xp - ( ( float ) ( SYSSIZE + 1 ) / 2.0 ) ) ) < ( ( float ) aggsize / 2.0 ) ) {
2009 nofits = AGG;
2010 }
2011 }
2012 }
2013 }
2014
2015 /* return flag indicating if sphere will fit */
2016 return ( nofits );
2017}
2018
2019
2020/* routine to perform flocculation of particles */
2021void CemhydMatStatus :: makefloc()
2022/* Calls: drawfloc, chkfloc, ran1 */
2023/* Called by: main program */
2024{
2025 int partdo, numfloc;
2026 int nstart;
2027 int nleft = 0, ckall;
2028 int xm, ym, zm, moveran;
2029 int xp, yp, zp, rp, clushit, valkeep;
2030 int iclus;
2031 int *cluspart;
2032 struct cluster *parttmp, *partpoint, *partkeep = NULL;
2033
2034 cluspart = new int [ NPARTC ];
2035
2036
2037 nstart = npart; /* Counter of number of flocs remaining */
2038 for ( iclus = 1; iclus <= npart; iclus++ ) {
2039 cluspart [ iclus ] = iclus;
2040 }
2041
2042 do {
2043#ifdef PRINTF
2044 printf("Enter number of flocs desired at end of routine (>0) \n");
2045#endif
2046#ifdef CMLFILE
2047 F->get_next_line_in_section(0, ( long & )numfloc);
2048#endif
2049#ifdef TINYXML
2050 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, numfloc);
2051#endif
2052 //fscanf(in, "%d",&numfloc);
2053#ifdef PRINTF
2054 printf("%d\n", numfloc);
2055#endif
2056 } while ( numfloc <= 0 );
2057
2058 while ( nstart > numfloc ) {
2059 nleft = 0;
2060
2061 /* Try to move each cluster in turn */
2062 for ( iclus = 1; iclus <= npart; iclus++ ) {
2063 if ( clust [ iclus ] == NULL ) {
2064 nleft += 1;
2065 } else {
2066 xm = ym = zm = 0;
2067 /* Generate a random move in one of 6 principal directions */
2068 moveran = ( int ) ( 6. * ran1(seed) );
2069 switch ( moveran ) {
2070 case 0:
2071 xm = 1;
2072 break;
2073 case 1:
2074 xm = ( -1 );
2075 break;
2076 case 2:
2077 ym = 1;
2078 break;
2079 case 3:
2080 ym = ( -1 );
2081 break;
2082 case 4:
2083 zm = 1;
2084 break;
2085 case 5:
2086 zm = ( -1 );
2087 break;
2088 default:
2089 break;
2090 }
2091
2092 /* First erase all particles in cluster */
2093 partpoint = clust [ iclus ];
2094 while ( partpoint != NULL ) {
2095 xp = partpoint->x;
2096 yp = partpoint->y;
2097 zp = partpoint->z;
2098 rp = partpoint->r;
2099 drawfloc(xp, yp, zp, rp, 0, 0);
2100 partpoint = partpoint->nextpart;
2101 }
2102
2103 ckall = 0;
2104 /* Now try to draw cluster at new location */
2105 partpoint = clust [ iclus ];
2106 while ( ( partpoint != NULL ) && ( ckall == 0 ) ) {
2107 xp = partpoint->x + xm;
2108 yp = partpoint->y + ym;
2109 zp = partpoint->z + zm;
2110 rp = partpoint->r;
2111 ckall = chkfloc(xp, yp, zp, rp);
2112 partpoint = partpoint->nextpart;
2113 }
2114
2115 if ( ckall == 0 ) {
2116 /* Place cluster particles at new location */
2117 partpoint = clust [ iclus ];
2118 while ( partpoint != NULL ) {
2119 xp = partpoint->x + xm;
2120 yp = partpoint->y + ym;
2121 zp = partpoint->z + zm;
2122 rp = partpoint->r;
2123 valkeep = partpoint->partphase;
2124 partdo = partpoint->partid;
2125 drawfloc(xp, yp, zp, rp, partdo + CEM - 1, valkeep);
2126 /* Update particle location */
2127 partpoint->x = xp;
2128 partpoint->y = yp;
2129 partpoint->z = zp;
2130 partpoint = partpoint->nextpart;
2131 }
2132 } else {
2133 /* A cluster or aggregate was hit */
2134 /* Draw particles at old location */
2135 partpoint = clust [ iclus ];
2136 /* partkeep stores pointer to last particle in list */
2137 while ( partpoint != NULL ) {
2138 xp = partpoint->x;
2139 yp = partpoint->y;
2140 zp = partpoint->z;
2141 rp = partpoint->r;
2142 valkeep = partpoint->partphase;
2143 partdo = partpoint->partid;
2144 drawfloc(xp, yp, zp, rp, partdo + CEM - 1, valkeep);
2145 partkeep = partpoint;
2146 partpoint = partpoint->nextpart;
2147 }
2148
2149 /* Determine the cluster hit */
2150 if ( ckall != AGG ) {
2151 clushit = cluspart [ ckall - CEM + 1 ];
2152 /* Move all of the particles from cluster clushit to cluster iclus */
2153 parttmp = clust [ clushit ];
2154 /* Attach new cluster to old one */
2155 partkeep->nextpart = parttmp;
2156 while ( parttmp != NULL ) {
2157 cluspart [ parttmp->partid ] = iclus;
2158 /* Relabel all particles added to this cluster */
2159 parttmp->clustid = iclus;
2160 parttmp = parttmp->nextpart;
2161 }
2162
2163 /* Disengage the cluster that was hit */
2164 clust [ clushit ] = NULL;
2165 nstart -= 1;
2166 }
2167 }
2168 }
2169 }
2170
2171 printf("Number left was %d but number of clusters is %d \n", nleft, nstart);
2172 }
2173
2174 /* end of while loop */
2175 clusleft = nleft;
2176
2177 delete [] cluspart;
2178}
2179
2180
2181/* routine to assess global phase fractions present in 3-D system */
2182void CemhydMatStatus :: measure()
2183/* Calls: no other routines */
2184/* Called by: main program */
2185{
2186 long int npor, nc2s, ngyp, ncem, nagg, npozz, ninert, nflyash, nanh, nhem, ncaco3, nslag;
2187 int i, j, k, valph;
2188
2189 /* counters for the various phase fractions */
2190 npor = 0;
2191 ngyp = 0;
2192 ncem = 0;
2193 nagg = 0;
2194 ninert = 0;
2195 nslag = 0;
2196 nc2s = 0;
2197 npozz = 0;
2198 nflyash = 0;
2199 nanh = 0;
2200 nhem = 0;
2201 ncaco3 = 0;
2202
2203 /* Check all pixels in 3-D microstructure */
2204 for ( i = 1; i <= SYSSIZE; i++ ) {
2205 for ( j = 1; j <= SYSSIZE; j++ ) {
2206 for ( k = 1; k <= SYSSIZE; k++ ) {
2207 valph = cemreal [ i ] [ j ] [ k ];
2208 if ( valph == POROSITY ) {
2209 npor += 1;
2210 } else if ( valph == CEMID ) {
2211 ncem += 1;
2212 } else if ( valph == C2SID ) {
2213 nc2s += 1;
2214 } else if ( valph == GYPID ) {
2215 ngyp += 1;
2216 } else if ( valph == ANHYDRITE ) {
2217 nanh += 1;
2218 } else if ( valph == HEMIHYDRATE ) {
2219 nhem += 1;
2220 } else if ( valph == AGG ) {
2221 nagg += 1;
2222 } else if ( valph == POZZID ) {
2223 npozz += 1;
2224 } else if ( valph == SLAGID ) {
2225 nslag += 1;
2226 } else if ( valph == INERTID ) {
2227 ninert += 1;
2228 } else if ( valph == FLYASH ) {
2229 nflyash += 1;
2230 } else if ( valph == CACO3 ) {
2231 ncaco3 += 1;
2232 }
2233 }
2234 }
2235 }
2236
2237 /* Output results */
2238 printf("\n Phase counts are: \n");
2239 printf("Porosity= %ld \n", npor);
2240 printf("Cement= %ld \n", ncem);
2241 printf("C2S= %ld \n", nc2s);
2242 printf("Gypsum= %ld \n", ngyp);
2243 printf("Anhydrite= %ld \n", nanh);
2244 printf("Hemihydrate= %ld \n", nhem);
2245 printf("Pozzolan= %ld \n", npozz);
2246 printf("Inert= %ld \n", ninert);
2247 printf("Slag= %ld \n", nslag);
2248 printf("CaCO3= %ld \n", ncaco3);
2249 printf("Fly Ash= %ld \n", nflyash);
2250 printf("Aggregate= %ld \n", nagg);
2251}
2252
2253
2254/* Routine to measure phase fractions as a function of distance from */
2255/* aggregate surface*/
2256void CemhydMatStatus :: measagg()
2257/* Calls: no other routines */
2258/* Called by: main program */
2259{
2260 int phase [ 40 ], ptot;
2261 int icnt, ixlo, ixhi, iy, iz, phid, idist;
2262 FILE *aggfile;
2263
2264 /* By default, results are sent to output file called agglist.out */
2265 aggfile = fopen("agglist.out", "w");
2266 printf("Distance Porosity Cement C2S Gypsum Anhydrite Hemihydrate Pozzolan Inert Slag CaCO3 Fly Ash\n");
2267 fprintf(aggfile, "Distance Porosity Cement C2S Gypsum Anhydrite Hemihydrate Pozzolan Inert Slag CaCO3 Fly Ash\n");
2268
2269 /* Increase distance from aggregate in increments of one */
2270 for ( idist = 1; idist <= ( SYSSIZE - aggsize ) / 2; idist++ ) {
2271 /* Pixel left of aggregate surface */
2272 ixlo = ( ( SYSSIZE - aggsize + 2 ) / 2 ) - idist;
2273 /* Pixel right of aggregate surface */
2274 ixhi = ( ( SYSSIZE + aggsize ) / 2 ) + idist;
2275
2276 /* Initialize phase counts for this distance */
2277 for ( icnt = 0; icnt < 39; icnt++ ) {
2278 phase [ icnt ] = 0;
2279 }
2280
2281 ptot = 0;
2282
2283 /* Check all pixels which are this distance from aggregate surface */
2284 for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2285 for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2286 phid = cemreal [ ixlo ] [ iy ] [ iz ];
2287 ptot += 1;
2288 if ( phid <= FLYASH ) {
2289 phase [ phid ] += 1;
2290 }
2291
2292 phid = cemreal [ ixhi ] [ iy ] [ iz ];
2293 ptot += 1;
2294 if ( phid <= FLYASH ) {
2295 phase [ phid ] += 1;
2296 }
2297 }
2298 }
2299
2300 /* Output results for this distance from surface */
2301 printf("%d %d %d %d %d %d %d %d %d %d %d %d\n", idist, phase [ 0 ], phase [ CEMID ], phase [ C2SID ], phase [ GYPID ], phase [ ANHYDRITE ], phase [ HEMIHYDRATE ], phase [ POZZID ], phase [ INERTID ], phase [ SLAGID ], phase [ CACO3 ], phase [ FLYASH ]);
2302 fprintf(aggfile, "%d %d %d %d %d %d %d %d %d %d %d %d\n", idist, phase [ 0 ], phase [ CEMID ], phase [ C2SID ], phase [ GYPID ], phase [ ANHYDRITE ], phase [ HEMIHYDRATE ], phase [ POZZID ], phase [ INERTID ], phase [ SLAGID ], phase [ CACO3 ], phase [ FLYASH ]);
2303 }
2304
2305 fclose(aggfile);
2306}
2307
2308
2309/* routine to assess the connectivity (percolation) of a single phase */
2310/* Two matrices are used here: one for the current burnt locations */
2311/* the other to store the newly found burnt locations */
2312void CemhydMatStatus :: connect()
2313/* Calls: no other routines */
2314/* Called by: main program */
2315{
2316 long int inew, ntop, nthrough, ncur, nnew, ntot;
2317 int i, j, k, nmatx [ 29000 ], nmaty [ 29000 ], nmatz [ 29000 ];
2318 int xcn, ycn, zcn, npix, x1, y1, z1, igood, nnewx [ 29000 ], nnewy [ 29000 ], nnewz [ 29000 ];
2319 int jnew, icur;
2320
2321 do {
2322 printf("Enter phase to analyze 0) pores 1) Cement \n");
2323#ifdef CMLFILE
2324 F->get_next_line_in_section(0, ( long & )npix);
2325#endif
2326#ifdef TINYXML
2327 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, npix);
2328#endif
2329 //fscanf(in, "%d",&npix);
2330 printf("%d \n", npix);
2331 } while ( ( npix != 0 ) && ( npix != 1 ) );
2332
2333 /* counters for number of pixels of phase accessible from top surface */
2334 /* and number which are part of a percolated pathway */
2335 ntop = 0;
2336 nthrough = 0;
2337
2338 /* percolation is assessed from top to bottom only */
2339 /* and burning algorithm is periodic in x and y directions */
2340 k = 1;
2341 for ( i = 1; i <= SYSSIZE; i++ ) {
2342 for ( j = 1; j <= SYSSIZE; j++ ) {
2343 ncur = 0;
2344 ntot = 0;
2345 igood = 0; /* Indicates if bottom has been reached */
2346 if ( ( ( cement [ i ] [ j ] [ k ] == npix ) && ( ( cement [ i ] [ j ] [ SYSSIZE ] == npix ) ||
2347 ( cement [ i ] [ j ] [ SYSSIZE ] == ( npix + BURNTG ) ) ) ) ||
2348 ( ( cement [ i ] [ j ] [ SYSSIZE ] >= CEM ) &&
2349 ( cement [ i ] [ j ] [ k ] >= CEM ) && ( cement [ i ] [ j ] [ k ] < BURNTG ) && ( npix == 1 ) ) ) {
2350 /* Start a burn front */
2351 cement [ i ] [ j ] [ k ] += BURNTG;
2352 ntot += 1;
2353 ncur += 1;
2354 /* burn front is stored in matrices nmat* */
2355 /* and nnew* */
2356 nmatx [ ncur ] = i;
2357 nmaty [ ncur ] = j;
2358 nmatz [ ncur ] = 1;
2359 /* Burn as long as new (fuel) pixels are found */
2360 do {
2361 nnew = 0;
2362 for ( inew = 1; inew <= ncur; inew++ ) {
2363 xcn = nmatx [ inew ];
2364 ycn = nmaty [ inew ];
2365 zcn = nmatz [ inew ];
2366
2367 /* Check all six neighbors */
2368 for ( jnew = 1; jnew <= 6; jnew++ ) {
2369 x1 = xcn;
2370 y1 = ycn;
2371 z1 = zcn;
2372 if ( jnew == 1 ) {
2373 x1 -= 1;
2374 if ( x1 < 1 ) {
2375 x1 += SYSSIZE;
2376 }
2377 } else if ( jnew == 2 ) {
2378 x1 += 1;
2379 if ( x1 > SYSSIZE ) {
2380 x1 -= SYSSIZE;
2381 }
2382 } else if ( jnew == 3 ) {
2383 y1 -= 1;
2384 if ( y1 < 1 ) {
2385 y1 += SYSSIZE;
2386 }
2387 } else if ( jnew == 4 ) {
2388 y1 += 1;
2389 if ( y1 > SYSSIZE ) {
2390 y1 -= SYSSIZE;
2391 }
2392 } else if ( jnew == 5 ) {
2393 z1 -= 1;
2394 } else if ( jnew == 6 ) {
2395 z1 += 1;
2396 }
2397
2398 /* Nonperiodic in z direction so be sure to remain in the 3-D box */
2399 if ( ( z1 >= 1 ) && ( z1 <= SYSSIZE ) ) {
2400 if ( ( cement [ x1 ] [ y1 ] [ z1 ] == npix ) || ( ( cement [ x1 ] [ y1 ] [ z1 ] >= CEM ) &&
2401 ( cement [ x1 ] [ y1 ] [ z1 ] < BURNTG ) && ( npix == 1 ) ) ) {
2402 ntot += 1;
2403 cement [ x1 ] [ y1 ] [ z1 ] += BURNTG;
2404 nnew += 1;
2405 if ( nnew >= 29000 ) {
2406 printf("error in size of nnew \n");
2407 }
2408
2409 nnewx [ nnew ] = x1;
2410 nnewy [ nnew ] = y1;
2411 nnewz [ nnew ] = z1;
2412 /* See if bottom of system has been reached */
2413 if ( z1 == SYSSIZE ) {
2414 igood = 1;
2415 }
2416 }
2417 }
2418 }
2419 }
2420
2421 if ( nnew > 0 ) {
2422 ncur = nnew;
2423 /* update the burn front matrices */
2424 for ( icur = 1; icur <= ncur; icur++ ) {
2425 nmatx [ icur ] = nnewx [ icur ];
2426 nmaty [ icur ] = nnewy [ icur ];
2427 nmatz [ icur ] = nnewz [ icur ];
2428 }
2429 }
2430 } while ( nnew > 0 );
2431
2432 ntop += ntot;
2433 if ( igood == 1 ) {
2434 nthrough += ntot;
2435 }
2436 }
2437 }
2438 }
2439
2440 printf("Phase ID= %d \n", npix);
2441 printf("Number accessible from top= %ld \n", ntop);
2442 printf("Number contained in through pathways= %ld \n", nthrough);
2443
2444 /* return the burnt sites to their original phase values */
2445 for ( i = 1; i <= SYSSIZE; i++ ) {
2446 for ( j = 1; j <= SYSSIZE; j++ ) {
2447 for ( k = 1; k <= SYSSIZE; k++ ) {
2448 if ( cement [ i ] [ j ] [ k ] >= BURNTG ) {
2449 cement [ i ] [ j ] [ k ] -= BURNTG;
2450 }
2451 }
2452 }
2453 }
2454}
2455
2456
2457/* Routine to output final microstructure to file */
2458void CemhydMatStatus :: outmic()
2459/* Calls: no other routines */
2460/* Called by: main program */
2461{
2462 FILE *outfile, *partfile;
2463 char filen [ 80 ], filepart [ 80 ];
2464 int ix, iy, iz, valout;
2465
2466#ifdef PRINTF
2467 printf("Enter name of file to save microstructure to \n");
2468#endif
2469#ifdef CMLFILE
2470 F->get_next_line_in_section(0, filen);
2471#endif
2472#ifdef TINYXML
2473 QueryStringAttributeExt(xmlFile, "Generate_microstructure", countKey++, filen);
2474#endif
2475 //fscanf(in, "%s",filen);
2476 printf("%s\n", filen);
2477
2478 outfile = fopen(filen, "w");
2479
2480#ifdef PRINTF
2481 printf("Enter name of file to save particle IDs to \n");
2482#endif
2483#ifdef CMLFILE
2484 F->get_next_line_in_section(0, filepart);
2485#endif
2486#ifdef TINYXML
2487 QueryStringAttributeExt(xmlFile, "Generate_microstructure", countKey++, filepart);
2488#endif
2489 //fscanf(in, "%s",filepart);
2490#ifdef PRINTF
2491 printf("%s\n", filepart);
2492#endif
2493
2494 partfile = fopen(filepart, "w");
2495
2496 for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2497 for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2498 for ( ix = 1; ix <= SYSSIZE; ix++ ) {
2499 valout = cemreal [ ix ] [ iy ] [ iz ];
2500 fprintf(outfile, "%1d\n", valout); //img file
2501 valout = cement [ ix ] [ iy ] [ iz ];
2502 if ( valout < 0 ) {
2503 valout = 0;
2504 }
2505
2506 fprintf(partfile, "%d\n", valout); //id file
2507 }
2508 }
2509 }
2510
2511 fclose(outfile);
2512 fclose(partfile);
2513}
2514
2515
2516int CemhydMatStatus :: genpartnew()
2517{
2518 int userc; /* User choice from menu */
2519 int ig, jg, kg;
2520
2521 n_sulfate = 0;
2522 target_sulfate = 0;
2523 n_total = 0;
2524 target_total = 0;
2525 n_anhydrite = 0;
2526 target_anhydrite = 0;
2527 n_hemi = 0;
2528 target_hemi = 0;
2529
2532
2533 clust = new cluster * [ NPARTC ];
2534
2535 /* Initialize volume array */
2536 volpart [ 0 ] = 1;
2537 volpart [ 1 ] = 19;
2538 volpart [ 2 ] = 81;
2539 volpart [ 3 ] = 179;
2540 volpart [ 4 ] = 389;
2541 volpart [ 5 ] = 739;
2542 volpart [ 6 ] = 1189;
2543 volpart [ 7 ] = 1791;
2544 volpart [ 8 ] = 2553;
2545 volpart [ 9 ] = 3695;
2546 volpart [ 10 ] = 4945;
2547 volpart [ 11 ] = 6403;
2548 volpart [ 12 ] = 8217;
2549 volpart [ 13 ] = 10395;
2550 volpart [ 14 ] = 12893;
2551 volpart [ 15 ] = 15515;
2552 volpart [ 16 ] = 18853;
2553 volpart [ 17 ] = 22575;
2554 volpart [ 18 ] = 26745;
2555 volpart [ 19 ] = 31103;
2556 volpart [ 20 ] = 36137;
2557 volpart [ 21 ] = 41851;
2558 volpart [ 22 ] = 47833;
2559 volpart [ 23 ] = 54435;
2560 volpart [ 24 ] = 61565;
2561 volpart [ 25 ] = 69599;
2562 volpart [ 26 ] = 78205;
2563 volpart [ 27 ] = 87271;
2564 volpart [ 28 ] = 97233;
2565 volpart [ 29 ] = 107783;
2566 volpart [ 30 ] = 119009;
2567 volpart [ 31 ] = 131155;
2568 volpart [ 32 ] = 143761;
2569 volpart [ 33 ] = 157563;
2570 volpart [ 34 ] = 172317;
2571 volpart [ 35 ] = 187511;
2572 volpart [ 36 ] = 203965;
2573
2574 //printf("Enter random number seed value (a negative integer) \n");
2575 //fscanf(in, "%d",&iseed);
2576 //printf("%d \n",iseed);
2577 nseed = iseed;
2578 seed = & nseed;
2579
2580 /* Initialize counters and system parameters */
2581 npart = 0;
2582 aggsize = 0;
2583 clusleft = 0;
2584
2585 /* clear the 3-D system to all porosity to start */
2586 for ( ig = 1; ig <= SYSSIZE; ig++ ) {
2587 for ( jg = 1; jg <= SYSSIZE; jg++ ) {
2588 for ( kg = 1; kg <= SYSSIZE; kg++ ) {
2589 cement [ ig ] [ jg ] [ kg ] = POROSITY; //particle ID
2590 cemreal [ ig ] [ jg ] [ kg ] = POROSITY; //microstructure
2591 }
2592 }
2593 }
2594
2595 /* present menu and execute user choice */
2596 do {
2597#ifdef PRINTF
2598 printf(" \n Input User Choice \n");
2599 printf("1) Exit \n");
2600 printf("2) Add spherical particles (cement,gypsum, pozzolans, etc.) to microstructure \n");
2601 printf("3) Flocculate system by reducing number of particle clusters \n");
2602 printf("4) Measure global phase fractions \n");
2603 printf("5) Add an aggregate to the microstructure \n");
2604 printf("6) Measure single phase connectivity (pores or solids) \n");
2605 printf("7) Measure phase fractions vs. distance from aggregate surface \n");
2606 printf("8) Output current microstructure to file \n");
2607#endif
2608#ifdef CMLFILE
2609 F->get_next_line_in_section(0, ( long & )userc);
2610#endif
2611#ifdef TINYXML
2612 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, userc);
2613#endif
2614 //fscanf(in, "%d",&userc);
2615 //printf("%d \n",userc);
2616 fflush(stdout);
2617
2618 switch ( userc ) {
2619 case 2:
2620 if ( create() == 1 ) { //unsuccessful generation of microstructure due to excessive amount of particles or too dense
2621 delete [] clust;
2624 return ( 1 );
2625 }
2626
2627 break;
2628 case 3:
2629 makefloc();
2630 break;
2631 case 4:
2632 measure();
2633 break;
2634 case 5:
2635 addagg();
2636 break;
2637 case 6:
2638 connect();
2639 break;
2640 case 7:
2641 if ( aggsize != 0 ) {
2642 measagg();
2643 } else {
2644 printf("No aggregate present. \n");
2645 }
2646
2647 break;
2648 case 8:
2649 outmic();
2650 break;
2651 default:
2652 break;
2653 }
2654 } while ( userc != 1 );
2655
2656 //store ID in an array
2657 for ( ig = 0; ig < SYSSIZE; ig++ ) {
2658 for ( jg = 0; jg < SYSSIZE; jg++ ) {
2659 for ( kg = 0; kg < SYSSIZE; kg++ ) {
2660 micpart [ ig ] [ jg ] [ kg ] = cement [ ig + 1 ] [ jg + 1 ] [ kg + 1 ];
2661 }
2662 }
2663 }
2664
2666 delete [] clust;
2667 return ( 0 );
2668}
2669
2670
2671/*************************************************************************/
2672/****************************DISTRIB3D************************************/
2673/*************************************************************************/
2674
2675/* routine to create a template for the sphere of interest of radius size */
2676/* to be used in curvature evaluation */
2677/* Called by: runsint */
2678/* Calls no other routines */
2679int CemhydMatStatus :: maketemp(int size)
2680{
2681 int icirc, xval, yval, zval;
2682 float xtmp, ytmp;
2683 float dist;
2684
2685 /* determine and store the locations of all pixels in the 3-D sphere */
2686 icirc = 0;
2687 for ( xval = ( -size ); xval <= size; xval++ ) {
2688 xtmp = ( float ) ( xval * xval );
2689 for ( yval = ( -size ); yval <= size; yval++ ) {
2690 ytmp = ( float ) ( yval * yval );
2691 for ( zval = ( -size ); zval <= size; zval++ ) {
2692 dist = sqrt( xtmp + ytmp + ( float ) ( zval * zval ) );
2693 if ( dist <= ( ( float ) size + 0.5 ) ) {
2694 icirc += 1;
2695 if ( icirc >= MAXSPH ) {
2696 printf("Too many elements in sphere \n");
2697 printf("Must change value of MAXSPH parameter \n");
2698 printf("Currently set at %ld \n", MAXSPH);
2699 exit(1);
2700 }
2701
2702 xsph [ icirc ] = xval;
2703 ysph [ icirc ] = yval;
2704 zsph [ icirc ] = zval;
2705 }
2706 }
2707 }
2708 }
2709
2710 /* return the number of pixels contained in sphere of radius (size+0.5) */
2711 return ( icirc );
2712}
2713
2714/* routine to count phase fractions (porosity and solids) */
2715/* Called by main routine */
2716/* Calls no other routines */
2717void CemhydMatStatus :: phcount()
2718{
2719 long int npore, nsolid [ 37 ];
2720 int ix, iy, iz;
2721
2722 npore = 0;
2723 for ( ix = 1; ix < 37; ix++ ) {
2724 nsolid [ ix ] = 0;
2725 }
2726
2727 /* check all pixels in the 3-D system */
2728 for ( ix = 1; ix <= SYSSIZE; ix++ ) {
2729 for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2730 for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2731 if ( mask [ ix ] [ iy ] [ iz ] == 0 ) {
2732 npore += 1;
2733 } else {
2734 nsolid [ mask [ ix ] [ iy ] [ iz ] ] += 1;
2735 }
2736 }
2737 }
2738 }
2739
2740 printf("Pores are: %ld \n", npore);
2741 printf("Solids are: %ld %ld %ld %ld %ld %ld\n", nsolid [ 1 ], nsolid [ 2 ],
2742 nsolid [ 3 ], nsolid [ 4 ], nsolid [ 5 ], nsolid [ 6 ]);
2743}
2744
2745/* routine to return number of surface faces exposed to porosity */
2746/* for pixel located at (xin,yin,zin) */
2747/* Called by rhcalc */
2748/* Calls no other routines */
2749int CemhydMatStatus :: surfpix(int xin, int yin, int zin)
2750{
2751 int npix, ix1, iy1, iz1;
2752
2753 npix = 0;
2754
2755 /* check each of the six immediate neighbors */
2756 /* using periodic boundary conditions */
2757 ix1 = xin - 1;
2758 if ( ix1 < 1 ) {
2759 ix1 += SYSSIZE;
2760 }
2761
2762 if ( mask [ ix1 ] [ yin ] [ zin ] == 0 ) {
2763 npix += 1;
2764 }
2765
2766 ix1 = xin + 1;
2767 if ( ix1 > SYSSIZE ) {
2768 ix1 -= SYSSIZE;
2769 }
2770
2771 if ( mask [ ix1 ] [ yin ] [ zin ] == 0 ) {
2772 npix += 1;
2773 }
2774
2775 iy1 = yin - 1;
2776 if ( iy1 < 1 ) {
2777 iy1 += SYSSIZE;
2778 }
2779
2780 if ( mask [ xin ] [ iy1 ] [ zin ] == 0 ) {
2781 npix += 1;
2782 }
2783
2784 iy1 = yin + 1;
2785 if ( iy1 > SYSSIZE ) {
2786 iy1 -= SYSSIZE;
2787 }
2788
2789 if ( mask [ xin ] [ iy1 ] [ zin ] == 0 ) {
2790 npix += 1;
2791 }
2792
2793 iz1 = zin - 1;
2794 if ( iz1 < 1 ) {
2795 iz1 += SYSSIZE;
2796 }
2797
2798 if ( mask [ xin ] [ yin ] [ iz1 ] == 0 ) {
2799 npix += 1;
2800 }
2801
2802 iz1 = zin + 1;
2803 if ( iz1 > SYSSIZE ) {
2804 iz1 -= SYSSIZE;
2805 }
2806
2807 if ( mask [ xin ] [ yin ] [ iz1 ] == 0 ) {
2808 npix += 1;
2809 }
2810
2811 return ( npix );
2812}
2813
2814/* routine to return the current hydraulic radius for phase phin */
2815/* Calls surfpix */
2816/* Called by runsint */
2817float CemhydMatStatus :: rhcalc(int phin)
2818{
2819 int ix, iy, iz;
2820 long int porc, surfc;
2821 float rhval;
2822
2823 porc = surfc = 0;
2824
2825 /* Check all pixels in the 3-D volume */
2826 for ( ix = 1; ix <= SYSSIZE; ix++ ) {
2827 for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2828 for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2829 if ( mask [ ix ] [ iy ] [ iz ] == phin ) {
2830 porc += 1;
2831 surfc += surfpix(ix, iy, iz);
2832 }
2833 }
2834 }
2835 }
2836
2837 printf("Phase area count is %ld \n", porc);
2838 printf("Phase surface count is %ld \n", surfc);
2839 rhval = ( float ) porc * 6. / ( 4. * ( float ) surfc );
2840 printf("Hydraulic radius is %f \n", rhval);
2841 return ( rhval );
2842}
2843
2844/* routine to return count of pixels in a spherical template which are phase */
2845/* phin or porosity (phase=0) */
2846/* Calls no other routines */
2847/* Called by sysinit */
2848int CemhydMatStatus :: countem(int xp, int yp, int zp, int phin)
2849{
2850 int xc, yc, zc;
2851 int cumnum, ic;
2852
2853 cumnum = 0;
2854 for ( ic = 1; ic <= nsph; ic++ ) {
2855 xc = xp + xsph [ ic ];
2856 yc = yp + ysph [ ic ];
2857 zc = zp + zsph [ ic ];
2858 /* Use periodic boundaries */
2859 if ( xc < 1 ) {
2860 xc += SYSSIZE;
2861 } else if ( xc > SYSSIZE ) {
2862 xc -= SYSSIZE;
2863 }
2864
2865 if ( yc < 1 ) {
2866 yc += SYSSIZE;
2867 } else if ( yc > SYSSIZE ) {
2868 yc -= SYSSIZE;
2869 }
2870
2871 if ( zc < 1 ) {
2872 zc += SYSSIZE;
2873 } else if ( zc > SYSSIZE ) {
2874 zc -= SYSSIZE;
2875 }
2876
2877 if ( ( xc != xp ) || ( yc != yp ) || ( zc != zp ) ) {
2878 if ( ( mask [ xc ] [ yc ] [ zc ] == phin ) || ( mask [ xc ] [ yc ] [ zc ] == 0 ) ) {
2879 cumnum += 1;
2880 }
2881 }
2882 }
2883
2884 return ( cumnum );
2885}
2886
2887/* routine to initialize system by determining local curvature */
2888/* of all phase 1 and phase 2 pixels */
2889/* Calls countem */
2890/* Called by runsint */
2891void CemhydMatStatus :: sysinit(int ph1, int ph2)
2892{
2893 int count, xl, yl, zl;
2894
2895 count = 0;
2896 /* process all pixels in the 3-D box */
2897 for ( xl = 1; xl <= SYSSIZE; xl++ ) {
2898 for ( yl = 1; yl <= SYSSIZE; yl++ ) {
2899 for ( zl = 1; zl <= SYSSIZE; zl++ ) {
2900 /* determine local curvature */
2901 /* For phase 1 want to determine number of porosity pixels */
2902 /* (phase=0) in immediate neighborhood */
2903 if ( mask [ xl ] [ yl ] [ zl ] == ph1 ) {
2904 count = countem(xl, yl, zl, 0);
2905 }
2906
2907 /* For phase 2 want to determine number of porosity or phase */
2908 /* 2 pixels in immediate neighborhood */
2909 if ( mask [ xl ] [ yl ] [ zl ] == ph2 ) {
2910 count = countem(xl, yl, zl, ph2);
2911 }
2912
2913 if ( ( count < 0 ) || ( count >= nsph ) ) {
2914 printf("Error count is %d \n", count);
2915 printf("xl %d yl %d zl %d \n", xl, yl, zl);
2916 }
2917
2918 /* case where we have a phase 1 surface pixel */
2919 /* with non-zero local curvature */
2920 if ( ( count >= 0 ) && ( mask [ xl ] [ yl ] [ zl ] == ph1 ) ) {
2921 curvature [ xl ] [ yl ] [ zl ] = count;
2922 /* update solid curvature histogram */
2923 nsolid [ count ] += 1;
2924 }
2925
2926 /* case where we have a phase 2 surface pixel */
2927 if ( ( count >= 0 ) && ( mask [ xl ] [ yl ] [ zl ] == ph2 ) ) {
2928 curvature [ xl ] [ yl ] [ zl ] = count;
2929 /* update air curvature histogram */
2930 nair [ count ] += 1;
2931 }
2932 }
2933 }
2934 }
2935
2936 /* end of xl loop */
2937}
2938
2939/* routine to scan system and determine nsolid (ph2) and nair (ph1) */
2940/* histograms based on values in phase and curvature arrays */
2941/* Calls no other routines */
2942/* Called by runsint */
2943void CemhydMatStatus :: sysscan(int ph1, int ph2)
2944{
2945 int xd, yd, zd, curvval;
2946
2947 /* Scan all pixels in 3-D system */
2948 for ( xd = 1; xd <= SYSSIZE; xd++ ) {
2949 for ( yd = 1; yd <= SYSSIZE; yd++ ) {
2950 for ( zd = 1; zd <= SYSSIZE; zd++ ) {
2951 curvval = curvature [ xd ] [ yd ] [ zd ];
2952
2953 if ( mask [ xd ] [ yd ] [ zd ] == ph2 ) {
2954 nair [ curvval ] += 1;
2955 } else if ( mask [ xd ] [ yd ] [ zd ] == ph1 ) {
2956 nsolid [ curvval ] += 1;
2957 }
2958 }
2959 }
2960 }
2961}
2962
2963/* routine to return how many cells of solid curvature histogram to use */
2964/* to accomodate nsearch pixels moving */
2965/* want to use highest values first */
2966/* Calls no other routines */
2967/* Called by movepix */
2968int CemhydMatStatus :: procsol(int nsearch)
2969{
2970 int valfound, i, stop;
2971 long int nsofar;
2972
2973 /* search histogram from top down until cumulative count */
2974 /* exceeds nsearch */
2975 valfound = nsph - 1;
2976 nsofar = 0;
2977 stop = 0;
2978 for ( i = ( nsph - 1 ); ( ( i >= 0 ) && ( stop == 0 ) ); i-- ) {
2979 nsofar += nsolid [ i ];
2980 if ( nsofar > nsearch ) {
2981 valfound = i;
2982 stop = 1;
2983 }
2984 }
2985
2986 return ( valfound );
2987}
2988
2989/* routine to determine how many cells of air curvature histogram to use */
2990/* to accomodate nsearch moving pixels */
2991/* want to use lowest values first */
2992/* Calls no other routines */
2993/* Called by movepix */
2994
2995int CemhydMatStatus :: procair(int nsearch)
2996{
2997 int valfound, i, stop;
2998 long int nsofar;
2999
3000 /* search histogram from bottom up until cumulative count */
3001 /* exceeds nsearch */
3002 valfound = 0;
3003 nsofar = 0;
3004 stop = 0;
3005 for ( i = 0; ( ( i < nsph ) && ( stop == 0 ) ); i++ ) {
3006 nsofar += nair [ i ];
3007 if ( nsofar > nsearch ) {
3008 valfound = i;
3009 stop = 1;
3010 }
3011 }
3012
3013 return ( valfound );
3014}
3015
3016/* routine to move requested number of pixels (ntomove) from highest */
3017/* curvature phase 1 (ph1) sites to lowest curvature phase 2 (ph2) sites */
3018/* Calls procsol and procair */
3019/* Called by runsint */
3020int CemhydMatStatus :: movepix(int ntomove, int ph1, int ph2)
3021{
3022 int count1, count2, ntot, countc, i, xp, yp, zp;
3023 int cmin, cmax, cfg;
3024 int alldone;
3025 long int nsolc, nairc, nsum, nsolm, nairm, nst1, nst2, next1, next2;
3026 float pck, plsol, plair;
3027
3028 alldone = 0;
3029 /* determine critical values for removal and placement */
3030 count1 = procsol(ntomove);
3031 nsum = 0;
3032 cfg = 0;
3033 cmax = count1;
3034 for ( i = nsph; i > count1; i-- ) {
3035 if ( ( nsolid [ i ] > 0 ) && ( cfg == 0 ) ) {
3036 cfg = 1;
3037 cmax = i;
3038 }
3039
3040 nsum += nsolid [ i ];
3041 }
3042
3043 /* Determine movement probability for last cell */
3044 plsol = ( float ) ( ntomove - nsum ) / ( float ) nsolid [ count1 ];
3045 next1 = ntomove - nsum;
3046 nst1 = nsolid [ count1 ];
3047
3048 count2 = procair(ntomove);
3049 nsum = 0;
3050 cmin = count2;
3051 cfg = 0;
3052 for ( i = 0; i < count2; i++ ) {
3053 if ( ( nair [ i ] > 0 ) && ( cfg == 0 ) ) {
3054 cfg = 1;
3055 cmin = i;
3056 }
3057
3058 nsum += nair [ i ];
3059 }
3060
3061 /* Determine movement probability for last cell */
3062 plair = ( float ) ( ntomove - nsum ) / ( float ) nair [ count2 ];
3063 next2 = ntomove - nsum;
3064 nst2 = nair [ count2 ];
3065
3066 /* Check to see if equilibrium has been reached --- */
3067 /* no further increase in hydraulic radius is possible */
3068 if ( cmin >= cmax ) {
3069 alldone = 1;
3070 printf("Stopping - at equilibrium \n");
3071 printf("cmin- %d cmax- %d \n", cmin, cmax);
3072 return ( alldone );
3073 }
3074
3075 /* initialize counters for performing sintering */
3076 ntot = 0;
3077 nsolc = 0;
3078 nairc = 0;
3079 nsolm = 0;
3080 nairm = 0;
3081
3082 /* Now process each pixel in turn */
3083 for ( xp = 1; xp <= SYSSIZE; xp++ ) {
3084 for ( yp = 1; yp <= SYSSIZE; yp++ ) {
3085 for ( zp = 1; zp <= SYSSIZE; zp++ ) {
3086 countc = curvature [ xp ] [ yp ] [ zp ];
3087 /* handle phase 1 case first */
3088 if ( mask [ xp ] [ yp ] [ zp ] == ph1 ) {
3089 if ( countc > count1 ) {
3090 /* convert from phase 1 to phase 2 */
3091 mask [ xp ] [ yp ] [ zp ] = ph2;
3092
3093 /* update appropriate histogram cells */
3094 nsolid [ countc ] -= 1;
3095 nair [ countc ] += 1;
3096 /* store the location of the modified pixel */
3097 ntot += 1;
3098 }
3099
3100 if ( countc == count1 ) {
3101 nsolm += 1;
3102 /* generate probability for pixel being removed */
3103 pck = ran1(seed);
3104 if ( ( pck < 0 ) || ( pck > 1.0 ) ) {
3105 pck = 1.0;
3106 }
3107
3108 if ( ( ( pck < plsol ) && ( nsolc < next1 ) ) || ( ( nst1 - nsolm ) < ( next1 - nsolc ) ) ) {
3109 nsolc += 1;
3110 /* convert phase 1 pixel to phase 2 */
3111 mask [ xp ] [ yp ] [ zp ] = ph2;
3112
3113 /* update appropriate histogram cells */
3114 nsolid [ count1 ] -= 1;
3115 nair [ count1 ] += 1;
3116 /* store the location of the modified pixel */
3117 ntot += 1;
3118 }
3119 }
3120 }
3121 /* handle phase 2 case here */
3122 else if ( mask [ xp ] [ yp ] [ zp ] == ph2 ) {
3123 if ( countc < count2 ) {
3124 /* convert phase 2 pixel to phase 1 */
3125 mask [ xp ] [ yp ] [ zp ] = ph1;
3126
3127 nsolid [ countc ] += 1;
3128 nair [ countc ] -= 1;
3129 ntot += 1;
3130 }
3131
3132 if ( countc == count2 ) {
3133 nairm += 1;
3134 pck = ran1(seed);
3135 if ( ( pck < 0 ) || ( pck > 1.0 ) ) {
3136 pck = 1.0;
3137 }
3138
3139 if ( ( ( pck < plair ) && ( nairc < next2 ) ) || ( ( nst2 - nairm ) < ( next2 - nairc ) ) ) {
3140 nairc += 1;
3141 /* convert phase 2 to phase 1 */
3142 mask [ xp ] [ yp ] [ zp ] = ph1;
3143
3144 nsolid [ count2 ] += 1;
3145 nair [ count2 ] -= 1;
3146 ntot += 1;
3147 }
3148 }
3149 }
3150 }
3151
3152 /* end of zp loop */
3153 }
3154
3155 /* end of yp loop */
3156 }
3157
3158 /* end of xloop */
3159 printf("ntot is %d \n", ntot);
3160 return ( alldone );
3161}
3162
3163/* routine to execute user input number of cycles of sintering algorithm */
3164/* Calls maketemp, rhcalc, sysinit, sysscan, and movepix */
3165/* Called by main routine */
3166void CemhydMatStatus :: sinter3d(int ph1id, int ph2id, float rhtarget)
3167{
3168 int natonce, i, rade, j, rflag;
3169 int keepgo;
3170 long int curvsum1, curvsum2, pixsum1, pixsum2;
3171 float rhnow, avecurv1, avecurv2;
3172
3173 /* initialize the solid and air count histograms */
3174 for ( i = 0; i <= 499; i++ ) {
3175 nsolid [ i ] = 0;
3176 nair [ i ] = 0;
3177 }
3178
3179 /* Obtain needed user input */
3180 natonce = 200;
3181 rade = 3;
3182 rflag = 0; /* always initialize system */
3183
3184 nsph = maketemp(rade);
3185 printf("nsph is %d \n", nsph);
3186 if ( rflag == 0 ) {
3187 sysinit(ph1id, ph2id);
3188 } else {
3189 sysscan(ph1id, ph2id);
3190 }
3191
3192 i = 0;
3193 rhnow = rhcalc(ph1id);
3194 while ( ( rhnow < rhtarget ) && ( i < MAXCYC_SEAL ) ) {
3195 printf("Now: %f Target: %f \n", rhnow, rhtarget);
3196 i += 1;
3197#ifdef PRINTF
3198 printf("Cycle: %d \n", i);
3199#endif
3200 keepgo = movepix(natonce, ph1id, ph2id);
3201 /* If equilibrium is reached, then return to calling routine */
3202 if ( keepgo == 1 ) {
3203 return;
3204 }
3205
3206 curvsum1 = 0;
3207 curvsum2 = 0;
3208 pixsum1 = 0;
3209 pixsum2 = 0;
3210 /* Determine average curvatures for phases 1 and 2 */
3211 for ( j = 0; j <= nsph; j++ ) {
3212 pixsum1 += nsolid [ j ];
3213 curvsum1 += ( j * nsolid [ j ] );
3214 pixsum2 += nair [ j ];
3215 curvsum2 += ( j * nair [ j ] );
3216 }
3217
3218 avecurv1 = ( float ) curvsum1 / ( float ) pixsum1;
3219 avecurv2 = ( float ) curvsum2 / ( float ) pixsum2;
3220 printf("Ave. solid curvature: %f \n", avecurv1);
3221 printf("Ave. air curvature: %f \n", avecurv2);
3222 rhnow = rhcalc(ph1id);
3223 }
3224}
3225
3226void CemhydMatStatus :: stat3d()
3227{
3228 int valin, ix, iy, iz;
3229 int ix1, iy1, iz1, k;
3230 long int voltot, surftot;
3231
3232 for ( ix = 0; ix <= 42; ix++ ) {
3233 volume [ ix ] = surface [ ix ] = 0;
3234 }
3235
3236 /* Read in image and accumulate volume totals */
3237 for ( iz = 1; iz <= SYSIZE; iz++ ) {
3238 for ( iy = 1; iy <= SYSIZE; iy++ ) {
3239 for ( ix = 1; ix <= SYSIZE; ix++ ) {
3240 valin = mask [ ix ] [ iy ] [ iz ];
3241 volume [ valin ] += 1;
3242 }
3243 }
3244 }
3245
3246
3247 for ( iz = 1; iz <= SYSIZE; iz++ ) {
3248 for ( iy = 1; iy <= SYSIZE; iy++ ) {
3249 for ( ix = 1; ix <= SYSIZE; ix++ ) {
3250 if ( mask [ ix ] [ iy ] [ iz ] != 0 ) {
3251 valin = mask [ ix ] [ iy ] [ iz ];
3252 /* Check six neighboring pixels for porosity */
3253 for ( k = 1; k <= 6; k++ ) {
3254 switch ( k ) {
3255 case 1:
3256 ix1 = ix - 1;
3257 if ( ix1 < 1 ) {
3258 ix1 += SYSIZE;
3259 }
3260
3261 iy1 = iy;
3262 iz1 = iz;
3263 break;
3264 case 2:
3265 ix1 = ix + 1;
3266 if ( ix1 > SYSIZE ) {
3267 ix1 -= SYSIZE;
3268 }
3269
3270 iy1 = iy;
3271 iz1 = iz;
3272 break;
3273 case 3:
3274 iy1 = iy - 1;
3275 if ( iy1 < 1 ) {
3276 iy1 += SYSIZE;
3277 }
3278
3279 ix1 = ix;
3280 iz1 = iz;
3281 break;
3282 case 4:
3283 iy1 = iy + 1;
3284 if ( iy1 > SYSIZE ) {
3285 iy1 -= SYSIZE;
3286 }
3287
3288 ix1 = ix;
3289 iz1 = iz;
3290 break;
3291 case 5:
3292 iz1 = iz - 1;
3293 if ( iz1 < 1 ) {
3294 iz1 += SYSIZE;
3295 }
3296
3297 iy1 = iy;
3298 ix1 = ix;
3299 break;
3300 case 6:
3301 iz1 = iz + 1;
3302 if ( iz1 > SYSIZE ) {
3303 iz1 -= SYSIZE;
3304 }
3305
3306 iy1 = iy;
3307 ix1 = ix;
3308 break;
3309 default:
3310 break;
3311 }
3312
3313 if ( ( ix1 < 1 ) || ( iy1 < 1 ) || ( iz1 < 1 ) || ( ix1 > SYSIZE ) || ( iy1 > SYSIZE ) || ( iz1 > SYSIZE ) ) {
3314 printf("%d %d %d \n", ix1, iy1, iz1);
3315 exit(1);
3316 }
3317
3318 if ( mask [ ix1 ] [ iy1 ] [ iz1 ] == 0 ) {
3319 surface [ valin ] += 1;
3320 }
3321 }
3322 }
3323 }
3324 }
3325 }
3326
3327#ifdef PRINTF
3328 printf("Phase Volume Surface Volume Surface \n");
3329 printf(" ID count count fraction fraction \n");
3330#endif
3331 /* Only include clinker phases in surface area fraction calculation */
3332 surftot = surface [ 1 ] + surface [ 2 ] + surface [ 3 ] + surface [ 4 ];
3333 voltot = volume [ 1 ] + volume [ 2 ] + volume [ 3 ] + volume [ 4 ];
3334 k = 0;
3335#ifdef PRINTF
3336 printf(" %d %8ld %8ld \n", k, volume [ 0 ], surface [ 0 ]);
3337
3338 for ( k = 1; k <= 4; k++ ) {
3339 printf(" %d %8ld %8ld %.5f %.5f\n", k, volume [ k ], surface [ k ],
3340 ( float ) volume [ k ] / ( float ) voltot, ( float ) surface [ k ] / ( float ) surftot);
3341 }
3342
3343 printf("Total %8ld %8ld\n\n\n", voltot, surftot);
3344
3345 for ( k = 5; k <= 11; k++ ) {
3346 printf(" %d %8ld %8ld\n", k, volume [ k ], surface [ k ]);
3347 }
3348
3349 printf(" 20 %8ld %8ld\n", volume [ 20 ], surface [ 20 ]);
3350
3351 for ( k = 24; k <= 27; k++ ) {
3352 printf(" %d %8ld %8ld\n", k, volume [ k ], surface [ k ]);
3353 }
3354
3355 printf(" 28 %8ld %8ld\n", volume [ 28 ], surface [ 28 ]);
3356#endif
3357 ( void ) surftot;
3358 ( void ) voltot;
3359}
3360
3361void CemhydMatStatus :: rand3d(int phasein, int phaseout, float xpt)
3362{
3363 float s2, ss, sdiff, xtmp, ytmp;
3364 //static float normm[SYSIZE+1][SYSIZE+1][SYSIZE+1];
3365 //static float res[SYSIZE+1][SYSIZE+1][SYSIZE+1];
3366 double ***normm, ***res;
3367 //static float filter [32][32][32];
3368 double ***filter;
3369 int done, r [ 61 ];
3370 //static float s[61],xr[61],sum[502];
3371 float *s, *xr, *sum;
3372 double val2;
3373 double t1, t2, x1, x2, u1, u2, xrad, resmax, resmin;
3374 float xtot, filval, radius, sect, sumtot, vcrit;
3375 int valin, r1, r2, i1, i2, i3, i, j, k, j1, k1;
3376 int ido, iii, jjj, ix, iy, iz, index;
3377#ifdef CMLFILE
3378 char tempstr [ 256 ];
3379#endif
3380
3381 alloc_double_3D(normm, SYSIZE + 1);
3382 alloc_double_3D(res, SYSIZE + 1);
3383 alloc_double_3D(filter, 32);
3384
3385 s = new float [ 61 ];
3386 xr = new float [ 61 ];
3387 sum = new float [ 502 ];
3388
3389 /* Create the Gaussian noise image */
3390 i1 = i2 = i3 = 1;
3391 for ( i = 1; i <= ( ( SYSIZE * SYSIZE * SYSIZE ) / 2 ); i++ ) {
3392 u1 = ran1(seed);
3393 u2 = ran1(seed);
3394 t1 = 2. * M_PI * u2;
3395 t2 = sqrt( -2. * log(u1) );
3396 x1 = cos(t1) * t2;
3397 x2 = sin(t1) * t2;
3398 normm [ i1 ] [ i2 ] [ i3 ] = x1;
3399 i1 += 1;
3400 if ( i1 > SYSIZE ) {
3401 i1 = 1;
3402 i2 += 1;
3403 if ( i2 > SYSIZE ) {
3404 i2 = 1;
3405 i3 += 1;
3406 }
3407 }
3408
3409 normm [ i1 ] [ i2 ] [ i3 ] = x2;
3410 i1 += 1;
3411 if ( i1 > SYSIZE ) {
3412 i1 = 1;
3413 i2 += 1;
3414 if ( i2 > SYSIZE ) {
3415 i2 = 1;
3416 i3 += 1;
3417 }
3418 }
3419 }
3420
3421 /* Now perform the convolution */
3422#ifdef CMLFILE
3423 F->get_next_line_in_section(0, ( long & )ido);
3424#endif
3425 //fscanf(in,"%d",&ido);
3426#ifdef TINYXML
3427 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, ido);
3428#endif
3429
3430#ifdef PRINTF
3431 printf("Number of points in correlation file is %d \n", ido);
3432#endif
3433
3434 for ( i = 1; i <= ido; i++ ) {
3435#ifdef CMLFILE
3436 F->get_next_line_in_section(0, tempstr);
3437 sscanf(tempstr, "%d %f", & valin, & val2);
3438#endif
3439#ifdef TINYXML
3440 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, valin);
3441 QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, val2);
3442#endif
3443 //fscanf(in,"%d %f",&valin,&val2);
3444 r [ i ] = valin;
3445 s [ i ] = ( float ) val2;
3446 xr [ i ] = ( float ) r [ i ];
3447 }
3448
3449 ss = s [ 1 ];
3450 s2 = ss * ss;
3451 /* Load up the convolution matrix */
3452 sdiff = ss - s2;
3453 for ( i = 0; i < 31; i++ ) {
3454 iii = i * i;
3455 for ( j = 0; j < 31; j++ ) {
3456 jjj = j * j;
3457 for ( k = 0; k < 31; k++ ) {
3458 xtmp = ( float ) ( iii + jjj + k * k );
3459 radius = sqrt(xtmp);
3460 r1 = ( int ) radius + 1;
3461 r2 = r1 + 1;
3462 if ( s [ r1 ] < 0.0 ) {
3463 printf("%d and %d %f and %f with xtmp of %f\n", r1, r2, s [ r1 ], s [ r2 ], xtmp);
3464 fflush(stdout);
3465 exit(1);
3466 }
3467
3468 xrad = radius + 1 - r1;
3469 filval = s [ r1 ] + ( s [ r2 ] - s [ r1 ] ) * xrad;
3470 filter [ i + 1 ] [ j + 1 ] [ k + 1 ] = ( filval - s2 ) / sdiff;
3471 }
3472 }
3473 }
3474
3475 /* Now filter the image maintaining periodic boundaries */
3476 /*fixed for periodic boundaries (small microstructures) - smilauer 4.12.2006*/
3477 resmax = 0.0;
3478 resmin = 1.0;
3479 for ( i = 1; i <= SYSIZE; i++ ) {
3480 for ( j = 1; j <= SYSIZE; j++ ) {
3481 for ( k = 1; k <= SYSIZE; k++ ) {
3482 res [ i ] [ j ] [ k ] = 0.0;
3483 if ( ( float ) mask [ i ] [ j ] [ k ] == phasein ) {
3484 for ( ix = 1; ix <= 31; ix++ ) {
3485 i1 = i + ix - 1;
3486 while ( i1 < 1 ) { //if(i1<1){i1+=SYSIZE;}
3487 i1 += SYSIZE;
3488 }
3489
3490 while ( i1 > SYSIZE ) { //else if(i1>SYSIZE){
3491 i1 -= SYSIZE;
3492 }
3493
3494 for ( iy = 1; iy <= 31; iy++ ) {
3495 j1 = j + iy - 1;
3496 while ( j1 < 1 ) { //if(j1<1){j1+=SYSIZE;}
3497 j1 += SYSIZE;
3498 }
3499
3500 while ( j1 > SYSIZE ) { //else if(j1>SYSIZE){
3501 j1 -= SYSIZE;
3502 }
3503
3504 for ( iz = 1; iz <= 31; iz++ ) {
3505 k1 = k + iz - 1;
3506 while ( k1 < 1 ) { //if(k1<1){k1+=SYSIZE;}
3507 k1 += SYSIZE;
3508 }
3509
3510 while ( k1 > SYSIZE ) { //else if(k1>SYSIZE){
3511 k1 -= SYSIZE;
3512 }
3513
3514 res [ i ] [ j ] [ k ] += normm [ i1 ] [ j1 ] [ k1 ] * filter [ ix ] [ iy ] [ iz ];
3515 }
3516 }
3517 }
3518
3519 if ( res [ i ] [ j ] [ k ] > resmax ) {
3520 resmax = res [ i ] [ j ] [ k ];
3521 }
3522
3523 if ( res [ i ] [ j ] [ k ] < resmin ) {
3524 resmin = res [ i ] [ j ] [ k ];
3525 }
3526 }
3527 }
3528
3529#ifdef PRINTF
3530 printf(".");
3531#endif
3532 }
3533
3534#ifdef PRINTF
3535 printf("%d out of %d\n", i, SYSIZE);
3536#endif
3537 }
3538
3539#ifdef PRINTF
3540 printf("\n");
3541#endif
3542 /* Now threshold the image */
3543 sect = ( resmax - resmin ) / 500.;
3544 for ( i = 1; i <= 500; i++ ) {
3545 sum [ i ] = 0.0;
3546 }
3547
3548 xtot = 0.0;
3549 for ( i = 1; i <= SYSIZE; i++ ) {
3550 for ( j = 1; j <= SYSIZE; j++ ) {
3551 for ( k = 1; k <= SYSIZE; k++ ) {
3552 if ( ( float ) mask [ i ] [ j ] [ k ] == phasein ) {
3553 xtot += 1.0;
3554 index = 1 + ( int ) ( ( res [ i ] [ j ] [ k ] - resmin ) / sect );
3555 if ( index > 500 ) {
3556 index = 500;
3557 }
3558
3559 sum [ index ] += 1.0;
3560 }
3561 }
3562 }
3563 }
3564
3565 /* Determine which bin to choose for correct thresholding */
3566 sumtot = vcrit = 0.0;
3567 done = 0;
3568 for ( i = 1; ( ( i <= 500 ) && ( done == 0 ) ); i++ ) {
3569 sumtot += sum [ i ] / xtot;
3570 if ( sumtot > xpt ) {
3571 ytmp = ( float ) i;
3572 vcrit = resmin + ( resmax - resmin ) * ( ytmp - 0.5 ) / 500.;
3573 done = 1;
3574 }
3575 }
3576
3577#ifdef PRINTF
3578 printf("Critical volume fraction is %f\n", vcrit);
3579#endif
3580
3581 for ( k = 1; k <= SYSIZE; k++ ) {
3582 for ( j = 1; j <= SYSIZE; j++ ) {
3583 for ( i = 1; i <= SYSIZE; i++ ) {
3584 if ( ( float ) mask [ i ] [ j ] [ k ] == phasein ) {
3585 if ( res [ i ] [ j ] [ k ] > vcrit ) {
3586 mask [ i ] [ j ] [ k ] = phaseout;
3587 }
3588 }
3589 }
3590 }
3591 }
3592
3593 dealloc_double_3D(normm, SYSIZE + 1);
3594 dealloc_double_3D(res, SYSIZE + 1);
3595 dealloc_double_3D(filter, 32);
3596
3597 delete [] s;
3598 delete [] xr;
3599 delete [] sum;
3600}
3601
3602
3603/*disabled sintering*/
3604void CemhydMatStatus :: distrib3d()
3605{
3606 int i, j, k, alumval, alum2, valin;
3607 int output_img;
3608 double volin, volf [ 5 ], surff [ 5 ], rhtest, rdesire;
3609 char filen [ 80 ];
3610 //char fileout[80],filecem[80]
3611 FILE *infile;
3612 FILE *outfile_img = NULL, *outfile_id = NULL;
3613
3615
3616 /* Seed the random number generator */
3617 //printf("Enter random number seed (negative integer) \n");
3618 //fscanf(in, "%d",&nseed);
3619 //printf("%d\n",nseed);
3620 nseed = iseed;
3621#ifdef PRINTF
3622 printf("%d\n", * seed);
3623#endif
3624
3625 /* Read in the parameters to use */
3626 //printf("Enter name of cement microstructure image file\n");
3627 //fscanf(in, "%s",filen);
3628 //printf("%s\n",filen);
3629
3630
3631 /* Set up the correlation filenames
3632 * printf("Enter name of sil correlation files\n");
3633 * fscanf(in, "%s",filesil);
3634 * printf("%s\n",filesil);
3635 * printf("Enter name of c3s correlation files\n");
3636 * fscanf(in, "%s",filec3s);
3637 * printf("%s\n",filec3s);
3638 * printf("Enter name of c4af correlation files\n");
3639 * fscanf(in, "%s",filealum);
3640 * printf("%s\n",filealum);
3641 */
3642
3643 alumval = 4;
3644
3645 //assume always C4AF
3646 /*
3647 * testfile=fopen(filealum,"r");
3648 * if(testfile==NULL){
3649 * alumflag=0;
3650 * sprintf(filealum,"%s",filecem);
3651 * strcat(filealum,".c3a");
3652 * alumval=3;
3653 * }
3654 * else{
3655 * fclose(testfile);
3656 * }
3657 */
3658 //printf("Enter name of new cement microstructure image file\n");
3659 //fscanf(in, "%s",fileout);
3660 // printf("%s\n",fileout);
3661 for ( i = 1; i <= 4; i++ ) {
3662#ifdef CMLFILE
3663 F->get_next_line_in_section(0, volin);
3664#endif
3665#ifdef TINYXML
3666 if ( i == 1 ) {
3667 QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C3S_unit_frac", volin);
3668 }
3669
3670 if ( i == 2 ) {
3671 QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C2S_unit_frac", volin);
3672 }
3673
3674 if ( i == 3 ) {
3675 QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C3A_unit_frac", volin);
3676 }
3677
3678 if ( i == 4 ) {
3679 QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C4AF_unit_frac", volin);
3680 }
3681
3682#endif
3683 //fscanf(in, "%f",&volin);
3684 volf [ i ] = volin;
3685#ifdef PRINTF
3686 printf("Volume %f\n", volf [ i ]);
3687#endif
3688 //fscanf(in, "%f",&volin);
3689 surff [ i ] = volin;
3690#ifdef PRINTF
3691 printf("Surface %f\n", surff [ i ]);
3692#endif
3693 }
3694
3695 /* Read in the original microstructure image file */
3696 if ( ( infile = fopen(filen, "r") ) != NULL ) {
3697 for ( k = 1; k <= SYSIZE; k++ ) {
3698 for ( j = 1; j <= SYSIZE; j++ ) {
3699 for ( i = 1; i <= SYSIZE; i++ ) {
3700 if ( fscanf(infile, "%d", & valin) != 1 ) {
3701 OOFEM_ERROR("distrib3d reading error");
3702 }
3703
3704 mask [ i ] [ j ] [ k ] = valin;
3705 curvature [ i ] [ j ] [ k ] = 0;
3706 }
3707 }
3708 }
3709
3710 fclose(infile);
3711 } else {
3712 for ( k = 1; k <= SYSIZE; k++ ) {
3713 for ( j = 1; j <= SYSIZE; j++ ) {
3714 for ( i = 1; i <= SYSIZE; i++ ) {
3715 mask [ i ] [ j ] [ k ] = cemreal [ i ] [ j ] [ k ];
3716 }
3717 }
3718 }
3719 }
3720
3721 stat3d();
3722
3723 /* First filtering */
3724 volin = volf [ 1 ] + volf [ 2 ];
3725 if ( volin < 1.0 ) {
3726 rand3d(1, alumval, volin);
3727
3728 /* First sintering */
3729 stat3d();
3730 rdesire = ( surff [ 1 ] + surff [ 2 ] ) * ( float ) ( surface [ 1 ] + surface [ alumval ] );
3731 if ( rdesire != 0.0 ) {
3732 if ( ( int ) rdesire < surface [ 1 ] ) {
3733 rhtest = ( 6. / 4. ) * ( float ) ( volume [ 1 ] ) / rdesire;
3734 //sinter3d(1,alumval,rhtest);
3735 } else {
3736 rdesire = ( surff [ 3 ] + surff [ 4 ] ) * ( float ) ( surface [ 1 ] + surface [ alumval ] );
3737 if ( rdesire != 0.0 ) {
3738 rhtest = ( 6. / 4. ) * ( float ) ( volume [ alumval ] ) / rdesire;
3739 //sinter3d(alumval,1,rhtest);
3740 }
3741 }
3742 }
3743 }
3744
3745 /* Second filtering */
3746 if ( ( volf [ 1 ] + volf [ 2 ] ) > 0.0 ) {
3747 volin = volf [ 1 ] / ( volf [ 1 ] + volf [ 2 ] );
3748 if ( volin < 1.0 ) {
3749 rand3d(1, 2, volin);
3750
3751 /* Second sintering */
3752 stat3d();
3753 rdesire = ( surff [ 1 ] / ( surff [ 1 ] + surff [ 2 ] ) ) * ( float ) ( surface [ 1 ] + surface [ 2 ] );
3754 if ( rdesire != 0.0 ) {
3755 if ( ( int ) rdesire < surface [ 1 ] ) {
3756 rhtest = ( 6. / 4. ) * ( float ) ( volume [ 1 ] ) / rdesire;
3757 //sinter3d(1,2,rhtest);
3758 } else {
3759 rdesire = ( surff [ 2 ] / ( surff [ 1 ] + surff [ 2 ] ) ) * ( float ) ( surface [ 1 ] + surface [ 2 ] );
3760 if ( rdesire != 0.0 ) {
3761 rhtest = ( 6. / 4. ) * ( float ) ( volume [ 2 ] ) / rdesire;
3762 //sinter3d(2,1,rhtest);
3763 }
3764 }
3765 }
3766 }
3767 }
3768
3769 /* Third (final) filtering */
3770 if ( alumval == 4 ) {
3771 volin = volf [ 4 ] / ( volf [ 4 ] + volf [ 3 ] );
3772 alum2 = 3;
3773 } else {
3774 volin = volf [ 3 ] / ( volf [ 4 ] + volf [ 3 ] );
3775 alum2 = 4;
3776 }
3777
3778 if ( volin < 1.0 ) {
3779 rand3d(alumval, alum2, volin);
3780
3781 /* Third (final) sintering */
3782 stat3d();
3783 if ( alumval == 4 ) {
3784 rdesire = ( surff [ 4 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3785 if ( rdesire != 0.0 ) {
3786 if ( ( int ) rdesire < surface [ 4 ] ) {
3787 rhtest = ( 6. / 4. ) * ( float ) ( volume [ 4 ] ) / rdesire;
3788 //sinter3d(alumval,alum2,rhtest);
3789 } else {
3790 rdesire = ( surff [ 3 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3791 if ( rdesire != 0.0 ) {
3792 rhtest = ( 6. / 4. ) * ( float ) ( volume [ 3 ] ) / rdesire;
3793 //sinter3d(alum2,alumval,rhtest);
3794 }
3795 }
3796 }
3797 } else {
3798 rdesire = ( surff [ 3 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3799 if ( rdesire != 0.0 ) {
3800 if ( ( int ) rdesire < surface [ 3 ] ) {
3801 rhtest = ( 6. / 4. ) * ( float ) ( volume [ 3 ] ) / rdesire;
3802 //sinter3d(alumval,alum2,rhtest);
3803 } else {
3804 rdesire = ( surff [ 4 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3805 if ( rdesire != 0.0 ) {
3806 rhtest = ( 6. / 4. ) * ( float ) ( volume [ 4 ] ) / rdesire;
3807 //sinter3d(alum2,alumval,rhtest);
3808 }
3809 }
3810 }
3811 }
3812 }
3813
3814 /* Output final microstructure */
3815
3816 //check whether to save it into img and id files
3817#ifdef CMLFILE
3818 F->get_value(14, ( long & )output_img);
3819#endif
3820#ifdef TINYXML
3821 QueryNumAttributeExt(xmlFile, "Output_initial_microstructure", 0, output_img);
3822#endif
3823
3824
3825 if ( output_img ) {
3826#ifdef CMLFILE
3827 F->get_value(15, filen);
3828#endif
3829#ifdef TINYXML
3830 QueryStringAttributeExt(xmlFile, "Output_initial_microstructure_img_file", 0, filen);
3831#endif
3832 if ( ( outfile_img = fopen(filen, "w") ) == NULL ) {
3833 printf("Output img file %s can not be created (file %s, line %d)\n", filen, __FILE__, __LINE__);
3834 exit(1);
3835 }
3836
3837#ifdef CMLFILE
3838 F->get_value(16, filen);
3839#endif
3840#ifdef TINYXML
3841 QueryStringAttributeExt(xmlFile, "Output_initial_microstructure_id_file", 0, filen);
3842#endif
3843 if ( ( outfile_id = fopen(filen, "w") ) == NULL ) {
3844 printf("Output id file %s can not be created (file %s, line %d)\n", filen, __FILE__, __LINE__);
3845 exit(1);
3846 }
3847 }
3848
3849 for ( k = 0; k < SYSIZE; k++ ) {
3850 for ( j = 0; j < SYSIZE; j++ ) {
3851 for ( i = 0; i < SYSIZE; i++ ) {
3852 mic [ i ] [ j ] [ k ] = mask [ i + 1 ] [ j + 1 ] [ k + 1 ];
3853 micorig [ i ] [ j ] [ k ] = mic [ i ] [ j ] [ k ];
3854 if ( output_img ) {
3855 fprintf(outfile_img, "%d\n", mic [ i ] [ j ] [ k ]);
3856 fprintf(outfile_id, "%ld\n", micpart [ i ] [ j ] [ k ]);
3857 }
3858 }
3859 }
3860 }
3861
3862 if ( output_img ) {
3863 fclose(outfile_img);
3864 fclose(outfile_id);
3865 }
3866
3867 //deallocate curvature
3869
3870 //deallocate cemreal[][][]
3872 ( void ) rhtest;
3873}
3874
3875
3876/**********************************************************/
3877/*************DISREALNEW***********************************/
3878/**********************************************************/
3879
3880void CemhydMatStatus :: init()
3881{
3882 int i;
3883 double slagin, CHperslag;
3884 FILE *slagfile;
3885
3886 for ( i = 0; i <= EMPTYP; i++ ) {
3887 creates [ i ] = 0;
3888 soluble [ i ] = 0;
3889 disprob [ i ] = 0.0;
3890 disbase [ i ] = 0.0;
3891 pHeffect [ i ] = 0.0;
3892 }
3893
3894 /* soluble [x] - flag indicating if phase x is soluble */
3895 /* disprob [x] - probability of dissolution (relative diss. rate) */
3896 gypabsprob = 0.01; /* One sulfate absorbed per 100 CSH units */
3897 /* Source is from Taylor's Cement Chemistry for K and Na absorption */
3898 /* Note that for the first cycle, of the clinker phases only the */
3899 /* aluminates and gypsum are soluble */
3900 soluble [ C4AF ] = 1;
3901 disprob [ C4AF ] = disbase [ C4AF ] = 0.067 / DISBIAS;
3902 creates [ C4AF ] = POROSITY;
3903 pHeffect [ C4AF ] = 1.0;
3904 soluble [ C3S ] = 0;
3905 disprob [ C3S ] = disbase [ C3S ] = 0.7 / DISBIAS;
3906 creates [ C3S ] = DIFFCSH;
3907 pHeffect [ C3S ] = 1.0;
3908 soluble [ C2S ] = 0;
3909 disprob [ C2S ] = disbase [ C2S ] = 0.1 / DISBIAS;
3910 creates [ C2S ] = DIFFCSH;
3911 pHeffect [ C2S ] = 1.0;
3912 soluble [ C3A ] = 1;
3913 /* increased back to 0.4 from 0.25 7/8/99 */
3914 disprob [ C3A ] = disbase [ C3A ] = 0.4 / DISBIAS;
3915 creates [ C3A ] = POROSITY;
3916 pHeffect [ C3A ] = 1.0;
3917 soluble [ GYPSUM ] = 1;
3918 /* Changed from 0.05 to 0.015 9/29/98 */
3919 /* Changed to 0.040 10/15/98 */
3920 /* back to 0.05 from 0.10 7/8/99 */
3921 /* from 0.05 to 0.02 4/4/00 */
3922 /* from 0.02 to 0.025 8/13/01 */
3923 disprob [ GYPSUM ] = disbase [ GYPSUM ] = 0.025; /*geaendert am 04.04.00, urspr. 0.05*/
3924 /* dissolved gypsum distributed at random throughout microstructure */
3925 creates [ GYPSUM ] = POROSITY;
3926 soluble [ GYPSUMS ] = 1;
3927 pHeffect [ GYPSUM ] = 0.0;
3928 /* Changed from 0.05 to 0.015 9/29/98 */
3929 /* Changed to 0.020 10/15/98 */
3930 /* and also changed all sulfate based dissolution rates */
3931 disprob [ GYPSUMS ] = disbase [ GYPSUMS ] = disprob [ GYPSUM ];
3932 creates [ GYPSUMS ] = POROSITY;
3933 pHeffect [ GYPSUMS ] = 0.0;
3934 soluble [ ANHYDRITE ] = 1;
3935 /* set anhydrite dissolution at 4/5ths of that of gypsum */
3936 /* Source: Uchikawa et al., CCR, 1984 */
3937 disprob [ ANHYDRITE ] = disbase [ ANHYDRITE ] = 0.8 * disprob [ GYPSUM ];
3938 /* dissolved anhydrite distributed at random throughout microstructure */
3940 pHeffect [ ANHYDRITE ] = 0.0;
3941 soluble [ HEMIHYD ] = 1;
3942 /* set hemihydrate dissolution at 3 times that of gypsum */
3943 /* Source: Uchikawa et al., CCR, 1984 */
3944 /* Changed to 1.5 times that of gypsum 6/1/00 */
3945 disprob [ HEMIHYD ] = disbase [ HEMIHYD ] = 1.5 * disprob [ GYPSUM ]; /* ge�ndert am 01.06.00, urspr. 3.0 */
3946 /* dissolved hemihydrate distributed at random throughout microstructure */
3947 creates [ HEMIHYD ] = POROSITY;
3948 pHeffect [ HEMIHYD ] = 0.0;
3949 /* CH soluble to allow for Ostwald ripening of crystals */
3950 soluble [ CH ] = 1;
3951 disprob [ CH ] = disbase [ CH ] = 0.5 / DISBIAS;
3952 creates [ CH ] = DIFFCH;
3953 pHeffect [ CH ] = 0.0;
3954 /* CaCO3 is only mildly soluble */
3955 soluble [ CACO3 ] = 1;
3956 disprob [ CACO3 ] = disbase [ CACO3 ] = 0.10 / DISBIAS;
3957 creates [ CACO3 ] = DIFFCACO3;
3958 pHeffect [ CACO3 ] = 0.0;
3959 /* Slag is not truly soluble, but use its dissolution probability for reaction probability */
3960 soluble [ SLAG ] = 0;
3961 disprob [ SLAG ] = disbase [ SLAG ] = 0.005 / DISBIAS;
3962 creates [ SLAG ] = 0;
3963 pHeffect [ SLAG ] = 1.0;
3964 soluble [ C3AH6 ] = 1;
3965 disprob [ C3AH6 ] = disbase [ C3AH6 ] = 0.01 / DISBIAS; /* changed from 0.5 to 0.01 06.09.00 */
3966 creates [ C3AH6 ] = POROSITY;
3967 pHeffect [ C3AH6 ] = 0.0;
3968 /* Ettringite is initially insoluble */
3969 soluble [ ETTR ] = 0;
3970 /* Changed to 0.008 from 0.020 3/11/99 */
3971 disprob [ ETTR ] = disbase [ ETTR ] = 0.008 / DISBIAS;
3972 creates [ ETTR ] = DIFFETTR;
3973 pHeffect [ ETTR ] = 0.0;
3974 /* Iron-rich ettringite is always insoluble */
3975 soluble [ ETTRC4AF ] = 0;
3976 disprob [ ETTRC4AF ] = disbase [ ETTRC4AF ] = 0.0;
3978 pHeffect [ ETTRC4AF ] = 0.0;
3979 /* calcium chloride is soluble */
3980 soluble [ CACL2 ] = 1;
3981 disprob [ CACL2 ] = disbase [ CACL2 ] = 0.1 / DISBIAS;
3982 creates [ CACL2 ] = DIFFCACL2;
3983 pHeffect [ CACL2 ] = 0.0;
3984 /* aluminosilicate glass is soluble */
3985 soluble [ ASG ] = 1;
3986 disprob [ ASG ] = disbase [ ASG ] = 0.2 / DISBIAS;
3987 creates [ ASG ] = DIFFAS;
3988 pHeffect [ ASG ] = 1.0;
3989 /* calcium aluminodisilicate is soluble */
3990 soluble [ CAS2 ] = 1;
3991 disprob [ CAS2 ] = disbase [ CAS2 ] = 0.2 / DISBIAS;
3992 creates [ CAS2 ] = DIFFCAS2;
3993 pHeffect [ CAS2 ] = 1.0;
3994
3995 /* establish molar volumes and heats of formation */
3996 /* molar volumes are in cm^3/mole */
3997 /* heats of formation are in kJ/mole */
3998 /* See paper by Fukuhara et al., Cem. & Conc. Res., 11, 407-14, 1981. */
3999 /* values for Porosity are those of water */
4000 molarv [ POROSITY ] = 18.068;
4001 heatf [ POROSITY ] = ( -285.83 );
4002 waterc [ POROSITY ] = 1.0;
4003 specgrav [ POROSITY ] = 0.99707;
4004
4005 molarv [ C3S ] = 71.129;
4006 heatf [ C3S ] = ( -2927.82 );
4007 waterc [ C3S ] = 0.0;
4008 specgrav [ C3S ] = 3.21;
4009 /* For improvement in chemical shrinkage correspondence */
4010 /* Changed molar volume of C(1.7)-S-H(4.0) to 108 5/24/95 */
4011 molarv [ CSH ] = 108.;
4012 heatf [ CSH ] = ( -3283.0 );
4013 waterc [ CSH ] = 4.0;
4014 specgrav [ CSH ] = 2.11;
4015
4016 molarv [ CH ] = 33.1;
4017 heatf [ CH ] = ( -986.1 );
4018 waterc [ CH ] = 1.0;
4019 specgrav [ CH ] = 2.24;
4020
4021 //uncomment to have the same values as in Pignat's thesis
4022 /*
4023 * molarv[C3S]=72.381;//changed 18.5.05
4024 * specgrav[C3S]=3.15;//changed 18.5.05
4025 * molarv[CSH]=113.5;//changed 18.5.05
4026 * specgrav[CSH]=2.0;//changed 18.5.05
4027 * molarv[CH]=33.036;//changed 18.5.05
4028 */
4029
4030 /* Assume that calcium carbonate is in the calcite form */
4031 molarv [ CACO3 ] = 36.93;
4032 waterc [ CACO3 ] = 0.0;
4033 specgrav [ CACO3 ] = 2.71;
4034 heatf [ CACO3 ] = ( -1206.92 );
4035
4036 molarv [ AFMC ] = 261.91;
4037 waterc [ AFMC ] = 11.0;
4038 specgrav [ AFMC ] = 2.17;
4039 /* Need to fill in heat of formation at a later date */
4040 heatf [ AFMC ] = ( 0.0 );
4041
4042 molarv [ C2S ] = 52.513;
4043 heatf [ C2S ] = ( -2311.6 );
4044 waterc [ C2S ] = 0.0;
4045 specgrav [ C2S ] = 3.28;
4046
4047 molarv [ C3A ] = 88.94;
4048 heatf [ C3A ] = ( -3587.8 );
4049 waterc [ C3A ] = 0.0;
4050 specgrav [ C3A ] = 3.038;
4051
4052 molarv [ GYPSUM ] = 74.21;
4053 heatf [ GYPSUM ] = ( -2022.6 );
4054 waterc [ GYPSUM ] = 0.0;
4055 specgrav [ GYPSUM ] = 2.32;
4056 molarv [ GYPSUMS ] = 74.21;
4057 heatf [ GYPSUMS ] = ( -2022.6 );
4058 waterc [ GYPSUMS ] = 0.0;
4059 specgrav [ GYPSUMS ] = 2.32;
4060
4061 molarv [ ANHYDRITE ] = 52.16;
4062 heatf [ ANHYDRITE ] = ( -1424.6 );
4063 waterc [ ANHYDRITE ] = 0.0;
4064 specgrav [ ANHYDRITE ] = 2.61;
4065
4066 molarv [ HEMIHYD ] = 52.973;
4067 heatf [ HEMIHYD ] = ( -1574.65 );
4068 waterc [ HEMIHYD ] = 0.0;
4069 specgrav [ HEMIHYD ] = 2.74;
4070
4071 molarv [ C4AF ] = 130.29;
4072 heatf [ C4AF ] = ( -5090.3 );
4073 waterc [ C4AF ] = 0.0;
4074 specgrav [ C4AF ] = 3.73;
4075
4076 molarv [ C3AH6 ] = 150.12;
4077 heatf [ C3AH6 ] = ( -5548. );
4078 waterc [ C3AH6 ] = 6.0;
4079 specgrav [ C3AH6 ] = 2.52;
4080
4081 /* Changed molar volume of FH3 to 69.8 (specific gravity of 3.06) 5/23/95 */
4082 molarv [ FH3 ] = 69.803;
4083 heatf [ FH3 ] = ( -823.9 );
4084 waterc [ FH3 ] = 3.0;
4085 specgrav [ FH3 ] = 3.062;
4086
4087 molarv [ ETTRC4AF ] = 735.01;
4088 heatf [ ETTRC4AF ] = ( -17539.0 );
4089 waterc [ ETTRC4AF ] = 26.0;
4090 specgrav [ ETTRC4AF ] = 1.7076;
4091 /* Changed molar volue of ettringite to 735 (spec. gr.=1.7076) 5/24/95 */
4092 molarv [ ETTR ] = 735.01;
4093 heatf [ ETTR ] = ( -17539.0 );
4094 waterc [ ETTR ] = 26.0;
4095 specgrav [ ETTR ] = 1.7076;
4096
4097 molarv [ AFM ] = 312.82;
4098 heatf [ AFM ] = ( -8778.0 );
4099 /* Each mole of AFM which forms requires 12 moles of water, */
4100 /* two of which are supplied by gypsum in forming ETTR */
4101 /* leaving 10 moles to be incorporated from free water */
4102 waterc [ AFM ] = 10.0;
4103 specgrav [ AFM ] = 1.99;
4104
4105 molarv [ CACL2 ] = 51.62;
4106 heatf [ CACL2 ] = ( -795.8 );
4107 waterc [ CACL2 ] = 0;
4108 specgrav [ CACL2 ] = 2.15;
4109
4110 molarv [ FREIDEL ] = 296.662;
4111 /* No data available for heat of formation */
4112 heatf [ FREIDEL ] = ( 0.0 );
4113 /* 10 moles of H2O per mole of Freidel's salt */
4114 waterc [ FREIDEL ] = 10.0;
4115 specgrav [ FREIDEL ] = 1.892;
4116
4117 /* Basic reaction is 2CH + ASG + 6H --> C2ASH8 (Stratlingite) */
4118 molarv [ ASG ] = 49.9;
4119 /* No data available for heat of formation */
4120 heatf [ ASG ] = 0.0;
4121 waterc [ ASG ] = 0.0;
4122 specgrav [ ASG ] = 3.247;
4123
4124 molarv [ CAS2 ] = 100.62;
4125 /* No data available for heat of formation */
4126 heatf [ CAS2 ] = 0.0;
4127 waterc [ CAS2 ] = 0.0;
4128 specgrav [ CAS2 ] = 2.77;
4129
4130 molarv [ STRAT ] = 215.63;
4131 /* No data available for heat of formation */
4132 heatf [ STRAT ] = 0.0;
4133 /* 8 moles of water per mole of stratlingite */
4134 waterc [ STRAT ] = 8.0;
4135 specgrav [ STRAT ] = 1.94;
4136
4137 molarv [ POZZ ] = 27.0;
4138 /* Use heat of formation of SiO2 (quartz) for unreacted pozzolan */
4139 /* Source- Handbook of Chemistry and Physics */
4140 heatf [ POZZ ] = -907.5;
4141 waterc [ POZZ ] = 0.0;
4142 specgrav [ POZZ ] = 2.22;
4143
4144 /* Data for Pozzolanic CSH based on work of Atlassi, DeLarrard, */
4145 /* and Jensen */
4146 /* gives a chemical shrinkage of 0.2 g H2O/g CSF */
4147 /* heat of formation estimated based on heat release of */
4148 /* 780 J/g Condensed Silica Fume */
4149 /* Changed stoichiometry to be C(1.1)SH(3.9) to see effect on */
4150 /* results 1/22/97 */
4151 /* MW is 191.8 g/mole */
4152 /* Changed molar volume to 101.81 3/10/97 */
4153 molarv [ POZZCSH ] = 101.81;
4154 waterc [ POZZCSH ] = 3.9;
4155 specgrav [ POZZCSH ] = 1.884;
4156 heatf [ POZZCSH ] = ( -2.1 );
4157
4158 /* Assume inert filler has same specific gravity and molar volume as SiO2 */
4159 molarv [ INERT ] = 27.0;
4160 heatf [ INERT ] = 0.0;
4161 waterc [ INERT ] = 0.0;
4162 specgrav [ INERT ] = 2.2;
4163
4164 molarv [ ABSGYP ] = 74.21;
4165 heatf [ ABSGYP ] = ( -2022.6 );
4166 waterc [ ABSGYP ] = 0.0;
4167 specgrav [ ABSGYP ] = 2.32;
4168
4169 molarv [ EMPTYP ] = 18.068;
4170 heatf [ EMPTYP ] = ( -285.83 );
4171 waterc [ EMPTYP ] = 0.0;
4172 specgrav [ EMPTYP ] = 0.99707;
4173
4174 /* Read in values for alkali characteristics and */
4175 /* convert them to fractions from percentages */
4176 // First define non-zero values due to divisions
4177 //totsodium=0.2/100;
4178 //totpotassium=0.5/100;
4179 //rssodium=0.03/100;
4180 //rspotassium=0.25/100;
4181 specgrav [ SLAG ] = 2.87;
4182 specgrav [ SLAGCSH ] = 2.35;
4183 molarv [ SLAG ] = 945.72;
4184 molarv [ SLAGCSH ] = 1717.53;
4185 slagcasi = 1.433;
4186 slaghydcasi = 1.35;
4187 siperslag = 15.0;
4188 waterc [ SLAGCSH ] = 5.533 * siperslag;
4189 slagc3a = 1.0;
4190 slagreact = 1.0;
4191
4192#ifdef CMLFILE
4193 F->get_value(19, totsodium);
4194 F->get_value(20, totpotassium);
4195 F->get_value(21, rssodium);
4196 F->get_value(22, rspotassium);
4197#endif
4198#ifdef TINYXML
4199 QueryNumAttributeExt(xmlFile, "Total_sodium", 0, totsodium);
4200 QueryNumAttributeExt(xmlFile, "Total_potassium", 0, totpotassium);
4201 QueryNumAttributeExt(xmlFile, "Readily_soluble_sodium", 0, rssodium);
4202 QueryNumAttributeExt(xmlFile, "Readily_soluble_potassium", 0, rspotassium);
4203#endif
4204
4205 /*fscanf(alkalifile,"%f",&totsodium);
4206 * fscanf(alkalifile,"%f",&totpotassium);
4207 * fscanf(alkalifile,"%f",&rssodium);
4208 * fscanf(alkalifile,"%f",&rspotassium);
4209 */
4210
4211 totsodium /= 100.;
4212 totpotassium /= 100.;
4213 rssodium /= 100.;
4214 rspotassium /= 100.;
4215
4216
4217 if ( pHactive ) {
4218 /* Read in values for slag characteristics */
4219
4220 if ( ( slagfile = fopen("slagchar.dat", "r") ) == NULL ) {
4221 OOFEM_ERROR("Slag file can not be opened");
4222 }
4223
4224
4225 if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4226 OOFEM_ERROR("slagfile reading error");
4227 }
4228
4229 if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4230 OOFEM_ERROR("slagfile reading error");
4231 }
4232
4233 if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4234 OOFEM_ERROR("slagfile reading error");
4235 }
4236
4237 specgrav [ SLAG ] = slagin;
4238 if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4239 OOFEM_ERROR("slagfile reading error");
4240 }
4241
4242 specgrav [ SLAGCSH ] = slagin;
4243 if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4244 OOFEM_ERROR("slagfile reading error");
4245 }
4246
4247 molarv [ SLAG ] = slagin;
4248 if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4249 OOFEM_ERROR("slagfile reading error");
4250 }
4251
4252 molarv [ SLAGCSH ] = slagin;
4253 if ( fscanf(slagfile, "%lf", & slagcasi) != 1 ) {
4254 OOFEM_ERROR("slagfile reading error");
4255 }
4256
4257 if ( fscanf(slagfile, "%lf", & slaghydcasi) != 1 ) {
4258 OOFEM_ERROR("slagfile reading error");
4259 }
4260
4261 if ( fscanf(slagfile, "%lf", & siperslag) != 1 ) {
4262 OOFEM_ERROR("slagfile reading error");
4263 }
4264
4265 if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4266 OOFEM_ERROR("slagfile reading error");
4267 }
4268
4269 waterc [ SLAGCSH ] = slagin * siperslag;
4270 if ( fscanf(slagfile, "%lf", & slagc3a) != 1 ) {
4271 OOFEM_ERROR("slagfile reading error");
4272 }
4273
4274 if ( fscanf(slagfile, "%lf", & slagreact) != 1 ) {
4275 OOFEM_ERROR("slagfile reading error");
4276 }
4277
4278 waterc [ SLAG ] = 0.0;
4279 heatf [ SLAG ] = 0.0;
4280 heatf [ SLAGCSH ] = 0.0;
4281 fclose(slagfile);
4282 }
4283
4284 //use default values
4285 specgrav [ SLAG ] = 2.87;
4286 specgrav [ SLAGCSH ] = 2.35;
4287 molarv [ SLAG ] = 945.72;
4288 molarv [ SLAGCSH ] = 1717.53;
4289 slagcasi = 1.4333;
4290 slaghydcasi = 1.35;
4291 siperslag = 15.0;
4292 waterc [ SLAGCSH ] = 5.533 * siperslag;
4293 slagc3a = 1.0;
4294 slagreact = 1.0;
4295
4296 /* Compute slag probabilities as defined above */
4297 CHperslag = siperslag * ( slaghydcasi - slagcasi ) + 3. * slagc3a;
4298 if ( CHperslag < 0.0 ) {
4299 CHperslag = 0.0;
4300 }
4301
4302 p2slag = ( molarv [ SLAG ] + molarv [ CH ] * CHperslag + molarv [ POROSITY ] * ( waterc [ SLAGCSH ] - CHperslag + waterc [ C3AH6 ] * slagc3a ) - molarv [ SLAGCSH ] - molarv [ C3AH6 ] * slagc3a ) / molarv [ SLAG ];
4303 p1slag = 1.0 - p2slag;
4304 p3slag = ( molarv [ SLAGCSH ] / molarv [ SLAG ] ) - p1slag;
4305 p4slag = CHperslag * molarv [ CH ] / molarv [ SLAG ];
4306 p5slag = slagc3a * molarv [ C3A ] / molarv [ SLAG ];
4307 if ( p5slag > 1.0 ) {
4308 p5slag = 1.0;
4309 printf("Error in range of C3A/slag value... reset to 1.0 \n");
4310 }
4311}
4312
4313/* routine to check if a pixel located at (xck,yck,zck) is on an edge */
4314/* (in contact with pore space) in 3-D system */
4315/* Called by passone */
4316/* Calls no other routines */
4317int CemhydMatStatus :: chckedge(int xck, int yck, int zck)
4318{
4319 int edgeback, x2, y2, z2;
4320 int ip;
4321
4322 edgeback = 0;
4323
4324 /* Check all six neighboring pixels */
4325 /* with periodic boundary conditions */
4326 for ( ip = 0; ( ( ip < NEIGHBORS ) && ( edgeback == 0 ) ); ip++ ) {
4327 x2 = xck + xoff [ ip ];
4328 y2 = yck + yoff [ ip ];
4329 z2 = zck + zoff [ ip ];
4330 if ( x2 >= SYSIZE ) {
4331 x2 = 0;
4332 }
4333
4334 if ( x2 < 0 ) {
4335 x2 = SYSIZEM1;
4336 }
4337
4338 if ( y2 >= SYSIZE ) {
4339 y2 = 0;
4340 }
4341
4342 if ( y2 < 0 ) {
4343 y2 = SYSIZEM1;
4344 }
4345
4346 if ( z2 >= SYSIZE ) {
4347 z2 = 0;
4348 }
4349
4350 if ( z2 < 0 ) {
4351 z2 = SYSIZEM1;
4352 }
4353
4354 if ( mic [ x2 ] [ y2 ] [ z2 ] == POROSITY ) {
4355 edgeback = 1;
4356 }
4357 }
4358
4359 return ( edgeback );
4360}
4361
4362/* routine for first pass through microstructure during dissolution */
4363/* low and high indicate phase ID range to check for surface sites */
4364/* Called by dissolve */
4365/* Calls chckedge */
4366void CemhydMatStatus :: passone(int low, int high, int cycid, int cshexflag)
4367{
4368 int i, xid, yid, zid, phid, edgef, phread, cshcyc;
4369
4370 /* gypready used to determine if any soluble gypsum remains */
4371 if ( ( low <= GYPSUM ) && ( GYPSUM <= high ) ) {
4372 gypready = 0;
4373 }
4374
4375 /* Zero out count for the relevant phases */
4376 for ( i = low; i <= high; i++ ) {
4377 count [ i ] = 0;
4378 }
4379
4380 /* Scan the entire 3-D microstructure */
4381 for ( xid = 0; xid < SYSIZE; xid++ ) {
4382 for ( yid = 0; yid < SYSIZE; yid++ ) {
4383 for ( zid = 0; zid < SYSIZE; zid++ ) {
4384 phread = mic [ xid ] [ yid ] [ zid ];
4385 /* Update heat data and water consumed for solid CSH */
4386 if ( ( cshexflag == 1 ) && ( phread == CSH ) ) {
4387 cshcyc = cshage [ xid ] [ yid ] [ zid ];
4388 heatsum += heatf [ CSH ] / molarvcsh [ cshcyc ];
4389 molesh2o += watercsh [ cshcyc ] / molarvcsh [ cshcyc ];
4390 }
4391
4392 /* Identify phase and update count */
4393 phid = 60;
4394 for ( i = low; ( ( i <= high ) && ( phid == 60 ) ); i++ ) {
4395 if ( mic [ xid ] [ yid ] [ zid ] == i ) {
4396 phid = i;
4397 /* Update count for this phase */
4398 count [ i ] += 1;
4399 if ( ( i == GYPSUM ) || ( i == GYPSUMS ) ) {
4400 gypready += 1;
4401 }
4402
4403 /* If first cycle, then accumulate initial counts */
4404 if ( cycid == 1 ) { //fixed (ncyc cancelled)
4405 if ( i == POROSITY ) {
4406 porinit += 1;
4407 }
4408 /* Ordered in terms of likely volume fractions */
4409 /* (largest to smallest) to speed execution */
4410 else if ( i == C3S ) {
4411 c3sinit += 1;
4412 } else if ( i == C2S ) {
4413 c2sinit += 1;
4414 } else if ( i == C3A ) {
4415 c3ainit += 1;
4416 } else if ( i == C4AF ) {
4417 c4afinit += 1;
4418 } else if ( i == GYPSUM ) {
4419 ncsbar += 1;
4420 } else if ( i == GYPSUMS ) {
4421 ncsbar += 1;
4422 } else if ( i == ANHYDRITE ) {
4423 anhinit += 1;
4424 } else if ( i == HEMIHYD ) {
4425 heminit += 1;
4426 } else if ( i == POZZ ) {
4427 nfill += 1;
4428 } else if ( i == SLAG ) {
4429 slaginit += 1;
4430 } else if ( i == ETTR ) {
4431 netbar += 1;
4432 } else if ( i == ETTRC4AF ) {
4433 netbar += 1;
4434 }
4435 }
4436 }
4437 }
4438
4439 if ( phid != 60 ) {
4440 /* If phase is soluble, see if it is in contact with porosity */
4441 if ( ( cycid != 0 ) && ( soluble [ phid ] == 1 ) ) {
4442 edgef = chckedge(xid, yid, zid);
4443 if ( edgef == 1 ) {
4444 /* Surface eligible species has an ID OFFSET greater than its original value */
4445 mic [ xid ] [ yid ] [ zid ] += OFFSET;
4446 }
4447 }
4448 }
4449 }
4450
4451 /* end of zid */
4452 }
4453
4454 /* end of yid */
4455 }
4456
4457 /* end of xid */
4458}
4459
4460/* routine to locate a diffusing CSH species near dissolution source */
4461/* at (xcur,ycur,zcur) */
4462/* Called by dissolve */
4463/* Calls no other routines */
4464int CemhydMatStatus :: loccsh(int xcur, int ycur, int zcur, int extent)
4465{
4466 int effort, tries, xmod, ymod, zmod;
4467 struct ants *antnew;
4468
4469 effort = 0; /* effort indicates if appropriate location found */
4470 tries = 0;
4471 /* 500 tries in immediate vicinity */
4472 while ( ( effort == 0 ) && ( tries < 500 ) ) {
4473 tries += 1;
4474 xmod = ( -extent ) + ( int ) ( ( 2. * ( float ) extent + 1. ) * ran1(seed) );
4475 ymod = ( -extent ) + ( int ) ( ( 2. * ( float ) extent + 1. ) * ran1(seed) );
4476 zmod = ( -extent ) + ( int ) ( ( 2. * ( float ) extent + 1. ) * ran1(seed) );
4477 if ( xmod > extent ) {
4478 xmod = extent;
4479 }
4480
4481 if ( ymod > extent ) {
4482 ymod = extent;
4483 }
4484
4485 if ( zmod > extent ) {
4486 zmod = extent;
4487 }
4488
4489 xmod += xcur;
4490 ymod += ycur;
4491 zmod += zcur;
4492 /* Periodic boundaries */
4493 if ( xmod >= SYSIZE ) {
4494 xmod -= SYSIZE;
4495 } else if ( xmod < 0 ) {
4496 xmod += SYSIZE;
4497 }
4498
4499 if ( zmod >= SYSIZE ) {
4500 zmod -= SYSIZE;
4501 } else if ( zmod < 0 ) {
4502 zmod += SYSIZE;
4503 }
4504
4505 if ( ymod < 0 ) {
4506 ymod += SYSIZE;
4507 } else if ( ymod >= SYSIZE ) {
4508 ymod -= SYSIZE;
4509 }
4510
4511 if ( mic [ xmod ] [ ymod ] [ zmod ] == POROSITY ) {
4512 effort = 1;
4513 mic [ xmod ] [ ymod ] [ zmod ] = DIFFCSH;
4514 nmade += 1;
4515 ngoing += 1;
4516 /* Add CSH diffusing species to the linked list */
4517 antnew = ( struct ants * ) malloc( sizeof( struct ants ) );
4518 antnew->x = xmod;
4519 antnew->y = ymod;
4520 antnew->z = zmod;
4521 antnew->id = DIFFCSH;
4522 antnew->cycbirth = cyccnt;
4523 /* Now connect this ant structure to end of linked list */
4524 antnew->prevant = tailant;
4525 tailant->nextant = antnew;
4526 antnew->nextant = NULL;
4527 tailant = antnew;
4528 }
4529 }
4530
4531 return ( effort );
4532}
4533
4534/* routine to count number of pore pixels in a cube of size boxsize */
4535/* centered at (qx,qy,qz) */
4536/* Called by makeinert */
4537/* Calls no other routines */
4538int CemhydMatStatus :: countbox(int boxsize, int qx, int qy, int qz)
4539{
4540 int nfound, ix, iy, iz, qxlo, qxhi, qylo, qyhi, qzlo, qzhi;
4541 int hx, hy, hz, boxhalf;
4542
4543 boxhalf = boxsize / 2;
4544 nfound = 0;
4545 qxlo = qx - boxhalf;
4546 qxhi = qx + boxhalf;
4547 qylo = qy - boxhalf;
4548 qyhi = qy + boxhalf;
4549 qzlo = qz - boxhalf;
4550 qzhi = qz + boxhalf;
4551 /* Count the number of requisite pixels in the 3-D cube box */
4552 /* using periodic boundaries */
4553 for ( ix = qxlo; ix <= qxhi; ix++ ) {
4554 hx = ix;
4555 if ( hx < 0 ) {
4556 hx += SYSIZE;
4557 } else if ( hx >= SYSIZE ) {
4558 hx -= SYSIZE;
4559 }
4560
4561 for ( iy = qylo; iy <= qyhi; iy++ ) {
4562 hy = iy;
4563 if ( hy < 0 ) {
4564 hy += SYSIZE;
4565 } else if ( hy >= SYSIZE ) {
4566 hy -= SYSIZE;
4567 }
4568
4569 for ( iz = qzlo; iz <= qzhi; iz++ ) {
4570 hz = iz;
4571 if ( hz < 0 ) {
4572 hz += SYSIZE;
4573 } else if ( hz >= SYSIZE ) {
4574 hz -= SYSIZE;
4575 }
4576
4577 /* Count if porosity, diffusing species, or empty porosity */
4578 if ( ( mic [ hx ] [ hy ] [ hz ] < C3S ) || ( mic [ hx ] [ hy ] [ hz ] > ABSGYP ) ) {
4579 nfound += 1;
4580 }
4581 }
4582 }
4583 }
4584
4585 return ( nfound );
4586}
4587
4588/* routine to count number of special pixels in a cube of size boxsize */
4589/* centered at (qx,qy,qz) */
4590/* special pixels are those not belonging to one of the cement clinker, */
4591/* calcium sulfate, or pozzolanic mineral admixture phases */
4592/* Called by addrand */
4593/* Calls no other routines */
4594int CemhydMatStatus :: countboxc(int boxsize, int qx, int qy, int qz)
4595{
4596 int nfound, ix, iy, iz, qxlo, qxhi, qylo, qyhi, qzlo, qzhi;
4597 int hx, hy, hz, boxhalf;
4598
4599 boxhalf = boxsize / 2;
4600 nfound = 0;
4601 qxlo = qx - boxhalf;
4602 qxhi = qx + boxhalf;
4603 qylo = qy - boxhalf;
4604 qyhi = qy + boxhalf;
4605 qzlo = qz - boxhalf;
4606 qzhi = qz + boxhalf;
4607 /* Count the number of requisite pixels in the 3-D cube box */
4608 /* using periodic boundaries */
4609 for ( ix = qxlo; ix <= qxhi; ix++ ) {
4610 hx = ix;
4611 if ( hx < 0 ) {
4612 hx += SYSIZE;
4613 } else if ( hx >= SYSIZE ) {
4614 hx -= SYSIZE;
4615 }
4616
4617 for ( iy = qylo; iy <= qyhi; iy++ ) {
4618 hy = iy;
4619 if ( hy < 0 ) {
4620 hy += SYSIZE;
4621 } else if ( hy >= SYSIZE ) {
4622 hy -= SYSIZE;
4623 }
4624
4625 for ( iz = qzlo; iz <= qzhi; iz++ ) {
4626 hz = iz;
4627 if ( hz < 0 ) {
4628 hz += SYSIZE;
4629 } else if ( hz >= SYSIZE ) {
4630 hz -= SYSIZE;
4631 }
4632
4633 /* Count if not cement clinker */
4634 if ( ( mic [ hx ] [ hy ] [ hz ] < C3S ) || ( mic [ hx ] [ hy ] [ hz ] > POZZ ) ) {
4635 nfound += 1;
4636 }
4637 }
4638 }
4639 }
4640
4641 return ( nfound );
4642}
4643
4644/* routine to create ndesire pixels of empty pore space to simulate */
4645/* self-desiccation, or external drying */
4646/* Called by dissolve */
4647/* Calls countbox */
4648/* each ....togo structure contains information only at x,y,z*/
4649/* headtogo is the first voxel where the water is taken from*/
4650
4651
4652void CemhydMatStatus :: makeinert(long int ndesire) {
4653 struct togo *headtogo, *tailtogo, *newtogo = nullptr, *lasttogo, *onetogo;
4654 long int idesire;
4655 int px, py, pz, placed, cntpore, cntmax;
4656
4657 /* First allocate the first element of the linked list */
4658 headtogo = ( struct togo * ) malloc( sizeof( struct togo ) );
4659 headtogo->x = headtogo->y = headtogo->z = ( -1 );
4660 headtogo->npore = 0;
4661 headtogo->nexttogo = NULL;
4662 headtogo->prevtogo = NULL;
4663 tailtogo = headtogo;
4664 cntmax = 0;
4665
4666#ifdef PRINTF
4667 printf("In makeinert with %ld needed elements \n", ndesire);
4668#endif
4669
4670 fflush(stdout);
4671 /* Add needed number of elements to the end of the list */
4672 for ( idesire = 2; idesire <= ndesire; idesire++ ) {
4673 newtogo = ( struct togo * ) malloc( sizeof( struct togo ) );
4674 newtogo->npore = 0;
4675 newtogo->x = newtogo->y = newtogo->z = ( -1 );
4676 tailtogo->nexttogo = newtogo;
4677 newtogo->prevtogo = tailtogo;
4678 tailtogo = newtogo;
4679 }
4680
4681 /* Now scan the microstructure and rank the sites */
4682 for ( px = 0; px < SYSIZE; px++ ) {
4683 for ( py = 0; py < SYSIZE; py++ ) {
4684 for ( pz = 0; pz < SYSIZE; pz++ ) {
4685 if ( mic [ px ] [ py ] [ pz ] == POROSITY ) {
4686 cntpore = countbox(cubesize, px, py, pz);
4687 if ( cntpore > cntmax ) {
4688 cntmax = cntpore;
4689 }
4690
4691 /* Store this site value at appropriate place in */
4692 /* sorted linked list */
4693 if ( cntpore > ( tailtogo->npore ) ) {
4694 placed = 0;
4695 lasttogo = tailtogo;
4696 while ( placed == 0 ) {
4697 newtogo = lasttogo->prevtogo;
4698 if ( newtogo == NULL ) { //if at the beginning of the list (tailtogo->prevtogo==NULL)
4699 placed = 2;
4700 } else {
4701 if ( cntpore <= ( newtogo->npore ) ) {
4702 placed = 1;
4703 }
4704 }
4705
4706 if ( placed == 0 ) {
4707 lasttogo = newtogo;
4708 }
4709 }
4710
4711 onetogo = ( struct togo * ) malloc( sizeof( struct togo ) );
4712 onetogo->x = px;
4713 onetogo->y = py;
4714 onetogo->z = pz;
4715 onetogo->npore = cntpore;
4716 /* Insertion at the head of the list */
4717 if ( placed == 2 ) {
4718 onetogo->prevtogo = NULL;
4719 onetogo->nexttogo = headtogo;
4720 headtogo->prevtogo = onetogo;
4721 headtogo = onetogo;
4722 }
4723
4724 if ( placed == 1 ) {
4725 onetogo->nexttogo = lasttogo;
4726 onetogo->prevtogo = newtogo;
4727 lasttogo->prevtogo = onetogo;
4728 newtogo->nexttogo = onetogo;
4729 }
4730
4731 /* Eliminate the last element */
4732 lasttogo = tailtogo;
4733 tailtogo = tailtogo->prevtogo;
4734 tailtogo->nexttogo = NULL;
4735 //printf("DEMEM lasttogo1 addr %p\n", lasttogo);
4736 free(lasttogo);
4737 }
4738 }
4739 }
4740 }
4741 }
4742
4743 /* Now remove the sites */
4744 /* starting at the head of the list */
4745 /* and deallocate all of the used memory */
4746 for ( idesire = 1; idesire <= ndesire; idesire++ ) {
4747 px = headtogo->x;
4748 py = headtogo->y;
4749 pz = headtogo->z;
4750 if ( px != ( -1 ) ) {
4751 mic [ px ] [ py ] [ pz ] = EMPTYP;
4752 count [ POROSITY ] -= 1;
4753 count [ EMPTYP ] += 1;
4754 }
4755
4756 lasttogo = headtogo;
4757 headtogo = headtogo->nexttogo;
4758 //printf("DEMEM lasttogo2 addr %p\n", (const void *)lasttogo);
4759 free(lasttogo);
4760 }
4761
4762 /* If only small cubes of porosity were found, then adjust */
4763 /* cubesize to have a more efficient search in the future */
4764 if ( cubesize > CUBEMIN ) {
4765 if ( ( 2 * cntmax ) < ( cubesize * cubesize * cubesize ) ) {
4766 cubesize -= 2;
4767 }
4768 }
4769}
4770
4771
4772/* routine to add extra SLAG CSH when SLAG reacts */
4773/* SLAG located at (xpres,ypres,zpres) */
4774/* Called by dissolve */
4775/* Calls moveone and edgecnt */
4776void CemhydMatStatus :: extslagcsh(int xpres, int ypres, int zpres) {
4777 int check, sump, xchr, ychr, zchr, fchr, i1, action, numnear;
4778 long int tries;
4779 int mstest = 0, mstest2 = 0;
4780
4781 /* first try 6 neighboring locations until */
4782 /* a) successful */
4783 /* b) all 6 sites are tried or */
4784 /* c) 100 tries are made */
4785 /* try to grow slag C-S-H as plates */
4786 fchr = 0;
4787 sump = 1;
4788 for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
4789 /* determine location of neighbor (using periodic boundaries) */
4790 xchr = xpres;
4791 ychr = ypres;
4792 zchr = zpres;
4793 action = 0;
4794 sump *= moveone(& xchr, & ychr, & zchr, & action, sump);
4795 if ( action == 0 ) {
4796 printf("Error in value of action in extpozz \n");
4797 }
4798
4799 check = mic [ xchr ] [ ychr ] [ zchr ];
4800 /* Determine the direction of the neighbor selected and */
4801 /* the plates possible for growth */
4802 if ( xchr != xpres ) {
4803 mstest = 1;
4804 mstest2 = 2;
4805 }
4806
4807 if ( ychr != ypres ) {
4808 mstest = 2;
4809 mstest2 = 3;
4810 }
4811
4812 if ( zchr != zpres ) {
4813 mstest = 3;
4814 mstest2 = 1;
4815 }
4816
4817 /* if neighbor is porosity, locate the SLAG CSH there */
4818 if ( check == POROSITY ) {
4819 if ( ( faces [ xpres ] [ ypres ] [ zpres ] == 0 ) || ( mstest == faces [ xpres ] [ ypres ] [ zpres ] ) || ( mstest2 == faces [ xpres ] [ ypres ] [ zpres ] ) ) {
4820 mic [ xchr ] [ ychr ] [ zchr ] = SLAGCSH;
4821 faces [ xchr ] [ ychr ] [ zchr ] = faces [ xpres ] [ ypres ] [ zpres ];
4822 count [ SLAGCSH ] += 1;
4823 count [ POROSITY ] -= 1;
4824 fchr = 1;
4825 }
4826 }
4827 }
4828
4829 /* if no neighbor available, locate SLAG CSH at random location */
4830 /* in pore space */
4831 tries = 0;
4832 while ( fchr == 0 ) {
4833 tries += 1;
4834 /* generate a random location in the 3-D system */
4835 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
4836 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
4837 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
4838 if ( xchr >= SYSIZE ) {
4839 xchr = 0;
4840 }
4841
4842 if ( ychr >= SYSIZE ) {
4843 ychr = 0;
4844 }
4845
4846 if ( zchr >= SYSIZE ) {
4847 zchr = 0;
4848 }
4849
4850 check = mic [ xchr ] [ ychr ] [ zchr ];
4851 /* if location is porosity, locate the extra SLAG CSH there */
4852 if ( check == POROSITY ) {
4853 numnear = edgecnt(xchr, ychr, zchr, SLAG, CSH, SLAGCSH);
4854 /* Be sure that one neighboring species is CSH or */
4855 /* SLAG material */
4856 if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
4857 mic [ xchr ] [ ychr ] [ zchr ] = SLAGCSH;
4858 count [ SLAGCSH ] += 1;
4859 count [ POROSITY ] -= 1;
4860 fchr = 1;
4861 }
4862 }
4863 }
4864}
4865
4866/* routine to implement a cycle of dissolution */
4867/* Called by main program */
4868/* Calls passone, loccsh, and makeinert */
4869void CemhydMatStatus :: dissolve(int cycle)
4870{
4871 int nc3aext, ncshext, nchext, ngypext, nanhext, plok;
4872 int nsum5, nsum4, nsum3, nsum2, nhemext, nsum6, nc4aext;
4873 int phid, phnew, plnew, cread;
4874 int i, xloop, yloop, zloop, xc, yc;
4875 int zc, cycnew;
4876 long int ctest;
4877 long int tries;
4878 int placed, cshrand, maxsulfate, msface;
4879 long int ncshgo, nsurf, suminit;
4880 long int xext, nhgd, npchext, nslagc3a = 0;
4881 float pdis, plfh3, fchext, fc3aext, fanhext, mass_now, mass_fa_now, tot_mass, heatfill;
4882 float dfact, dfact1, molesdh2o, h2oinit, heat4, fhemext, fc4aext;
4883 float pconvert, pc3scsh, pc2scsh, calcx, calcy, calcz, tdisfact;
4884 float frafm, frettr, frhyg, frtot, mc3ar, mc4ar, p3init;
4885 struct ants *antadd;
4886
4887 /* Initialize variables */
4888 nmade = 0;
4889 npchext = ncshgo = cshrand = 0; /* counter for number of csh diffusing species to */
4890 /* be located at random locations in microstructure */
4891 heat_old = heat_new; /* new and old values for heat released */
4892
4893 /* Initialize dissolution and phase counters */
4894 nsurf = 0;
4895 for ( i = 0; i <= EMPTYP; i++ ) {
4896 discount [ i ] = 0;
4897 count [ i ] = 0;
4898 }
4899
4900 /* Pass one- highlight all edge points which are soluble */
4901 soluble [ C3AH6 ] = 0;
4902 heatsum = 0.0;
4903 molesh2o = 0.0;
4904 passone(0, EMPTYP, cycle, 1);
4905#ifdef PRINTF
4906 printf("Returned from passone \n");
4907#endif
4908 fflush(stdout);
4909
4911 /* If first cycle, then determine all mixture proportions based */
4912 /* on user input and original microstructure */
4913 if ( cycle == 1 ) {
4914 /* Mass of cement in system */
4915 cemmass = ( specgrav [ C3S ] * ( float ) count [ C3S ] + specgrav [ C2S ] *
4916 ( float ) count [ C2S ] + specgrav [ C3A ] * ( float ) count [ C3A ] +
4917 specgrav [ C4AF ] * ( float ) count [ C4AF ] );
4918 /* +specgrav[GYPSUM]*
4919 * (float)count[GYPSUM]+specgrav[ANHYDRITE]*(float)
4920 * count[ANHYDRITE]+specgrav[HEMIHYD]*(float)count[HEMIHYD]); */
4921 cemmasswgyp = ( specgrav [ C3S ] * ( float ) count [ C3S ] + specgrav [ C2S ] *
4922 ( float ) count [ C2S ] + specgrav [ C3A ] * ( float ) count [ C3A ] +
4923 specgrav [ C4AF ] * ( float ) count [ C4AF ] + specgrav [ GYPSUM ] *
4924 ( float ) count [ GYPSUM ] + specgrav [ ANHYDRITE ] * ( float )
4925 count [ ANHYDRITE ] + specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] );
4926 flyashmass = ( specgrav [ ASG ] * ( float ) count [ ASG ] + specgrav [ CAS2 ] *
4927 ( float ) count [ CAS2 ] + specgrav [ POZZ ] * ( float ) count [ POZZ ] );
4928 CH_mass = specgrav [ CH ] * ( float ) count [ CH ];
4929 /* Total mass in system neglecting single aggregate */
4930 tot_mass = cemmass + ( float ) count [ POROSITY ] + specgrav [ INERT ] *
4931 ( float ) count [ INERT ] + specgrav [ CACL2 ] * ( float ) count [ CACL2 ] +
4932 specgrav [ ASG ] * ( float ) count [ ASG ] +
4933 specgrav [ SLAG ] * ( float ) count [ SLAG ] +
4934 specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] +
4935 specgrav [ ANHYDRITE ] * ( float ) count [ ANHYDRITE ] +
4936 specgrav [ CAS2 ] * ( float ) count [ CAS2 ] +
4937 specgrav [ CSH ] * ( float ) count [ CSH ] +
4938 specgrav [ GYPSUM ] * ( float ) count [ GYPSUM ] +
4939 specgrav [ ANHYDRITE ] * ( float ) count [ ANHYDRITE ] +
4940 specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] +
4941 specgrav [ GYPSUMS ] * ( float ) count [ GYPSUMS ] +
4942 specgrav [ POZZ ] * ( float ) count [ POZZ ] + CH_mass;
4943 /* water-to-cement ratio */
4944 if ( cemmass != 0.0 ) {
4945 w_to_c = ( float ) count [ POROSITY ] / ( cemmass +
4946 specgrav [ GYPSUM ] * ( float ) count [ GYPSUM ] +
4947 specgrav [ ANHYDRITE ] * ( float ) count [ ANHYDRITE ] +
4948 specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] );
4949 } else {
4950 w_to_c = 0.0;
4951 }
4952
4953 /* totfract is the total cement volume count including calcium sulfates */
4954 /* fractwithfill is the total count of cement and solid fillers and */
4955 /* mineral admixtures DPB- 10/04 */
4956 totfract = count [ C3S ] + count [ C2S ];
4957 totfract += ( count [ C3A ] + count [ C4AF ] );
4958 totfract += ( count [ GYPSUM ] + count [ ANHYDRITE ] + count [ HEMIHYD ] );
4959 fractwithfill = totfract + count [ CACO3 ] + count [ SLAG ] + count [ INERT ];
4960 fractwithfill += count [ POZZ ] + count [ CAS2 ] + count [ ASG ] + count [ CACL2 ];
4961 totfract /= ( float ) SYSIZE;
4962 totfract /= ( float ) SYSIZE;
4963 totfract /= ( float ) SYSIZE;
4964 fractwithfill /= ( float ) SYSIZE;
4965 fractwithfill /= ( float ) SYSIZE;
4966 fractwithfill /= ( float ) SYSIZE;
4967 /* Adjust masses for presence of aggregates in concrete */
4968 mass_water = ( 1. - mass_agg ) * ( float ) count [ POROSITY ] / tot_mass;
4969 mass_CH = ( 1. - mass_agg ) * CH_mass / tot_mass;
4970 /* pozzolan-to-cement ratio */
4971 if ( cemmass != 0.0 ) {
4972 s_to_c = ( float ) ( count [ INERT ] * specgrav [ INERT ] +
4973 count [ CACL2 ] * specgrav [ CACL2 ] + count [ ASG ] * specgrav [ ASG ] +
4974 count [ CAS2 ] * specgrav [ CAS2 ] +
4975 count [ SLAG ] * specgrav [ SLAG ] +
4976 count [ POZZ ] * specgrav [ POZZ ] ) / cemmass;
4977 } else {
4978 s_to_c = 0.0;
4979 }
4980
4981 /* Conversion factor to kJ/kg for heat produced */
4982 if ( cemmass != 0.0 ) {
4983 heatfill = ( float ) ( count [ INERT ] + count [ SLAG ] + count [ POZZ ] + count [ CACL2 ] + count [ ASG ] + count [ CAS2 ] ) / cemmass; //units pixels^3/g, inverse to the density
4984 } else {
4985 heatfill = 0.0;
4986 }
4987
4988 if ( w_to_c > 0.01 ) {
4989 heat_cf = 1000. / SYSIZE_POW3 * ( 0.3125 + w_to_c + heatfill ); //heat conversion factor,1/ro_c=0.3125, fixed
4990 } else {
4991 /* Need volume per 1 gram of silica fume */
4992 heat_cf = 1000. / SYSIZE_POW3 * ( ( 1. / specgrav [ POZZ ] ) + ( float ) ( count [ POROSITY ] + count [ CH ] + count [ INERT ] ) / ( specgrav [ POZZ ] * ( float ) count [ POZZ ] ) ); //fixed
4993 }
4994
4995 mass_fill_pozz = ( 1. - mass_agg ) * ( float ) ( count [ POZZ ] * specgrav [ POZZ ] ) / tot_mass;
4996 mass_fill = ( 1. - mass_agg ) * ( float ) ( count [ INERT ] * specgrav [ INERT ] +
4997 count [ ASG ] * specgrav [ ASG ] + count [ SLAG ] * specgrav [ SLAG ] +
4998 count [ CAS2 ] * specgrav [ CAS2 ] + count [ POZZ ] * specgrav [ POZZ ] +
4999 count [ CACL2 ] * specgrav [ CACL2 ] ) / tot_mass;
5000#ifdef PRINTF
5001 printf("Calculated w/c is %.4f\n", w_to_c);
5002 printf("Calculated s/c is %.4f \n", s_to_c);
5003 printf("Calculated heat conversion factor is %f \n", heat_cf);
5004 printf("Calculated mass fractions of water and filler are %.4f and %.4f \n",
5006#endif
5007 }
5008
5009 molesdh2o = 0.0;
5010 alpha = 0.0; /* degree of hydration of clinker minerals*/
5011 /* heat4 contains measured heat release for C4AF hydration from */
5012 /* Fukuhara et al., Cem. and Conc. Res. article */
5013 heat4 = 0.0;
5014 mass_now = 0.0; /* total cement mass corrected for hydration */
5015 suminit = c3sinit + c2sinit + c3ainit + c4afinit;
5016 /* suminit=c3sinit+c2sinit+c3ainit+c4afinit+ncsbar+anhinit+heminit; */
5017 /* ctest is number of gypsum likely to form ettringite */
5018 /* 1 unit of C3A can react with 2.5 units of Gypsum */
5019 ctest = count [ DIFFGYP ];
5020#ifdef PRINTF
5021 printf("ctest is %ld\n", ctest);
5022#endif
5023 fflush(stdout);
5024 if ( ( float ) ctest > ( 2.5 * ( float ) ( count [ DIFFC3A ] + count [ DIFFC4A ] ) ) ) {
5025 ctest = ( long int ) ( 2.5 * ( float ) ( count [ DIFFC3A ] + count [ DIFFC4A ] ) );
5026 }
5027
5028 for ( i = 0; i <= EMPTYP; i++ ) {
5029 if ( ( i != 0 ) && ( i <= ABSGYP ) && ( i != INERTAGG ) && ( i != CSH ) ) {
5030 heatsum += ( float ) count [ i ] * heatf [ i ] / molarv [ i ];
5031 /* Tabulate moles of H2O consumed by reactions so far */
5032 molesh2o += ( float ) count [ i ] * waterc [ i ] / molarv [ i ];
5033 }
5034
5035 /* assume that all C3A which can, does form ettringite */
5036 if ( i == DIFFC3A ) {
5037 heatsum += ( ( float ) count [ DIFFC3A ] - ( float ) ctest / 2.5 ) * heatf [ C3A ] / molarv [ C3A ];
5038 }
5039
5040 /* assume that all C4A which can, does form ettringite */
5041 if ( i == DIFFC4A ) {
5042 heatsum += ( ( float ) count [ DIFFC4A ] - ( float ) ctest / 2.5 ) * heatf [ C4AF ] / molarv [ C4AF ];
5043 }
5044
5045 /* assume all gypsum which can, does form ettringite */
5046 /* rest will remain as gypsum */
5047 if ( i == DIFFGYP ) {
5048 heatsum += ( float ) ( count [ DIFFGYP ] - ctest ) * heatf [ GYPSUM ] / molarv [ GYPSUM ];
5049 /* 3.3 is the molar expansion from GYPSUM to ETTR */
5050 heatsum += ( float ) ctest * 3.30 * heatf [ ETTR ] / molarv [ ETTR ];
5051 molesdh2o += ( float ) ctest * 3.30 * waterc [ ETTR ] / molarv [ ETTR ];
5052 } else if ( i == DIFFCH ) {
5053 heatsum += ( float ) count [ DIFFCH ] * heatf [ CH ] / molarv [ CH ];
5054 molesdh2o += ( float ) count [ DIFFCH ] * waterc [ CH ] / molarv [ CH ];
5055 } else if ( i == DIFFFH3 ) {
5056 heatsum += ( float ) count [ DIFFFH3 ] * heatf [ FH3 ] / molarv [ FH3 ];
5057 molesdh2o += ( float ) count [ DIFFFH3 ] * waterc [ FH3 ] / molarv [ FH3 ];
5058 } else if ( i == DIFFCSH ) {
5059 /* use current CSH properties */
5060 heatsum += ( float ) count [ DIFFCSH ] * heatf [ CSH ] / molarvcsh [ cycle ];
5061 molesdh2o += ( float ) count [ DIFFCSH ] * watercsh [ cycle ] / molarvcsh [ cycle ];
5062 } else if ( i == DIFFETTR ) {
5063 heatsum += ( float ) count [ DIFFETTR ] * heatf [ ETTR ] / molarv [ ETTR ];
5064 molesdh2o += ( float ) count [ DIFFETTR ] * waterc [ ETTR ] / molarv [ ETTR ];
5065 } else if ( i == DIFFCACL2 ) {
5066 heatsum += ( float ) count [ DIFFCACL2 ] * heatf [ CACL2 ] / molarv [ CACL2 ];
5067 molesdh2o += ( float ) count [ DIFFCACL2 ] * waterc [ CACL2 ] / molarv [ CACL2 ];
5068 } else if ( i == DIFFAS ) {
5069 heatsum += ( float ) count [ DIFFAS ] * heatf [ ASG ] / molarv [ ASG ];
5070 molesdh2o += ( float ) count [ DIFFAS ] * waterc [ ASG ] / molarv [ ASG ];
5071 } else if ( i == DIFFCAS2 ) {
5072 heatsum += ( float ) count [ DIFFCAS2 ] * heatf [ CAS2 ] / molarv [ CAS2 ];
5073 molesdh2o += ( float ) count [ DIFFCAS2 ] * waterc [ CAS2 ] / molarv [ CAS2 ];
5074 }
5075 /* assume that all diffusing anhydrite leads to gypsum formation */
5076 else if ( i == DIFFANH ) {
5077 heatsum += ( float ) count [ DIFFANH ] * heatf [ GYPSUMS ] / molarv [ GYPSUMS ];
5078 /* 2 moles of water per mole of gypsum formed */
5079 molesdh2o += ( float ) count [ DIFFANH ] * 2.0 / molarv [ GYPSUMS ];
5080 }
5081 /* assume that all diffusing hemihydrate leads to gypsum formation */
5082 else if ( i == DIFFHEM ) {
5083 heatsum += ( float ) count [ DIFFHEM ] * heatf [ GYPSUMS ] / molarv [ GYPSUMS ];
5084 /* 1.5 moles of water per mole of gypsum formed */
5085 molesdh2o += ( float ) count [ DIFFHEM ] * 1.5 / molarv [ GYPSUMS ];
5086 } else if ( i == C3S ) {
5087 alpha += ( float ) ( c3sinit - count [ C3S ] );
5088 mass_now += specgrav [ C3S ] * ( float ) count [ C3S ];
5089 heat4 += .517 * ( float ) ( c3sinit - count [ C3S ] ) * specgrav [ C3S ];
5090 } else if ( i == C2S ) {
5091 alpha += ( float ) ( c2sinit - count [ C2S ] );
5092 mass_now += specgrav [ C2S ] * ( float ) count [ C2S ];
5093 heat4 += .262 * ( float ) ( c2sinit - count [ C2S ] ) * specgrav [ C2S ];
5094 } else if ( i == C3A ) {
5095 alpha += ( float ) ( c3ainit - count [ C3A ] );
5096 mass_now += specgrav [ C3A ] * ( float ) count [ C3A ];
5097 mc3ar = ( c3ainit - ( float ) count [ C3A ] ) / molarv [ C3A ];
5098 mc4ar = ( c4afinit - ( float ) count [ C4AF ] ) / molarv [ C4AF ];
5099 if ( ( mc3ar + mc4ar ) > 0.0 ) {
5100 frhyg = ( mc3ar / ( mc3ar + mc4ar ) ) * ( float ) count [ C3AH6 ] / molarv [ C3AH6 ];
5101 } else {
5102 frhyg = 0.0;
5103 }
5104
5105 frettr = ( float ) count [ ETTR ] / molarv [ ETTR ];
5106 frafm = 3 * ( float ) count [ AFM ] / molarv [ AFM ];
5107 frtot = frafm + frettr + frhyg;
5108 if ( frtot > 0.0 ) {
5109 frettr /= frtot;
5110 frafm /= frtot;
5111 frhyg /= frtot;
5112 heat4 += frafm * 1.144 * ( float ) ( c3ainit - count [ C3A ] ) * specgrav [ C3A ];
5113 heat4 += frhyg * 0.908 * ( float ) ( c3ainit - count [ C3A ] ) * specgrav [ C3A ];
5114 heat4 += frettr * 1.672 * ( float ) ( c3ainit - count [ C3A ] ) * specgrav [ C3A ];
5115 }
5116 } else if ( i == C4AF ) {
5117 alpha += ( float ) ( c4afinit - count [ C4AF ] );
5118 mass_now += specgrav [ C4AF ] * ( float ) count [ C4AF ];
5119 mc3ar = ( c3ainit - ( float ) count [ C3A ] ) / molarv [ C3A ];
5120 mc4ar = ( c4afinit - ( float ) count [ C4AF ] ) / molarv [ C4AF ];
5121 if ( ( mc3ar + mc4ar ) > 0.0 ) {
5122 frhyg = ( mc4ar / ( mc3ar + mc4ar ) ) * ( float ) count [ C3AH6 ] / molarv [ C3AH6 ];
5123 } else {
5124 frhyg = 0.0;
5125 }
5126
5127 frettr = ( float ) count [ ETTRC4AF ] / molarv [ ETTRC4AF ];
5128 frtot = frettr + frhyg;
5129 if ( frtot > 0.0 ) {
5130 frettr /= frtot;
5131 frhyg /= frtot;
5132 heat4 += frhyg * .418 * ( float ) ( c4afinit - count [ C4AF ] ) * specgrav [ C4AF ];
5133 heat4 += frettr * .725 * ( float ) ( c4afinit - count [ C4AF ] ) * specgrav [ C4AF ];
5134 }
5135 }
5136 /* else if(i==GYPSUM){
5137 * alpha+=(float)(ncsbar-count[GYPSUM]);
5138 * mass_now+=specgrav[GYPSUM]*(float)count[GYPSUM];
5139 * } */
5140 /* 0.187 kJ/g anhydrite for anhydrite --> gypsum conversion */
5141 else if ( i == ANHYDRITE ) {
5142 /* alpha+=(float)(anhinit-count[ANHYDRITE]);
5143 * mass_now+=specgrav[ANHYDRITE]*(float)count[ANHYDRITE]; */
5144 heat4 += .187 * ( float ) ( anhinit - count [ ANHYDRITE ] ) * specgrav [ ANHYDRITE ];
5145 /* 2 moles of water consumed per mole of anhydrite reacted */
5146 molesh2o += ( float ) ( anhinit - count [ ANHYDRITE ] ) * 2.0 / molarv [ ANHYDRITE ];
5147 }
5148 /* 0.132 kJ/g hemihydrate for hemihydrate-->gypsum conversion */
5149 else if ( i == HEMIHYD ) {
5150 /* alpha+=(float)(heminit-count[HEMIHYD]);
5151 * mass_now+=specgrav[HEMIHYD]*(float)count[HEMIHYD]; */
5152 heat4 += .132 * ( float ) ( heminit - count [ HEMIHYD ] ) * specgrav [ HEMIHYD ];
5153 /* 1.5 moles of water consumed per mole of anhydrite reacted */
5154 molesh2o += ( float ) ( heminit - count [ HEMIHYD ] ) * 1.5 / molarv [ HEMIHYD ];
5155 }
5156 }
5157
5158 mass_fa_now = specgrav [ ASG ] * ( float ) count [ ASG ];
5159 mass_fa_now += specgrav [ CAS2 ] * ( float ) count [ CAS2 ];
5160 mass_fa_now += specgrav [ POZZ ] * ( float ) count [ POZZ ];
5161 if ( suminit != 0 ) {
5162 alpha = alpha / ( float ) suminit;
5163 } else {
5164 alpha = 0.0;
5165 }
5166
5167 /* Current degree of hydration on a mass basis */
5168 if ( cemmass != 0.0 ) {
5169 alpha_cur = 1.0 - ( mass_now / cemmass );
5170 } else {
5171 alpha_cur = 0.0;
5172 }
5173
5174 if ( flyashmass != 0.0 ) {
5175 alpha_fa_cur = 1.0 - ( mass_fa_now / flyashmass );
5176 } else {
5177 alpha_fa_cur = 0.0;
5178 }
5179
5180 h2oinit = ( float ) porinit / molarv [ POROSITY ];
5181
5182 /* Assume 780 J/g S for pozzolanic reaction */
5183 /* Each unit of silica fume consumes 1.35 units of CH, */
5184 /* so divide npr by 1.35 to get silca fume which has reacted */
5185 heat4 += 0.78 * ( ( float ) npr / 1.35 ) * specgrav [ POZZ ];
5186
5187 /* Assume 800 J/g S for slag reaction */
5188 /* Seems reasonable with measurements of Biernacki and Richardson */
5189 heat4 += 0.8 * ( ( float ) nslagr ) * specgrav [ SLAG ];
5190
5191 /* Assume 800 J/g AS for stratlingite formation (DeLarrard) */
5192 /* Each unit of AS consumes 1.3267 units of CH, */
5193 /* so divide nasr by 1.3267 to get ASG which has reacted */
5194 heat4 += 0.80 * ( ( float ) nasr / 1.3267 ) * specgrav [ ASG ];
5195
5196 /* Should be additional code here for heat release due to CAS2 to */
5197 /* stratlingite conversion, but data unavailable at this time */
5198
5199 /* Adjust heat sum for water left in system */
5200 water_left = ( long int ) ( ( h2oinit - molesh2o ) * molarv [ POROSITY ] + 0.5 );
5201 countkeep = count [ POROSITY ];
5202 heatsum += ( h2oinit - molesh2o - molesdh2o ) * heatf [ POROSITY ];
5203 if ( cyccnt == 0 ) {
5204#ifdef OUTFILES
5205 fprintf(heatfile, "Cycle time(h) alpha_vol alpha_mass heat4(kJ/kg_solid) Gsratio2 G-s_ratio\n");
5206#endif
5207 }
5208
5209 heat_new = heat4; /* use heat4 for all adiabatic calculations */
5210 /* due to best agreement with calorimetry data */
5211
5212 if ( cyccnt == 0 ) {
5213 //fprintf(chsfile,"Cycle time(h) alpha_mass Chemical shrinkage (ml/g cement)\n");
5214 }
5215
5216 chs_new = ( ( float ) ( count [ EMPTYP ] + count [ POROSITY ] - water_left ) * heat_cf / 1000. );
5217 /* if((molesh2o>h2oinit)&&(sealed==1)){ */
5218 if ( ( ( water_left + water_off ) < 0 ) && ( sealed == 1 ) ) {
5219#ifdef PRINTF
5220 printf("All water consumed at cycle %d \n", cyccnt);
5221 fflush(stdout);
5222#endif
5223 //exit(1);the simulation can be stopped
5224 }
5225
5226 //remove defined amount of water (outer drying)
5227 //makeinert(10);
5228
5229 /* Attempt to create empty porosity to account for self-desiccation */
5230 if ( ( sealed == 1 ) && ( ( count [ POROSITY ] - water_left ) > 0 ) ) {
5231 poretodo = ( count [ POROSITY ] - pore_off ) - ( water_left - water_off );
5233 if ( poretodo > 0 ) {
5235 poregone += poretodo;
5236 }
5237 }
5238
5239 /* Output phase counts */
5240 /* phasfile for reactant and product phases */
5241#ifdef OUTFILES
5242 if ( cyccnt == 0 ) {
5243 fprintf(phasfile, "#Cycle DoH Time Porosity C3S C2S C3A C4AF GYPSUM HEMIHYD ANHYDRITE POZZ INERT SLAG ASG CAS2 CH CSH C3AH6 ETTR ETTRC4AF AFM FH3 POZZCSH SLAGCSH CACL2 FREIDEL STRAT GYPSUMS CACO3 AFMC AGG ABSGYP EMPTYP HDCSH water_left \n");
5244 fprintf(perc_phases, "#Cyc Time[h] DoH SOL_per SOL_tot| Porosity C3S C2S C3A C4AF GYPSUM HEMIHYD ANHYDRITE POZZ INERT SLAG ASG CAS2 CH CSH C3AH6 ETTR ETTRC4AF AFM FH3 POZZCSH SLAGCSH CACL2 FREIDEL STRAT GYPSUMS CACO3 AFMC AGG ABSGYP EMPTYP HDCSH\n");
5245 }
5246
5247 fprintf(phasfile, "%d %.4f %.4f ", cyccnt, alpha_cur, time_cur);
5248 fprintf(disprobfile, "%d %.4f %.4f ", cyccnt, alpha_cur, time_cur);
5249
5250
5252
5253
5254 for ( i = 0; i <= HDCSH; i++ ) {
5255 if ( ( i < DIFFCSH ) || ( i >= EMPTYP ) ) {
5256 if ( i == CSH ) {
5257 fprintf(phasfile, "%ld ", count [ CSH ] - count [ HDCSH ]);
5258 } else {
5259 fprintf(phasfile, "%ld ", count [ i ]);
5260 }
5261
5262 fprintf(disprobfile, "%f ", disprob [ i ]);
5263 }
5264
5265 // printf("%ld ",count[i]);
5266 }
5267
5268 fprintf(disprobfile, "\n");
5269 fprintf(phasfile, "%ld\n", water_left);
5270 fflush(phasfile);
5271 fflush(disprobfile);
5272#endif
5273
5274#ifdef PRINTF
5275 printf("\n");
5276#endif
5277
5278 if ( cycle == 0 ) {
5279 return;
5280 }
5281
5282#ifdef PRINTF
5283 #ifdef __TM_MODULE
5284 printf("Cycle cyccnt %d, DoH %f, time %f, GP %p\n", cyccnt, alpha_cur, time_cur, this->gp);
5285 #else
5286 printf("Cycle cyccnt %d, DoH %f, time %f\n", cyccnt, alpha_cur, time_cur);
5287 #endif
5288#endif
5289
5290 cyccnt += 1;
5291 fflush(stdout);
5292 /* Update current volume count for CH */
5293 chold = chnew;
5294 chnew = count [ CH ];
5295
5296 /* See if ettringite is soluble yet */
5297 /* Gypsum 80% consumed, changed 06.09.00 from 90% to 80% */
5298 /* Gypsum 75% consumed, changed 09.09.01 from 80% to 75% */
5299 /* or system temperature exceeds 70 C */
5300 if ( ( ( ncsbar + anhinit + heminit ) != 0.0 ) || ( temp_cur >= 70.0 ) ) {
5301 /* Account for all sulfate sources and forms */
5302 if ( ( soluble [ ETTR ] == 0 ) && ( ( temp_cur >= 70.0 ) || ( count [ AFM ] != 0 ) ||
5303 ( ( ( ( float ) count [ GYPSUM ] + 1.42 * ( float ) count [ ANHYDRITE ] + 1.4 *
5304 ( float ) count [ HEMIHYD ] + ( float ) count [ GYPSUMS ] ) / ( ( float ) ncsbar +
5305 1.42 * ( float ) anhinit + 1.4 * ( float ) heminit + ( ( float ) netbar / 3.30 ) ) ) < 0.25 ) ) ) {
5306 soluble [ ETTR ] = 1;
5307#ifdef PRINTF
5308 printf("Ettringite is soluble beginning at cycle %d \n", cycle);
5309#endif
5310 /* identify all new soluble ettringite */
5311 passone(ETTR, ETTR, 2, 0);
5312 }
5313 }
5314
5315 /* end of soluble ettringite test */
5316
5317 /* Adjust ettringite solubility */
5318 /* if too many ettringites already in solution */
5319 if ( count [ DIFFETTR ] > DETTRMAX ) {
5320 disprob [ ETTR ] = 0.0;
5321 } else {
5322 disprob [ ETTR ] = disbase [ ETTR ];
5323 }
5324
5325 /* Adjust CaCl2 solubility */
5326 /* if too many CaCl2 already in solution */
5327 if ( count [ DIFFCACL2 ] > DCACL2MAX ) {
5328 disprob [ CACL2 ] = 0.0;
5329 } else {
5330 disprob [ CACL2 ] = disbase [ CACL2 ];
5331 }
5332
5333 /* Adjust CaCO3 solubility */
5334 /* if too many CaCO3 already in solution */
5335 if ( ( count [ DIFFCACO3 ] > DCACO3MAX ) && ( soluble [ ETTR ] == 0 ) ) {
5336 disprob [ CACO3 ] = 0.0;
5337 } else if ( count [ DIFFCACO3 ] > ( 4 * DCACO3MAX ) ) {
5338 disprob [ CACO3 ] = 0.0;
5339 } else {
5340 disprob [ CACO3 ] = disbase [ CACO3 ];
5341 }
5342
5343 /* Adjust solubility of CH */
5344 /* based on amount of CH currently diffusing */
5345 /* Note that CH is always soluble to allow some */
5346 /* Ostwald ripening of the CH crystals */
5347 if ( ( float ) count [ DIFFCH ] >= CHCRIT ) {
5348 disprob [ CH ] = disbase [ CH ] * CHCRIT / ( float ) count [ DIFFCH ];
5349 } else {
5350 disprob [ CH ] = disbase [ CH ];
5351 }
5352
5353 /* Adjust solubility of CH for temperature */
5354 /* Fit to data provided in Taylor, Cement Chemistry */
5355 /* Scale to a reference temperature of 25 C */
5356 /* and adjust based on availability of pozzolan */
5357
5358#ifdef PRINTF
5359 printf("CH dissolution probability goes from %f ", disprob [ CH ]);
5360#endif
5361 disprob [ CH ] *= ( ( A0_CHSOL - A1_CHSOL * temp_cur ) / ( A0_CHSOL - A1_CHSOL * 25.0 ) );
5362 if ( ( ppozz > 0.0 ) && ( nfill > 0 ) ) {
5363 disprob [ CH ] *= ppozz / PPOZZ;
5364 }
5365
5366#ifdef PRINTF
5367 printf("to %f \n", disprob [ CH ]);
5368#endif
5369
5370 /* Adjust solubility of ASG and CAS2 phases */
5371 /* based on pH rise during hydration */
5372 /* To be added at a later date */
5373 disprob [ ASG ] = disbase [ ASG ];
5374 disprob [ CAS2 ] = disbase [ CAS2 ];
5375 /* Address solubility of C3AH6 */
5376 /* If lots of gypsum or reactive ettringite, allow C3AH6 to dissolve */
5377 /* to generate diffusing C3A species */
5378 if ( ( ( count [ GYPSUM ] + count [ GYPSUMS ] ) > ( int ) ( ( ( float ) ncsbar +
5379 1.42 * ( float ) anhinit + 1.4 * ( float ) heminit ) * 0.05 ) ) ||
5380 ( count [ ETTR ] > 500 * SYSIZE_POW3 / 1000000. ) ) {
5381 soluble [ C3AH6 ] = 1;
5382 passone(C3AH6, C3AH6, 2, 0);
5383 /* Base C3AH6 solubility on maximum sulfate in solution */
5384 /* from gypsum or ettringite available for dissolution */
5385 /* The more the sulfate, the higher this solubility should be */
5386 maxsulfate = count [ DIFFGYP ];
5387 if ( ( maxsulfate < count [ DIFFETTR ] ) && ( soluble [ ETTR ] == 1 ) ) {
5388 maxsulfate = count [ DIFFETTR ];
5389 }
5390
5391 /* Adjust C3AH6 solubility based on potential gypsum which will dissolve */
5392 /*gypready and maxsulfate is size dependent */
5393 if ( maxsulfate < ( int ) ( ( float ) gypready * disprob [ GYPSUM ] * ( float ) count [ POROSITY ] / SYSIZE_POW3 ) ) { //fixed
5394 maxsulfate = ( int ) ( ( float ) gypready * disprob [ GYPSUM ] * ( float ) count [ POROSITY ] / SYSIZE_POW3 ); //fixed
5395 }
5396
5397 if ( maxsulfate > 0 ) {
5398 disprob [ C3AH6 ] = disbase [ C3AH6 ] * ( float ) ( maxsulfate / C3AH6CRIT );
5399 if ( disprob [ C3AH6 ] > 0.5 ) {
5400 disprob [ C3AH6 ] = 0.5;
5401 }
5402 } else {
5403 disprob [ C3AH6 ] = disbase [ C3AH6 ];
5404 }
5405 } else {
5406 soluble [ C3AH6 ] = 0;
5407 }
5408
5409 /* See if silicates are soluble yet */
5410 if ( ( soluble [ C3S ] == 0 ) && ( ( cycle > 1 ) || ( count [ ETTR ] > 0 ) || ( count [ AFM ] > 0 ) || ( count [ ETTRC4AF ] > 0 ) ) ) {
5411 soluble [ C2S ] = 1;
5412 soluble [ C3S ] = 1;
5413 /* identify all new soluble silicates */
5414 passone(C3S, C2S, 2, 0);
5415 }
5416
5417 /* end of soluble silicate test */
5418 /* Adjust solubility of C3S and C2S with CSH concentration */
5419 /* for simulation of induction period */
5420
5421 tdisfact = A0_CHSOL - temp_cur * A1_CHSOL;
5422 /* printf("tdisfact is %f\n",tdisfact);
5423 * fflush(stdout); */
5424
5425 /* Calculation of cs_acc; acceleration of C3S and C2S reaction by CaSO4 */
5426 /* Calculation of ca_acc; acceleration of C3A and C4AF reaction by CaSO4 */
5427 /* November 2004 --- modified to be on a sulfate per unit initial cement */
5428 /* per unit porosity basis */
5429 /* Try using current porosity count to see if this helps in initial */
5430 /* hydration rates of sealed vs. saturated */
5431 pfract = ( float ) count [ POROSITY ] / ( float ) ( SYSIZE * SYSIZE * SYSIZE );
5432 if ( ( ncsbar + anhinit + heminit ) == 0.0 ) {
5433 cs_acc = 1.0;
5434 ca_acc = 1.0;
5435 dismin_c3a = 5.0 * DISMIN_C3A_0;
5436 dismin_c4af = 5.0 * DISMIN_C4AF_0;
5437 } else {
5439 sulf_conc *= ( 1000000. / SYSIZE_POW3 ); //fixed
5440 if ( sulf_conc < 10.0 ) {
5441 cs_acc = 1.0;
5442 ca_acc = 1.0;
5445 } else if ( sulf_conc < 20.0 ) {
5446 cs_acc = 1.0 + ( ( sulf_conc ) - 10.0 ) / 10.0;
5447 ca_acc = 1.0;
5450 } else {
5451 cs_acc = 1.0 + ( double ) log10(sulf_conc - 10.0);
5452 ca_acc = 1.0;
5453 dismin_c3a = ( 6.0 - ( double ) log10(sulf_conc) ) * DISMIN_C3A_0;
5454 dismin_c4af = ( 6.0 - ( double ) log10(sulf_conc) ) * DISMIN_C4AF_0;
5455 if ( dismin_c3a < DISMIN_C3A_0 ) {
5457 }
5458
5459 if ( dismin_c4af < DISMIN_C4AF_0 ) {
5461 }
5462 }
5463 }
5464
5465 /* Suggest change WCSCALE/w_to_c to (0.3125+WCSCALE)/(0.3125+w_to_c) */
5466 /* to have the induction period scaling depend on volume of CSH */
5467 /* produced per volume (not mass) of cement */
5468 /* dfact=tdisfact*((float)count[CSH]/((float)CSHSCALE*(0.3125+WCSCALE)/(w_to_c+0.3125)))*((float)count[CSH]/((float)CSHSCALE*(0.3125+WCSCALE)/(w_to_c+0.3125)))*cs_acc;*/
5469 /* October 2004 --- changed to truly scale with volume of cement in */
5470 /* system for both plain portland cements and filled systems */
5471
5472 dfact = tdisfact * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * cs_acc;
5473
5474 disprob [ C3S ] = DISMIN + dfact * disbase [ C3S ];
5475 disprob [ C2S ] = DISMIN2 + dfact * disbase [ C2S ];
5476 if ( disprob [ C3S ] > ( 1. * disbase [ C3S ] ) ) {
5477 disprob [ C3S ] = ( 1. * disbase [ C3S ] );
5478 }
5479
5480 if ( disprob [ C2S ] > ( 1. * disbase [ C2S ] ) ) {
5481 disprob [ C2S ] = ( 1. * disbase [ C2S ] );
5482 }
5483
5484 /* Also adjust slag and fly ash dissolution rates here */
5485 /* Really slow down initial slag and fly ash dissolutions */
5486 /* Ultimately should be linked to pH of pore solution, most likely */
5487 disprob [ SLAG ] = slagreact * ( DISMINSLAG + dfact * disbase [ SLAG ] ) / 10.0;
5488 if ( disprob [ SLAG ] > ( slagreact * disbase [ SLAG ] ) ) {
5489 disprob [ SLAG ] = ( slagreact * disbase [ SLAG ] );
5490 }
5491
5492 if ( disprob [ C3S ] == disbase [ C3S ] ) {
5493 disprob [ SLAG ] = slagreact * disbase [ SLAG ];
5494 }
5495
5496 disprob [ ASG ] = DISMINASG + dfact * disbase [ ASG ] / 5.0;
5497 if ( disprob [ ASG ] > ( 1. * disbase [ ASG ] ) ) {
5498 disprob [ ASG ] = ( 1. * disbase [ ASG ] );
5499 }
5500
5501 if ( disprob [ C3S ] == disbase [ C3S ] ) {
5502 disprob [ ASG ] = disbase [ ASG ];
5503 }
5504
5505 disprob [ CAS2 ] = DISMINCAS2 + dfact * disbase [ CAS2 ] / 5.0;
5506 if ( disprob [ CAS2 ] > ( 1. * disbase [ CAS2 ] ) ) {
5507 disprob [ CAS2 ] = ( 1. * disbase [ CAS2 ] );
5508 }
5509
5510 if ( disprob [ C3S ] == disbase [ C3S ] ) {
5511 disprob [ CAS2 ] = disbase [ CAS2 ];
5512 }
5513
5514 /* Adjust CAS2 solubility */
5515 /* if too many CAS2 already in solution */
5516 if ( count [ DIFFCAS2 ] > DCAS2MAX ) {
5517 disprob [ CAS2 ] = 0.0;
5518 }
5519
5520#ifdef PRINTF
5521 printf("Silicate probabilities: %f %f\n", disprob [ C3S ], disprob [ C2S ]);
5522#endif
5523 fflush(stdout);
5524 /* Assume that aluminate dissolution controlled by formation */
5525 /* of impermeable layer proportional to CSH concentration */
5526 /* if sulfates are present in the system */
5527
5528 /* dfact1=tdisfact*((float)count[CSH]/CSHSCALE)*((float)count[CSH]/CSHSCALE)*ca_acc; */
5529 if ( ( ncsbar + heminit + anhinit ) > 1000 * SYSIZE_POW3 / 1000000. ) { //fixed
5530 /* dfact1=tdisfact*((float)count[CSH]/((float)CSHSCALE*(0.3125+WCSCALE)/(0.3125+w_to_c)))*((float)count[CSH]/((float)CSHSCALE*(0.3125+WCSCALE)/(0.3125+w_to_c)))*ca_acc; */
5531 /* October 2004 --- changed to truly scale with volume of cement in */
5532 /* system for both plain portland cements and filled systems */
5533 dfact1 = tdisfact * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * ca_acc;
5534 disprob [ C3A ] = dismin_c3a + dfact1 * disbase [ C3A ];
5535 disprob [ C4AF ] = dismin_c4af + dfact1 * disbase [ C4AF ];
5536 if ( disprob [ C3A ] > ( 1. * disbase [ C3A ] ) ) {
5537 disprob [ C3A ] = ( 1. * disbase [ C3A ] );
5538 }
5539
5540 if ( disprob [ C4AF ] > ( 1. * disbase [ C4AF ] ) ) {
5541 disprob [ C4AF ] = ( 1. * disbase [ C4AF ] );
5542 }
5543
5544 /* Location to add in dissolution reduction in calcium sulfate phases */
5545 /* if needed */
5546 disprob [ GYPSUM ] = ( disbase [ GYPSUM ] / 15. ) + dfact1 * disbase [ GYPSUM ];
5547 if ( disprob [ GYPSUM ] > ( disbase [ GYPSUM ] ) ) {
5548 disprob [ GYPSUM ] = ( disbase [ GYPSUM ] );
5549 }
5550
5551 disprob [ GYPSUMS ] = ( disbase [ GYPSUMS ] / 15. ) + dfact1 * disbase [ GYPSUMS ];
5552 if ( disprob [ GYPSUMS ] > ( disbase [ GYPSUMS ] ) ) {
5553 disprob [ GYPSUMS ] = ( disbase [ GYPSUMS ] );
5554 }
5555
5556 /* Adjust gypsum solubility */
5557 /* if too many diffusing gypsums already in solution */
5558 if ( count [ DIFFGYP ] > DGYPMAX ) {
5559 disprob [ GYPSUM ] = disprob [ GYPSUMS ] = 0.0;
5560 }
5561
5562 disprob [ HEMIHYD ] = ( disbase [ HEMIHYD ] / 15. ) + dfact1 * disbase [ HEMIHYD ];
5563 if ( disprob [ HEMIHYD ] > ( disbase [ HEMIHYD ] ) ) {
5564 disprob [ HEMIHYD ] = ( disbase [ HEMIHYD ] );
5565 }
5566
5567 disprob [ ANHYDRITE ] = ( disbase [ ANHYDRITE ] / 15. ) + dfact1 * disbase [ ANHYDRITE ];
5568 if ( disprob [ ANHYDRITE ] > ( disbase [ ANHYDRITE ] ) ) {
5569 disprob [ ANHYDRITE ] = ( disbase [ ANHYDRITE ] );
5570 }
5571 } else {
5572 /* Cause flash set by increasing dissolution rates of C3A and C4AF */
5573 /* each by a factor of four */
5574 disprob [ C3A ] = 4. * disbase [ C3A ];
5575 disprob [ C4AF ] = 4. * disbase [ C4AF ];
5576 disprob [ GYPSUM ] = disbase [ GYPSUM ];
5577 disprob [ HEMIHYD ] = disbase [ HEMIHYD ];
5579 }
5580
5581 /* Reduce dissolution probabilities based on saturation of system */
5582 if ( ( count [ EMPTYP ] > 0 ) && ( ( count [ POROSITY ] + count [ EMPTYP ] ) < 220000. * ( double ) ( SYSIZE_POW3 / 1000000. ) ) ) { //fixed
5583 if ( countpore == 0 ) {
5584 countpore = count [ EMPTYP ];
5585 }
5586
5587 saturation = ( float ) ( count [ POROSITY ] ) / ( float ) ( count [ POROSITY ] + ( count [ EMPTYP ] - countpore ) );
5588 /* Roughly according to results of Jensen, powers for RH
5589 * sensitivity are:
5590 * C3S-19
5591 * C2S-29
5592 * C3A, C4AF-6 */
5593 /* Adjust fly ash silicates (ASG and CAS2) and pozzolanic reactivity */
5594 /* by same factor as C3S (also CH) */
5595 disprob [ C3S ] *= ( saturation * saturation );
5596 disprob [ C3S ] *= ( saturation * saturation );
5597 disprob [ C3S ] *= ( saturation * saturation );
5598 disprob [ C3S ] *= ( saturation * saturation );
5599 disprob [ C3S ] *= ( saturation * saturation );
5600 disprob [ C3S ] *= ( saturation * saturation );
5601 disprob [ C3S ] *= ( saturation * saturation );
5602 disprob [ C3S ] *= ( saturation * saturation );
5603 disprob [ C3S ] *= ( saturation * saturation );
5604 disprob [ C3S ] *= ( saturation );
5605 disprob [ SLAG ] *= ( saturation * saturation );
5606 disprob [ SLAG ] *= ( saturation * saturation );
5607 disprob [ SLAG ] *= ( saturation * saturation );
5608 disprob [ SLAG ] *= ( saturation * saturation );
5609 disprob [ SLAG ] *= ( saturation * saturation );
5610 disprob [ SLAG ] *= ( saturation * saturation );
5611 disprob [ SLAG ] *= ( saturation * saturation );
5612 disprob [ SLAG ] *= ( saturation * saturation );
5613 disprob [ SLAG ] *= ( saturation * saturation );
5614 disprob [ SLAG ] *= ( saturation );
5615 disprob [ CH ] *= ( saturation * saturation );
5616 disprob [ CH ] *= ( saturation * saturation );
5617 disprob [ CH ] *= ( saturation * saturation );
5618 disprob [ CH ] *= ( saturation * saturation );
5619 disprob [ CH ] *= ( saturation * saturation );
5620 disprob [ CH ] *= ( saturation * saturation );
5621 disprob [ CH ] *= ( saturation * saturation );
5622 disprob [ CH ] *= ( saturation * saturation );
5623 disprob [ CH ] *= ( saturation * saturation );
5624 disprob [ CH ] *= ( saturation );
5625 disprob [ ASG ] *= ( saturation * saturation );
5626 disprob [ ASG ] *= ( saturation * saturation );
5627 disprob [ ASG ] *= ( saturation * saturation );
5628 disprob [ ASG ] *= ( saturation * saturation );
5629 disprob [ ASG ] *= ( saturation * saturation );
5630 disprob [ ASG ] *= ( saturation * saturation );
5631 disprob [ ASG ] *= ( saturation * saturation );
5632 disprob [ ASG ] *= ( saturation * saturation );
5633 disprob [ ASG ] *= ( saturation * saturation );
5634 disprob [ ASG ] *= ( saturation );
5635 disprob [ CAS2 ] *= ( saturation * saturation );
5636 disprob [ CAS2 ] *= ( saturation * saturation );
5637 disprob [ CAS2 ] *= ( saturation * saturation );
5638 disprob [ CAS2 ] *= ( saturation * saturation );
5639 disprob [ CAS2 ] *= ( saturation * saturation );
5640 disprob [ CAS2 ] *= ( saturation * saturation );
5641 disprob [ CAS2 ] *= ( saturation * saturation );
5642 disprob [ CAS2 ] *= ( saturation * saturation );
5643 disprob [ CAS2 ] *= ( saturation * saturation );
5644 disprob [ CAS2 ] *= ( saturation );
5645 ppozz *= ( saturation * saturation );
5646 ppozz *= ( saturation * saturation );
5647 ppozz *= ( saturation * saturation );
5648 ppozz *= ( saturation * saturation );
5649 ppozz *= ( saturation * saturation );
5650 ppozz *= ( saturation * saturation );
5651 ppozz *= ( saturation * saturation );
5652 ppozz *= ( saturation * saturation );
5653 ppozz *= ( saturation * saturation );
5654 ppozz *= ( saturation );
5655 disprob [ C2S ] *= ( saturation * saturation );
5656 disprob [ C2S ] *= ( saturation * saturation );
5657 disprob [ C2S ] *= ( saturation * saturation );
5658 disprob [ C2S ] *= ( saturation * saturation );
5659 disprob [ C2S ] *= ( saturation * saturation );
5660 disprob [ C2S ] *= ( saturation * saturation );
5661 disprob [ C2S ] *= ( saturation * saturation );
5662 disprob [ C2S ] *= ( saturation * saturation );
5663 disprob [ C2S ] *= ( saturation * saturation );
5664 disprob [ C2S ] *= ( saturation * saturation );
5665 disprob [ C2S ] *= ( saturation * saturation );
5666
5667 disprob [ C2S ] *= ( saturation * saturation );
5668 disprob [ C2S ] *= ( saturation * saturation );
5669 disprob [ C2S ] *= ( saturation * saturation );
5670 disprob [ C2S ] *= ( saturation );
5671 disprob [ C3A ] *= ( saturation * saturation );
5672 disprob [ C3A ] *= ( saturation * saturation );
5673 disprob [ C3A ] *= ( saturation * saturation );
5674 disprob [ C4AF ] *= ( saturation * saturation );
5675 disprob [ C4AF ] *= ( saturation * saturation );
5676 disprob [ C4AF ] *= ( saturation * saturation );
5677 }
5678
5679#ifdef PRINTF
5680 printf("Silicate and aluminate probabilities: %f %f %f %f\n", disprob [ C3S ], disprob [ C2S ], disprob [ C3A ], disprob [ C4AF ]);
5681 printf("cs_acc is %f and ca_acc is %f sulf_cur is %ld\n", cs_acc, ca_acc, sulf_cur);
5682#endif
5683 fflush(stdout);
5684 /* Pass two- perform the dissolution of species */
5685 /* Determine the pH factor to use */
5686 pHfactor = 0.0;
5687 if ( ( pHactive == 1 ) && ( count [ CSH ] > ( ( CSHSCALE * surffract * surffract * totfract * totfract / tfractw04 / tfractw04 ) / 8.0 ) ) ) {
5688 pHfactor = 1.5;
5689 if ( pH_cur > 12.5 ) {
5690 pHfactor = 1.0;
5691 }
5692
5693 /* 2/02*/
5694 /* pHfactor=0.30*(((14.1-pH_cur)/0.3)-1.0); */
5695 /* 3/02*/
5696 /* pHfactor=0.60*(((14.1-pH_cur)/0.5)-1.0); */
5697 if ( pH_cur > 12.75 ) {
5698 pHfactor = 0.667;
5699 }
5700
5701 if ( pH_cur > 13.00 ) {
5702 pHfactor = 0.333;
5703 }
5704
5705 if ( pH_cur > 13.25 ) {
5706 pHfactor = ( 0.0 );
5707 }
5708
5709 if ( pH_cur > 13.75 ) {
5710 pHfactor = ( -0.25 );
5711 }
5712
5713 pHfactor += concsulfate; /* influence of sulfate on reactivity */
5714 }
5715
5716 nhgd = 0;
5717 /* Update molar volume ratios for CSH formation */
5718 pc3scsh = molarvcsh [ cyccnt ] / molarv [ C3S ] - 1.0;
5719 pc2scsh = molarvcsh [ cyccnt ] / molarv [ C2S ] - 1.0;
5720 /* Once again, scan all pixels in microstructure */
5721 slagemptyp = 0;
5722 for ( xloop = 0; xloop < SYSIZE; xloop++ ) {
5723 for ( yloop = 0; yloop < SYSIZE; yloop++ ) {
5724 for ( zloop = 0; zloop < SYSIZE; zloop++ ) {
5725 if ( mic [ xloop ] [ yloop ] [ zloop ] > OFFSET ) {
5726 phid = mic [ xloop ] [ yloop ] [ zloop ] - OFFSET;
5727 /* attempt a one-step random walk to dissolve */
5728 plnew = ( int ) ( ( float ) NEIGHBORS * ran1(seed) );
5729 if ( ( plnew < 0 ) || ( plnew >= NEIGHBORS ) ) {
5730 plnew = NEIGHBORS - 1;
5731 }
5732
5733 xc = xloop + xoff [ plnew ];
5734 yc = yloop + yoff [ plnew ];
5735 zc = zloop + zoff [ plnew ];
5736 if ( xc < 0 ) {
5737 xc = ( SYSIZEM1 );
5738 }
5739
5740 if ( yc < 0 ) {
5741 yc = ( SYSIZEM1 );
5742 }
5743
5744 if ( xc >= SYSIZE ) {
5745 xc = 0;
5746 }
5747
5748 if ( yc >= SYSIZE ) {
5749 yc = 0;
5750 }
5751
5752 if ( zc < 0 ) {
5753 zc = ( SYSIZEM1 );
5754 }
5755
5756 if ( zc >= SYSIZE ) {
5757 zc = 0;
5758 }
5759
5760 /* Generate probability for dissolution */
5761 pdis = ran1(seed);
5762 /* Bias dissolution for one pixel particles as */
5763 /* indicated by a pixel value of zero in the */
5764 /* particle microstructure image */
5765 if ( ( ( pdis <= ( disprob [ phid ] / ( 1. + pHfactor * pHeffect [ phid ] ) ) ) || ( ( pdis <= ( onepixelbias * disprob [ phid ] / ( 1. + pHfactor * pHeffect [ phid ] ) ) ) && ( micpart [ xloop ] [ yloop ] [ zloop ] == 0 ) ) ) && ( mic [ xc ] [ yc ] [ zc ] == POROSITY ) ) { //not fixed yet for one-voxel particles
5766 discount [ phid ] += 1;
5767 cread = creates [ phid ];
5768 count [ phid ] -= 1;
5769 mic [ xloop ] [ yloop ] [ zloop ] = POROSITY;
5770 if ( phid == C3AH6 ) {
5771 nhgd += 1;
5772 }
5773
5774 /* Special dissolution for C4AF */
5775 if ( phid == C4AF ) {
5776 plfh3 = ran1(seed);
5777 if ( ( plfh3 < 0.0 ) || ( plfh3 > 1.0 ) ) {
5778 plfh3 = 1.0;
5779 }
5780
5781 /* For every C4AF that dissolves, 0.5453 */
5782 /* diffusing FH3 species should be created */
5783 if ( plfh3 <= 0.5453 ) {
5784 cread = DIFFFH3;
5785 }
5786 }
5787
5788 if ( cread == POROSITY ) {
5789 count [ POROSITY ] += 1;
5790 }
5791
5792 if ( cread != POROSITY ) {
5793 nmade += 1;
5794 ngoing += 1;
5795 phnew = cread;
5796 count [ phnew ] += 1;
5797 mic [ xc ] [ yc ] [ zc ] = phnew;
5798 antadd = ( struct ants * ) malloc( sizeof( struct ants ) );
5799 antadd->x = xc;
5800 antadd->y = yc;
5801 antadd->z = zc;
5802 antadd->id = phnew;
5803 antadd->cycbirth = cyccnt;
5804 /* Now connect this ant structure to end of linked list */
5805 antadd->prevant = tailant;
5806 tailant->nextant = antadd;
5807 antadd->nextant = NULL;
5808 tailant = antadd;
5809 }
5810
5811 /* Extra CSH diffusing species based on current temperature */
5812 if ( ( phid == C3S ) || ( phid == C2S ) ) {
5813 plfh3 = ran1(seed);
5814 if ( ( ( phid == C2S ) && ( plfh3 <= pc2scsh ) ) || ( plfh3 <= pc3scsh ) ) {
5815 cshboxsize = ( int ) ( 3. + 5. * ( 40. - temp_cur ) / 20. );
5816 if ( cshboxsize < 1 ) {
5817 cshboxsize = 1;
5818 }
5819
5820 if ( cshboxsize >= SYSIZE ) {
5822 }
5823
5824 //11.12.2006 smilauer
5825 placed = loccsh(xc, yc, zc, cshboxsize);
5826 if ( placed != 0 ) {
5827 count [ DIFFCSH ] += 1;
5828 count [ POROSITY ] -= 1;
5829 } else {
5830 cshrand += 1;
5831 }
5832 }
5833 }
5834
5835 if ( ( phid == C2S ) && ( pc2scsh > 1.0 ) ) {
5836 plfh3 = ran1(seed);
5837 if ( plfh3 <= ( pc2scsh - 1.0 ) ) {
5838 cshboxsize = ( int ) ( 3. + 5. * ( 40. - temp_cur ) / 20. );
5839 if ( cshboxsize < 1 ) {
5840 cshboxsize = 1;
5841 }
5842
5843 if ( cshboxsize >= SYSIZE ) {
5845 }
5846
5847 //11.12.2006 smilauer
5848 placed = loccsh(xc, yc, zc, cshboxsize);
5849 if ( placed != 0 ) {
5850 count [ DIFFCSH ] += 1;
5851 count [ POROSITY ] -= 1;
5852 } else {
5853 cshrand += 1;
5854 }
5855 }
5856 }
5857 } else {
5858 mic [ xloop ] [ yloop ] [ zloop ] -= OFFSET;
5859 }
5860 }
5861
5862 /* end of if edge loop */
5863 /* Now check if CSH to pozzolanic CSH conversion is possible */
5864 /* Only if CH is less than 15% in volume */
5865 /* Only if CSH is in contact with at least one porosity */
5866 /* and user wishes to use this option */
5867 if ( ( count [ POZZ ] >= 13000 ) && ( chnew < ( 0.15 * SYSIZE * SYSIZE * SYSIZE ) ) && ( csh2flag == 1 ) ) {
5868 if ( mic [ xloop ] [ yloop ] [ zloop ] == CSH ) {
5869 if ( ( countbox(3, xloop, yloop, zloop) ) >= 1 ) {
5870 pconvert = ran1(seed);
5871 if ( pconvert < PCSH2CSH ) {
5872 count [ CSH ] -= 1;
5873 plfh3 = ran1(seed);
5874 /* molarvcsh units of C1.7SHx goes to */
5875 /* 101.81 units of C1.1SH3.9 */
5876 /* with 19.86 units of CH */
5877 /* so p=calcy */
5878 calcz = 0.0;
5879 cycnew = cshage [ xloop ] [ yloop ] [ zloop ];
5880 calcy = molarv [ POZZCSH ] / molarvcsh [ cycnew ];
5881 if ( calcy > 1.0 ) {
5882 calcz = calcy - 1.0;
5883 calcy = 1.0;
5884 printf("Problem of not creating enough pozzolanic CSH during CSH conversion \n");
5885 printf("Current temperature is %f C\n", temp_cur);
5886 }
5887
5888 if ( plfh3 <= calcy ) {
5889 mic [ xloop ] [ yloop ] [ zloop ] = POZZCSH;
5890 count [ POZZCSH ] += 1;
5891 } else {
5892 mic [ xloop ] [ yloop ] [ zloop ] = DIFFCH;
5893 nmade += 1;
5894 ncshgo += 1;
5895 ngoing += 1;
5896 count [ DIFFCH ] += 1;
5897 antadd = ( struct ants * ) malloc( sizeof( struct ants ) );
5898 antadd->x = xloop;
5899 antadd->y = yloop;
5900 antadd->z = zloop;
5901 antadd->id = DIFFCH;
5902 antadd->cycbirth = cyccnt;
5903 /* Now connect this ant structure to end of linked list */
5904 antadd->prevant = tailant;
5905 tailant->nextant = antadd;
5906 antadd->nextant = NULL;
5907 tailant = antadd;
5908 }
5909
5910 /* Possibly need even more pozzolanic CSH */
5911 /* Would need a diffusing pozzolanic
5912 * CSH species??? */
5913 /* if(calcz>0.0){
5914 * plfh3=ran1(seed);
5915 * if(plfh3<=calcz){
5916 * cshrand+=1;
5917 * }
5918 * } */
5919
5920
5921 plfh3 = ran1(seed);
5922 calcx = ( 19.86 / molarvcsh [ cycnew ] ) - ( 1. - calcy );
5923 /* Ex. 0.12658=(19.86/108.)-(1.-0.94269) */
5924 if ( plfh3 < calcx ) {
5925 npchext += 1;
5926 }
5927 }
5928 }
5929 }
5930 }
5931
5932 /* See if slag can react --- in contact with at least one porosity */
5933 if ( mic [ xloop ] [ yloop ] [ zloop ] == SLAG ) {
5934 if ( ( countbox(3, xloop, yloop, zloop) ) >= 1 ) {
5935 pconvert = ran1(seed);
5936 if ( pconvert < ( disprob [ SLAG ] / ( 1. + pHfactor * pHeffect [ SLAG ] ) ) ) {
5937 nslagr += 1;
5938 count [ SLAG ] -= 1;
5939 discount [ SLAG ] += 1;
5940 /* Check on extra C3A generation */
5941 plfh3 = ran1(seed);
5942 if ( plfh3 < p5slag ) {
5943 nslagc3a += 1;
5944 }
5945
5946 /* Convert slag to reaction products */
5947 plfh3 = ran1(seed);
5948 if ( plfh3 < p1slag ) {
5949 mic [ xloop ] [ yloop ] [ zloop ] = SLAGCSH;
5950 /* Assign a plate axes identifier to this slag C-S-H voxel */
5951 msface = ( int ) ( 3. * ran1(seed) + 1. );
5952 if ( msface > 3 ) {
5953 msface = 1;
5954 }
5955
5956 faces [ xloop ] [ yloop ] [ zloop ] = msface;
5957 count [ SLAGCSH ] += 1;
5958 } else {
5959 if ( sealed == 1 ) {
5960 /* Create empty porosity at slag site */
5961 slagemptyp += 1;
5962 mic [ xloop ] [ yloop ] [ zloop ] = EMPTYP;
5963 count [ EMPTYP ] += 1;
5964 } else {
5965 mic [ xloop ] [ yloop ] [ zloop ] = POROSITY;
5966 count [ POROSITY ] += 1;
5967 }
5968 }
5969
5970 /* Add in extra SLAGCSH as needed */
5971 p3init = p3slag;
5972 while ( p3init > 1.0 ) {
5973 extslagcsh(xloop, yloop, zloop);
5974 p3init -= 1.0;
5975 }
5976
5977 plfh3 = ran1(seed);
5978 if ( plfh3 < p3init ) {
5979 extslagcsh(xloop, yloop, zloop);
5980 }
5981 }
5982 }
5983 }
5984 }
5985
5986 /* end of zloop */
5987 }
5988
5989 /* end of yloop */
5990 }
5991
5992 /* end of xloop */
5993
5994 if ( ncshgo != 0 ) {
5995 printf("CSH dissolved is %ld \n", ncshgo);
5996 }
5997
5998 if ( npchext > 0 ) {
5999 printf("npchext is %ld at cycle %d \n", npchext, cycle);
6000 }
6001
6002 /* Now add in the extra diffusing species for dissolution */
6003 /* Expansion factors from Young and Hansen and */
6004 /* Mindess and Young (Concrete) */
6005 ncshext = cshrand;
6006 if ( cshrand != 0 ) {
6007 printf("cshrand is %d \n", cshrand);
6008 }
6009
6010 /* CH, Gypsum, and diffusing C3A are added at totally random
6011 * locations as opposed to at the dissolution site
6012 * molar_weight[CH]=74 g/mol
6013 * molar_weight[C3S]=228 g/mol
6014 * only for C3S hydration - reason is the Pignat's thesis
6015 * C3S+5.3 H2O -> C1.7SH4 + 1.3 CH
6016 */
6017
6018 fchext = 1.3 * 74 * specgrav [ C3S ] / ( specgrav [ CH ] * 228 ) * ( float ) discount [ C3S ] + 0.191 * ( float ) discount [ C2S ] +
6019 0.2584 * ( float ) discount [ C4AF ]; //originally 0.61
6020
6021 nchext = ( int ) fchext;
6022 if ( fchext > ( float ) nchext ) {
6023 pdis = ran1(seed);
6024 if ( ( fchext - ( float ) nchext ) > pdis ) {
6025 nchext += 1;
6026 }
6027 }
6028
6029 nchext += npchext;
6030 /* Adjust CH addition for slag consumption and maintain deficit as needed */
6031 slagcum += discount [ SLAG ];
6032 chgone = ( int ) ( p4slag * ( float ) slagcum );
6033 nchext -= chgone;
6034 slagcum -= ( int ) ( ( float ) chgone / p4slag );
6035 nchext -= DIFFCHdeficit;
6036 DIFFCHdeficit = 0;
6037 if ( nchext < 0 ) {
6038 DIFFCHdeficit -= nchext;
6039 nchext = 0;
6040 }
6041
6042 fc3aext = discount [ C3A ] + 0.5917 * ( float ) discount [ C3AH6 ];
6043 nc3aext = ( int ) ( fc3aext + nslagc3a );
6044 if ( fc3aext > ( float ) nc3aext ) {
6045 pdis = ran1(seed);
6046 if ( ( fc3aext - ( float ) nc3aext ) > pdis ) {
6047 nc3aext += 1;
6048 }
6049 }
6050
6051 fc4aext = 0.696 * ( float ) discount [ C4AF ];
6052 nc4aext = ( int ) fc4aext;
6053 if ( fc4aext > ( float ) nc4aext ) {
6054 pdis = ran1(seed);
6055 if ( ( fc4aext - ( float ) nc4aext ) > pdis ) {
6056 nc4aext += 1;
6057 }
6058 }
6059
6060 /* both forms of GYPSUM form same DIFFGYP species */
6061 ngypext = discount [ GYPSUM ] + discount [ GYPSUMS ];
6062 /* Convert to diffusing anhydrite at volume necessary for final */
6063 /* gypsum formation (1 anhydrite --> 1.423 gypsum) */
6064 /* Since hemihydrate can now react with C3A, etc., can't */
6065 /* do expansion here any longer 7/99 */
6066 /* fanhext=1.423*(float)discount[ANHYDRITE]; */
6067 fanhext = ( float ) discount [ ANHYDRITE ];
6068 nanhext = ( int ) fanhext;
6069 if ( fanhext > ( float ) nanhext ) {
6070 pdis = ran1(seed);
6071 if ( ( fanhext - ( float ) nanhext ) > pdis ) {
6072 nanhext += 1;
6073 }
6074 }
6075
6076 /* Convert to diffusing hemiydrate at volume necessary for final */
6077 /* gypsum formation (1 hemihydrate --> 1.4 gypsum) */
6078 /* Since hemihydrate can now react with C3A, etc., can't */
6079 /* do expansion here any longer 7/99 */
6080 fhemext = ( float ) discount [ HEMIHYD ];
6081 /* fhemext=1.3955*(float)discount[HEMIHYD]; */
6082
6083 nhemext = ( int ) fhemext;
6084 if ( fhemext > ( float ) nhemext ) {
6085 pdis = ran1(seed);
6086 if ( ( fhemext - ( float ) nhemext ) > pdis ) {
6087 nhemext += 1;
6088 }
6089 }
6090
6091 count [ DIFFGYP ] += ngypext;
6092 count [ DIFFANH ] += nanhext;
6093 count [ DIFFHEM ] += nhemext;
6094 count [ DIFFCH ] += nchext;
6095 count [ DIFFCSH ] += ncshext;
6096 count [ DIFFC3A ] += nc3aext;
6097 count [ DIFFC4A ] += nc4aext;
6098
6099 nsum2 = nchext + ncshext;
6100 nsum3 = nsum2 + nc3aext;
6101 nsum4 = nsum3 + nc4aext;
6102 nsum5 = nsum4 + ngypext;
6103 nsum6 = nsum5 + nhemext;
6104 fflush(stdout);
6105
6106 //add extra diffusing species - check for infinite looping if porosity is not available - smilauer 01/16/2008
6107 for ( xext = 1; xext <= ( nsum6 + nanhext ); xext++ ) {
6108 plok = 0;
6109 tries = 0;
6110 do {
6111 xc = ( int ) ( ( float ) SYSIZE * ran1(seed) ); //locate random place in the microstructure
6112 yc = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6113 zc = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6114 if ( xc >= SYSIZE ) {
6115 xc = 0;
6116 }
6117
6118 if ( yc >= SYSIZE ) {
6119 yc = 0;
6120 }
6121
6122 if ( zc >= SYSIZE ) {
6123 zc = 0;
6124 }
6125
6126 tries++;
6127
6128 if ( mic [ xc ] [ yc ] [ zc ] == POROSITY ) {
6129 plok = 1;
6130 phid = DIFFCH;
6131 count [ POROSITY ] -= 1;
6132 if ( xext > nsum6 ) {
6133 phid = DIFFANH;
6134 } else if ( xext > nsum5 ) {
6135 phid = DIFFHEM;
6136 } else if ( xext > nsum4 ) {
6137 phid = DIFFGYP;
6138 } else if ( xext > nsum3 ) {
6139 phid = DIFFC4A;
6140 } else if ( xext > nsum2 ) {
6141 phid = DIFFC3A;
6142 } else if ( xext > nchext ) {
6143 phid = DIFFCSH;
6144 }
6145
6146 mic [ xc ] [ yc ] [ zc ] = phid;
6147 nmade += 1;
6148 ngoing += 1;
6149 antadd = ( struct ants * ) malloc( sizeof( struct ants ) );
6150 //printf("MEM addr %p\n", (const void *)antadd);
6151 antadd->x = xc;
6152 antadd->y = yc;
6153 antadd->z = zc;
6154 antadd->id = phid;
6155 antadd->cycbirth = cyccnt;
6156 /* Now connect this ant structure to end of linked list */
6157 antadd->prevant = tailant;
6158 tailant->nextant = antadd;
6159 antadd->nextant = NULL;
6160 tailant = antadd;
6161 }
6162
6163 if ( tries > 10 * SYSIZE_POW3 ) {
6164#ifdef PRINTF
6165 printf("Could not place extra diffusing species (too few POROSITY voxels), continuing (line %d),\n", __LINE__);
6166#endif
6167 continue;
6168 }
6169 } while ( plok == 0 );
6170 }
6171
6172 /* end of xext for extra species generation */
6173
6174#ifdef PRINTF
6175 printf("Dissolved- %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", count [ DIFFCSH ],
6176 count [ DIFFCH ], count [ DIFFGYP ], count [ DIFFC3A ], count [ DIFFFH3 ],
6177 count [ DIFFETTR ], count [ DIFFAS ], count [ DIFFANH ], count [ DIFFHEM ],
6179#endif
6180
6181 sulf_cur = count [ DIFFGYP ] + count [ DIFFANH ] + count [ DIFFHEM ];
6182 /* difffile=fopen("diffuse.out","a");
6183 * fprintf(difffile,"%d %ld %f %f %f %f %f %f %f\n",cycle, sulf_cur, cs_acc, ca_acc, disprob[C3S], disprob[C3A], disprob[C4AF], dfact, dfact1);
6184 *
6185 * fclose(difffile); */
6186
6187 /* if too many diffusing gypsums already in solution */
6188 if ( sulf_cur > DGYPMAX ) {
6189 disprob [ GYPSUM ] = disprob [ GYPSUMS ] = 0.0;
6190 } else {
6191 disprob [ GYPSUM ] = disbase [ GYPSUM ];
6193 disprob [ HEMIHYD ] = disbase [ HEMIHYD ];
6194 disprob [ GYPSUMS ] = disbase [ GYPSUMS ];
6195 }
6196
6197#ifdef PRINTF
6198 printf("C3AH6 dissolved- %ld with prob. of %f \n", nhgd, disprob [ C3AH6 ]);
6199#endif
6200
6201 fflush(stdout);
6202 ( void ) nsurf;
6203 ( void ) calcz;
6204}
6205/* routine to add nneed one pixel elements of phase randid at random */
6206/* locations in microstructure */
6207/* Special features for addition of 1-pixel CACO3 and INERT particles */
6208/* added 5/26/2004 */
6209/* Called by main program */
6210/* Calls no other routines */
6211void CemhydMatStatus :: addrand(int randid, long int nneed)
6212{
6213 int ix, iy, iz;
6214 long int ic;
6215 int success, cpores;
6216
6217 /* Add number of requested phase pixels at random pore locations */
6218 for ( ic = 1; ic <= nneed; ic++ ) {
6219 success = 0;
6220 while ( success == 0 ) {
6221 ix = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6222 iy = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6223 iz = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6224 if ( ix == SYSIZE ) {
6225 ix = 0;
6226 }
6227
6228 if ( iy == SYSIZE ) {
6229 iy = 0;
6230 }
6231
6232 if ( iz == SYSIZE ) {
6233 iz = 0;
6234 }
6235
6236 if ( mic [ ix ] [ iy ] [ iz ] == POROSITY ) {
6237 if ( ( randid != CACO3 ) && ( randid != INERT ) ) {
6238 mic [ ix ] [ iy ] [ iz ] = randid;
6239 micorig [ ix ] [ iy ] [ iz ] = randid;
6240 success = 1;
6241 } else {
6242 cpores = countboxc(3, ix, iy, iz);
6243 if ( cpores >= 26 ) {
6244 mic [ ix ] [ iy ] [ iz ] = randid;
6245 micorig [ ix ] [ iy ] [ iz ] = randid;
6246 success = 1;
6247 }
6248 }
6249 }
6250 }
6251 }
6252}
6253/* Routine measuresurf to measure initial surface counts for cement */
6254/* and for all phases (cement= C3S, C2S, C3A, C4AF, and calcium sulfates */
6255void CemhydMatStatus :: measuresurf()
6256{
6257 int sx, sy, sz, jx = 0, jy = 0, jz = 0, faceid;
6258
6259 for ( sx = 0; sx < SYSIZE; sx++ ) {
6260 for ( sy = 0; sy < SYSIZE; sy++ ) {
6261 for ( sz = 0; sz < SYSIZE; sz++ ) {
6262 if ( mic [ sx ] [ sy ] [ sz ] == POROSITY ) {
6263 for ( faceid = 0; faceid < 6; faceid++ ) {
6264 if ( faceid == 1 ) {
6265 jx = sx - 1;
6266 if ( jx < 0 ) {
6267 jx = SYSIZE - 1;
6268 }
6269
6270 jy = sy;
6271 jz = sz;
6272 } else if ( faceid == 0 ) {
6273 jx = sx + 1;
6274 if ( jx > ( SYSIZE - 1 ) ) {
6275 jx = 0;
6276 }
6277
6278 jy = sy;
6279 jz = sz;
6280 } else if ( faceid == 2 ) {
6281 jy = sy + 1;
6282 if ( jy > ( SYSIZE - 1 ) ) {
6283 jy = 0;
6284 }
6285
6286 jx = sx;
6287 jz = sz;
6288 } else if ( faceid == 3 ) {
6289 jy = sy - 1;
6290 if ( jy < 0 ) {
6291 jy = SYSIZE - 1;
6292 }
6293
6294 jx = sx;
6295 jz = sz;
6296 } else if ( faceid == 4 ) {
6297 jz = sz + 1;
6298 if ( jz > ( SYSIZE - 1 ) ) {
6299 jz = 0;
6300 }
6301
6302 jx = sx;
6303 jy = sy;
6304 } else if ( faceid == 5 ) {
6305 jz = sz - 1;
6306 if ( jz < 0 ) {
6307 jz = SYSIZE - 1;
6308 }
6309
6310 jx = sx;
6311 jy = sy;
6312 }
6313
6314 /* If the neighboring pixel is solid, update surface counts */
6315 if ( ( mic [ jx ] [ jy ] [ jz ] == C3S ) || ( mic [ jx ] [ jy ] [ jz ] == C2S ) || ( mic [ jx ] [ jy ] [ jz ] == C3A ) || ( mic [ jx ] [ jy ] [ jz ] == C4AF ) || ( mic [ jx ] [ jy ] [ jz ] == INERT ) || ( mic [ jx ] [ jy ] [ jz ] == CACO3 ) ) {
6316 scnttotal += 1;
6317 if ( ( mic [ jx ] [ jy ] [ jz ] == C3S ) || ( mic [ jx ] [ jy ] [ jz ] == C2S ) || ( mic [ jx ] [ jy ] [ jz ] == C3A ) || ( mic [ jx ] [ jy ] [ jz ] == C4AF ) ) {
6318 scntcement += 1;
6319 }
6320 }
6321 }
6322 }
6323 }
6324 }
6325 }
6326
6327#ifdef PRINTF
6328 printf("Cement surface count is %ld \n", scntcement);
6329 printf("Total surface count is %ld \n", scnttotal);
6330#endif
6331
6332 surffract = ( float ) scntcement / ( float ) scnttotal;
6333
6334#ifdef PRINTF
6335 printf("Surface fraction is %f \n", surffract);
6336#endif
6337
6338 fflush(stdout);
6339}
6340
6341/* Routine to resaturate all empty porosity */
6342/* and continue with hydration under saturated conditions */
6343void CemhydMatStatus :: resaturate()
6344{
6345 int sx, sy, sz;
6346 long int nresat = 0;
6347
6348 for ( sx = 0; sx < SYSIZE; sx++ ) {
6349 for ( sy = 0; sy < SYSIZE; sy++ ) {
6350 for ( sz = 0; sz < SYSIZE; sz++ ) {
6351 if ( mic [ sx ] [ sy ] [ sz ] == EMPTYP ) {
6352 mic [ sx ] [ sy ] [ sz ] = POROSITY;
6353 nresat++;
6354 }
6355 }
6356 }
6357 }
6358
6359 if ( nresat > 0 ) {
6360 porefl1 = porefl2 = porefl3 = 1;
6361 }
6362
6363 printf("Number resaturated is %ld \n", nresat);
6364 fflush(stdout);
6365}
6366
6367
6368/*called from main loop*/
6369void CemhydMatStatus :: outputImageFileUnperc(char ***m)
6370{
6371 FILE *imgout;
6372 char extension [ 10 ];
6373 //char outputname[80];
6374 char *prefix;
6375 prefix = ( char * ) malloc(80);
6376
6377 //mkdir("unperc", 0777);//make directory (every time)
6378 //system("mk unperc");
6379 //system("mkdir unperc 2> /dev/null");
6380 fprintf(infoUnperc, "%d %.4f %.3f\n", icyc, alpha_cur, time_cur);
6381 fflush(infoUnperc);
6382
6383 sprintf(extension, "%04d", icyc);
6384 strcpy(prefix, "unperc/out5."); //see line with mkdir in order to be the same
6385 strcat(prefix, extension);
6386 strcat(prefix, ".img");
6387#ifdef PRINTF
6388 printf("Name of output file is %s\n", prefix);
6389#endif
6390
6391 if ( ( imgout = fopen(prefix, "w") ) == NULL ) {
6392 printf("File %s can not be opened\n", prefix);
6393 free(prefix);
6394 return;
6395 }
6396
6397 for ( int dz = 0; dz < SYSIZE; dz++ ) {
6398 for ( int dy = 0; dy < SYSIZE; dy++ ) {
6399 for ( int dx = 0; dx < SYSIZE; dx++ ) {
6400 fprintf(imgout, "%d\n", m [ dx ] [ dy ] [ dz ]);
6401 }
6402 }
6403 }
6404
6405 fclose(imgout);
6406#ifdef PRINTF
6407 printf("Unpercolated file %s wrote\n", prefix);
6408#endif
6409 free(prefix);
6410}
6411
6412
6413void CemhydMatStatus :: readhydrparam()
6414{
6415 int fidc3s, fidc2s, fidc3a, fidc4af, fidgyp, fidagg, ffac3a;
6416 int fidhem, fidanh, fidcaco3;
6417 int read_micr;
6418 long int valin;
6419 int ix, iy, iz, phtodo;
6420 long int nadd;
6421 char filei [ 80 ];
6422 FILE *infile;
6423
6424 /* Get random number seed */
6425 //printf("Enter random number seed \n");
6426 //fscanf(in, "%d",&nseed);
6427 nseed = iseed;
6428 seed = ( & nseed );
6429
6430#ifdef PRINTF
6431 printf("Seed %d\n", * seed);
6432#endif
6433
6434 //check whether microstructure from file should be used
6435#ifdef CMLFILE
6436 F->get_value(13, ( long & )read_micr);
6437#endif
6438#ifdef TINYXML
6439 QueryNumAttributeExt(xmlFile, "Given_microstructure", 0, read_micr);
6440#endif
6441
6442 /* Open file and read in original cement particle microstructure if required*/
6443 if ( read_micr ) {
6444#ifdef PRINTF
6445 printf("Enter name of file to read initial microstructure from \n");
6446#endif
6447#ifdef CMLFILE
6448 F->get_value(1, filei);
6449#endif
6450#ifdef TINYXML
6451 QueryStringAttributeExt(xmlFile, "Input_img_file", 0, filei);
6452#endif
6453 //fscanf(in, "%s",filei);
6454
6455#ifdef PRINTF
6456 printf("%s\n", filei);
6457 fflush(stdout);
6458#endif
6459 }
6460
6461 /* Get phase assignments for original microstructure */
6462 /* to transform to needed ID values */
6463
6464#ifdef PRINTF
6465 printf("Enter IDs in file for C3S, C2S, C3A, C4AF, Gypsum, Hemihydrate, Anhydrite, Aggregate, CaCO3\n");
6466#endif
6467
6468 fidc3s = C3S;
6469 fidc2s = C2S;
6470 fidc3a = C3A;
6471 fidc4af = C4AF;
6472 fidgyp = GYPSUM;
6473 fidhem = HEMIHYD;
6474 fidanh = ANHYDRITE;
6475 fidagg = INERTAGG;
6476 fidcaco3 = CACO3;
6477
6478 //scanf("%d %d %d %d %d %d %d %d %d",&fidc3s,&fidc2s,&fidc3a,&fidc4af,&fidgyp,&fidhem,&fidanh,&fidagg,&fidcaco3);
6479#ifdef PRINTF
6480 printf("%d %d %d %d %d %d %d %d %d\n", fidc3s, fidc2s, fidc3a, fidc4af, fidgyp, fidhem, fidanh, fidagg, fidcaco3);
6481 printf("Enter ID in file for C3A in fly ash (default=35)\n");
6482#endif
6483 //fscanf(in, "%d",&ffac3a);
6484 ffac3a = 35;
6485#ifdef PRINTF
6486 printf("%d\n", ffac3a);
6487#endif
6488 fflush(stdout);
6489
6490 if ( read_micr ) {
6491 if ( ( infile = fopen(filei, "r") ) == NULL ) {
6492 printf("CEMHYD3D microstructure file %s not found\n", filei);
6493 exit(0);
6494 }
6495
6496 for ( iz = 0; iz < SYSIZE; iz++ ) { //fixed cycle order
6497 for ( iy = 0; iy < SYSIZE; iy++ ) {
6498 for ( ix = 0; ix < SYSIZE; ix++ ) {
6499 cshage [ ix ] [ iy ] [ iz ] = 0;
6500 faces [ ix ] [ iy ] [ iz ] = 0;
6501
6502 if ( fscanf(infile, "%ld", & valin) == EOF ) {
6503 printf("End of file %s reached, terminating\n", filei);
6504 exit(1);
6505 }
6506
6507 if ( valin < 0 ) {
6508 printf("Error in the reading at x=%d y=%d z=%d, value %ld\n", ix, iy, iz, valin);
6509 exit(1);
6510 }
6511
6512 mic [ ix ] [ iy ] [ iz ] = valin;
6513 if ( valin == fidc3s ) {
6514 mic [ ix ] [ iy ] [ iz ] = C3S;
6515 } else if ( valin == fidc2s ) {
6516 mic [ ix ] [ iy ] [ iz ] = C2S;
6517 } else if ( ( valin == fidc3a ) || ( valin == ffac3a ) ) {
6518 mic [ ix ] [ iy ] [ iz ] = C3A;
6519 } else if ( valin == fidc4af ) {
6520 mic [ ix ] [ iy ] [ iz ] = C4AF;
6521 } else if ( valin == fidgyp ) {
6522 mic [ ix ] [ iy ] [ iz ] = GYPSUM;
6523 } else if ( valin == fidanh ) {
6524 mic [ ix ] [ iy ] [ iz ] = ANHYDRITE;
6525 } else if ( valin == fidhem ) {
6526 mic [ ix ] [ iy ] [ iz ] = HEMIHYD;
6527 } else if ( valin == fidcaco3 ) {
6528 mic [ ix ] [ iy ] [ iz ] = CACO3;
6529 } else if ( valin == fidagg ) {
6530 mic [ ix ] [ iy ] [ iz ] = INERTAGG;
6531 }
6532
6533 micorig [ ix ] [ iy ] [ iz ] = mic [ ix ] [ iy ] [ iz ];
6534 }
6535 }
6536 }
6537
6538 fclose(infile);
6539 } else {
6540#ifdef PRINTF
6541 printf("Generated microstructure from memory will be used\n");
6542#endif
6543 }
6544
6545 fflush(stdout);
6546
6547 /* Now read in particle IDs from file if required*/
6548 if ( read_micr ) {
6549#ifdef PRINTF
6550 printf("Enter name of file to read particle IDs from \n");
6551#endif
6552#ifdef CMLFILE
6553 F->get_value(2, filei);
6554#endif
6555#ifdef TINYXML
6556 QueryStringAttributeExt(xmlFile, "Input_id_file", 0, filei);
6557#endif
6558 //fscanf(in, "%s",filei);
6559
6560#ifdef PRINTF
6561 printf("%s\n", filei);
6562#endif
6563
6564 if ( ( infile = fopen(filei, "r") ) == NULL ) {
6565 printf("CEMHYD3D microstructure ID file %s not found\n", filei);
6566 exit(0);
6567 }
6568
6569 for ( iz = 0; iz < SYSIZE; iz++ ) { //fixed cycle order
6570 for ( iy = 0; iy < SYSIZE; iy++ ) {
6571 for ( ix = 0; ix < SYSIZE; ix++ ) {
6572 if ( fscanf(infile, "%ld", & valin) == EOF ) {
6573 printf("End of file %s reached, terminating\n", filei);
6574 exit(1);
6575 }
6576
6577 micpart [ ix ] [ iy ] [ iz ] = valin;
6578 }
6579 }
6580 }
6581
6582 fclose(infile);
6583 } else {
6584#ifdef PRINTF
6585 printf("Generated microstructure ID from memory will be used\n");
6586#endif
6587 }
6588
6589
6590 fflush(stdout);
6591
6592
6593 /* Allow user to iteratively add one pixel particles of various phases */
6594 /* Typical application would be for addition of silica fume */
6595#ifdef PRINTF
6596 printf("Enter number of one pixel particles to add (0 to quit) \n");
6597#endif
6598 //fscanf(in, "%ld",&nadd);
6599 nadd = 0;
6600
6601#ifdef PRINTF
6602 printf("%ld\n", nadd);
6603#endif
6604
6605 while ( nadd > 0 ) {
6606#ifdef PRINTF
6607 printf("Enter phase to add \n");
6608 printf(" C3S 1 \n");
6609 printf(" C2S 2 \n");
6610 printf(" C3A 3 \n");
6611 printf(" C4AF 4 \n");
6612 printf(" GYPSUM 5 \n");
6613 printf(" HEMIHYD 6 \n");
6614 printf(" ANHYDRITE 7 \n");
6615 printf(" POZZ 8 \n");
6616 printf(" INERT 9 \n");
6617 printf(" SLAG 10 \n");
6618 printf(" ASG 11 \n");
6619 printf(" CAS2 12 \n");
6620 printf(" CH 13 \n");
6621 printf(" CSH 14 \n");
6622 printf(" C3AH6 15 \n");
6623 printf(" Ettringite 16 \n");
6624 printf(" Stable Ettringite from C4AF 17 \n");
6625 printf(" AFM 18 \n");
6626 printf(" FH3 19 \n");
6627 printf(" POZZCSH 20 \n");
6628 printf(" SLAGCSH 21 \n");
6629 printf(" CACL2 22 \n");
6630 printf(" Friedels salt 23 \n");
6631 printf(" Stratlingite 24 \n");
6632 printf(" Calcium carbonate 26 \n");
6633#endif
6634 //fscanf(in, "%d",&phtodo);
6635 phtodo = 0;
6636#ifdef PRINTF
6637 printf("%d \n", phtodo);
6638#endif
6639 if ( ( phtodo < 0 ) || ( phtodo > CACO3 ) ) {
6640 printf("Error in phase input for one pixel particles \n");
6641 exit(1);
6642 }
6643
6644 addrand(phtodo, nadd);
6645
6646#ifdef PRINTF
6647 printf("Enter number of one pixel particles to add (0 to quit) \n");
6648#endif
6649
6650 //fscanf(in, "%ld",&nadd);
6651 nadd = 0;
6652#ifdef PRINTF
6653 printf("%ld\n", nadd);
6654#endif
6655 }
6656
6657 fflush(stdout);
6658
6659 //printf("Do you wish hydration under 0) saturated or 1) sealed conditions \n");
6660#ifdef CMLFILE
6661 F->get_value(3, ( long & )sealed);
6662#endif
6663#ifdef TINYXML
6664 QueryNumAttributeExt(xmlFile, "Saturated_sealed", 0, sealed);
6665#endif
6666 //fscanf(in, "%d",&sealed);
6667 //printf("%d \n",sealed);
6668 //printf("Enter max. # of diffusion steps per cycle (500) \n");
6669 //fscanf(in, "%d",&ntimes);
6670#ifdef CMLFILE
6671 F->get_value(23, ( long & )ntimes);
6672#endif
6673#ifdef TINYXML
6674 QueryNumAttributeExt(xmlFile, "Diffusion_steps_per_cycle", 0, ntimes);
6675#endif
6676 //ntimes=500;
6677 //printf("%d \n",ntimes);
6678 //printf("Enter nuc. prob. and scale factor for CH nucleation \n");
6679 //fscanf(in, "%f %f",&pnucch,&pscalech);
6680#ifdef CMLFILE
6681 F->get_value(24, pnucch);
6682 F->get_value(25, pscalech);
6683#endif
6684#ifdef TINYXML
6685 QueryNumAttributeExt(xmlFile, "CH_nucleation_probability", 0, pnucch);
6686 QueryNumAttributeExt(xmlFile, "CH_scale_factor", 0, pscalech);
6687#endif
6688 //pnucch=0.0001;
6689 //pscalech=9000.;
6690 //printf("%f %f \n",pnucch,pscalech);
6691 //printf("Enter nuc. prob. and scale factor for gypsum nucleation \n");
6692 //fscanf(in, "%f %f",&pnucgyp,&pscalegyp);
6693#ifdef CMLFILE
6694 F->get_value(26, pnucgyp);
6695 F->get_value(27, pscalegyp);
6696#endif
6697#ifdef TINYXML
6698 QueryNumAttributeExt(xmlFile, "Gypsum_nucleation_probability", 0, pnucgyp);
6699 QueryNumAttributeExt(xmlFile, "Gypsum_scale_factor", 0, pscalegyp);
6700#endif
6701 //pnucgyp=0.01;
6702 //pscalegyp=9000.;
6703 //printf("%f %f \n",pnucgyp,pscalegyp);
6704 //printf("Enter nuc. prob. and scale factor for C3AH6 nucleation \n");
6705 //fscanf(in, "%f %f",&pnuchg,&pscalehg);
6706#ifdef CMLFILE
6707 F->get_value(28, pnuchg);
6708 F->get_value(29, pscalehg);
6709#endif
6710#ifdef TINYXML
6711 QueryNumAttributeExt(xmlFile, "C3AH6_nucleation_probability", 0, pnuchg);
6712 QueryNumAttributeExt(xmlFile, "C3AH6_scale_factor", 0, pscalehg);
6713#endif
6714 //pnuchg=0.00002;
6715 //pscalehg=10000.;
6716 //printf("%f %f \n",pnuchg,pscalehg);
6717 //printf("Enter nuc. prob. and scale factor for FH3 nucleation \n");
6718 //fscanf(in, "%f %f",&pnucfh3,&pscalefh3);
6719#ifdef CMLFILE
6720 F->get_value(30, pnucfh3);
6721 F->get_value(31, pscalefh3);
6722#endif
6723#ifdef TINYXML
6724 QueryNumAttributeExt(xmlFile, "FH3_nucleation_probability", 0, pnucfh3);
6725 QueryNumAttributeExt(xmlFile, "FH3_scale_factor", 0, pscalefh3);
6726#endif
6727 //pnucfh3=0.002;
6728 //pscalefh3=2500.;
6729 //printf("%f %f \n",pnucfh3,pscalefh3);
6730 //printf("Enter cycle frequency for checking pore space percolation \n");
6731 //fscanf(in, "%d",&burnfreq);
6732#ifdef CMLFILE
6733 F->get_value(17, ( long & )burnfreq);
6734 F->get_value(33, adiabatic_curing);
6735#endif
6736#ifdef TINYXML
6737 QueryNumAttributeExt(xmlFile, "Cycle_freq_perc_pore", 0, burnfreq);
6738 QueryNumAttributeExt(xmlFile, "Adiabatic_conditions", 0, adiabatic_curing);
6739#endif
6740
6741#ifdef __TM_MODULE //OOFEM transport module
6742 adiabatic_curing = 0;
6743#endif
6744
6745#ifdef PRINTF
6746 printf("Enter cycle frequency for checking percolation of solids (set) \n");
6747 printf("%d\n", burnfreq);
6748 printf("Adiabatic curing conditions %d\n", adiabatic_curing);
6749#endif
6750 //fscanf(in, "%d",&setfreq);
6751#ifdef CMLFILE
6752 F->get_value(18, ( long & )setfreq);
6753#endif
6754#ifdef TINYXML
6755 QueryNumAttributeExt(xmlFile, "Cycle_freq_perc_sol", 0, setfreq);
6756#endif
6757 //setfreq=50000;
6758#ifdef PRINTF
6759 printf("Enter cycle frequency for checking hydration of particles \n");
6760 printf("%d\n", setfreq);
6761#endif
6762 //fscanf(in, "%d",&phydfreq);
6763 phydfreq = 50000; //disabled
6764 //printf("%d\n",phydfreq);
6765 //printf("Enter cycle frequency for outputting hydrating microstructure \n");
6766 //fscanf(in, "%d",&outfreq);
6767 outfreq = 50000;
6768 //printf("%d\n",outfreq);
6769 //printf("Enter the induction time in hours \n");
6770#ifdef CMLFILE
6771 F->get_value(4, ind_time);
6772#endif
6773#ifdef TINYXML
6774 QueryNumAttributeExt(xmlFile, "Induction_time", 0, ind_time);
6775#endif
6776 //fscanf(in, "%lf",&ind_time);
6777 //printf("%f \n",ind_time);
6778 time_cur += ind_time;
6779 /* heat transfer coefficient in J/g/C/s - not used*/
6780 //fscanf(in, "%f",&U_coeff);
6781 U_coeff = 0;
6782#ifdef PRINTF
6783 printf("Enter apparent activation energy for hydration in kJ/mole \n");
6784#endif
6785#ifdef CMLFILE
6786 F->get_value(5, E_act);
6787#endif
6788#ifdef TINYXML
6789 QueryNumAttributeExt(xmlFile, "Ea_cement", 0, E_act);
6790#endif
6791 //fscanf(in, "%lf",&E_act);
6792#ifdef PRINTF
6793 printf("%f \n", E_act);
6794 printf("Enter apparent activation energy for pozzolanic reactions in kJ/mole \n");
6795#endif
6796#ifdef CMLFILE
6797 F->get_value(6, E_act_pozz);
6798#endif
6799#ifdef TINYXML
6800 QueryNumAttributeExt(xmlFile, "Ea_pozz", 0, E_act_pozz);
6801#endif
6802 //fscanf(in, "%f",&E_act_pozz);
6803#ifdef PRINTF
6804 printf("%f \n", E_act_pozz);
6805 printf("Enter apparent activation energy for slag reactions in kJ/mole \n");
6806#endif
6807#ifdef CMLFILE
6808 F->get_value(7, E_act_slag);
6809#endif
6810#ifdef TINYXML
6811 QueryNumAttributeExt(xmlFile, "Ea_slag", 0, E_act_slag);
6812#endif
6813 //fscanf(in, "%f",&E_act_slag);
6814#ifdef PRINTF
6815 printf("%f \n", E_act_slag);
6816 printf("Enter kinetic factor to convert cycles to time for 25 C \n");
6817#endif
6818#ifdef CMLFILE
6819 F->get_value(8, beta);
6820#endif
6821#ifdef TINYXML
6822 QueryNumAttributeExt(xmlFile, "Beta", 0, beta);
6823#endif
6824 //fscanf(in, "%lf",&beta);
6825#ifdef PRINTF
6826 printf("%f \n", beta);
6827 printf("Enter mass fraction of aggregate in concrete \n");
6828#endif
6829#ifdef CMLFILE
6830 F->get_value(9, mass_agg);
6831#endif
6832#ifdef TINYXML
6833 QueryNumAttributeExt(xmlFile, "Mass_SCM_FA_CA_inert_frac", 0, mass_agg);
6834#endif
6835 //fscanf(in, "%f",&mass_agg);
6836#ifdef PRINTF
6837 printf("%f \n", mass_agg);
6838 printf("Enter kg of cement (+admixtures) in 1 m3\n");
6839#endif
6840#ifdef CMLFILE
6841 F->get_value(10, Mass_cement_concrete);
6842#endif
6843#ifdef TINYXML
6844 QueryNumAttributeExt(xmlFile, "Mass_cement_concrete", 0, Mass_cement_concrete);
6845#endif
6846 //fscanf(in, "%f",&Mass_cement_concrete);
6847#ifdef PRINTF
6848 printf("%f \n", Mass_cement_concrete);
6849 printf("Enter heat capacity of aggregate in concrete J/g/C\n");
6850#endif
6851#ifdef CMLFILE
6852 F->get_value(11, Cp_agg);
6853 Cp_agg /= 1000.; //scale to J/g/K
6854#endif
6855#ifdef TINYXML
6856 QueryNumAttributeExt(xmlFile, "Cp_SCM_FA_CA_inert", 0, Cp_agg);
6857 Cp_agg /= 1000.; //scale to J/g/K
6858#endif
6859 //fscanf(in, "%f",&Cp_agg);
6860#ifdef PRINTF
6861 printf("%f \n", Cp_agg);
6862 printf("Enter heat capacity of cement J/g/C\n");
6863#endif
6864#ifdef CMLFILE
6865 F->get_value(12, Cp_cement);
6866 Cp_cement /= 1000.; //scale to J/g/K
6867#endif
6868#ifdef TINYXML
6869 QueryNumAttributeExt(xmlFile, "Cp_cem", 0, Cp_cement);
6870 Cp_cement /= 1000.; //scale to J/g/K
6871#endif
6872 //fscanf(in, "%f",&Cp_cement);
6873#ifdef PRINTF
6874 printf("%f \n", Cp_cement);
6875 printf("CSH to pozzolanic CSH 0) prohibited or 1) allowed \n");
6876#endif
6877 //fscanf(in, "%d",&csh2flag);
6878 csh2flag = 0;
6879#ifdef PRINTF
6880 printf("%d \n", csh2flag);
6881 printf("CH precipitation on aggregate surfaces 0) prohibited or 1) allowed \n");
6882#endif
6883 //fscanf(in, "%d",&chflag);
6884 chflag = 0;
6885#ifdef PRINTF
6886 printf("%d \n", chflag);
6887 printf("Enter number of cycles before executing total resaturation \n");
6888#endif
6889 //fscanf(in, "%d\n",&resatcyc);
6890 resatcyc = 0;
6891#ifdef PRINTF
6892 printf("%d\n", resatcyc);
6893 printf("Enter choice for C-S-H geometry 0) random or 1) plates \n");
6894#endif
6895 //fscanf(in, "%d\n",&cshgeom);
6896 cshgeom = 0;
6897#ifdef PRINTF
6898 printf("%d \n", cshgeom);
6899 printf("Does pH influence hydration kinetics 0) no or 1) yes \n");
6900#endif
6901 //fscanf(in, "%d\n",&pHactive);
6902 pHactive = 0;
6903#ifdef PRINTF
6904 printf("%d\n", pHactive);
6905#endif
6906#ifdef CMLFILE
6907 F->get_value(34, Vol_cement_clinker_gypsum);
6908 F->get_value(35, Vol_cement_SCM);
6909 F->get_value(36, Vol_water);
6910 F->get_value(37, Vol_FA);
6911 F->get_value(38, Vol_CA);
6912 F->get_value(39, Vol_inert_filler);
6913 F->get_value(40, Vol_entrained_entrapped_air);
6914 F->get_value(41, Grain_average_FA);
6915 F->get_value(42, Grain_average_CA);
6916 F->get_value(43, ITZ_thickness);
6917 F->get_value(44, ITZ_Young_red);
6918 F->get_value(45, Young_SCM);
6919 F->get_value(46, Poisson_SCM);
6920 F->get_value(47, Young_FA);
6921 F->get_value(48, Poisson_FA);
6922 F->get_value(49, Young_CA);
6923 F->get_value(50, Poisson_CA);
6924 F->get_value(51, Young_inert);
6925 F->get_value(52, Poisson_inert);
6926 F->get_value(53, Calculate_elastic_homogenization);
6927#endif
6928#ifdef TINYXML
6929 QueryNumAttributeExt(xmlFile, "Vol_cement_clinker_gypsum", 0, Vol_cement_clinker_gypsum);
6930 QueryNumAttributeExt(xmlFile, "Vol_cement_SCM", 0, Vol_cement_SCM);
6931 QueryNumAttributeExt(xmlFile, "Vol_water", 0, Vol_water);
6932 QueryNumAttributeExt(xmlFile, "Vol_FA", 0, Vol_FA);
6933 QueryNumAttributeExt(xmlFile, "Vol_CA", 0, Vol_CA);
6934 QueryNumAttributeExt(xmlFile, "Vol_inert_filler", 0, Vol_inert_filler);
6935 QueryNumAttributeExt(xmlFile, "Vol_entrained_entrapped_air", 0, Vol_entrained_entrapped_air);
6936 QueryNumAttributeExt(xmlFile, "Grain_average_FA", 0, Grain_average_FA);
6937 QueryNumAttributeExt(xmlFile, "Grain_average_CA", 0, Grain_average_CA);
6938 QueryNumAttributeExt(xmlFile, "ITZ_thickness", 0, ITZ_thickness);
6939 QueryNumAttributeExt(xmlFile, "ITZ_Young_red", 0, ITZ_Young_red);
6940 QueryNumAttributeExt(xmlFile, "Young_SCM", 0, Young_SCM);
6941 QueryNumAttributeExt(xmlFile, "Poisson_SCM", 0, Poisson_SCM);
6942 QueryNumAttributeExt(xmlFile, "Young_FA", 0, Young_FA);
6943 QueryNumAttributeExt(xmlFile, "Poisson_FA", 0, Poisson_FA);
6944 QueryNumAttributeExt(xmlFile, "Young_CA", 0, Young_CA);
6945 QueryNumAttributeExt(xmlFile, "Poisson_CA", 0, Poisson_CA);
6946 QueryNumAttributeExt(xmlFile, "Young_inert", 0, Young_inert);
6947 QueryNumAttributeExt(xmlFile, "Poisson_inert", 0, Poisson_inert);
6948 QueryNumAttributeExt(xmlFile, "Calculate_elastic_homogenization", 0, Calculate_elastic_homogenization);
6949 //needed in OOFEM for conductivity and capacity calculations
6950 QueryNumAttributeExt(xmlFile, "Mass_tot_concrete", 0, Mass_tot_concrete);
6951 QueryNumAttributeExt(xmlFile, "Cp_SCM", 0, Cp_SCM);
6952 QueryNumAttributeExt(xmlFile, "Cp_FA", 0, Cp_FA);
6953 QueryNumAttributeExt(xmlFile, "Cp_CA", 0, Cp_CA);
6954 QueryNumAttributeExt(xmlFile, "Cp_inert", 0, Cp_inert);
6955 QueryNumAttributeExt(xmlFile, "Mass_SCM_frac", 0, Mass_SCM_frac);
6956 QueryNumAttributeExt(xmlFile, "Mass_FA_frac", 0, Mass_FA_frac);
6957 QueryNumAttributeExt(xmlFile, "Mass_CA_frac", 0, Mass_CA_frac);
6958 QueryNumAttributeExt(xmlFile, "Mass_inert_frac", 0, Mass_inert_frac);
6959 QueryNumAttributeExt(xmlFile, "Concrete_thermal_conductivity", 0, Concrete_thermal_conductivity); //[W/m/K]
6960 QueryNumAttributeExt(xmlFile, "Concrete_bulk_density", 0, Concrete_bulk_density); //[kg/m3]
6961#endif
6962}
6963
6964
6965/* Calls init, dissolve and addrand */
6966void CemhydMatStatus :: disrealnew_init()
6967{
6968#ifdef OUTFILES
6969 char fileo [ 80 ];
6970#endif
6971
6972 nseed = iseed; //set random number generator the same number
6973 seed = & nseed;
6974
6975 ncshplategrow = 0;
6976 ncshplateinit = 0;
6977 slagemptyp = 0;
6978 countpore = 0;
6979 time_step = 0.0;
6980 w_to_c = 0.0;
6981 totfract = 1.0;
6982 tfractw04 = 0.438596;
6983 fractwithfill = 1.0;
6984 tfractw05 = 0.384615;
6985 surffract = 0.0;
6986 pfractw05 = 0.615385;
6987 scntcement = 0;
6988 scnttotal = 0;
6989 saturation = 1.0;
6990 cs_acc = 1.0;
6991 ca_acc = 1.0;
6994 gsratio2 = 0.0;
6995 onepixelbias = 1.0;
6996 DIFFCHdeficit = 0;
6997 slaginit = 0;
6998 slagcum = 0;
6999 chgone = 0;
7000 nch_slag = 0;
7001 sulf_cur = 0;
7002 pHfactor = 0.0;
7003 conccaplus = 0.0;
7004 moles_syn_precip = 0.0;
7005 concsulfate = 0.0;
7006
7007 primevalues [ 0 ] = 2;
7008 primevalues [ 1 ] = 3;
7009 primevalues [ 2 ] = 5;
7010 primevalues [ 3 ] = 7;
7011 primevalues [ 4 ] = 11;
7012 primevalues [ 5 ] = 13;
7013
7014 ngoing = 0;
7015 porefl1 = porefl2 = porefl3 = 1;
7016 pore_off = water_off = 0;
7017 cycflag = 0;
7018 heat_old = heat_new = 0.0;
7019 chold = chnew = 0; /* Current and previous cycle CH counts */
7020 cubesize = CUBEMAX;
7021 ppozz = PPOZZ;
7022 poregone = poretodo = 0;
7023
7024 /* Initialize counters, etc. */
7025 npr = nasr = nslagr = 0;
7026 nfill = 0;
7027 ncsbar = 0;
7028 netbar = 0;
7029 porinit = 0;
7030 cyccnt = 0;
7031 setflag = 0;
7033
7034 /* Initialize structure for ants */
7035 headant = ( struct ants * ) malloc( sizeof( struct ants ) );
7036 headant->prevant = NULL;
7037 headant->nextant = NULL;
7038 headant->x = 0;
7039 headant->y = 0;
7040 headant->z = 0;
7041 headant->id = 100; /* special ID indicating first ant in list */
7042 headant->cycbirth = 0;
7043 tailant = headant;
7044
7045 LastHydrTime = 0.;
7046 LastCycHeat = 0.;
7047 LastTotHeat = 0.;
7048 LastCycCnt = 0;
7049 PrevHydrTime = 0.;
7050 PrevCycHeat = 0.;
7051
7052
7053 init();
7054#ifdef PRINTF
7055 printf("After init routine \n");
7056#endif
7057 fflush(stdout);
7058
7059
7060
7061#ifdef OUTFILES
7062 fileperc = fopen("percpore.out", "w"); //in burn3d.cpp
7063 //fprintf(fileperc,"Cycle time(h) alpha_mass conn_por total_por frac_conn\n");
7064 fprintf(fileperc, "#cycle alpha #through #tot_phase\n");
7065 disprobfile = fopen("disprob.out", "w");
7066 //percfile = fopen("percset.out", "w"); //in burnset.cpp
7067 //fprintf(percfile, "#cycle time alpha #through #C3S+C2S+C3A+C4AF+CAS2+SLAG+ASG+POZZ+ETTR+ETTRC4AF+CSH conn_frac\n");
7068 strcpy(heatname, "heat.out");
7069 heatfile = fopen(heatname, "w");
7070 strcpy(chshrname, "chemshr.out");
7071 //chsfile=fopen(chshrname,"w");
7072 strcpy(adianame, "adiabatic.out");
7073 strcpy(pHname, "pHfile.out");
7074 pHfile = fopen(pHname, "w");
7075 fprintf(pHfile, "Cycle time(h) alpha_mass pH sigma [Na+] [K+] [Ca++] [SO4--] activityCa activityOH activitySO4 activityK molesSyngenite\n");
7076 strcpy(fileo, "out5.img");
7077 strcpy(phasname, "phases.out");
7078 phasfile = fopen(phasname, "w");
7079 strcpy(ppsname, "percpore.out");
7080 strcpy(phrname, "parthydr.out");
7081 perc_phases = fopen("perc_phases.out", "w");
7082 adiafile = fopen(adianame, "w");
7083 fprintf(adiafile, "Cyc Time(h) Temperature Alpha Krate Cp_now Mass_cem kpozz/khyd kslag/khyd DoR_Blend\n");
7084 elasfile = fopen("elas.out", "w");
7085 fprintf(elasfile, "Cyc\tTime[h] Alpha E_paste nu_paste E_paste_fil nu_paste_fil E_mortar nu_mortar E_concrete nu_concrete\n");
7086 CSHfile = fopen("CSH.out", "w");
7087 fprintf(CSHfile, "cyc alpha [h] HD CSH-total HD/CSH\n");
7088 system("mkdir perc 2> /dev/null");
7089 system("mkdir unperc 2> /dev/null");
7090#endif
7091
7092#ifdef IMAGEFILES
7093 infoperc = fopen("perc/info.dat", "w");
7094 fprintf(infoperc, "#Cyc DoH Time[h]\n");
7095 infoUnperc = fopen("unperc/info.dat", "w");
7096 fprintf(infoUnperc, "#Cyc DoH Time[h]\n");
7097#endif
7098 /* Set initial properties of CSH */
7099 molarvcsh [ 0 ] = molarv [ CSH ];
7100 watercsh [ 0 ] = waterc [ CSH ];
7101
7102 krate = exp( -( 1000. * E_act / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7103 /* Determine pozzolanic and slag reaction rate constants */
7104 kpozz = exp( -( 1000. * E_act_pozz / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7105 kslag = exp( -( 1000. * E_act_slag / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7106 ppozz = PPOZZ * kpozz / krate;
7107 /* Assume same holds for dissolution of fly ash phases */
7108 disprob [ ASG ] = disbase [ ASG ] * kpozz / krate;
7109 disprob [ CAS2 ] = disbase [ CAS2 ] * kpozz / krate;
7110 /* Update probability of slag dissolution */
7111 disprob [ SLAG ] = slagreact * disbase [ SLAG ] * kslag / krate;
7112
7113
7114 /* Determine surface counts */
7115 measuresurf();
7116}
7117
7118
7119/*perform as many hydration cycles as necessary
7120 * flag = 0 - controlled with hydrationTime
7121 * flag != 0 - perform exactly flag cycles
7122 * GiveTemp is effective in the first cycle of adiabatic regime only
7123 */
7124void CemhydMatStatus :: disrealnew(double GiveTemp, double hydrationTime, int flag)
7125{
7126 int counter = 0;
7127
7128 if ( adiabatic_curing != 1 ) {
7129 temp_cur = GiveTemp;
7130 temp_0 = GiveTemp;
7131 }
7132
7134
7135 if ( icyc == 1 ) { //first cycle
7136 temp_cur = GiveTemp;
7137 temp_0 = GiveTemp;
7139 }
7140
7141 /****************************************************************/
7142 /**************************MAIN LOOP*****************************/
7143 /****************************************************************/
7144
7145 /*determine the minimum number of cycles*/
7146 while ( flag == 0 ? ( time_cur < hydrationTime ) : counter < flag ) {
7148
7149 //printf("CNT seed=%d\n", *seed);
7150 //update counters of "previous", i.e. before any last cycle
7151 PrevHydrTime = time_cur * 3600.;
7152 PrevCycHeat = ( double ) ( heat_new ) * heat_cf;
7153
7154 if ( ( sealed == 1 ) && ( icyc == ( resatcyc + 1 ) ) && ( resatcyc != 0 ) ) {
7155 resaturate();
7156 sealed = 0;
7157 }
7158
7159 if ( temp_cur <= 80.0 ) {
7160 molarvcsh [ icyc ] = molarv [ CSH ] - 8.0 * ( ( temp_cur - 20. ) / ( 80. - 20. ) );
7161 watercsh [ icyc ] = waterc [ CSH ] - 1.3 * ( ( temp_cur - 20. ) / ( 80. - 20. ) );
7162 } else {
7163 molarvcsh [ icyc ] = molarv [ CSH ] - 8.0;
7164 watercsh [ icyc ] = waterc [ CSH ] - 1.3;
7165 }
7166
7167 dissolve(icyc); //cyccnt is increased
7168#ifdef OUTFILES
7169 //printf("Number dissolved this pass- %ld total diffusing- %ld \n",nmade,ngoing);
7170
7171 fflush(stdout);
7172 if ( icyc == 1 ) {
7173 // printf("ncsbar is %ld netbar is %ld \n",ncsbar,netbar);
7174 }
7175
7176#endif
7177
7179 temp_0 = temp_cur;
7180
7181 /* Handle adiabatic case first */
7182 /* Cement + aggregate +water + filler=1; that's all there is */
7185
7186 /* determine heat capacity of current mixture, */
7187 /* accounting for imbided water if necessary */
7188 if ( sealed == 1 ) {
7192 Cp_now += Cp_CH * mass_CH;
7195 }
7196 /* Else need to account for extra capillary water drawn in */
7197 /* Basis is WCHSH(0.06) g H2O per gram cement for chemical shrinkage */
7198 /* Need to adjust mass basis to account for extra imbibed H2O */
7199 else {
7208 }
7209
7210
7211 /* Recall that temp_cur is in degrees Celsius */
7212 krate = exp( -( 1000. * E_act / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7213 /* Determine pozzolanic and slag reaction rate constant */
7214 kpozz = exp( -( 1000. * E_act_pozz / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7215 kslag = exp( -( 1000. * E_act_slag / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7216 /* Update probability of pozzolanic and slag reactions */
7217 /* based on ratio of pozzolanic (slag) reaction rate to hydration rate */
7218 ppozz = PPOZZ * kpozz / krate;
7219 disprob [ ASG ] = disbase [ ASG ] * kpozz / krate;
7220 disprob [ CAS2 ] = disbase [ CAS2 ] * kpozz / krate;
7221 disprob [ SLAG ] = slagreact * disbase [ SLAG ] * kslag / krate;
7222
7223 /* Update temperature based on heat generated and current Cp only in adiabatic case*/
7224 if ( adiabatic_curing == 1 ) {
7225 if ( mass_cem_now > 0.01 ) {
7227 } else {
7229 }
7230 }
7231
7232 /* Update system temperature due to heat loss/gain to/from */
7233 /* surroundings (semi-adiabatic case) */
7234 //temp_cur-=(temp_cur-T_ambient)*time_step*U_coeff/Cp_now;
7235
7236 /* Update time based on simple numerical integration */
7237 /* simulating maturity approach */
7238 /* with parabolic kinetics (Knudsen model) */
7239 if ( cyccnt > 1 ) {
7240 time_cur += ( 2. * ( double ) ( cyccnt - 1 ) - 1.0 ) * beta / krate;
7241 time_step = ( 2. * ( double ) ( cyccnt - 1 ) - 1.0 ) * beta / krate;
7242 }
7243
7244 gsratio2 = 0.0;
7245 gsratio2 += ( float ) ( count [ CH ] + count [ CSH ] + count [ C3AH6 ] + count [ ETTR ] );
7246 gsratio2 += ( float ) ( count [ POZZCSH ] + count [ SLAGCSH ] + count [ FH3 ] + count [ AFM ] + count [ ETTRC4AF ] );
7247 gsratio2 += ( float ) ( count [ FREIDEL ] + count [ STRAT ] + count [ ABSGYP ] + count [ AFMC ] );
7248 gsratio2 = ( gsratio2 ) / ( gsratio2 + ( float ) ( count [ POROSITY ] + count [ EMPTYP ] ) );
7249
7250
7251#ifdef OUTFILES
7252 fprintf(adiafile, "%d \t %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n", cyccnt, time_cur, temp_cur, alpha_cur, krate, Cp_now, mass_cem_now, kpozz / krate, kslag / krate, alpha_fa_cur);
7253 fprintf( heatfile, "%d %f %f %f %f %f %f \n",
7254 cyccnt - 1, time_cur, alpha, alpha_cur, heat_new * heat_cf, gsratio2, ( ( 0.68 * alpha_cur ) / ( 0.32 * alpha_cur + w_to_c ) ) );
7255 fflush(adiafile);
7256 fflush(heatfile);
7257#endif
7258
7259 /*chemical shrinkage*/
7260 //fprintf(chsfile,"%d %f %f %f\n", cyccnt-1,time_cur,alpha_cur,chs_new);
7261 //fflush(chsfile);
7262 //pHpred();-dangerous function - can lead to zero division etc.
7263
7264 /* Check percolation of pore space */
7265 /* Note that first variable passed corresponds to phase to check */
7266 /* Could easily add calls to check for percolation of CH, CSH, etc. */
7267
7268 if ( ( ( icyc % burnfreq ) == 0 ) && ( ( porefl1 + porefl2 + porefl3 ) != 0 ) ) {
7269 porefl1 = burn3d(0, 1, 0, 0);
7270 porefl2 = burn3d(0, 0, 1, 0);
7271 porefl3 = burn3d(0, 0, 0, 1);
7272 /* Switch to self-desiccating conditions when porosity */
7273 /* disconnects */
7274 if ( ( ( porefl1 + porefl2 + porefl3 ) == 0 ) && ( sealed == 0 ) ) {
7277 sealed = 1;
7278#ifdef PRINTF
7279 printf("Switching to self-desiccating at cycle %d \n", cyccnt);
7280#endif
7281 fflush(stdout);
7282 }
7283 }
7284
7285
7286 /*update microstructure in mic_CSH[][][] to HDCSH and use it in*/
7287 /*burn_phases function and outputImageFile function*/
7288 //CSHbox(CSH_vicinity); - called independently, does not influence percolation
7289
7290
7291 /* Check percolation of solids (set point) */
7292 if ( ( ( icyc % setfreq ) == 0 ) && ( setflag == 0 ) ) {
7293 // sf1 = burnset(1, 0, 0);
7294 // sf2 = burnset(0, 1, 0);
7295 // sf3 = burnset(0, 0, 1);
7296 // setflag = sf1 * sf2 * sf3;
7297 }
7298
7299#ifdef IMAGEFILES
7300 //outputImageFilePerc();//is executed from CemhydMatStatus :: burn_phases
7302#endif
7303 /* Check hydration of particles */
7304 if ( ( icyc % phydfreq ) == 0 ) {
7305 // parthyd();
7306 }
7307
7308 /* Calculate homogenized elastic values if turned on */
7310 //increase DoH by 0.02 till 0.2 and then by 0.05 step
7311 if ( TargDoHelas < 0.1 ) {
7312 TargDoHelas += 0.01; //0.02
7313 } else if ( TargDoHelas < 0.2 ) {
7314 TargDoHelas += 0.01; //0.05
7315 } else {
7316 TargDoHelas += 0.01; //0.05
7317 }
7318
7319 double E_paste_SCM_filler_air, nu_paste_SCM_filler_air, E_mortar, nu_mortar;
7320
7321 CreateHDCSH(); //alters microstructure so it contains HDCSH - need for all homogenizations
7323 AnalyticHomogenizationPaste(last_values [ 2 ], last_values [ 3 ], 0); //0-perc, 1-unperc
7324 AnalyticHomogenizationConcrete(last_values [ 2 ], last_values [ 3 ], & E_paste_SCM_filler_air, & nu_paste_SCM_filler_air, & E_mortar, & nu_mortar, last_values [ 4 ], last_values [ 5 ]);
7325#ifdef OUTFILES
7326 fprintf(elasfile, "%d \t%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n", cyccnt, time_cur, alpha_cur, last_values [ 2 ], last_values [ 3 ], E_paste_SCM_filler_air, nu_paste_SCM_filler_air, E_mortar, nu_mortar, last_values [ 4 ], last_values [ 5 ]);
7327 fflush(elasfile);
7328#endif
7329 }
7330
7331#ifdef OUTFILES
7332 fprintf(CSHfile, "%d %.4f %.4f %ld %ld %f\n", icyc, alpha_cur, time_cur, count [ HDCSH ], count [ CSH ], ( double ) count [ HDCSH ] / count [ CSH ]);
7333 fflush(CSHfile);
7334#endif
7335
7336 icyc++;
7337 counter++;
7338 }
7339
7340 //end of main while loop
7341}
7342
7343
7344/*Function returning the concrete released heat during the difference in given times
7345 * of hydration. Units are in kJ/kg_all_cement_solids.
7346 * All solids include cement clinker minerals, gypsum forms, [INERT],
7347 * [SLAG],[POZZ],[CACL2],[ASG],[CAS2], NOT aggregates!!!
7348 * The heat is independent on the hydrating cube size but may slightly
7349 * decrease as some reversible reactions exist!!! (checked)
7350 * ^
7351 ***|Released heat (stops now)
7352 | CYC_m
7353 | (last stop) t_n+1 |
7354 | CYC ..CYC.. CYC_m-1 | |
7355 | t_n ! | | |
7356 | !LastTotHeat !LastHydrTime |PrevHydrTime |TargTime |time_cur
7357 | !LastCallTime !LastCycHeat |PrevCycHeat |LastTargTime |heat_new
7358 | ! !LastCycCnt | | |
7359 ||||------------------------------------------------------------------->time
7360 *
7361 * let all time counters in seconds! (numerical precision)
7362 * TargTime, LastCallTime, LastTargTime are in absolute time taken from OOFEM
7363 * time_cur, PrevHydrTime, LastHydrTime is hydration time, ofset with the castingTime
7364 */
7365
7366// GiveTemp in [C], TargTime in [s]
7367double CemhydMatStatus :: GivePower(double GiveTemp, double TargTime)
7368{
7369#ifdef __TM_MODULE //OOFEM transport module
7370 double castingTime = this->gp->giveMaterial()->giveCastingTime();
7371#else
7372 double castingTime = 0.;
7373#endif
7374
7375 //do not calculate anything before casting time
7376 if ( TargTime - castingTime <= 0 ) {
7377 PartHeat = 0.;
7378 LastCallTime = castingTime;
7379 return 0.;
7380 }
7381
7382 LastTargTime = TargTime;
7383
7384 if ( TargTime < LastCallTime ) {
7385 printf("Cannot go backwards in hydration, TargTime = %f s < LastCallTime = %f s\n", TargTime, LastCallTime);
7386 exit(0);
7387 }
7388
7389#ifdef __TM_MODULE //OOFEM transport module
7390 CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
7391 if ( !cemhydmat->nowarnings.at(4) && ( GiveTemp > 200. ) ) {
7392 printf("Temperature exceeds 200 C (file %s, line %d),\n", __FILE__, __LINE__);
7393 }
7394
7395#else
7396 if ( GiveTemp > 200. ) {
7397 printf("Temperature exceeds 200 C (file %s, line %d),\n", __FILE__, __LINE__);
7398 }
7399
7400#endif
7401
7402
7403 /*perform as many cycles as necessary, always more than required
7404 * first, calculate everything on the cement paste*/
7405
7406 disrealnew(GiveTemp, ( TargTime - castingTime ) / 3600., 0); //perform hydration cycles controled with TargTime [h]
7407
7408#ifdef PRINTF
7409 printf("Hydration heat %f [J/g of cement]\n", heat_new * heat_cf);
7410 printf("time_cur %f [h]\n", time_cur);
7411 printf("PrevHydrTime %f [h]\n", PrevHydrTime / 3600.);
7412#endif
7413
7414 PartHeat = 0.;
7415
7416 if ( TargTime != LastCallTime && icyc > 1 ) {
7417 if ( LastCycCnt - icyc ) { //if at least one hydration cycle has elapsed
7418 //interpolate between CYC_m-1 and CYC_m
7419 PartHeat = ( heat_new * heat_cf - PrevCycHeat ) * ( TargTime - PrevHydrTime - castingTime ) / ( 3600. * time_cur - PrevHydrTime );
7420 //add between CYC and CYC_m-1
7422 //add between t_n and CYC
7424 } else { //not even one cycle elapsed
7425 PartHeat = ( LastCycHeat - LastTotHeat ) * ( TargTime - LastCallTime ) / ( LastHydrTime - LastCallTime + castingTime );
7426 }
7427
7429
7430 if ( TargTime != LastCallTime ) {
7431 //Mass_cement_concrete tells the amount of cement [kg] in a m3 of concrete
7432 //add aggregates and rescale to kJ/m3 of concrete
7434 //rescale from kJ/m3/time_interval to J/m3/s or W/m3
7435 PartHeat /= ( TargTime - LastCallTime );
7436 PartHeat *= 1000;
7437 }
7438 }
7439
7440 LastCallTime = TargTime;
7441 LastHydrTime = time_cur * 3600.;
7442 LastCycHeat = ( double ) ( heat_new ) * heat_cf;
7443 LastCycCnt = icyc;
7444
7445#ifdef PRINTF
7446 printf("PartHeat %f [W/m3 of concrete]\n", PartHeat);
7447#endif
7448
7449 //PartHeat = 1500;
7450 return PartHeat;
7451}
7452
7453
7454//move hydration model by several steps and update all internal variables
7455double CemhydMatStatus :: MoveCycles(double GiveTemp, int cycles)
7456{
7457 double PartHeat;
7458 double castingTime = 0.;
7459#ifdef __TM_MODULE
7460 castingTime = this->gp->giveMaterial()->giveCastingTime();
7461#endif
7462
7463 disrealnew(GiveTemp, -1., cycles); //perform amount of hydration cycles controlled
7464
7465 //at least one cycle elapsed
7466 //difference in heat before and now at CYC_m
7468 //add between CYC and CYC_m-1
7470 //add between t_n and CYC
7472
7474
7475 //Mass_cement_concrete tells the amount of cement [kg] in a m3 of concrete
7476 //add aggregates and rescale to kJ/m3 of concrete
7478 //rescale from kJ/m3/time_interval to J/m3/s
7479 PartHeat /= ( 3600. * time_cur - LastCallTime + castingTime );
7480 PartHeat *= 1000;
7481
7482 LastCallTime = 3600. * time_cur + castingTime;
7483 LastHydrTime = 3600. * time_cur;
7484 LastCycHeat = ( double ) ( heat_new ) * heat_cf;
7485 LastCycCnt = icyc;
7486
7487 LastTargTime = time_cur * 3600.;
7488 return time_cur; //return in hours
7489}
7490
7491//move to desired DoH (the next DoH in CEMHYD3D cycle) limited by maxcyc
7492//return 1 if the number of cycles was exceeded
7493int CemhydMatStatus :: MoveToDoH(double GiveTemp, double DesiredDoH, int maxcyc)
7494{
7495 int cycle = 1;
7496
7497 while ( alpha_cur < DesiredDoH ) {
7498 if ( cycle > maxcyc ) {
7499#ifdef PRINTF
7500 printf("Target DoH %f (now is %f) was not reached after %d cycles (%s, line %d)\n", DesiredDoH, alpha_cur, maxcyc, __FILE__, __LINE__);
7501#endif
7502 return 1;
7503 }
7504
7505 MoveCycles(GiveTemp, 1); //move one cycle
7506 cycle++;
7507 }
7508
7509 return 0;
7510}
7511
7512//TargTime in [h]
7513//move to desired Time[h] (the next time in CEMHYD3D cycle, no interpolation)
7514//no cycle limit is specified (any time can be reached)
7515int CemhydMatStatus :: MoveToTime(double GiveTemp, double TargTime)
7516{
7517 GivePower(GiveTemp, 3600. * TargTime);
7518 return 0;
7519}
7520
7521
7522//return total released heat from cement in kJ/kg_cement_solids at TargTime
7523double CemhydMatStatus :: GiveTotCemHeat()
7524{
7525 return LastTotHeat;
7526}
7527
7528//return total heat in J/m3_of_concrete at TargTime
7529double CemhydMatStatus :: GiveTotHeat()
7530{
7531 return 1000 * LastTotHeat * Mass_cement_concrete;
7532}
7533
7534//return heat capacity in kJ/K/kg_of_everything in the last CEMHYD cycle
7535double CemhydMatStatus :: GiveCp()
7536{
7537 return Cp_now;
7538}
7539
7540
7541//see D. P. Bentz: Transient Plane Source Measurements of the Thermal Properties of Hydrating Cement Pastes, Materials and Structures, 1073-1080, 2007
7542double CemhydMatStatus :: computeConcreteCapacityBentz()
7543{
7544 double capacityPaste, capacityConcrete;
7545 capacityPaste = ( 4180. * Vol_water * 1.0 + Cp_cement * 1000. * Mass_cement_concrete ) / Mass_tot_concrete; //capacity of cement paste [J/kg/K]
7546 capacityPaste *= ( 1. - 0.26 * ( 1 - pow(2.71828, -2.9 * alpha_cur) ) );
7547 capacityConcrete = capacityPaste + Cp_SCM * Mass_SCM_frac + Cp_FA * Mass_FA_frac + Cp_CA * Mass_CA_frac + Cp_inert * Mass_inert_frac;
7548
7549 return capacityConcrete;
7550}
7551
7552double CemhydMatStatus :: GiveDensity()
7553{
7554 return Concrete_bulk_density;
7555}
7556
7557//return degree of hydration in the last CEMHYD cycle, corresponding to time_cur
7558double CemhydMatStatus :: GiveDoHLastCyc()
7559{
7560 return alpha_cur;
7561}
7562
7563//return actual degree of hydration (interpolated)
7564double CemhydMatStatus :: GiveDoHActual()
7565{
7566 double castingTime = 0;
7567
7568 if ( icyc <= 1 ) { //not even one cycle has elapsed
7569 return 0;
7570 }
7571
7572#ifdef __TM_MODULE
7573 castingTime = this->gp->giveMaterial()->giveCastingTime();
7574#endif
7575
7576 return alpha_last + ( alpha_cur - alpha_last ) * ( LastTargTime - castingTime - PrevHydrTime ) / ( 3600. * time_cur - PrevHydrTime ); //interpolate
7577}
7578
7579
7580//return cycle in the last CEMHYD cycle (higher or the same as actual time)
7581int CemhydMatStatus :: GiveCycNum()
7582{
7583 return icyc;
7584}
7585
7586//return actual time of the last cycle (higher or the same as actual time)
7587double CemhydMatStatus :: GiveCycTime()
7588{
7589 return time_cur;
7590}
7591
7592
7593
7594/* routine to assess the connectivity (percolation) of a single phase */
7595/* Two matrices are used here: one to store the recently burnt locations */
7596/* burn3d.cpp:97: implicit declaration of function `int printf(...)'
7597 * the other to store the newly found burnt locations */
7598
7599int CemhydMatStatus :: burn3d(int npix, int d1, int d2, int d3)
7600/* npix is ID of phase to perform burning on */
7601/* directional flags */
7602{
7603 long int ntop, nthrough, ncur, nnew, ntot, nphc;
7604 int i, inew, j, k;
7605 int xl, xh, j1, k1, px, py, pz, qx, qy, qz, xcn, ycn, zcn;
7606 int x1, y1, z1, igood;
7607 int *nmatx, *nmaty, *nmatz, *nnewx, *nnewy, *nnewz;
7608 int jnew, icur;
7609 int bflag;
7610 float mass_burn = 0.0, alpha_burn = 0.0;
7611
7612 nmatx = new int [ SIZE2D ];
7613 nmaty = new int [ SIZE2D ];
7614 nmatz = new int [ SIZE2D ];
7615 nnewx = new int [ SIZE2D ];
7616 nnewy = new int [ SIZE2D ];
7617 nnewz = new int [ SIZE2D ];
7618
7619
7620 /* counters for number of pixels of phase accessible from surface #1 */
7621 /* and number which are part of a percolated pathway to surface #2 */
7622 ntop = 0;
7623 bflag = 0;
7624 nthrough = 0;
7625 nphc = 0;
7626
7627 /* percolation is assessed from top to bottom only */
7628 /* and burning algorithm is periodic in other two directions */
7629 /* use of directional flags allow transformation of coordinates */
7630 /* to burn in direction of choosing (x, y, or z) */
7631 i = 0;
7632
7633 for ( k = 0; k < SYSIZE; k++ ) {
7634 for ( j = 0; j < SYSIZE; j++ ) {
7635 igood = 0;
7636 ncur = 0;
7637 ntot = 0;
7638 /* Transform coordinates */
7639 px = cx(i, j, k, d1, d2, d3);
7640 py = cy(i, j, k, d1, d2, d3);
7641 pz = cz(i, j, k, d1, d2, d3);
7642 if ( mic [ px ] [ py ] [ pz ] == npix ) {
7643 /* Start a burn front */
7644 mic [ px ] [ py ] [ pz ] = BURNT;
7645 ntot += 1;
7646 ncur += 1;
7647 /* burn front is stored in matrices nmat* */
7648 /* and nnew* */
7649 nmatx [ ncur ] = i;
7650 nmaty [ ncur ] = j;
7651 nmatz [ ncur ] = k;
7652 /* Burn as long as new (fuel) pixels are found */
7653 do {
7654 nnew = 0;
7655 for ( inew = 1; inew <= ncur; inew++ ) {
7656 xcn = nmatx [ inew ];
7657 ycn = nmaty [ inew ];
7658 zcn = nmatz [ inew ];
7659
7660 /* Check all six neighbors */
7661 for ( jnew = 1; jnew <= 6; jnew++ ) {
7662 x1 = xcn;
7663 y1 = ycn;
7664 z1 = zcn;
7665 if ( jnew == 1 ) {
7666 x1 -= 1;
7667 }
7668
7669 if ( jnew == 2 ) {
7670 x1 += 1;
7671 }
7672
7673 if ( jnew == 3 ) {
7674 y1 -= 1;
7675 }
7676
7677 if ( jnew == 4 ) {
7678 y1 += 1;
7679 }
7680
7681 if ( jnew == 5 ) {
7682 z1 -= 1;
7683 }
7684
7685 if ( jnew == 6 ) {
7686 z1 += 1;
7687 }
7688
7689 /* Periodic in y and */
7690 if ( y1 >= SYSIZE ) {
7691 y1 -= SYSIZE;
7692 } else if ( y1 < 0 ) {
7693 y1 += SYSIZE;
7694 }
7695
7696 /* Periodic in z direction */
7697 if ( z1 >= SYSIZE ) {
7698 z1 -= SYSIZE;
7699 } else if ( z1 < 0 ) {
7700 z1 += SYSIZE;
7701 }
7702
7703 /* Nonperiodic so be sure to remain in the 3-D box */
7704 if ( ( x1 >= 0 ) && ( x1 < SYSIZE ) ) {
7705 /* Transform coordinates */
7706 px = cx(x1, y1, z1, d1, d2, d3);
7707 py = cy(x1, y1, z1, d1, d2, d3);
7708 pz = cz(x1, y1, z1, d1, d2, d3);
7709 if ( mic [ px ] [ py ] [ pz ] == npix ) {
7710 ntot += 1;
7711 mic [ px ] [ py ] [ pz ] = BURNT;
7712 nnew += 1;
7713 if ( nnew >= SIZE2D ) {
7714 printf("error in size of nnew \n");
7715 }
7716
7717 nnewx [ nnew ] = x1;
7718 nnewy [ nnew ] = y1;
7719 nnewz [ nnew ] = z1;
7720 }
7721 }
7722 }
7723 }
7724
7725 if ( nnew > 0 ) {
7726 ncur = nnew;
7727 /* update the burn front matrices */
7728 for ( icur = 1; icur <= ncur; icur++ ) {
7729 nmatx [ icur ] = nnewx [ icur ];
7730 nmaty [ icur ] = nnewy [ icur ];
7731 nmatz [ icur ] = nnewz [ icur ];
7732 }
7733 }
7734 } while ( nnew > 0 );
7735
7736 ntop += ntot;
7737 xl = 0;
7738 xh = SYSIZE - 1;
7739 /* See if current path extends through the microstructure */
7740 for ( j1 = 0; j1 < SYSIZE; j1++ ) {
7741 for ( k1 = 0; k1 < SYSIZE; k1++ ) {
7742 px = cx(xl, j1, k1, d1, d2, d3);
7743 py = cy(xl, j1, k1, d1, d2, d3);
7744 pz = cz(xl, j1, k1, d1, d2, d3);
7745 qx = cx(xh, j1, k1, d1, d2, d3);
7746 qy = cy(xh, j1, k1, d1, d2, d3);
7747 qz = cz(xh, j1, k1, d1, d2, d3);
7748 if ( ( mic [ px ] [ py ] [ pz ] == BURNT ) && ( mic [ qx ] [ qy ] [ qz ] == BURNT ) ) {
7749 igood = 2;
7750 }
7751
7752 if ( mic [ px ] [ py ] [ pz ] == BURNT ) {
7753 mic [ px ] [ py ] [ pz ] = BURNT + 1;
7754 }
7755
7756 if ( mic [ qx ] [ qy ] [ qz ] == BURNT ) {
7757 mic [ qx ] [ qy ] [ qz ] = BURNT + 1;
7758 }
7759 }
7760 }
7761
7762 if ( igood == 2 ) {
7763 nthrough += ntot;
7764 }
7765 }
7766 }
7767 }
7768
7769 /* return the burnt sites to their original phase values */
7770 for ( i = 0; i < SYSIZE; i++ ) {
7771 for ( j = 0; j < SYSIZE; j++ ) {
7772 for ( k = 0; k < SYSIZE; k++ ) {
7773 if ( mic [ i ] [ j ] [ k ] >= BURNT ) {
7774 nphc += 1;
7775 mic [ i ] [ j ] [ k ] = npix;
7776 } else if ( mic [ i ] [ j ] [ k ] == npix ) {
7777 nphc += 1;
7778 }
7779 }
7780 }
7781 }
7782
7783#ifdef PRINTF
7784 printf("Phase ID= %d \n", npix);
7785 printf("Number accessible from first surface = %ld \n", ntop);
7786 printf("Number contained in through pathways= %ld \n", nthrough);
7787#endif
7788
7789
7790 mass_burn += specgrav [ C3S ] * count [ C3S ];
7791 mass_burn += specgrav [ C2S ] * count [ C2S ];
7792 mass_burn += specgrav [ C3A ] * count [ C3A ];
7793 mass_burn += specgrav [ C4AF ] * count [ C4AF ];
7794 alpha_burn = 1. - ( mass_burn / cemmass );
7795
7796#ifdef OUTFILES
7797 fprintf(fileperc, "%d %f %ld %ld \n", cyccnt, alpha_cur, nthrough, nphc);
7798 fflush(fileperc);
7799#endif
7800
7801 if ( nthrough > 0 ) {
7802 bflag = 1;
7803 }
7804
7805 delete [] nmatx;
7806 delete [] nmaty;
7807 delete [] nmatz;
7808 delete [] nnewx;
7809 delete [] nnewy;
7810 delete [] nnewz;
7811 return ( bflag );
7812
7813 ( void ) alpha_burn;
7814}
7815
7816
7817/* routine to assess connectivity (percolation) of solids for set estimation*/
7818/* Definition of set is a through pathway of cement particles connected */
7819/* together by CSH or ettringite */
7820/* Two matrices are used here: one to store the recently burnt locations */
7821/* the other to store the newly found burnt locations */
7822//use perc_phases instead. It contains all solid phases, :: burnset function is outdated
7823
7824int CemhydMatStatus :: burnset(int d1, int d2, int d3)
7825{
7826 long int ntop, nthrough, icur, inew, ncur, nnew, ntot, count_solid;
7827 int i, j, k, setyet;
7828 //static int nmatx[SIZESET],nmaty[SIZESET],nmatz[SIZESET];
7829 int *nmatx, *nmaty, *nmatz;
7830 int xl, xh, j1, k1, px, py, pz, qx, qy, qz;
7831 int xcn, ycn, zcn, x1, y1, z1, igood;
7832 //static int nnewx[SIZESET],nnewy[SIZESET],nnewz[SIZESET];
7833 int *nnewx, *nnewy, *nnewz;
7834 int jnew;
7835 float mass_burn = 0.0, alpha_burn = 0.0, con_frac;
7836 //static char newmat [SYSIZE] [SYSIZE] [SYSIZE];
7837 char ***newmat;
7838
7839 alloc_char_3D(newmat, SYSIZE);
7840 nmatx = new int [ SIZESET ];
7841 nmaty = new int [ SIZESET ];
7842 nmatz = new int [ SIZESET ];
7843 nnewx = new int [ SIZESET ];
7844 nnewy = new int [ SIZESET ];
7845 nnewz = new int [ SIZESET ];
7846
7847 /* counters for number of pixels of phase accessible from surface #1 */
7848 /* and number which are part of a percolated pathway to surface #2 */
7849 ntop = 0;
7850 nthrough = 0;
7851 setyet = 0;
7852 for ( k = 0; k < SYSIZE; k++ ) {
7853 for ( j = 0; j < SYSIZE; j++ ) {
7854 for ( i = 0; i < SYSIZE; i++ ) {
7855 newmat [ i ] [ j ] [ k ] = mic [ i ] [ j ] [ k ];
7856 }
7857 }
7858 }
7859
7860 /* percolation is assessed from top to bottom only */
7861 /* in transformed coordinates */
7862 /* and burning algorithm is periodic in other two directions */
7863 i = 0;
7864
7865 for ( k = 0; k < SYSIZE; k++ ) {
7866 for ( j = 0; j < SYSIZE; j++ ) {
7867 igood = 0;
7868 ncur = 0;
7869 ntot = 0;
7870 /* Transform coordinates */
7871 px = cx(i, j, k, d1, d2, d3);
7872 py = cy(i, j, k, d1, d2, d3);
7873 pz = cz(i, j, k, d1, d2, d3);
7874 /* start from a cement clinker, slag, fly ash ettringite, C3AH6, or
7875 * CSH pixel */
7876 if ( ( mic [ px ] [ py ] [ pz ] == C3S ) ||
7877 ( mic [ px ] [ py ] [ pz ] == C2S ) ||
7878 ( mic [ px ] [ py ] [ pz ] == SLAG ) ||
7879 ( mic [ px ] [ py ] [ pz ] == ASG ) ||
7880 ( mic [ px ] [ py ] [ pz ] == CAS2 ) ||
7881 ( mic [ px ] [ py ] [ pz ] == POZZ ) ||
7882 ( mic [ px ] [ py ] [ pz ] == CSH ) ||
7883 ( mic [ px ] [ py ] [ pz ] == C3AH6 ) ||
7884 ( mic [ px ] [ py ] [ pz ] == ETTR ) ||
7885 ( mic [ px ] [ py ] [ pz ] == ETTRC4AF ) ||
7886 ( mic [ px ] [ py ] [ pz ] == C3A ) ||
7887 ( mic [ px ] [ py ] [ pz ] == C4AF ) ) {
7888 /* Start a burn front */
7889 mic [ px ] [ py ] [ pz ] = BURNT;
7890 ntot += 1;
7891 ncur += 1;
7892 /* burn front is stored in matrices nmat* */
7893 /* and nnew* */
7894 nmatx [ ncur ] = i;
7895 nmaty [ ncur ] = j;
7896 nmatz [ ncur ] = k;
7897 /* Burn as long as new (fuel) pixels are found */
7898 do {
7899 nnew = 0;
7900 for ( inew = 1; inew <= ncur; inew++ ) {
7901 xcn = nmatx [ inew ];
7902 ycn = nmaty [ inew ];
7903 zcn = nmatz [ inew ];
7904 /* Convert to directional coordinates */
7905 qx = cx(xcn, ycn, zcn, d1, d2, d3);
7906 qy = cy(xcn, ycn, zcn, d1, d2, d3);
7907 qz = cz(xcn, ycn, zcn, d1, d2, d3);
7908
7909 /* Check all six neighbors */
7910 for ( jnew = 1; jnew <= 6; jnew++ ) {
7911 x1 = xcn;
7912 y1 = ycn;
7913 z1 = zcn;
7914 if ( jnew == 1 ) {
7915 x1 -= 1;
7916 }
7917
7918 if ( jnew == 2 ) {
7919 x1 += 1;
7920 }
7921
7922 if ( jnew == 3 ) {
7923 y1 -= 1;
7924 }
7925
7926 if ( jnew == 4 ) {
7927 y1 += 1;
7928 }
7929
7930 if ( jnew == 5 ) {
7931 z1 -= 1;
7932 }
7933
7934 if ( jnew == 6 ) {
7935 z1 += 1;
7936 }
7937
7938 /* Periodic in y and */
7939 if ( y1 >= SYSIZE ) {
7940 y1 -= SYSIZE;
7941 } else if ( y1 < 0 ) {
7942 y1 += SYSIZE;
7943 }
7944
7945 /* Periodic in z direction */
7946 if ( z1 >= SYSIZE ) {
7947 z1 -= SYSIZE;
7948 } else if ( z1 < 0 ) {
7949 z1 += SYSIZE;
7950 }
7951
7952 /* Nonperiodic so be sure to remain in the 3-D box */
7953 if ( ( x1 >= 0 ) && ( x1 < SYSIZE ) ) {
7954 px = cx(x1, y1, z1, d1, d2, d3);
7955 py = cy(x1, y1, z1, d1, d2, d3);
7956 pz = cz(x1, y1, z1, d1, d2, d3);
7957 /* Conditions for propagation of burning */
7958 /* 1) new pixel is CH, CSH or ETTR or C3AH6*/
7959 if ( ( mic [ px ] [ py ] [ pz ] == CSH ) || ( mic [ px ] [ py ] [ pz ] == ETTRC4AF ) || ( mic [ px ] [ py ] [ pz ] == C3AH6 ) || ( mic [ px ] [ py ] [ pz ] == ETTR ) ) {
7960 ntot += 1;
7961 mic [ px ] [ py ] [ pz ] = BURNT;
7962 nnew += 1;
7963 if ( nnew >= SIZESET ) {
7964 printf("error in size of nnew %ld\n", nnew);
7965 }
7966
7967 nnewx [ nnew ] = x1;
7968 nnewy [ nnew ] = y1;
7969 nnewz [ nnew ] = z1;
7970 }
7971 /* 2) old pixel is CSH or ETTR or C3AH6 and new pixel is one of cement clinker, slag, or fly ash phases */
7972 else if ( ( ( newmat [ qx ] [ qy ] [ qz ] == CSH ) || ( newmat [ qx ] [ qy ] [ qz ] == ETTRC4AF ) || ( newmat [ qx ] [ qy ] [ qz ] == C3AH6 ) || ( newmat [ qx ] [ qy ] [ qz ] == ETTR ) ) &&
7973 ( ( mic [ px ] [ py ] [ pz ] == C3S ) ||
7974 ( mic [ px ] [ py ] [ pz ] == C2S ) ||
7975 ( mic [ px ] [ py ] [ pz ] == CAS2 ) ||
7976 ( mic [ px ] [ py ] [ pz ] == SLAG ) ||
7977 ( mic [ px ] [ py ] [ pz ] == POZZ ) ||
7978 ( mic [ px ] [ py ] [ pz ] == ASG ) ||
7979 ( mic [ px ] [ py ] [ pz ] == C3A ) ||
7980 ( mic [ px ] [ py ] [ pz ] == C4AF ) ) ) {
7981 ntot += 1;
7982 mic [ px ] [ py ] [ pz ] = BURNT;
7983 nnew += 1;
7984 if ( nnew >= SIZESET ) {
7985 printf("error in size of nnew %ld\n", nnew);
7986 }
7987
7988 nnewx [ nnew ] = x1;
7989 nnewy [ nnew ] = y1;
7990 nnewz [ nnew ] = z1;
7991 }
7992 /* 3) old and new pixels belong to one of cement clinker, slag, or fly ash phases and */
7993 /* are contained in the same initial cement particle */
7994 /* and it is not a one-pixel particle */
7995 else if ( ( micpart [ qx ] [ qy ] [ qz ] == micpart [ px ] [ py ] [ pz ] ) &&
7996 ( ( mic [ px ] [ py ] [ pz ] == C3S ) ||
7997 ( mic [ px ] [ py ] [ pz ] == C2S ) ||
7998 ( mic [ px ] [ py ] [ pz ] == POZZ ) ||
7999 ( mic [ px ] [ py ] [ pz ] == SLAG ) ||
8000 ( mic [ px ] [ py ] [ pz ] == ASG ) ||
8001 ( mic [ px ] [ py ] [ pz ] == CAS2 ) ||
8002 ( mic [ px ] [ py ] [ pz ] == C3A ) ||
8003 ( mic [ px ] [ py ] [ pz ] == C4AF ) ) && ( ( newmat [ qx ] [ qy ] [ qz ] == C3S ) ||
8004 ( newmat [ qx ] [ qy ] [ qz ] == C2S ) ||
8005 ( newmat [ qx ] [ qy ] [ qz ] == SLAG ) ||
8006 ( newmat [ qx ] [ qy ] [ qz ] == ASG ) ||
8007 ( newmat [ qx ] [ qy ] [ qz ] == POZZ ) ||
8008 ( newmat [ qx ] [ qy ] [ qz ] == CAS2 ) ||
8009 ( newmat [ qx ] [ qy ] [ qz ] == C3A ) ||
8010 ( newmat [ qx ] [ qy ] [ qz ] == C4AF ) ) ) {
8011 ntot += 1;
8012 mic [ px ] [ py ] [ pz ] = BURNT;
8013 nnew += 1;
8014 if ( nnew >= SIZESET ) {
8015 printf("error in size of nnew %ld\n", nnew);
8016 }
8017
8018 nnewx [ nnew ] = x1;
8019 nnewy [ nnew ] = y1;
8020 nnewz [ nnew ] = z1;
8021 }
8022 }
8023
8024 /* nonperiodic if delimiter */
8025 }
8026
8027 /* neighbors loop */
8028 }
8029
8030 /* propagators loop */
8031 if ( nnew > 0 ) {
8032 ncur = nnew;
8033 /* update the burn front matrices */
8034 for ( icur = 1; icur <= ncur; icur++ ) {
8035 nmatx [ icur ] = nnewx [ icur ];
8036 nmaty [ icur ] = nnewy [ icur ];
8037 nmatz [ icur ] = nnewz [ icur ];
8038 }
8039 }
8040 } while ( nnew > 0 );
8041
8042 ntop += ntot;
8043 xl = 0;
8044 xh = SYSIZE - 1;
8045 /* Check for percolated path through system */
8046 for ( j1 = 0; j1 < SYSIZE; j1++ ) {
8047 for ( k1 = 0; k1 < SYSIZE; k1++ ) {
8048 px = cx(xl, j1, k1, d1, d2, d3);
8049 py = cy(xl, j1, k1, d1, d2, d3);
8050 pz = cz(xl, j1, k1, d1, d2, d3);
8051 qx = cx(xh, j1, k1, d1, d2, d3);
8052 qy = cy(xh, j1, k1, d1, d2, d3);
8053 qz = cz(xh, j1, k1, d1, d2, d3);
8054 if ( ( mic [ px ] [ py ] [ pz ] == BURNT ) && ( mic [ qx ] [ qy ] [ qz ] == BURNT ) ) {
8055 igood = 2;
8056 }
8057
8058 if ( mic [ px ] [ py ] [ pz ] == BURNT ) {
8059 mic [ px ] [ py ] [ pz ] = BURNT + 1;
8060 }
8061
8062 if ( mic [ qx ] [ qy ] [ qz ] == BURNT ) {
8063 mic [ qx ] [ qy ] [ qz ] = BURNT + 1;
8064 }
8065 }
8066 }
8067
8068 if ( igood == 2 ) {
8069 nthrough += ntot;
8070 }
8071 }
8072 }
8073 }
8074
8075#ifdef PRINTF
8076 printf("Phase ID= Solid Phases \n");
8077 printf("Number accessible from first surface = %ld \n", ntop);
8078 printf("Number contained in through pathways= %ld \n", nthrough);
8079#endif
8080
8081 mass_burn += specgrav [ C3S ] * count [ C3S ];
8082 mass_burn += specgrav [ C2S ] * count [ C2S ];
8083 mass_burn += specgrav [ C3A ] * count [ C3A ];
8084 mass_burn += specgrav [ C4AF ] * count [ C4AF ];
8085 alpha_burn = 1. - ( mass_burn / cemmass );
8086
8087 con_frac = 0.0;
8088 count_solid = count [ C3S ] + count [ C2S ] + count [ C3A ] + count [ C4AF ] + count [ ETTR ] + count [ CSH ] + count [ C3AH6 ] + count [ ETTRC4AF ] + count [ POZZ ] + count [ ASG ] + count [ SLAG ] + count [ CAS2 ];
8089
8090 if ( count_solid > 0 ) {
8091 con_frac = ( float ) nthrough / ( float ) count_solid;
8092 }
8093
8094#ifdef OUTFILES
8095 //fprintf(percfile, "%d %f %f %ld %ld %f\n", cyccnt, time_cur + ( 2. * ( float ) ( cyccnt ) - 1.0 ) * beta / krate, alpha_cur, nthrough, count [ C3S ] + count [ C2S ] + count [ C3A ] + count [ C4AF ] + count [ CAS2 ] + count [ SLAG ] + count [ ASG ] + count [ POZZ ] + count [ ETTR ] + count [ C3AH6 ] + count [ ETTRC4AF ] + count [ CSH ], con_frac);
8096 //fflush(percfile);
8097#endif
8098
8099 if ( con_frac > 0.985 ) {
8100 setyet = 1;
8101 }
8102
8104
8105 /* return the burnt sites to their original phase values */
8106 for ( i = 0; i < SYSIZE; i++ ) {
8107 for ( j = 0; j < SYSIZE; j++ ) {
8108 for ( k = 0; k < SYSIZE; k++ ) {
8109 if ( mic [ i ] [ j ] [ k ] >= BURNT ) {
8110 mic [ i ] [ j ] [ k ] = newmat [ i ] [ j ] [ k ];
8111 }
8112 }
8113 }
8114 }
8115
8116
8117 dealloc_char_3D(newmat, SYSIZE);
8118 delete [] nmatx;
8119 delete [] nmaty;
8120 delete [] nmatz;
8121 delete [] nnewx;
8122 delete [] nnewy;
8123 delete [] nnewz;
8124
8125 /* Return flag indicating if set has indeed occurred */
8126 return ( setyet );
8127
8128 ( void ) alpha_burn;
8129}
8130
8131
8132
8133/* Routine to assess relative particle hydration */
8134void CemhydMatStatus :: parthyd()
8135{
8136 int norig [ 100000 ], nleft [ 100000 ];
8137 int ix, iy, iz;
8138 char valmic, valmicorig;
8139 int valpart, partmax;
8140 float alpart;
8141 FILE *phydfile;
8142
8143 /* Initialize the particle count arrays */
8144 for ( ix = 0; ix < 100000; ix++ ) {
8145 nleft [ ix ] = norig [ ix ] = 0;
8146 }
8147
8148 phydfile = fopen(phrname, "a");
8149 fprintf(phydfile, "%d %f\n", cyccnt, alpha_cur);
8150
8151 partmax = 0;
8152 /* Scan the microstructure pixel by pixel and update counts */
8153 for ( ix = 0; ix < SYSIZE; ix++ ) {
8154 for ( iy = 0; iy < SYSIZE; iy++ ) {
8155 for ( iz = 0; iz < SYSIZE; iz++ ) {
8156 if ( micpart [ ix ] [ iy ] [ iz ] != 0 ) {
8157 valpart = micpart [ ix ] [ iy ] [ iz ];
8158 if ( valpart > partmax ) {
8159 partmax = valpart;
8160 }
8161
8162 valmic = mic [ ix ] [ iy ] [ iz ];
8163 if ( ( valmic == C3S ) || ( valmic == C2S ) || ( valmic == C3A ) || ( valmic == C4AF ) ) {
8164 nleft [ valpart ] += 1;
8165 }
8166
8167 valmicorig = micorig [ ix ] [ iy ] [ iz ];
8168 if ( ( valmicorig == C3S ) || ( valmicorig == C2S ) || ( valmicorig == C3A ) || ( valmicorig == C4AF ) ) {
8169 norig [ valpart ] += 1;
8170 }
8171 }
8172 }
8173 }
8174 }
8175
8176 /* Output results to end of particle hydration file */
8177 for ( ix = 100; ix <= partmax; ix++ ) {
8178 alpart = 0.0;
8179 if ( norig [ ix ] != 0 ) {
8180 alpart = 1. - ( float ) nleft [ ix ] / ( float ) norig [ ix ];
8181 }
8182
8183 fprintf(phydfile, "%d %d %d %.3f\n", ix, norig [ ix ], nleft [ ix ], alpart);
8184 }
8185
8186 fclose(phydfile);
8187}
8188
8189
8190/* extpozz, movefh3, movech, extc3ah6, movec3a */
8191/* extfreidel, movecacl2, extstrat, moveas */
8192int CemhydMatStatus :: moveone(int *xloc, int *yloc, int *zloc, int *act, int sumold)
8193{
8194 int plok, sumnew, xl1, yl1, zl1, act1;
8195
8196 sumnew = 1;
8197 /* store the input values for location */
8198 xl1 = ( * xloc );
8199 yl1 = ( * yloc );
8200 zl1 = ( * zloc );
8201 act1 = ( * act );
8202
8203 /* Choose one of six directions (at random) for the new */
8204 /* location */
8205 plok = ( int ) ( 6. * ran1(seed) );
8206 if ( ( plok > 5 ) || ( plok < 0 ) ) {
8207 plok = 5;
8208 }
8209
8210 switch ( plok ) {
8211 case 0:
8212 xl1 -= 1;
8213 act1 = 1;
8214 if ( xl1 < 0 ) {
8215 xl1 = ( SYSIZEM1 );
8216 }
8217
8218 if ( sumold % 2 != 0 ) {
8219 sumnew = 2;
8220 }
8221
8222 break;
8223 case 1:
8224 xl1 += 1;
8225 act1 = 2;
8226 if ( xl1 >= SYSIZE ) {
8227 xl1 = 0;
8228 }
8229
8230 if ( sumold % 3 != 0 ) {
8231 sumnew = 3;
8232 }
8233
8234 break;
8235 case 2:
8236 yl1 -= 1;
8237 act1 = 3;
8238 if ( yl1 < 0 ) {
8239 yl1 = ( SYSIZEM1 );
8240 }
8241
8242 if ( sumold % 5 != 0 ) {
8243 sumnew = 5;
8244 }
8245
8246 break;
8247 case 3:
8248 yl1 += 1;
8249 act1 = 4;
8250 if ( yl1 >= SYSIZE ) {
8251 yl1 = 0;
8252 }
8253
8254 if ( sumold % 7 != 0 ) {
8255 sumnew = 7;
8256 }
8257
8258 break;
8259 case 4:
8260 zl1 -= 1;
8261 act1 = 5;
8262 if ( zl1 < 0 ) {
8263 zl1 = ( SYSIZEM1 );
8264 }
8265
8266 if ( sumold % 11 != 0 ) {
8267 sumnew = 11;
8268 }
8269
8270 break;
8271 case 5:
8272 zl1 += 1;
8273 act1 = 6;
8274 if ( zl1 >= SYSIZE ) {
8275 zl1 = 0;
8276 }
8277
8278 if ( sumold % 13 != 0 ) {
8279 sumnew = 13;
8280 }
8281
8282 break;
8283 default:
8284 break;
8285 }
8286
8287 /* Return the new location */
8288 * xloc = xl1;
8289 * yloc = yl1;
8290 * zloc = zl1;
8291 * act = act1;
8292 /* sumnew returns a prime number indicating that a specific direction */
8293 /* has been chosen */
8294 return ( sumnew );
8295}
8296
8297/* routine to return count of number of neighboring pixels for pixel */
8298/* (xck,yck,zck) which are not phase ph1, ph2, or ph3 which are input as */
8299/* parameters */
8300/* Calls no other routines */
8301/* Called by extettr, extfh3, extch, extafm, extpozz, extc3ah6 */
8302/* extfreidel, extcsh, and extstrat */
8303int CemhydMatStatus :: edgecnt(int xck, int yck, int zck, int ph1, int ph2, int ph3)
8304{
8305 int ixe, iye, ize, edgeback, x2, y2, z2, check;
8306
8307 /* counter for number of neighboring pixels which are not ph1, ph2, or ph3 */
8308 edgeback = 0;
8309
8310 /* Examine all pixels in a 3*3*3 box centered at (xck,yck,zck) */
8311 /* except for the central pixel */
8312 for ( ixe = ( -1 ); ixe <= 1; ixe++ ) {
8313 x2 = xck + ixe;
8314 for ( iye = ( -1 ); iye <= 1; iye++ ) {
8315 y2 = yck + iye;
8316 for ( ize = ( -1 ); ize <= 1; ize++ ) {
8317 if ( ( ixe != 0 ) || ( iye != 0 ) || ( ize != 0 ) ) {
8318 z2 = zck + ize;
8319 /* adjust to maintain periodic boundaries */
8320 if ( x2 < 0 ) {
8321 x2 = ( SYSIZEM1 );
8322 } else if ( x2 >= SYSIZE ) {
8323 x2 = 0;
8324 }
8325
8326 if ( y2 < 0 ) {
8327 y2 = ( SYSIZEM1 );
8328 } else if ( y2 >= SYSIZE ) {
8329 y2 = 0;
8330 }
8331
8332 if ( z2 < 0 ) {
8333 z2 = ( SYSIZEM1 );
8334 } else if ( z2 >= SYSIZE ) {
8335 z2 = 0;
8336 }
8337
8338 check = mic [ x2 ] [ y2 ] [ z2 ];
8339 if ( ( check != ph1 ) && ( check != ph2 ) && ( check != ph3 ) ) {
8340 edgeback += 1;
8341 }
8342 }
8343 }
8344 }
8345 }
8346
8347 /* return number of neighboring pixels which are not ph1, ph2, or ph3 */
8348 return ( edgeback );
8349}
8350
8351/* routine to add extra CSH when diffusing CSH reacts */
8352/* Called by movecsh */
8353/* Calls edgecnt */
8354void CemhydMatStatus :: extcsh()
8355{
8356 int numnear, xchr, ychr, zchr, fchr, check, msface;
8357 long int tries;
8358
8359 fchr = 0;
8360 tries = 0;
8361 /* locate CSH at random location */
8362 /* in pore space in contact with at least another CSH or C3S or C2S */
8363 while ( fchr == 0 ) {
8364 tries += 1;
8365 /* generate a random location in the 3-D system */
8366 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8367 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8368 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8369 if ( xchr >= SYSIZE ) {
8370 xchr = 0;
8371 }
8372
8373 if ( ychr >= SYSIZE ) {
8374 ychr = 0;
8375 }
8376
8377 if ( zchr >= SYSIZE ) {
8378 zchr = 0;
8379 }
8380
8381 check = mic [ xchr ] [ ychr ] [ zchr ];
8382
8383 /* if location is porosity, locate the CSH there */
8384 if ( check == POROSITY ) {
8385 numnear = edgecnt(xchr, ychr, zchr, CSH, C3S, C2S);
8386 /* be sure that at least one neighboring pixel */
8387 /* is C2S, C3S, or diffusing CSH */
8388 if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8389 mic [ xchr ] [ ychr ] [ zchr ] = CSH;
8390 count [ CSH ] += 1;
8391 count [ POROSITY ] -= 1;
8392 cshage [ xchr ] [ ychr ] [ zchr ] = cyccnt;
8393 if ( cshgeom == 1 ) {
8394 msface = ( int ) ( 3. * ran1(seed) + 1. );
8395 if ( msface > 3 ) {
8396 msface = 1;
8397 }
8398
8399 faces [ xchr ] [ ychr ] [ zchr ] = msface;
8400 ncshplateinit += 1;
8401 }
8402
8403 fchr = 1;
8404 }
8405 }
8406 }
8407}
8408
8409/* routine to move a diffusing CSH species */
8410/* Inputs: current location (xcur,ycur,zcur) and flag indicating if final */
8411/* step in diffusion process */
8412/* Returns flag indicating action taken (reaction or diffusion/no movement) */
8413/* Calls moveone,extcsh */
8414/* Called by hydrate */
8415int CemhydMatStatus :: movecsh(int xcur, int ycur, int zcur, int finalstep, int cycorig)
8416{
8417 int xnew, ynew, znew, action, sumback, sumin, check;
8418 int msface, mstest = 0, mstest2 = 0;
8419 float prcsh, prcsh1, prcsh2, prtest;
8420
8421 action = 0;
8422 /* Store current location of species */
8423 xnew = xcur;
8424 ynew = ycur;
8425 znew = zcur;
8426 sumin = 1;
8427 sumback = moveone(& xnew, & ynew, & znew, & action, sumin);
8428 if ( cshgeom == 1 ) {
8429 /* Determine eligible faces based on direction of move */
8430 if ( xnew != xcur ) {
8431 mstest = 1;
8432 mstest2 = 2;
8433 }
8434
8435 if ( ynew != ycur ) {
8436 mstest = 2;
8437 mstest2 = 3;
8438 }
8439
8440 if ( znew != zcur ) {
8441 mstest = 3;
8442 mstest2 = 1;
8443 }
8444 }
8445
8446 if ( action == 0 ) {
8447 printf("Error in value of action \n");
8448 }
8449
8450 check = mic [ xnew ] [ ynew ] [ znew ];
8451
8452
8453 /* if new location is solid CSH and plate growth is favorable, */
8454 /* then convert diffusing CSH species to solid CSH */
8455 prcsh = ran1(seed);
8456 if ( ( check == CSH ) && ( ( cshgeom == 0 ) || ( faces [ xnew ] [ ynew ] [ znew ] == 0 ) || ( faces [ xnew ] [ ynew ] [ znew ] == mstest ) || ( faces [ xnew ] [ ynew ] [ znew ] == mstest2 ) ) ) {
8457 /* decrement count of diffusing CSH species */
8458 count [ DIFFCSH ] -= 1;
8459 /* and increment count of solid CSH if needed */
8460 prtest = molarvcsh [ cyccnt ] / molarvcsh [ cycorig ];
8461 prcsh1 = ran1(seed);
8462 if ( prcsh1 <= prtest ) {
8463 mic [ xcur ] [ ycur ] [ zcur ] = CSH;
8464 if ( cshgeom == 1 ) {
8465 faces [ xcur ] [ ycur ] [ zcur ] = faces [ xnew ] [ ynew ] [ znew ];
8466 ncshplategrow += 1;
8467 }
8468
8469 cshage [ xcur ] [ ycur ] [ zcur ] = cyccnt;
8470 count [ CSH ] += 1;
8471 } else {
8472 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
8473 count [ POROSITY ] += 1;
8474 }
8475
8476 /* May need extra solid CSH if temperature goes down with time */
8477 if ( prtest > 1.0 ) {
8478 prcsh2 = ran1(seed);
8479 if ( prcsh2 < ( prtest - 1.0 ) ) {
8480 extcsh();
8481 }
8482 }
8483
8484 action = 0;
8485 }
8486 /* Changed prcsh limit from 0.1 to 0.01 for CH test 1/27/05 */
8487 else if ( ( check == SLAGCSH ) || ( check == POZZCSH ) || ( finalstep == 1 ) ||
8488 ( ( ( check == C3S ) || ( check == C2S ) ) && ( prcsh < 0.001 ) ) ||
8489 ( ( ( check == C3A ) || ( check == C4AF ) ) && ( prcsh < 0.2 ) ) ||
8490 ( ( check == CH ) && ( prcsh < 0.01 ) ) ||
8491 ( check == CACO3 ) || ( check == INERT ) ) {
8492 /* decrement count of diffusing CSH species */
8493 count [ DIFFCSH ] -= 1;
8494 /* and increment count of solid CSH if needed */
8495 prtest = molarvcsh [ cyccnt ] / molarvcsh [ cycorig ];
8496 prcsh1 = ran1(seed);
8497 if ( prcsh1 <= prtest ) {
8498 mic [ xcur ] [ ycur ] [ zcur ] = CSH;
8499 cshage [ xcur ] [ ycur ] [ zcur ] = cyccnt;
8500 if ( cshgeom == 1 ) {
8501 msface = ( int ) ( 2. * ran1(seed) + 1. );
8502 if ( msface > 2 ) {
8503 msface = 1;
8504 }
8505
8506 if ( msface == 1 ) {
8507 faces [ xcur ] [ ycur ] [ zcur ] = mstest;
8508 } else {
8509 faces [ xcur ] [ ycur ] [ zcur ] = mstest2;
8510 }
8511
8512 ncshplateinit += 1;
8513 }
8514
8515 count [ CSH ] += 1;
8516 } else {
8517 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
8518 count [ POROSITY ] += 1;
8519 }
8520
8521 /* May need extra solid CSH if temperature goes down with time */
8522 if ( prtest > 1.0 ) {
8523 prcsh2 = ran1(seed);
8524 if ( prcsh2 < ( prtest - 1.0 ) ) {
8525 extcsh();
8526 }
8527 }
8528
8529 action = 0;
8530 }
8531
8532 if ( action != 0 ) {
8533 /* if diffusion step is possible, perform it */
8534 if ( check == POROSITY ) {
8535 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
8536 mic [ xnew ] [ ynew ] [ znew ] = DIFFCSH;
8537 } else {
8538 /* indicate that diffusing CSH species remained */
8539 /* at original location */
8540 action = 7;
8541 }
8542 }
8543
8544 return ( action );
8545
8546 ( void ) sumback;
8547}
8548
8549/* routine to add extra FH3 when gypsum, hemihydrate, anhydrite, CAS2, or */
8550/* CaCl2 reacts with C4AF at location (xpres,ypres,zpres) */
8551/* Called by movegyp, moveettr, movecas2, movehem, moveanh, and movecacl2 */
8552/* Calls moveone and edgecnt */
8553void CemhydMatStatus :: extfh3(int xpres, int ypres, int zpres)
8554{
8555 int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
8556 long int tries;
8557
8558 /* first try 6 neighboring locations until */
8559 /* a) successful */
8560 /* b) all 6 sites are tried and full or */
8561 /* c) 500 tries are made */
8562 fchr = 0;
8563 sump = 1;
8564 for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
8565 /* choose a neighbor at random */
8566 xchr = xpres;
8567 ychr = ypres;
8568 zchr = zpres;
8569 newact = 0;
8570 multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
8571 if ( newact == 0 ) {
8572 printf("Error in value of newact in extfh3 \n");
8573 }
8574
8575 check = mic [ xchr ] [ ychr ] [ zchr ];
8576
8577 /* if neighbor is porosity */
8578 /* then locate the FH3 there */
8579 if ( check == POROSITY ) {
8580 mic [ xchr ] [ ychr ] [ zchr ] = FH3;
8581 count [ FH3 ] += 1;
8582 count [ POROSITY ] -= 1;
8583 fchr = 1;
8584 } else {
8585 sump *= multf;
8586 }
8587 }
8588
8589 /* if no neighbor available, locate FH3 at random location */
8590 /* in pore space in contact with at least one FH3 */
8591 tries = 0;
8592 while ( fchr == 0 ) {
8593 tries += 1;
8594 /* generate a random location in the 3-D system */
8595 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8596 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8597 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8598 if ( xchr >= SYSIZE ) {
8599 xchr = 0;
8600 }
8601
8602 if ( ychr >= SYSIZE ) {
8603 ychr = 0;
8604 }
8605
8606 if ( zchr >= SYSIZE ) {
8607 zchr = 0;
8608 }
8609
8610 check = mic [ xchr ] [ ychr ] [ zchr ];
8611 /* if location is porosity, locate the FH3 there */
8612 if ( check == POROSITY ) {
8613 numnear = edgecnt(xchr, ychr, zchr, FH3, FH3, DIFFFH3);
8614 /* be sure that at least one neighboring pixel */
8615 /* is FH3 or diffusing FH3 */
8616 if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8617 mic [ xchr ] [ ychr ] [ zchr ] = FH3;
8618 count [ FH3 ] += 1;
8619 count [ POROSITY ] -= 1;
8620 fchr = 1;
8621 }
8622 }
8623 }
8624}
8625
8626/* routine to add extra ettringite when gypsum, anhydrite, or hemihydrate */
8627/* reacts with aluminates addition adjacent to location (xpres,ypres,zpres) */
8628/* in a fashion to preserve needle growth */
8629/* etype=0 indicates primary ettringite */
8630/* etype=1 indicates iron-rich stable ettringite */
8631/* Returns flag indicating action taken */
8632/* Calls moveone and edgecnt */
8633/* Called by movegyp, movehem, moveanh, and movec3a */
8634int CemhydMatStatus :: extettr(int xpres, int ypres, int zpres, int etype)
8635{
8636 int check, newact, multf, numnear, sump, xchr, ychr, zchr, fchr, i1;
8637 int numalum, numsil;
8638 float pneigh, ptest;
8639 long int tries;
8640
8641 /* first try neighboring locations until */
8642 /* a) successful */
8643 /* c) 1000 tries are made */
8644 fchr = 0;
8645 sump = 1;
8646 /* Note that 30030 = 2*3*5*7*11*13 */
8647 /* indicating that all six sites have been tried */
8648 for ( i1 = 1; ( ( i1 <= 1000 ) && ( fchr == 0 ) ); i1++ ) {
8649 /* determine location of neighbor (using periodic boundaries) */
8650 xchr = xpres;
8651 ychr = ypres;
8652 zchr = zpres;
8653 newact = 0;
8654 multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
8655 if ( newact == 0 ) {
8656 printf("Error in value of action \n");
8657 }
8658
8659 check = mic [ xchr ] [ ychr ] [ zchr ];
8660
8661 /* if neighbor is porosity, and conditions are favorable */
8662 /* based on number of neighboring ettringite, C3A, or C4AF */
8663 /* pixels then locate the ettringite there */
8664 if ( check == POROSITY ) {
8665 /* be sure ettringite doesn't touch C3S */
8666 numsil = edgecnt(xchr, ychr, zchr, C3S, C2S, C3S);
8667 numsil = 26 - numsil;
8668 if ( etype == 0 ) {
8669 numnear = edgecnt(xchr, ychr, zchr, ETTR, ETTR, ETTR);
8670 numalum = edgecnt(xchr, ychr, zchr, C3A, C3A, C3A);
8671 numalum = 26 - numalum;
8672 } else {
8673 numnear = edgecnt(xchr, ychr, zchr, ETTRC4AF, ETTRC4AF, ETTRC4AF);
8674 numalum = edgecnt(xchr, ychr, zchr, C4AF, C4AF, C4AF);
8675 numalum = 26 - numalum;
8676 }
8677
8678 pneigh = ( float ) ( numnear + 1 ) / 26.0;
8679 pneigh *= pneigh;
8680 if ( numalum <= 1 ) {
8681 pneigh = 0.0;
8682 }
8683
8684 if ( numalum >= 2 ) {
8685 pneigh += 0.5;
8686 }
8687
8688 if ( numalum >= 3 ) {
8689 pneigh += 0.25;
8690 }
8691
8692 if ( numalum >= 5 ) {
8693 pneigh += 0.25;
8694 }
8695
8696 ptest = ran1(seed);
8697 if ( numsil < 1 ) {
8698 if ( pneigh >= ptest ) {
8699 if ( etype == 0 ) {
8700 mic [ xchr ] [ ychr ] [ zchr ] = ETTR;
8701 count [ ETTR ] += 1;
8702 } else {
8703 mic [ xchr ] [ ychr ] [ zchr ] = ETTRC4AF;
8704 count [ ETTRC4AF ] += 1;
8705 }
8706
8707 fchr = 1;
8708 count [ POROSITY ] -= 1;
8709 }
8710 }
8711 }
8712 }
8713
8714 /* if no neighbor available, locate ettringite at random location */
8715 /* in pore space in contact with at least another ettringite */
8716 /* or aluminate surface */
8717 tries = 0;
8718 while ( fchr == 0 ) {
8719 tries += 1;
8720 newact = 7;
8721 /* generate a random location in the 3-D system */
8722 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8723 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8724 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8725 if ( xchr >= SYSIZE ) {
8726 xchr = 0;
8727 }
8728
8729 if ( ychr >= SYSIZE ) {
8730 ychr = 0;
8731 }
8732
8733 if ( zchr >= SYSIZE ) {
8734 zchr = 0;
8735 }
8736
8737 check = mic [ xchr ] [ ychr ] [ zchr ];
8738 /* if location is porosity, locate the ettringite there */
8739 if ( check == POROSITY ) {
8740 numsil = edgecnt(xchr, ychr, zchr, C3S, C2S, C3S);
8741 numsil = 26 - numsil;
8742 if ( etype == 0 ) {
8743 numnear = edgecnt(xchr, ychr, zchr, ETTR, C3A, C4AF);
8744 } else {
8745 numnear = edgecnt(xchr, ychr, zchr, ETTRC4AF, C3A, C4AF);
8746 }
8747
8748 /* be sure that at least one neighboring pixel */
8749 /* is ettringite, or aluminate clinker */
8750 if ( ( tries > 5000 ) || ( ( numnear < 26 ) && ( numsil < 1 ) ) ) {
8751 if ( etype == 0 ) {
8752 mic [ xchr ] [ ychr ] [ zchr ] = ETTR;
8753 count [ ETTR ] += 1;
8754 } else {
8755 mic [ xchr ] [ ychr ] [ zchr ] = ETTRC4AF;
8756 count [ ETTRC4AF ] += 1;
8757 }
8758
8759 count [ POROSITY ] -= 1;
8760 fchr = 1;
8761 }
8762 }
8763 }
8764
8765 return ( newact );
8766
8767 ( void ) multf;
8768}
8769
8770/* routine to add extra CH when gypsum, hemihydrate, anhydrite, CaCl2, or */
8771/* diffusing CAS2 reacts with C4AF */
8772/* Called by movegyp, movehem, moveanh, moveettr, movecas2, and movecacl2 */
8773/* Calls edgecnt */
8774void CemhydMatStatus :: extch()
8775{
8776 int numnear, xchr, ychr, zchr, fchr, check;
8777 long int tries;
8778
8779 fchr = 0;
8780 tries = 0;
8781 /* locate CH at random location */
8782 /* in pore space in contact with at least another CH */
8783 while ( fchr == 0 ) {
8784 tries += 1;
8785 /* generate a random location in the 3-D system */
8786 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8787 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8788 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8789 if ( xchr >= SYSIZE ) {
8790 xchr = 0;
8791 }
8792
8793 if ( ychr >= SYSIZE ) {
8794 ychr = 0;
8795 }
8796
8797 if ( zchr >= SYSIZE ) {
8798 zchr = 0;
8799 }
8800
8801 check = mic [ xchr ] [ ychr ] [ zchr ];
8802
8803 /* if location is porosity, locate the CH there */
8804 if ( check == POROSITY ) {
8805 numnear = edgecnt(xchr, ychr, zchr, CH, DIFFCH, CH);
8806 /* be sure that at least one neighboring pixel */
8807 /* is CH or diffusing CH */
8808 if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8809 mic [ xchr ] [ ychr ] [ zchr ] = CH;
8810 count [ CH ] += 1;
8811 count [ POROSITY ] -= 1;
8812 fchr = 1;
8813 }
8814 }
8815 }
8816}
8817
8818/* routine to add extra gypsum when hemihydrate or anhydrite hydrates */
8819/* Called by movehem and moveanh */
8820/* Calls moveone and edgecnt */
8821void CemhydMatStatus :: extgyps(int xpres, int ypres, int zpres)
8822{
8823 int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
8824 long int tries;
8825
8826 /* first try 6 neighboring locations until */
8827 /* a) successful */
8828 /* b) all 6 sites are tried and full or */
8829 /* c) 500 tries are made */
8830 fchr = 0;
8831 sump = 1;
8832 for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
8833 /* choose a neighbor at random */
8834 xchr = xpres;
8835 ychr = ypres;
8836 zchr = zpres;
8837 newact = 0;
8838 multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
8839 if ( newact == 0 ) {
8840 printf("Error in value of newact in extfh3 \n");
8841 }
8842
8843 check = mic [ xchr ] [ ychr ] [ zchr ];
8844
8845 /* if neighbor is porosity */
8846 /* then locate the GYPSUMS there */
8847 if ( check == POROSITY ) {
8848 mic [ xchr ] [ ychr ] [ zchr ] = GYPSUMS;
8849 count [ GYPSUMS ] += 1;
8850 count [ POROSITY ] -= 1;
8851 fchr = 1;
8852 } else {
8853 sump *= multf;
8854 }
8855 }
8856
8857 /* if no neighbor available, locate GYPSUMS at random location */
8858 /* in pore space in contact with at least one GYPSUMS */
8859 tries = 0;
8860 while ( fchr == 0 ) {
8861 tries += 1;
8862 /* generate a random location in the 3-D system */
8863 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8864 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8865 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8866 if ( xchr >= SYSIZE ) {
8867 xchr = 0;
8868 }
8869
8870 if ( ychr >= SYSIZE ) {
8871 ychr = 0;
8872 }
8873
8874 if ( zchr >= SYSIZE ) {
8875 zchr = 0;
8876 }
8877
8878 check = mic [ xchr ] [ ychr ] [ zchr ];
8879 /* if location is porosity, locate the GYPSUMS there */
8880 if ( check == POROSITY ) {
8881 numnear = edgecnt(xchr, ychr, zchr, HEMIHYD, GYPSUMS, ANHYDRITE);
8882 /* be sure that at least one neighboring pixel */
8883 /* is Gypsum in some form */
8884 if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8885 mic [ xchr ] [ ychr ] [ zchr ] = GYPSUMS;
8886 count [ GYPSUMS ] += 1;
8887 count [ POROSITY ] -= 1;
8888 fchr = 1;
8889 }
8890 }
8891 }
8892}
8893
8894/* routine to move a diffusing ANHYDRITE species */
8895/* Inputs: current location (xcur,ycur,zcur) and flag indicating if final */
8896/* step in diffusion process */
8897/* Returns flag indicating action taken (reaction or diffusion/no movement) */
8898/* Calls moveone */
8899/* Called by hydrate */
8900int CemhydMatStatus :: moveanh(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
8901{
8902 int xnew, ynew, znew, action, sumback, sumin, check = -1;
8903 int nexp, iexp, xexp, yexp, zexp, newact, ettrtype;
8904 float pgen, pexp, pext, p2diff;
8905
8906 action = 0;
8907 /* first check for nucleation */
8908 pgen = ran1(seed);
8909 p2diff = ran1(seed);
8910 if ( ( nucprgyp >= pgen ) || ( finalstep == 1 ) ) {
8911 action = 0;
8912 mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
8913 count [ DIFFANH ] -= 1;
8914 count [ GYPSUMS ] += 1;
8915 pexp = ran1(seed);
8916 if ( pexp < 0.4 ) {
8917 extgyps(xcur, ycur, zcur);
8918 }
8919 } else {
8920 /* Store current location of species */
8921 xnew = xcur;
8922 ynew = ycur;
8923 znew = zcur;
8924 sumin = 1;
8925 sumback = moveone(& xnew, & ynew, & znew, & action, sumin);
8926
8927 if ( action == 0 ) {
8928 printf("Error in value of action \n");
8929 }
8930
8931 check = mic [ xnew ] [ ynew ] [ znew ];
8932
8933 /* if new location is solid GYPSUM(S) or diffusing GYPSUM, then convert */
8934 /* diffusing ANHYDRITE species to solid GYPSUM */
8935 if ( ( check == GYPSUM ) || ( check == GYPSUMS ) || ( check == DIFFGYP ) ) {
8936 mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
8937 /* decrement count of diffusing ANHYDRITE species */
8938 /* and increment count of solid GYPSUMS */
8939 count [ DIFFANH ] -= 1;
8940 count [ GYPSUMS ] += 1;
8941 action = 0;
8942 /* Add extra gypsum as necessary */
8943 pexp = ran1(seed);
8944 if ( pexp < 0.4 ) {
8945 extgyps(xnew, ynew, znew);
8946 }
8947 }
8948 /* if new location is C3A or diffusing C3A, execute conversion */
8949 /* to ettringite (including necessary volumetric expansion) */
8950 else if ( ( ( check == C3A ) && ( p2diff < SOLIDC3AGYP ) ) || ( ( check == DIFFC3A ) && ( p2diff < C3AGYP ) ) || ( ( check == DIFFC4A ) && ( p2diff < C3AGYP ) ) ) {
8951 /* Convert diffusing gypsum to an ettringite pixel */
8952 ettrtype = 0;
8953 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
8954 if ( check == DIFFC4A ) {
8955 ettrtype = 1;
8956 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
8957 }
8958
8959 action = 0;
8960 count [ DIFFANH ] -= 1;
8961 count [ check ] -= 1;
8962
8963 /* determine if C3A should be converted to ettringite */
8964 /* 1 unit of hemihydrate requires 0.569 units of C3A */
8965 /* and should form 4.6935 units of ettringite */
8966 pexp = ran1(seed);
8967 nexp = 3;
8968 if ( pexp <= 0.569 ) {
8969 if ( ettrtype == 0 ) {
8970 mic [ xnew ] [ ynew ] [ znew ] = ETTR;
8971 count [ ETTR ] += 1;
8972 } else {
8973 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
8974 count [ ETTRC4AF ] += 1;
8975 }
8976
8977 nexp = 2;
8978 } else {
8979 /* maybe someday, use a new FIXEDC3A here */
8980 /* so it won't dissolve later */
8981 if ( check == C3A ) {
8982 mic [ xnew ] [ ynew ] [ znew ] = C3A;
8983 count [ C3A ] += 1;
8984 } else {
8985 if ( ettrtype == 0 ) {
8986 count [ DIFFC3A ] += 1;
8987 mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
8988 } else {
8989 count [ DIFFC4A ] += 1;
8990 mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
8991 }
8992 }
8993
8994 nexp = 3;
8995 }
8996
8997 /* create extra ettringite pixels to maintain volume stoichiometry */
8998 /* xexp, yexp, and zexp hold coordinates of most recently added ettringite */
8999 /* species as we attempt to grow a needle like structure */
9000 xexp = xcur;
9001 yexp = ycur;
9002 zexp = zcur;
9003 for ( iexp = 1; iexp <= nexp; iexp++ ) {
9004 newact = extettr(xexp, yexp, zexp, ettrtype);
9005 /* update xexp, yexp and zexp as needed */
9006 switch ( newact ) {
9007 case 1:
9008 xexp -= 1;
9009 if ( xexp < 0 ) {
9010 xexp = ( SYSIZEM1 );
9011 }
9012
9013 break;
9014 case 2:
9015 xexp += 1;
9016 if ( xexp >= SYSIZE ) {
9017 xexp = 0;
9018 }
9019
9020 break;
9021 case 3:
9022 yexp -= 1;
9023 if ( yexp < 0 ) {
9024 yexp = ( SYSIZEM1 );
9025 }
9026
9027 break;
9028 case 4:
9029 yexp += 1;
9030 if ( yexp >= SYSIZE ) {
9031 yexp = 0;
9032 }
9033
9034 break;
9035 case 5:
9036 zexp -= 1;
9037 if ( zexp < 0 ) {
9038 zexp = ( SYSIZEM1 );
9039 }
9040
9041 break;
9042 case 6:
9043 zexp += 1;
9044 if ( zexp >= SYSIZE ) {
9045 zexp = 0;
9046 }
9047
9048 break;
9049 default:
9050 break;
9051 }
9052 }
9053
9054 /* probabilistic-based expansion for last ettringite pixel */
9055 pexp = ran1(seed);
9056 if ( pexp <= 0.6935 ) {
9057 newact = extettr(xexp, yexp, zexp, ettrtype);
9058 }
9059 }
9060
9061 /* if new location is C4AF execute conversion */
9062 /* to ettringite (including necessary volumetric expansion) */
9063 if ( ( check == C4AF ) && ( p2diff < SOLIDC4AFGYP ) ) {
9064 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9065 count [ ETTRC4AF ] += 1;
9066 count [ DIFFANH ] -= 1;
9067
9068 /* determine if C4AF should be converted to ettringite */
9069 /* 1 unit of gypsum requires 0.8174 units of C4AF */
9070 /* and should form 4.6935 units of ettringite */
9071 pexp = ran1(seed);
9072 nexp = 3;
9073 if ( pexp <= 0.8174 ) {
9074 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9075 count [ ETTRC4AF ] += 1;
9076 count [ C4AF ] -= 1;
9077 nexp = 2;
9078 pext = ran1(seed);
9079 /* Addition of extra CH */
9080 if ( pext < 0.2584 ) {
9081 extch();
9082 }
9083
9084 pext = ran1(seed);
9085 /* Addition of extra FH3 */
9086 if ( pext < 0.5453 ) {
9087 extfh3(xnew, ynew, znew);
9088 }
9089 } else {
9090 /* maybe someday, use a new FIXEDC4AF here */
9091 /* so it won't dissolve later */
9092 mic [ xnew ] [ ynew ] [ znew ] = C4AF;
9093 nexp = 3;
9094 }
9095
9096 /* create extra ettringite pixels to maintain volume stoichiometry */
9097 /* xexp, yexp and zexp hold coordinates of most recently added ettringite */
9098 /* species as we attempt to grow a needle like structure */
9099 xexp = xcur;
9100 yexp = ycur;
9101 zexp = zcur;
9102 for ( iexp = 1; iexp <= nexp; iexp++ ) {
9103 newact = extettr(xexp, yexp, zexp, 1);
9104 /* update xexp, yexp and zexp as needed */
9105 switch ( newact ) {
9106 case 1:
9107 xexp -= 1;
9108 if ( xexp < 0 ) {
9109 xexp = ( SYSIZEM1 );
9110 }
9111
9112 break;
9113 case 2:
9114 xexp += 1;
9115 if ( xexp >= SYSIZE ) {
9116 xexp = 0;
9117 }
9118
9119 break;
9120 case 3:
9121 yexp -= 1;
9122 if ( yexp < 0 ) {
9123 yexp = ( SYSIZEM1 );
9124 }
9125
9126 break;
9127 case 4:
9128 yexp += 1;
9129 if ( yexp >= SYSIZE ) {
9130 yexp = 0;
9131 }
9132
9133 break;
9134 case 5:
9135 zexp -= 1;
9136 if ( zexp < 0 ) {
9137 zexp = ( SYSIZEM1 );
9138 }
9139
9140 break;
9141 case 6:
9142 zexp += 1;
9143 if ( zexp >= SYSIZE ) {
9144 zexp = 0;
9145 }
9146
9147 break;
9148 default:
9149 break;
9150 }
9151 }
9152
9153 /* probabilistic-based expansion for last ettringite pixel */
9154 pexp = ran1(seed);
9155 if ( pexp <= 0.6935 ) {
9156 newact = extettr(xexp, yexp, zexp, 1);
9157 }
9158
9159 action = 0;
9160 }
9161 }
9162
9163 if ( action != 0 ) {
9164 /* if diffusion step is possible, perform it */
9165 if ( check == POROSITY ) {
9166 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
9167 mic [ xnew ] [ ynew ] [ znew ] = DIFFANH;
9168 } else {
9169 /* indicate that diffusing ANHYDRITE species remained */
9170 /* at original location */
9171 action = 7;
9172 }
9173 }
9174
9175 return ( action );
9176
9177 ( void ) sumback;
9178}
9179
9180/* routine to move a diffusing HEMIHYDRATE species */
9181/* Inputs: current location (xcur,ycur,zcur) and flag indicating if final */
9182/* step in diffusion process */
9183/* Returns flag indicating action taken (reaction or diffusion/no movement) */
9184/* Calls moveone, extettr, extch, and extfh3 */
9185/* Called by hydrate */
9186int CemhydMatStatus :: movehem(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
9187{
9188 int xnew, ynew, znew, action, sumback, sumin, check = -1;
9189 int nexp, iexp, xexp, yexp, zexp, newact, ettrtype;
9190 float pgen, pexp, pext, p2diff;
9191
9192 action = 0;
9193 /* first check for nucleation */
9194 pgen = ran1(seed);
9195 p2diff = ran1(seed);
9196 if ( ( nucprgyp >= pgen ) || ( finalstep == 1 ) ) {
9197 action = 0;
9198 mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
9199 count [ DIFFHEM ] -= 1;
9200 count [ GYPSUMS ] += 1;
9201 /* Add extra gypsum as necessary */
9202 pexp = ran1(seed);
9203 if ( pexp < 0.4 ) {
9204 extgyps(xcur, ycur, zcur);
9205 }
9206 } else {
9207 /* Store current location of species */
9208 xnew = xcur;
9209 ynew = ycur;
9210 znew = zcur;
9211 sumin = 1;
9212 sumback = moveone(& xnew, & ynew, & znew, & action, sumin);
9213
9214 if ( action == 0 ) {
9215 printf("Error in value of action \n");
9216 }
9217
9218 check = mic [ xnew ] [ ynew ] [ znew ];
9219
9220 /* if new location is solid GYPSUM(S) or diffusing GYPSUM, then convert */
9221 /* diffusing HEMIHYDRATE species to solid GYPSUM */
9222 if ( ( check == GYPSUM ) || ( check == GYPSUMS ) || ( check == DIFFGYP ) ) {
9223 mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
9224 /* decrement count of diffusing HEMIHYDRATE species */
9225 /* and increment count of solid GYPSUMS */
9226 count [ DIFFHEM ] -= 1;
9227 count [ GYPSUMS ] += 1;
9228 action = 0;
9229 /* Add extra gypsum as necessary */
9230 pexp = ran1(seed);
9231 if ( pexp < 0.4 ) {
9232 extgyps(xnew, ynew, znew);
9233 }
9234 }
9235 /* if new location is C3A or diffusing C3A, execute conversion */
9236 /* to ettringite (including necessary volumetric expansion) */
9237 else if ( ( ( check == C3A ) && ( p2diff < SOLIDC3AGYP ) ) || ( ( check == DIFFC3A ) && ( p2diff < C3AGYP ) ) || ( ( check == DIFFC4A ) && ( p2diff < C3AGYP ) ) ) {
9238 /* Convert diffusing gypsum to an ettringite pixel */
9239 ettrtype = 0;
9240 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
9241 if ( check == DIFFC4A ) {
9242 ettrtype = 1;
9243 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9244 }
9245
9246 action = 0;
9247 count [ DIFFHEM ] -= 1;
9248 count [ check ] -= 1;
9249
9250 /* determine if C3A should be converted to ettringite */
9251 /* 1 unit of hemihydrate requires 0.5583 units of C3A */
9252 /* and should form 4.6053 units of ettringite */
9253 pexp = ran1(seed);
9254 nexp = 3;
9255 if ( pexp <= 0.5583 ) {
9256 if ( ettrtype == 0 ) {
9257 mic [ xnew ] [ ynew ] [ znew ] = ETTR;
9258 count [ ETTR ] += 1;
9259 } else {
9260 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9261 count [ ETTRC4AF ] += 1;
9262 }
9263
9264 nexp = 2;
9265 } else {
9266 /* maybe someday, use a new FIXEDC3A here */
9267 /* so it won't dissolve later */
9268 if ( check == C3A ) {
9269 mic [ xnew ] [ ynew ] [ znew ] = C3A;
9270 count [ C3A ] += 1;
9271 } else {
9272 if ( ettrtype == 0 ) {
9273 count [ DIFFC3A ] += 1;
9274 mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
9275 } else {
9276 count [ DIFFC4A ] += 1;
9277 mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
9278 }
9279 }
9280
9281 nexp = 3;
9282 }
9283
9284 /* create extra ettringite pixels to maintain volume stoichiometry */
9285 /* xexp, yexp, and zexp hold coordinates of most recently added ettringite */
9286 /* species as we attempt to grow a needle like structure */
9287 xexp = xcur;
9288 yexp = ycur;
9289 zexp = zcur;
9290 for ( iexp = 1; iexp <= nexp; iexp++ ) {
9291 newact = extettr(xexp, yexp, zexp, ettrtype);
9292 /* update xexp, yexp and zexp as needed */
9293 switch ( newact ) {
9294 case 1:
9295 xexp -= 1;
9296 if ( xexp < 0 ) {
9297 xexp = ( SYSIZEM1 );
9298 }
9299
9300 break;
9301 case 2:
9302 xexp += 1;
9303 if ( xexp >= SYSIZE ) {
9304 xexp = 0;
9305 }
9306
9307 break;
9308 case 3:
9309 yexp -= 1;
9310 if ( yexp < 0 ) {
9311 yexp = ( SYSIZEM1 );
9312 }
9313
9314 break;
9315 case 4:
9316 yexp += 1;
9317 if ( yexp >= SYSIZE ) {
9318 yexp = 0;
9319 }
9320
9321 break;
9322 case 5:
9323 zexp -= 1;
9324 if ( zexp < 0 ) {
9325 zexp = ( SYSIZEM1 );
9326 }
9327
9328 break;
9329 case 6:
9330 zexp += 1;
9331 if ( zexp >= SYSIZE ) {
9332 zexp = 0;
9333 }
9334
9335 break;
9336 default:
9337 break;
9338 }
9339 }
9340
9341 /* probabilistic-based expansion for last ettringite pixel */
9342 pexp = ran1(seed);
9343 if ( pexp <= 0.6053 ) {
9344 newact = extettr(xexp, yexp, zexp, ettrtype);
9345 }
9346 }
9347
9348 /* if new location is C4AF execute conversion */
9349 /* to ettringite (including necessary volumetric expansion) */
9350 if ( ( check == C4AF ) && ( p2diff < SOLIDC4AFGYP ) ) {
9351 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9352 count [ ETTRC4AF ] += 1;
9353 count [ DIFFHEM ] -= 1;
9354
9355 /* determine if C4AF should be converted to ettringite */
9356 /* 1 unit of gypsum requires 0.802 units of C4AF */
9357 /* and should form 4.6053 units of ettringite */
9358 pexp = ran1(seed);
9359 nexp = 3;
9360 if ( pexp <= 0.802 ) {
9361 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9362 count [ ETTRC4AF ] += 1;
9363 count [ C4AF ] -= 1;
9364 nexp = 2;
9365 pext = ran1(seed);
9366 /* Addition of extra CH */
9367 if ( pext < 0.2584 ) {
9368 extch();
9369 }
9370
9371 pext = ran1(seed);
9372 /* Addition of extra FH3 */
9373 if ( pext < 0.5453 ) {
9374 extfh3(xnew, ynew, znew);
9375 }
9376 } else {
9377 /* maybe someday, use a new FIXEDC4AF here */
9378 /* so it won't dissolve later */
9379 mic [ xnew ] [ ynew ] [ znew ] = C4AF;
9380 nexp = 3;
9381 }
9382
9383 /* create extra ettringite pixels to maintain volume stoichiometry */
9384 /* xexp, yexp and zexp hold coordinates of most recently added ettringite */
9385 /* species as we attempt to grow a needle like structure */
9386 xexp = xcur;
9387 yexp = ycur;
9388 zexp = zcur;
9389 for ( iexp = 1; iexp <= nexp; iexp++ ) {
9390 newact = extettr(xexp, yexp, zexp, 1);
9391 /* update xexp, yexp and zexp as needed */
9392 switch ( newact ) {
9393 case 1:
9394 xexp -= 1;
9395 if ( xexp < 0 ) {
9396 xexp = ( SYSIZEM1 );
9397 }
9398
9399 break;
9400 case 2:
9401 xexp += 1;
9402 if ( xexp >= SYSIZE ) {
9403 xexp = 0;
9404 }
9405
9406 break;
9407 case 3:
9408 yexp -= 1;
9409 if ( yexp < 0 ) {
9410 yexp = ( SYSIZEM1 );
9411 }
9412
9413 break;
9414 case 4:
9415 yexp += 1;
9416 if ( yexp >= SYSIZE ) {
9417 yexp = 0;
9418 }
9419
9420 break;
9421 case 5:
9422 zexp -= 1;
9423 if ( zexp < 0 ) {
9424 zexp = ( SYSIZEM1 );
9425 }
9426
9427 break;
9428 case 6:
9429 zexp += 1;
9430 if ( zexp >= SYSIZE ) {
9431 zexp = 0;
9432 }
9433
9434 break;
9435 default:
9436 break;
9437 }
9438 }
9439
9440 /* probabilistic-based expansion for last ettringite pixel */
9441 pexp = ran1(seed);
9442 if ( pexp <= 0.6053 ) {
9443 newact = extettr(xexp, yexp, zexp, 1);
9444 }
9445
9446 action = 0;
9447 }
9448 }
9449
9450 if ( action != 0 ) {
9451 /* if diffusion step is possible, perform it */
9452 if ( check == POROSITY ) {
9453 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
9454 mic [ xnew ] [ ynew ] [ znew ] = DIFFHEM;
9455 } else {
9456 /* indicate that diffusing HEMIHYDRATE species */
9457 /* remained at original location */
9458 action = 7;
9459 }
9460 }
9461
9462 return ( action );
9463
9464 ( void ) sumback;
9465}
9466
9467/* routine to add extra Freidel's salt when CaCl2 reacts with */
9468/* C3A or C4AF at location (xpres,ypres,zpres) */
9469/* Called by movecacl2 and movec3a */
9470/* Calls moveone and edgecnt */
9471int CemhydMatStatus :: extfreidel(int xpres, int ypres, int zpres)
9472{
9473 int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
9474 long int tries;
9475
9476 /* first try 6 neighboring locations until */
9477 /* a) successful */
9478 /* b) all 6 sites are tried and full or */
9479 /* c) 500 tries are made */
9480 fchr = 0;
9481 sump = 1;
9482 for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
9483 /* choose a neighbor at random */
9484 xchr = xpres;
9485 ychr = ypres;
9486 zchr = zpres;
9487 newact = 0;
9488 multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
9489 if ( newact == 0 ) {
9490 printf("Error in value of newact in extfreidel \n");
9491 }
9492
9493 check = mic [ xchr ] [ ychr ] [ zchr ];
9494
9495 /* if neighbor is porosity */
9496 /* then locate the freidel's salt there */
9497 if ( check == POROSITY ) {
9498 mic [ xchr ] [ ychr ] [ zchr ] = FREIDEL;
9499 count [ FREIDEL ] += 1;
9500 count [ POROSITY ] -= 1;
9501 fchr = 1;
9502 } else {
9503 sump *= multf;
9504 }
9505 }
9506
9507 /* if no neighbor available, locate FREIDEL at random location */
9508 /* in pore space in contact with at least one FREIDEL */
9509 tries = 0;
9510 while ( fchr == 0 ) {
9511 tries += 1;
9512 newact = 7;
9513 /* generate a random location in the 3-D system */
9514 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9515 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9516 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9517 if ( xchr >= SYSIZE ) {
9518 xchr = 0;
9519 }
9520
9521 if ( ychr >= SYSIZE ) {
9522 ychr = 0;
9523 }
9524
9525 if ( zchr >= SYSIZE ) {
9526 zchr = 0;
9527 }
9528
9529 check = mic [ xchr ] [ ychr ] [ zchr ];
9530 /* if location is porosity, locate the FREIDEL there */
9531 if ( check == POROSITY ) {
9532 numnear = edgecnt(xchr, ychr, zchr, FREIDEL, FREIDEL, DIFFCACL2);
9533 /* be sure that at least one neighboring pixel */
9534 /* is FREIDEL or diffusing CACL2 */
9535 if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
9536 mic [ xchr ] [ ychr ] [ zchr ] = FREIDEL;
9537 count [ FREIDEL ] += 1;
9538 count [ POROSITY ] -= 1;
9539 fchr = 1;
9540 }
9541 }
9542 }
9543
9544 return ( newact );
9545}
9546
9547/* routine to add extra stratlingite when AS reacts with */
9548/* CH at location (xpres,ypres,zpres) */
9549/* or when diffusing CAS2 reacts with aluminates */
9550/* Called by moveas, movech, and movecas2 */
9551/* Calls moveone and edgecnt */
9552int CemhydMatStatus :: extstrat(int xpres, int ypres, int zpres)
9553{
9554 int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
9555 long int tries;
9556
9557 /* first try 6 neighboring locations until */
9558 /* a) successful */
9559 /* b) all 6 sites are tried and full or */
9560 /* c) 500 tries are made */
9561 fchr = 0;
9562 sump = 1;
9563 for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
9564 /* choose a neighbor at random */
9565 xchr = xpres;
9566 ychr = ypres;
9567 zchr = zpres;
9568 newact = 0;
9569 multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
9570 if ( newact == 0 ) {
9571 printf("Error in value of newact in extstrat \n");
9572 }
9573
9574 check = mic [ xchr ] [ ychr ] [ zchr ];
9575
9576 /* if neighbor is porosity */
9577 /* then locate the stratlingite there */
9578 if ( check == POROSITY ) {
9579 mic [ xchr ] [ ychr ] [ zchr ] = STRAT;
9580 count [ STRAT ] += 1;
9581 count [ POROSITY ] -= 1;
9582 fchr = 1;
9583 } else {
9584 sump *= multf;
9585 }
9586 }
9587
9588 /* if no neighbor available, locate STRAT at random location */
9589 /* in pore space in contact with at least one STRAT */
9590 tries = 0;
9591 while ( fchr == 0 ) {
9592 tries += 1;
9593 newact = 7;
9594 /* generate a random location in the 3-D system */
9595 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9596 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9597 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9598 if ( xchr >= SYSIZE ) {
9599 xchr = 0;
9600 }
9601
9602 if ( ychr >= SYSIZE ) {
9603 ychr = 0;
9604 }
9605
9606 if ( zchr >= SYSIZE ) {
9607 zchr = 0;
9608 }
9609
9610 check = mic [ xchr ] [ ychr ] [ zchr ];
9611 /* if location is porosity, locate the STRAT there */
9612 if ( check == POROSITY ) {
9613 numnear = edgecnt(xchr, ychr, zchr, STRAT, DIFFCAS2, DIFFAS);
9614 /* be sure that at least one neighboring pixel */
9615 /* is STRAT, diffusing CAS2, or diffusing AS */
9616 if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
9617 mic [ xchr ] [ ychr ] [ zchr ] = STRAT;
9618 count [ STRAT ] += 1;
9619 count [ POROSITY ] -= 1;
9620 fchr = 1;
9621 }
9622 }
9623 }
9624
9625 return ( newact );
9626}
9627
9628/* routine to move a diffusing gypsum species */
9629/* from current location (xcur,ycur,zcur) */
9630/* Returns action flag indicating response taken */
9631/* Called by hydrate */
9632/* Calls moveone, extettr, extch, and extfh3 */
9633int CemhydMatStatus :: movegyp(int xcur, int ycur, int zcur, int finalstep)
9634{
9635 int check, xnew, ynew, znew, action, nexp, iexp;
9636 int xexp, yexp, zexp, newact, sumold, sumgarb, ettrtype;
9637 float pexp, pext, p2diff;
9638
9639 sumold = 1;
9640
9641 /* First be sure that a diffusing gypsum species is located at xcur,ycur,zcur */
9642 /* if not, return to calling routine */
9643 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFGYP ) {
9644 action = 0;
9645 return ( action );
9646 }
9647
9648 /* Determine new coordinates (periodic boundaries are used) */
9649 xnew = xcur;
9650 ynew = ycur;
9651 znew = zcur;
9652 action = 0;
9653 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
9654 if ( action == 0 ) {
9655 printf("Error in value of action in movegyp \n");
9656 }
9657
9658 check = mic [ xnew ] [ ynew ] [ znew ];
9659 p2diff = ran1(seed);
9660 /* if new location is CSH, check for absorption of gypsum */
9661 if ( ( check == CSH ) && ( ( float ) count [ ABSGYP ] < ( gypabsprob * ( float ) count [ CSH ] ) ) ) {
9662 pexp = ran1(seed);
9663 if ( pexp < AGRATE ) {
9664 /* update counts for absorbed and diffusing gypsum */
9665 count [ ABSGYP ] += 1;
9666 count [ DIFFGYP ] -= 1;
9667 mic [ xcur ] [ ycur ] [ zcur ] = ABSGYP;
9668 action = 0;
9669 }
9670 }
9671 /* if new location is C3A or diffusing C3A, execute conversion */
9672 /* to ettringite (including necessary volumetric expansion) */
9673 /* Use p2diff to try to favor formation of ettringite on */
9674 /* aluminate surfaces as opposed to in solution */
9675 else if ( ( ( check == C3A ) && ( p2diff < SOLIDC3AGYP ) ) || ( ( check == DIFFC3A ) && ( p2diff < C3AGYP ) ) || ( ( check == DIFFC4A ) && ( p2diff < C3AGYP ) ) ) {
9676 /* Convert diffusing gypsum to an ettringite pixel */
9677 ettrtype = 0;
9678 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
9679 if ( check == DIFFC4A ) {
9680 ettrtype = 1;
9681 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9682 }
9683
9684 action = 0;
9685 count [ DIFFGYP ] -= 1;
9686 count [ check ] -= 1;
9687
9688 /* determine if C3A should be converted to ettringite */
9689 /* 1 unit of gypsum requires 0.40 units of C3A */
9690 /* and should form 3.30 units of ettringite */
9691 pexp = ran1(seed);
9692 nexp = 2;
9693 if ( pexp <= 0.40 ) {
9694 if ( ettrtype == 0 ) {
9695 mic [ xnew ] [ ynew ] [ znew ] = ETTR;
9696 count [ ETTR ] += 1;
9697 } else {
9698 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9699 count [ ETTRC4AF ] += 1;
9700 }
9701
9702 nexp = 1;
9703 } else {
9704 /* maybe someday, use a new FIXEDC3A here */
9705 /* so it won't dissolve later */
9706 if ( check == C3A ) {
9707 mic [ xnew ] [ ynew ] [ znew ] = C3A;
9708 count [ C3A ] += 1;
9709 } else {
9710 if ( ettrtype == 0 ) {
9711 count [ DIFFC3A ] += 1;
9712 mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
9713 } else {
9714 count [ DIFFC4A ] += 1;
9715 mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
9716 }
9717 }
9718
9719 nexp = 2;
9720 }
9721
9722 /* create extra ettringite pixels to maintain volume stoichiometry */
9723 /* xexp, yexp, and zexp hold coordinates of most recently added ettringite */
9724 /* species as we attempt to grow a needle like structure */
9725 xexp = xcur;
9726 yexp = ycur;
9727 zexp = zcur;
9728 for ( iexp = 1; iexp <= nexp; iexp++ ) {
9729 newact = extettr(xexp, yexp, zexp, ettrtype);
9730 /* update xexp, yexp and zexp as needed */
9731 switch ( newact ) {
9732 case 1:
9733 xexp -= 1;
9734 if ( xexp < 0 ) {
9735 xexp = ( SYSIZEM1 );
9736 }
9737
9738 break;
9739 case 2:
9740 xexp += 1;
9741 if ( xexp >= SYSIZE ) {
9742 xexp = 0;
9743 }
9744
9745 break;
9746 case 3:
9747 yexp -= 1;
9748 if ( yexp < 0 ) {
9749 yexp = ( SYSIZEM1 );
9750 }
9751
9752 break;
9753 case 4:
9754 yexp += 1;
9755 if ( yexp >= SYSIZE ) {
9756 yexp = 0;
9757 }
9758
9759 break;
9760 case 5:
9761 zexp -= 1;
9762 if ( zexp < 0 ) {
9763 zexp = ( SYSIZEM1 );
9764 }
9765
9766 break;
9767 case 6:
9768 zexp += 1;
9769 if ( zexp >= SYSIZE ) {
9770 zexp = 0;
9771 }
9772
9773 break;
9774 default:
9775 break;
9776 }
9777 }
9778
9779 /* probabilistic-based expansion for last ettringite pixel */
9780 pexp = ran1(seed);
9781 if ( pexp <= 0.30 ) {
9782 newact = extettr(xexp, yexp, zexp, ettrtype);
9783 }
9784 }
9785
9786 /* if new location is C4AF execute conversion */
9787 /* to ettringite (including necessary volumetric expansion) */
9788 if ( ( check == C4AF ) && ( p2diff < SOLIDC4AFGYP ) ) {
9789 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9790 count [ ETTRC4AF ] += 1;
9791 count [ DIFFGYP ] -= 1;
9792
9793 /* determine if C4AF should be converted to ettringite */
9794 /* 1 unit of gypsum requires 0.575 units of C4AF */
9795 /* and should form 3.30 units of ettringite */
9796 pexp = ran1(seed);
9797 nexp = 2;
9798 if ( pexp <= 0.575 ) {
9799 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9800 count [ ETTRC4AF ] += 1;
9801 count [ C4AF ] -= 1;
9802 nexp = 1;
9803 pext = ran1(seed);
9804 /* Addition of extra CH */
9805 if ( pext < 0.2584 ) {
9806 extch();
9807 }
9808
9809 pext = ran1(seed);
9810 /* Addition of extra FH3 */
9811 if ( pext < 0.5453 ) {
9812 extfh3(xnew, ynew, znew);
9813 }
9814 } else {
9815 /* maybe someday, use a new FIXEDC4AF here */
9816 /* so it won't dissolve later */
9817 mic [ xnew ] [ ynew ] [ znew ] = C4AF;
9818 nexp = 2;
9819 }
9820
9821 /* create extra ettringite pixels to maintain volume stoichiometry */
9822 /* xexp, yexp and zexp hold coordinates of most recently added ettringite */
9823 /* species as we attempt to grow a needle like structure */
9824 xexp = xcur;
9825 yexp = ycur;
9826 zexp = zcur;
9827 for ( iexp = 1; iexp <= nexp; iexp++ ) {
9828 newact = extettr(xexp, yexp, zexp, 1);
9829 /* update xexp, yexp and zexp as needed */
9830 switch ( newact ) {
9831 case 1:
9832 xexp -= 1;
9833 if ( xexp < 0 ) {
9834 xexp = ( SYSIZEM1 );
9835 }
9836
9837 break;
9838 case 2:
9839 xexp += 1;
9840 if ( xexp >= SYSIZE ) {
9841 xexp = 0;
9842 }
9843
9844 break;
9845 case 3:
9846 yexp -= 1;
9847 if ( yexp < 0 ) {
9848 yexp = ( SYSIZEM1 );
9849 }
9850
9851 break;
9852 case 4:
9853 yexp += 1;
9854 if ( yexp >= SYSIZE ) {
9855 yexp = 0;
9856 }
9857
9858 break;
9859 case 5:
9860 zexp -= 1;
9861 if ( zexp < 0 ) {
9862 zexp = ( SYSIZEM1 );
9863 }
9864
9865 break;
9866 case 6:
9867 zexp += 1;
9868 if ( zexp >= SYSIZE ) {
9869 zexp = 0;
9870 }
9871
9872 break;
9873 default:
9874 break;
9875 }
9876 }
9877
9878 /* probabilistic-based expansion for last ettringite pixel */
9879 pexp = ran1(seed);
9880 if ( pexp <= 0.30 ) {
9881 newact = extettr(xexp, yexp, zexp, 1);
9882 }
9883
9884 action = 0;
9885 }
9886
9887 /* if last diffusion step and no reaction, convert back to */
9888 /* primary solid gypsum */
9889 if ( ( action != 0 ) && ( finalstep == 1 ) ) {
9890 action = 0;
9891 count [ DIFFGYP ] -= 1;
9892 count [ GYPSUM ] += 1;
9893 mic [ xcur ] [ ycur ] [ zcur ] = GYPSUM;
9894 }
9895
9896 if ( action != 0 ) {
9897 /* if diffusion is possible, execute it */
9898 if ( check == POROSITY ) {
9899 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
9900 mic [ xnew ] [ ynew ] [ znew ] = DIFFGYP;
9901 } else {
9902 /* indicate that diffusing gypsum remained at */
9903 /* original location */
9904 action = 7;
9905 }
9906 }
9907
9908 return ( action );
9909
9910 ( void ) sumgarb;
9911}
9912
9913/* routine to move a diffusing CaCl2 species */
9914/* from current location (xcur,ycur,zcur) */
9915/* Returns action flag indicating response taken */
9916/* Called by hydrate */
9917/* Calls moveone, extfreidel, extch, and extfh3 */
9918int CemhydMatStatus :: movecacl2(int xcur, int ycur, int zcur, int finalstep)
9919{
9920 int check, xnew, ynew, znew, action, nexp, iexp;
9921 int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
9922 float pexp, pext;
9923
9924 sumold = 1;
9925 keep = 0;
9926
9927 /* First be sure that a diffusing CaCl2 species is located at xcur,ycur,zcur */
9928 /* if not, return to calling routine */
9929 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFCACL2 ) {
9930 action = 0;
9931 return ( action );
9932 }
9933
9934 /* Determine new coordinates (periodic boundaries are used) */
9935 xnew = xcur;
9936 ynew = ycur;
9937 znew = zcur;
9938 action = 0;
9939 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
9940 if ( action == 0 ) {
9941 printf("Error in value of action in movecacl2 \n");
9942 }
9943
9944 check = mic [ xnew ] [ ynew ] [ znew ];
9945
9946 /* if new location is C3A or diffusing C3A, execute conversion */
9947 /* to freidel's salt (including necessary volumetric expansion) */
9948 if ( ( check == C3A ) || ( check == DIFFC3A ) || ( check == DIFFC4A ) ) {
9949 /* Convert diffusing C3A or C3A to a freidel's salt pixel */
9950 action = 0;
9951 mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
9952 count [ FREIDEL ] += 1;
9953 count [ check ] -= 1;
9954
9955 /* determine if diffusing CaCl2 should be converted to FREIDEL */
9956 /* 0.5793 unit of CaCl2 requires 1 unit of C3A */
9957 /* and should form 3.3295 units of FREIDEL */
9958 pexp = ran1(seed);
9959 nexp = 2;
9960 if ( pexp <= 0.5793 ) {
9961 mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
9962 count [ FREIDEL ] += 1;
9963 count [ DIFFCACL2 ] -= 1;
9964 nexp = 1;
9965 } else {
9966 keep = 1;
9967 nexp = 2;
9968 }
9969
9970 /* create extra Freidel's salt pixels to maintain volume stoichiometry */
9971 /* xexp, yexp, and zexp hold coordinates of most recently added FREIDEL */
9972 xexp = xcur;
9973 yexp = ycur;
9974 zexp = zcur;
9975 for ( iexp = 1; iexp <= nexp; iexp++ ) {
9976 newact = extfreidel(xexp, yexp, zexp);
9977 /* update xexp, yexp and zexp as needed */
9978 switch ( newact ) {
9979 case 1:
9980 xexp -= 1;
9981 if ( xexp < 0 ) {
9982 xexp = ( SYSIZEM1 );
9983 }
9984
9985 break;
9986 case 2:
9987 xexp += 1;
9988 if ( xexp >= SYSIZE ) {
9989 xexp = 0;
9990 }
9991
9992 break;
9993 case 3:
9994 yexp -= 1;
9995 if ( yexp < 0 ) {
9996 yexp = ( SYSIZEM1 );
9997 }
9998
9999 break;
10000 case 4:
10001 yexp += 1;
10002 if ( yexp >= SYSIZE ) {
10003 yexp = 0;
10004 }
10005
10006 break;
10007 case 5:
10008 zexp -= 1;
10009 if ( zexp < 0 ) {
10010 zexp = ( SYSIZEM1 );
10011 }
10012
10013 break;
10014 case 6:
10015 zexp += 1;
10016 if ( zexp >= SYSIZE ) {
10017 zexp = 0;
10018 }
10019
10020 break;
10021 default:
10022 break;
10023 }
10024 }
10025
10026 /* probabilistic-based expansion for last FREIDEL pixel */
10027 pexp = ran1(seed);
10028 if ( pexp <= 0.3295 ) {
10029 newact = extfreidel(xexp, yexp, zexp);
10030 }
10031 }
10032 /* if new location is C4AF execute conversion */
10033 /* to freidel's salt (including necessary volumetric expansion) */
10034 else if ( check == C4AF ) {
10035 mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
10036 count [ FREIDEL ] += 1;
10037 count [ C4AF ] -= 1;
10038
10039 /* determine if CACL2 should be converted to FREIDEL */
10040 /* 0.4033 unit of CaCl2 requires 1 unit of C4AF */
10041 /* and should form 2.3176 units of FREIDEL */
10042 /* Also 0.6412 units of CH and 1.3522 units of FH3 */
10043 /* per unit of CACL2 */
10044 pexp = ran1(seed);
10045 nexp = 1;
10046 if ( pexp <= 0.4033 ) {
10047 mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
10048 count [ FREIDEL ] += 1;
10049 count [ DIFFCACL2 ] -= 1;
10050 nexp = 0;
10051 pext = ran1(seed);
10052 /* Addition of extra CH */
10053 if ( pext < 0.6412 ) {
10054 extch();
10055 }
10056
10057 pext = ran1(seed);
10058 /* Addition of extra FH3 */
10059 if ( pext < 0.3522 ) {
10060 extfh3(xnew, ynew, znew);
10061 }
10062
10063 extfh3(xnew, ynew, znew);
10064 } else {
10065 nexp = 1;
10066 keep = 1;
10067 }
10068
10069 /* create extra freidel's salt pixels to maintain volume stoichiometry */
10070 /* xexp, yexp and zexp hold coordinates of most recently added FREIDEL */
10071 xexp = xcur;
10072 yexp = ycur;
10073 zexp = zcur;
10074 for ( iexp = 1; iexp <= nexp; iexp++ ) {
10075 newact = extfreidel(xexp, yexp, zexp);
10076 /* update xexp, yexp and zexp as needed */
10077 switch ( newact ) {
10078 case 1:
10079 xexp -= 1;
10080 if ( xexp < 0 ) {
10081 xexp = ( SYSIZEM1 );
10082 }
10083
10084 break;
10085 case 2:
10086 xexp += 1;
10087 if ( xexp >= SYSIZE ) {
10088 xexp = 0;
10089 }
10090
10091 break;
10092 case 3:
10093 yexp -= 1;
10094 if ( yexp < 0 ) {
10095 yexp = ( SYSIZEM1 );
10096 }
10097
10098 break;
10099 case 4:
10100 yexp += 1;
10101 if ( yexp >= SYSIZE ) {
10102 yexp = 0;
10103 }
10104
10105 break;
10106 case 5:
10107 zexp -= 1;
10108 if ( zexp < 0 ) {
10109 zexp = ( SYSIZEM1 );
10110 }
10111
10112 break;
10113 case 6:
10114 zexp += 1;
10115 if ( zexp >= SYSIZE ) {
10116 zexp = 0;
10117 }
10118
10119 break;
10120 default:
10121 break;
10122 }
10123 }
10124
10125 /* probabilistic-based expansion for last FREIDEL pixel */
10126 pexp = ran1(seed);
10127 if ( pexp <= 0.3176 ) {
10128 newact = extfreidel(xexp, yexp, zexp);
10129 }
10130
10131 action = 0;
10132 }
10133
10134 /* if last diffusion step and no reaction, convert back to */
10135 /* solid CaCl2 */
10136 if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10137 action = 0;
10138 count [ DIFFCACL2 ] -= 1;
10139 count [ CACL2 ] += 1;
10140 mic [ xcur ] [ ycur ] [ zcur ] = CACL2;
10141 }
10142
10143 if ( action != 0 ) {
10144 /* if diffusion is possible, execute it */
10145 if ( check == POROSITY ) {
10146 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10147 mic [ xnew ] [ ynew ] [ znew ] = DIFFCACL2;
10148 } else {
10149 /* indicate that diffusing CACL2 remained at */
10150 /* original location */
10151 action = 7;
10152 }
10153 }
10154
10155 if ( keep == 1 ) {
10156 action = 7;
10157 }
10158
10159 return ( action );
10160
10161 ( void ) sumgarb;
10162}
10163
10164/* routine to move a diffusing CAS2 species */
10165/* from current location (xcur,ycur,zcur) */
10166/* Returns action flag indicating response taken */
10167/* Called by hydrate */
10168/* Calls moveone, extstrat, extch, and extfh3 */
10169int CemhydMatStatus :: movecas2(int xcur, int ycur, int zcur, int finalstep)
10170{
10171 int check, xnew, ynew, znew, action, nexp, iexp;
10172 int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
10173 float pexp, pext;
10174
10175 sumold = 1;
10176 keep = 0;
10177
10178 /* First be sure that a diffusing CAS2 species is located at xcur,ycur,zcur */
10179 /* if not, return to calling routine */
10180 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFCAS2 ) {
10181 action = 0;
10182 return ( action );
10183 }
10184
10185 /* Determine new coordinates (periodic boundaries are used) */
10186 xnew = xcur;
10187 ynew = ycur;
10188 znew = zcur;
10189 action = 0;
10190 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10191 if ( action == 0 ) {
10192 printf("Error in value of action in movecas2 \n");
10193 }
10194
10195 check = mic [ xnew ] [ ynew ] [ znew ];
10196
10197 /* if new location is C3A or diffusing C3A, execute conversion */
10198 /* to stratlingite (including necessary volumetric expansion) */
10199 if ( ( check == C3A ) || ( check == DIFFC3A ) || ( check == DIFFC4A ) ) {
10200 /* Convert diffusing CAS2 to a stratlingite pixel */
10201 action = 0;
10202 mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
10203 count [ STRAT ] += 1;
10204 count [ DIFFCAS2 ] -= 1;
10205
10206 /* determine if diffusing or solid C3A should be converted to STRAT*/
10207 /* 1 unit of CAS2 requires 0.886 units of C3A */
10208 /* and should form 4.286 units of STRAT */
10209 pexp = ran1(seed);
10210 nexp = 3;
10211 if ( pexp <= 0.886 ) {
10212 mic [ xnew ] [ ynew ] [ znew ] = STRAT;
10213 count [ STRAT ] += 1;
10214 count [ check ] -= 1;
10215 nexp = 2;
10216 }
10217
10218 /* create extra stratlingite pixels to maintain volume stoichiometry */
10219 /* xexp, yexp, and zexp hold coordinates of most recently added STRAT */
10220 xexp = xcur;
10221 yexp = ycur;
10222 zexp = zcur;
10223 for ( iexp = 1; iexp <= nexp; iexp++ ) {
10224 newact = extstrat(xexp, yexp, zexp);
10225 /* update xexp, yexp and zexp as needed */
10226 switch ( newact ) {
10227 case 1:
10228 xexp -= 1;
10229 if ( xexp < 0 ) {
10230 xexp = ( SYSIZEM1 );
10231 }
10232
10233 break;
10234 case 2:
10235 xexp += 1;
10236 if ( xexp >= SYSIZE ) {
10237 xexp = 0;
10238 }
10239
10240 break;
10241 case 3:
10242 yexp -= 1;
10243 if ( yexp < 0 ) {
10244 yexp = ( SYSIZEM1 );
10245 }
10246
10247 break;
10248 case 4:
10249 yexp += 1;
10250 if ( yexp >= SYSIZE ) {
10251 yexp = 0;
10252 }
10253
10254 break;
10255 case 5:
10256 zexp -= 1;
10257 if ( zexp < 0 ) {
10258 zexp = ( SYSIZEM1 );
10259 }
10260
10261 break;
10262 case 6:
10263 zexp += 1;
10264 if ( zexp >= SYSIZE ) {
10265 zexp = 0;
10266 }
10267
10268 break;
10269 default:
10270 break;
10271 }
10272 }
10273
10274 /* probabilistic-based expansion for last STRAT pixel */
10275 pexp = ran1(seed);
10276 if ( pexp <= 0.286 ) {
10277 newact = extstrat(xexp, yexp, zexp);
10278 }
10279 }
10280 /* if new location is C4AF execute conversion */
10281 /* to stratlingite (including necessary volumetric expansion) */
10282 else if ( check == C4AF ) {
10283 mic [ xnew ] [ ynew ] [ znew ] = STRAT;
10284 count [ STRAT ] += 1;
10285 count [ C4AF ] -= 1;
10286
10287 /* determine if CAS2 should be converted to STRAT */
10288 /* 0.786 units of CAS2 requires 1 unit of C4AF */
10289 /* and should form 3.37 units of STRAT */
10290 /* Also 0.2586 units of CH and 0.5453 units of FH3 */
10291 /* per unit of C4AF */
10292 pexp = ran1(seed);
10293 nexp = 2;
10294 if ( pexp <= 0.786 ) {
10295 mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
10296 count [ STRAT ] += 1;
10297 count [ DIFFCAS2 ] -= 1;
10298 nexp = 1;
10299 pext = ran1(seed);
10300 /* Addition of extra CH */
10301 /* 0.329= 0.2586/0.786 */
10302 if ( pext < 0.329 ) {
10303 extch();
10304 }
10305
10306 pext = ran1(seed);
10307 /* Addition of extra FH3 */
10308 /* 0.6938= 0.5453/0.786 */
10309 if ( pext < 0.6938 ) {
10310 extfh3(xnew, ynew, znew);
10311 }
10312 } else {
10313 nexp = 2;
10314 keep = 1;
10315 }
10316
10317 /* create extra stratlingite pixels to maintain volume stoichiometry */
10318 /* xexp, yexp and zexp hold coordinates of most recently added STRAT */
10319 xexp = xcur;
10320 yexp = ycur;
10321 zexp = zcur;
10322 for ( iexp = 1; iexp <= nexp; iexp++ ) {
10323 newact = extstrat(xexp, yexp, zexp);
10324 /* update xexp, yexp and zexp as needed */
10325 switch ( newact ) {
10326 case 1:
10327 xexp -= 1;
10328 if ( xexp < 0 ) {
10329 xexp = ( SYSIZEM1 );
10330 }
10331
10332 break;
10333 case 2:
10334 xexp += 1;
10335 if ( xexp >= SYSIZE ) {
10336 xexp = 0;
10337 }
10338
10339 break;
10340 case 3:
10341 yexp -= 1;
10342 if ( yexp < 0 ) {
10343 yexp = ( SYSIZEM1 );
10344 }
10345
10346 break;
10347 case 4:
10348 yexp += 1;
10349 if ( yexp >= SYSIZE ) {
10350 yexp = 0;
10351 }
10352
10353 break;
10354 case 5:
10355 zexp -= 1;
10356 if ( zexp < 0 ) {
10357 zexp = ( SYSIZEM1 );
10358 }
10359
10360 break;
10361 case 6:
10362 zexp += 1;
10363 if ( zexp >= SYSIZE ) {
10364 zexp = 0;
10365 }
10366
10367 break;
10368 default:
10369 break;
10370 }
10371 }
10372
10373 /* probabilistic-based expansion for last STRAT pixel */
10374 pexp = ran1(seed);
10375 if ( pexp <= 0.37 ) {
10376 newact = extstrat(xexp, yexp, zexp);
10377 }
10378
10379 action = 0;
10380 }
10381
10382 /* if last diffusion step and no reaction, convert back to */
10383 /* solid CAS2 */
10384 if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10385 action = 0;
10386 count [ DIFFCAS2 ] -= 1;
10387 count [ CAS2 ] += 1;
10388 mic [ xcur ] [ ycur ] [ zcur ] = CAS2;
10389 }
10390
10391 if ( action != 0 ) {
10392 /* if diffusion is possible, execute it */
10393 if ( check == POROSITY ) {
10394 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10395 mic [ xnew ] [ ynew ] [ znew ] = DIFFCAS2;
10396 } else {
10397 /* indicate that diffusing CAS2 remained at */
10398 /* original location */
10399 action = 7;
10400 }
10401 }
10402
10403 if ( keep == 1 ) {
10404 action = 7;
10405 }
10406
10407 return ( action );
10408
10409 ( void ) sumgarb;
10410}
10411
10412/* routine to move a diffusing AS species */
10413/* from current location (xcur,ycur,zcur) */
10414/* Returns action flag indicating response taken */
10415/* Called by hydrate */
10416/* Calls moveone, extstrat */
10417int CemhydMatStatus :: moveas(int xcur, int ycur, int zcur, int finalstep)
10418{
10419 int check, xnew, ynew, znew, action, nexp, iexp;
10420 int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
10421 float pexp;
10422
10423 sumold = 1;
10424 keep = 0;
10425
10426 /* First be sure that a diffusing AS species is located at xcur,ycur,zcur */
10427 /* if not, return to calling routine */
10428 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFAS ) {
10429 action = 0;
10430 return ( action );
10431 }
10432
10433 /* Determine new coordinates (periodic boundaries are used) */
10434 xnew = xcur;
10435 ynew = ycur;
10436 znew = zcur;
10437 action = 0;
10438 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10439 if ( action == 0 ) {
10440 printf("Error in value of action in moveas \n");
10441 }
10442
10443 check = mic [ xnew ] [ ynew ] [ znew ];
10444
10445 /* if new location is CH or diffusing CH, execute conversion */
10446 /* to stratlingite (including necessary volumetric expansion) */
10447 if ( ( check == CH ) || ( check == DIFFCH ) ) {
10448 /* Convert diffusing CH or CH to a stratlingite pixel */
10449 action = 0;
10450 mic [ xnew ] [ ynew ] [ znew ] = STRAT;
10451 count [ STRAT ] += 1;
10452 count [ check ] -= 1;
10453
10454 /* determine if diffusing AS should be converted to STRAT */
10455 /* 0.7538 unit of AS requires 1 unit of CH */
10456 /* and should form 3.26 units of STRAT */
10457 pexp = ran1(seed);
10458 nexp = 2;
10459 if ( pexp <= 0.7538 ) {
10460 mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
10461 count [ STRAT ] += 1;
10462 count [ DIFFAS ] -= 1;
10463 nexp = 1;
10464 } else {
10465 keep = 1;
10466 nexp = 2;
10467 }
10468
10469 /* create extra stratlingite pixels to maintain volume stoichiometry */
10470 /* xexp, yexp, and zexp hold coordinates of most recently added STRAT */
10471 xexp = xcur;
10472 yexp = ycur;
10473 zexp = zcur;
10474 for ( iexp = 1; iexp <= nexp; iexp++ ) {
10475 newact = extstrat(xexp, yexp, zexp);
10476 /* update xexp, yexp and zexp as needed */
10477 switch ( newact ) {
10478 case 1:
10479 xexp -= 1;
10480 if ( xexp < 0 ) {
10481 xexp = ( SYSIZEM1 );
10482 }
10483
10484 break;
10485 case 2:
10486 xexp += 1;
10487 if ( xexp >= SYSIZE ) {
10488 xexp = 0;
10489 }
10490
10491 break;
10492 case 3:
10493 yexp -= 1;
10494 if ( yexp < 0 ) {
10495 yexp = ( SYSIZEM1 );
10496 }
10497
10498 break;
10499 case 4:
10500 yexp += 1;
10501 if ( yexp >= SYSIZE ) {
10502 yexp = 0;
10503 }
10504
10505 break;
10506 case 5:
10507 zexp -= 1;
10508 if ( zexp < 0 ) {
10509 zexp = ( SYSIZEM1 );
10510 }
10511
10512 break;
10513 case 6:
10514 zexp += 1;
10515 if ( zexp >= SYSIZE ) {
10516 zexp = 0;
10517 }
10518
10519 break;
10520 default:
10521 break;
10522 }
10523 }
10524
10525 /* probabilistic-based expansion for last stratlingite pixel */
10526 pexp = ran1(seed);
10527 if ( pexp <= 0.326 ) {
10528 newact = extstrat(xexp, yexp, zexp);
10529 }
10530 }
10531
10532 /* if last diffusion step and no reaction, convert back to */
10533 /* solid ASG */
10534 if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10535 action = 0;
10536 count [ DIFFAS ] -= 1;
10537 count [ ASG ] += 1;
10538 mic [ xcur ] [ ycur ] [ zcur ] = ASG;
10539 }
10540
10541 if ( action != 0 ) {
10542 /* if diffusion is possible, execute it */
10543 if ( check == POROSITY ) {
10544 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10545 mic [ xnew ] [ ynew ] [ znew ] = DIFFAS;
10546 } else {
10547 /* indicate that diffusing AS remained at */
10548 /* original location */
10549 action = 7;
10550 }
10551 }
10552
10553 if ( keep == 1 ) {
10554 action = 7;
10555 }
10556
10557 return ( action );
10558
10559 ( void ) sumgarb;
10560}
10561
10562/* routine to move a diffusing CACO3 species */
10563/* from current location (xcur,ycur,zcur) */
10564/* Returns action flag indicating response taken */
10565/* Called by hydrate */
10566/* Calls moveone, extettr */
10567int CemhydMatStatus :: movecaco3(int xcur, int ycur, int zcur, int finalstep)
10568{
10569 int check, xnew, ynew, znew, action;
10570 int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
10571 float pexp;
10572
10573 sumold = 1;
10574 keep = 0;
10575
10576 /* First be sure that a diffusing CACO3 species is located at xcur,ycur,zcur */
10577 /* if not, return to calling routine */
10578 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFCACO3 ) {
10579 action = 0;
10580 return ( action );
10581 }
10582
10583 /* Determine new coordinates (periodic boundaries are used) */
10584 xnew = xcur;
10585 ynew = ycur;
10586 znew = zcur;
10587 action = 0;
10588 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10589 if ( action == 0 ) {
10590 printf("Error in value of action in moveas \n");
10591 }
10592
10593 check = mic [ xnew ] [ ynew ] [ znew ];
10594
10595 /* if new location is AFM execute conversion */
10596 /* to carboaluminate and ettringite (including necessary */
10597 /* volumetric expansion) */
10598 if ( check == AFM ) {
10599 /* Convert AFM to a carboaluminate or ettringite pixel */
10600 action = 0;
10601 pexp = ran1(seed);
10602 if ( pexp <= 0.479192 ) {
10603 mic [ xnew ] [ ynew ] [ znew ] = AFMC;
10604 count [ AFMC ] += 1;
10605 } else {
10606 mic [ xnew ] [ ynew ] [ znew ] = ETTR;
10607 count [ ETTR ] += 1;
10608 }
10609
10610 count [ check ] -= 1;
10611
10612 /* determine if diffusing CACO3 should be converted to AFMC */
10613 /* 0.078658 unit of AS requires 1 unit of AFM */
10614 /* and should form 0.55785 units of AFMC */
10615 pexp = ran1(seed);
10616 if ( pexp <= 0.078658 ) {
10617 mic [ xcur ] [ ycur ] [ zcur ] = AFMC;
10618 count [ AFMC ] += 1;
10619 count [ DIFFCACO3 ] -= 1;
10620 } else {
10621 keep = 1;
10622 }
10623
10624 /* create extra ettringite pixels to maintain volume stoichiometry */
10625 /* xexp, yexp, and zexp hold coordinates of most recently added ETTR */
10626 xexp = xnew;
10627 yexp = ynew;
10628 zexp = znew;
10629
10630 /* probabilistic-based expansion for new ettringite pixel */
10631 pexp = ran1(seed);
10632 if ( pexp <= 0.26194 ) {
10633 newact = extettr(xexp, yexp, zexp, 0);
10634 }
10635 }
10636
10637 /* if last diffusion step and no reaction, convert back to */
10638 /* solid CACO3 */
10639 if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10640 action = 0;
10641 count [ DIFFCACO3 ] -= 1;
10642 count [ CACO3 ] += 1;
10643 mic [ xcur ] [ ycur ] [ zcur ] = CACO3;
10644 }
10645
10646 if ( action != 0 ) {
10647 /* if diffusion is possible, execute it */
10648 if ( check == POROSITY ) {
10649 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10650 mic [ xnew ] [ ynew ] [ znew ] = DIFFCACO3;
10651 } else {
10652 /* indicate that diffusing CACO3 remained at */
10653 /* original location */
10654 action = 7;
10655 }
10656 }
10657
10658 if ( keep == 1 ) {
10659 action = 7;
10660 }
10661
10662 return ( action );
10663
10664 ( void ) newact;
10665 ( void ) sumgarb;
10666}
10667
10668/* routine to add extra AFm phase when diffusing ettringite reacts */
10669/* with C3A (diffusing or solid) at location (xpres,ypres,zpres) */
10670/* Called by moveettr and movec3a */
10671/* Calls moveone and edgecnt */
10672void CemhydMatStatus :: extafm(int xpres, int ypres, int zpres)
10673{
10674 int check, sump, xchr, ychr, zchr, fchr, i1, newact, numnear;
10675 long int tries;
10676
10677 /* first try 6 neighboring locations until */
10678 /* a) successful */
10679 /* b) all 6 sites are tried or */
10680 /* c) 100 tries are made */
10681 fchr = 0;
10682 sump = 1;
10683 for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
10684 /* determine location of neighbor (using periodic boundaries) */
10685 xchr = xpres;
10686 ychr = ypres;
10687 zchr = zpres;
10688 newact = 0;
10689 sump *= moveone(& xchr, & ychr, & zchr, & newact, sump);
10690 if ( newact == 0 ) {
10691 printf("Error in value of newact in extafm \n");
10692 }
10693
10694 check = mic [ xchr ] [ ychr ] [ zchr ];
10695
10696 /* if neighbor is porosity, locate the AFm phase there */
10697 if ( check == POROSITY ) {
10698 mic [ xchr ] [ ychr ] [ zchr ] = AFM;
10699 count [ AFM ] += 1;
10700 count [ POROSITY ] -= 1;
10701 fchr = 1;
10702 }
10703 }
10704
10705 /* if no neighbor available, locate AFm phase at random location */
10706 /* in pore space */
10707 tries = 0;
10708 while ( fchr == 0 ) {
10709 tries += 1;
10710 /* generate a random location in the 3-D system */
10711 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10712 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10713 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10714 if ( xchr >= SYSIZE ) {
10715 xchr = 0;
10716 }
10717
10718 if ( ychr >= SYSIZE ) {
10719 ychr = 0;
10720 }
10721
10722 if ( zchr >= SYSIZE ) {
10723 zchr = 0;
10724 }
10725
10726 check = mic [ xchr ] [ ychr ] [ zchr ];
10727
10728 /* if location is porosity, locate the extra AFm there */
10729 if ( check == POROSITY ) {
10730 numnear = edgecnt(xchr, ychr, zchr, AFM, C3A, C4AF);
10731 /* Be sure that at least one neighboring pixel is */
10732 /* Afm phase, C3A, or C4AF */
10733 if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
10734 mic [ xchr ] [ ychr ] [ zchr ] = AFM;
10735 count [ AFM ] += 1;
10736 count [ POROSITY ] -= 1;
10737 fchr = 1;
10738 }
10739 }
10740 }
10741}
10742
10743/* routine to move a diffusing ettringite species */
10744/* currently located at (xcur,ycur,zcur) */
10745/* Called by hydrate */
10746/* Calls moveone, extch, extfh3, and extafm */
10747int CemhydMatStatus :: moveettr(int xcur, int ycur, int zcur, int finalstep)
10748{
10749 int check, xnew, ynew, znew, action;
10750 int sumold, sumgarb;
10751 float pexp, pafm, pgrow;
10752
10753 /* First be sure a diffusing ettringite species is located at xcur,ycur,zcur */
10754 /* if not, return to calling routine */
10755 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFETTR ) {
10756 action = 0;
10757 return ( action );
10758 }
10759
10760 /* Determine new coordinates (periodic boundaries are used) */
10761 xnew = xcur;
10762 ynew = ycur;
10763 znew = zcur;
10764 action = 0;
10765 sumold = 1;
10766 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10767 if ( action == 0 ) {
10768 printf("Error in value of action in moveettr \n");
10769 }
10770
10771 check = mic [ xnew ] [ ynew ] [ znew ];
10772
10773 /* if new location is C4AF, execute conversion */
10774 /* to AFM phase (including necessary volumetric expansion) */
10775 if ( check == C4AF ) {
10776 /* Convert diffusing ettringite to AFM phase */
10777 mic [ xcur ] [ ycur ] [ zcur ] = AFM;
10778 count [ AFM ] += 1;
10779 count [ DIFFETTR ] -= 1;
10780
10781 /* determine if C4AF should be converted to Afm */
10782 /* or FH3- 1 unit of ettringite requires 0.348 units */
10783 /* of C4AF to form 1.278 units of Afm, */
10784 /* 0.0901 units of CH and 0.1899 units of FH3 */
10785 pexp = ran1(seed);
10786
10787 if ( pexp <= 0.278 ) {
10788 mic [ xnew ] [ ynew ] [ znew ] = AFM;
10789 count [ AFM ] += 1;
10790 count [ C4AF ] -= 1;
10791 pafm = ran1(seed);
10792 /* 0.3241= 0.0901/0.278 */
10793 if ( pafm <= 0.3241 ) {
10794 extch();
10795 }
10796
10797 pafm = ran1(seed);
10798 /* 0.4313= ((.1899-(.348-.278))/.278) */
10799 if ( pafm <= 0.4313 ) {
10800 extfh3(xnew, ynew, znew);
10801 }
10802 } else if ( pexp <= 0.348 ) {
10803 mic [ xnew ] [ ynew ] [ znew ] = FH3;
10804 count [ FH3 ] += 1;
10805 count [ C4AF ] -= 1;
10806 }
10807
10808 action = 0;
10809 }
10810 /* if new location is C3A or diffusing C3A, execute conversion */
10811 /* to AFM phase (including necessary volumetric expansion) */
10812 else if ( ( check == C3A ) || ( check == DIFFC3A ) ) {
10813 /* Convert diffusing ettringite to AFM phase */
10814 action = 0;
10815 mic [ xcur ] [ ycur ] [ zcur ] = AFM;
10816 count [ DIFFETTR ] -= 1;
10817 count [ AFM ] += 1;
10818 count [ check ] -= 1;
10819
10820 /* determine if C3A should be converted to AFm */
10821 /* 1 unit of ettringite requires 0.2424 units of C3A */
10822 /* and should form 1.278 units of AFm phase */
10823 pexp = ran1(seed);
10824 if ( pexp <= 0.2424 ) {
10825 mic [ xnew ] [ ynew ] [ znew ] = AFM;
10826 count [ AFM ] += 1;
10827 pafm = ( -0.1 );
10828 } else {
10829 /* maybe someday, use a new FIXEDC3A here */
10830 /* so it won't dissolve later */
10831 if ( check == C3A ) {
10832 mic [ xnew ] [ ynew ] [ znew ] = C3A;
10833 count [ C3A ] += 1;
10834 } else {
10835 count [ DIFFC3A ] += 1;
10836 mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
10837 }
10838
10839 /* pafm=(0.278-0.2424)/(1.0-0.2424); */
10840 pafm = 0.04699;
10841 }
10842
10843 /* probabilistic-based expansion for new AFm phase pixel */
10844 pexp = ran1(seed);
10845 if ( pexp <= pafm ) {
10846 extafm(xcur, ycur, zcur);
10847 }
10848 }
10849 /* Check for conversion back to solid ettringite */
10850 else if ( check == ETTR ) {
10851 pgrow = ran1(seed);
10852 if ( pgrow <= ETTRGROW ) {
10853 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
10854 count [ ETTR ] += 1;
10855 action = 0;
10856 count [ DIFFETTR ] -= 1;
10857 }
10858 }
10859
10860 /* if last diffusion step and no reaction, convert back to */
10861 /* solid ettringite */
10862 if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10863 action = 0;
10864 count [ DIFFETTR ] -= 1;
10865 count [ ETTR ] += 1;
10866 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
10867 }
10868
10869 if ( action != 0 ) {
10870 /* if diffusion is possible, execute it */
10871 if ( check == POROSITY ) {
10872 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10873 mic [ xnew ] [ ynew ] [ znew ] = DIFFETTR;
10874 } else {
10875 /* indicate that diffusing ettringite remained at */
10876 /* original location */
10877 action = 7;
10878 }
10879 }
10880
10881 return ( action );
10882
10883 ( void ) sumgarb;
10884}
10885
10886/* routine to add extra pozzolanic CSH when CH reacts at */
10887/* pozzolanic surface (e.g. silica fume) located at (xpres,ypres,zpres) */
10888/* Called by movech */
10889/* Calls moveone and edgecnt */
10890void CemhydMatStatus :: extpozz(int xpres, int ypres, int zpres)
10891{
10892 int check, sump, xchr, ychr, zchr, fchr, i1, action, numnear;
10893 long int tries;
10894
10895 /* first try 6 neighboring locations until */
10896 /* a) successful */
10897 /* b) all 6 sites are tried or */
10898 /* c) 100 tries are made */
10899 fchr = 0;
10900 sump = 1;
10901 for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
10902 /* determine location of neighbor (using periodic boundaries) */
10903 xchr = xpres;
10904 ychr = ypres;
10905 zchr = zpres;
10906 action = 0;
10907 sump *= moveone(& xchr, & ychr, & zchr, & action, sump);
10908 if ( action == 0 ) {
10909 printf("Error in value of action in extpozz \n");
10910 }
10911
10912 check = mic [ xchr ] [ ychr ] [ zchr ];
10913
10914 /* if neighbor is porosity, locate the pozzolanic CSH there */
10915 if ( check == POROSITY ) {
10916 mic [ xchr ] [ ychr ] [ zchr ] = POZZCSH;
10917 count [ POZZCSH ] += 1;
10918 count [ POROSITY ] -= 1;
10919 fchr = 1;
10920 }
10921 }
10922
10923 /* if no neighbor available, locate pozzolanic CSH at random location */
10924 /* in pore space */
10925 tries = 0;
10926 while ( fchr == 0 ) {
10927 tries += 1;
10928 /* generate a random location in the 3-D system */
10929 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10930 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10931 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10932 if ( xchr >= SYSIZE ) {
10933 xchr = 0;
10934 }
10935
10936 if ( ychr >= SYSIZE ) {
10937 ychr = 0;
10938 }
10939
10940 if ( zchr >= SYSIZE ) {
10941 zchr = 0;
10942 }
10943
10944 check = mic [ xchr ] [ ychr ] [ zchr ];
10945 /* if location is porosity, locate the extra pozzolanic CSH there */
10946 if ( check == POROSITY ) {
10947 numnear = edgecnt(xchr, ychr, zchr, POZZ, CSH, POZZCSH);
10948 /* Be sure that one neighboring species is CSH or */
10949 /* pozzolanic material */
10950 if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
10951 mic [ xchr ] [ ychr ] [ zchr ] = POZZCSH;
10952 count [ POZZCSH ] += 1;
10953 count [ POROSITY ] -= 1;
10954 fchr = 1;
10955 }
10956 }
10957 }
10958}
10959
10960/* routine to move a diffusing FH3 species */
10961/* from location (xcur,ycur,zcur) with nucleation probability nucprob */
10962/* Called by hydrate */
10963/* Calls moveone */
10964int CemhydMatStatus :: movefh3(int xcur, int ycur, int zcur, int finalstep, float nucprob)
10965{
10966 int check, xnew, ynew, znew, action, sumold, sumgarb;
10967 float pgen;
10968
10969 /* first check for nucleation */
10970 pgen = ran1(seed);
10971
10972 if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
10973 action = 0;
10974 mic [ xcur ] [ ycur ] [ zcur ] = FH3;
10975 count [ FH3 ] += 1;
10976 count [ DIFFFH3 ] -= 1;
10977 } else {
10978 /* determine new location (using periodic boundaries) */
10979 xnew = xcur;
10980 ynew = ycur;
10981 znew = zcur;
10982 action = 0;
10983 sumold = 1;
10984 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10985 if ( action == 0 ) {
10986 printf("Error in value of action in movefh3 \n");
10987 }
10988
10989 check = mic [ xnew ] [ ynew ] [ znew ];
10990
10991 /* check for growth of FH3 crystal */
10992 if ( check == FH3 ) {
10993 mic [ xcur ] [ ycur ] [ zcur ] = FH3;
10994 count [ FH3 ] += 1;
10995 count [ DIFFFH3 ] -= 1;
10996 action = 0;
10997 }
10998
10999 if ( action != 0 ) {
11000 /* if diffusion is possible, execute it */
11001 if ( check == POROSITY ) {
11002 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
11003 mic [ xnew ] [ ynew ] [ znew ] = DIFFFH3;
11004 } else {
11005 /* indicate that diffusing FH3 species */
11006 /* remained at original location */
11007 action = 7;
11008 }
11009 }
11010 }
11011
11012 return ( action );
11013
11014 ( void ) sumgarb;
11015}
11016
11017/* routine to move a diffusing CH species */
11018/* from location (xcur,ycur,zcur) with nucleation probability nucprob */
11019/* Called by hydrate */
11020/* Calls moveone and extpozz */
11021int CemhydMatStatus :: movech(int xcur, int ycur, int zcur, int finalstep, float nucprob)
11022{
11023 int check, xnew, ynew, znew, action, sumgarb, sumold;
11024 float pexp, pgen, pfix;
11025
11026 /* first check for nucleation */
11027 pgen = ran1(seed);
11028 if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
11029 action = 0;
11030 mic [ xcur ] [ ycur ] [ zcur ] = CH;
11031 count [ DIFFCH ] -= 1;
11032 count [ CH ] += 1;
11033 } else {
11034 /* determine new location (using periodic boundaries) */
11035 xnew = xcur;
11036 ynew = ycur;
11037 znew = zcur;
11038 action = 0;
11039 sumold = 1;
11040 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
11041 if ( action == 0 ) {
11042 printf("Error in value of action in movech \n");
11043 }
11044
11045 check = mic [ xnew ] [ ynew ] [ znew ];
11046
11047 /* check for growth of CH crystal */
11048 if ( ( check == CH ) && ( pgen <= CHGROW ) ) {
11049 mic [ xcur ] [ ycur ] [ zcur ] = CH;
11050 count [ DIFFCH ] -= 1;
11051 count [ CH ] += 1;
11052 action = 0;
11053 }
11054 /* check for growth of CH crystal on aggregate or CaCO3 surface */
11055 /* re suggestion of Sidney Diamond */
11056 else if ( ( ( check == INERTAGG ) || ( check == CACO3 ) || ( check == INERT ) ) && ( pgen <= CHGROWAGG ) && ( chflag == 1 ) ) {
11057 mic [ xcur ] [ ycur ] [ zcur ] = CH;
11058 count [ DIFFCH ] -= 1;
11059 count [ CH ] += 1;
11060 action = 0;
11061 }
11062 /* check for pozzolanic reaction */
11063 /* 36.41 units CH can react with 27 units of S */
11064 else if ( ( pgen <= ppozz ) && ( check == POZZ ) && ( npr <= ( int ) ( ( float ) nfill * 1.35 ) ) ) {
11065 action = 0;
11066 mic [ xcur ] [ ycur ] [ zcur ] = POZZCSH;
11067 count [ POZZCSH ] += 1;
11068 /* update counter of number of diffusing CH */
11069 /* which have reacted pozzolanically */
11070 npr += 1;
11071 count [ DIFFCH ] -= 1;
11072 /* Convert pozzolan to pozzolanic CSH as needed */
11073 pfix = ran1(seed);
11074 if ( pfix <= ( 1. / 1.35 ) ) {
11075 mic [ xnew ] [ ynew ] [ znew ] = POZZCSH;
11076 count [ POZZ ] -= 1;
11077 count [ POZZCSH ] += 1;
11078 }
11079
11080 /* allow for extra pozzolanic CSH as needed */
11081 pexp = ran1(seed);
11082 /* should form 101.81 units of pozzolanic CSH for */
11083 /* each 36.41 units of CH and 27 units of S */
11084 /* 1.05466=(101.81-36.41-27)/36.41 */
11085 extpozz(xcur, ycur, zcur);
11086 if ( pexp <= 0.05466 ) {
11087 extpozz(xcur, ycur, zcur);
11088 }
11089 } else if ( check == DIFFAS ) {
11090 action = 0;
11091 mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
11092 count [ STRAT ] += 1;
11093 /* update counter of number of diffusing CH */
11094 /* which have reacted to form stratlingite */
11095 nasr += 1;
11096 count [ DIFFCH ] -= 1;
11097 /* Convert DIFFAS to STRAT as needed */
11098 pfix = ran1(seed);
11099 if ( pfix <= 0.7538 ) {
11100 mic [ xnew ] [ ynew ] [ znew ] = STRAT;
11101 count [ STRAT ] += 1;
11102 count [ DIFFAS ] -= 1;
11103 }
11104
11105 /* allow for extra stratlingite as needed */
11106 /* 1.5035=(215.63-66.2-49.9)/66.2 */
11107 extstrat(xcur, ycur, zcur);
11108 pexp = ran1(seed);
11109 if ( pexp <= 0.5035 ) {
11110 extstrat(xcur, ycur, zcur);
11111 }
11112 }
11113
11114 if ( action != 0 ) {
11115 /* if diffusion is possible, execute it */
11116 if ( check == POROSITY ) {
11117 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
11118 mic [ xnew ] [ ynew ] [ znew ] = DIFFCH;
11119 } else {
11120 /* indicate that diffusing CH species */
11121 /* remained at original location */
11122 action = 7;
11123 }
11124 }
11125 }
11126
11127 return ( action );
11128
11129 ( void ) sumgarb;
11130}
11131
11132/* routine to add extra C3AH6 when diffusing C3A nucleates or reacts at */
11133/* C3AH6 surface at location (xpres,ypres,zpres) */
11134/* Called by movec3a */
11135/* Calls moveone and edgecnt */
11136void CemhydMatStatus :: extc3ah6(int xpres, int ypres, int zpres)
11137{
11138 int check, sump, xchr, ychr, zchr, fchr, i1, action, numnear;
11139 long int tries;
11140
11141 /* First try 6 neighboring locations until */
11142 /* a) successful */
11143 /* b) all 6 sites are tried or */
11144 /* c) 100 random attempts are made */
11145 fchr = 0;
11146 sump = 1;
11147 for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
11148 /* determine new coordinates (using periodic boundaries) */
11149 xchr = xpres;
11150 ychr = ypres;
11151 zchr = zpres;
11152 action = 0;
11153 sump *= moveone(& xchr, & ychr, & zchr, & action, sump);
11154 if ( action == 0 ) {
11155 printf("Error in action value in extc3ah6 \n");
11156 }
11157
11158 check = mic [ xchr ] [ ychr ] [ zchr ];
11159
11160 /* if neighbor is pore space, convert it to C3AH6 */
11161 if ( check == POROSITY ) {
11162 mic [ xchr ] [ ychr ] [ zchr ] = C3AH6;
11163 count [ C3AH6 ] += 1;
11164 count [ POROSITY ] -= 1;
11165 fchr = 1;
11166 }
11167 }
11168
11169 /* if unsuccessful, add C3AH6 at random location in pore space */
11170 tries = 0;
11171 while ( fchr == 0 ) {
11172 tries += 1;
11173 xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
11174 ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
11175 zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
11176 if ( xchr >= SYSIZE ) {
11177 xchr = 0;
11178 }
11179
11180 if ( ychr >= SYSIZE ) {
11181 ychr = 0;
11182 }
11183
11184 if ( zchr >= SYSIZE ) {
11185 zchr = 0;
11186 }
11187
11188 check = mic [ xchr ] [ ychr ] [ zchr ];
11189
11190 if ( check == POROSITY ) {
11191 numnear = edgecnt(xchr, ychr, zchr, C3AH6, C3A, C3AH6);
11192 /* Be sure that new C3AH6 is in contact with */
11193 /* at least one C3AH6 or C3A */
11194 if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
11195 mic [ xchr ] [ ychr ] [ zchr ] = C3AH6;
11196 count [ C3AH6 ] += 1;
11197 count [ POROSITY ] -= 1;
11198 fchr = 1;
11199 }
11200 }
11201 }
11202}
11203
11204/* routine to move a diffusing C3A species */
11205/* from location (xcur,ycur,zcur) with nucleation probability of nucprob */
11206/* Called by hydrate */
11207/* Calls extc3ah6, moveone, extettr, and extafm */
11208int CemhydMatStatus :: movec3a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
11209{
11210 int check, xnew, ynew, znew, action, sumgarb, sumold;
11211 int xexp, yexp, zexp, nexp, iexp, newact;
11212 float pgen, pexp, pafm, pgrow, p2diff;
11213
11214 /* First be sure that a diffusing C3A species is at (xcur,ycur,zcur) */
11215 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFC3A ) {
11216 action = 0;
11217 return ( action );
11218 }
11219
11220 /* Check for nucleation into solid C3AH6 */
11221 pgen = ran1(seed);
11222 p2diff = ran1(seed);
11223
11224 if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
11225 action = 0;
11226 mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11227 count [ C3AH6 ] += 1;
11228 /* decrement count of diffusing C3A species */
11229 count [ DIFFC3A ] -= 1;
11230 /* allow for probabilistic-based expansion of C3AH6 */
11231 /* crystal to account for volume stoichiometry */
11232 pexp = ran1(seed);
11233 if ( pexp <= 0.69 ) {
11234 extc3ah6(xcur, ycur, zcur);
11235 }
11236 } else {
11237 /* determine new coordinates (using periodic boundaries) */
11238 xnew = xcur;
11239 ynew = ycur;
11240 znew = zcur;
11241 action = 0;
11242 sumold = 1;
11243 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
11244 if ( action == 0 ) {
11245 printf("Error in value of action in movec3a \n");
11246 }
11247
11248 check = mic [ xnew ] [ ynew ] [ znew ];
11249
11250 /* check for growth of C3AH6 crystal */
11251 if ( check == C3AH6 ) {
11252 pgrow = ran1(seed);
11253 /* Try to slow down growth of C3AH6 crystals to */
11254 /* promote ettringite and Afm formation */
11255 if ( pgrow <= C3AH6GROW ) {
11256 mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11257 count [ C3AH6 ] += 1;
11258 count [ DIFFC3A ] -= 1;
11259 action = 0;
11260 /* allow for probabilistic-based expansion of C3AH6 */
11261 /* crystal to account for volume stoichiometry */
11262 pexp = ran1(seed);
11263 if ( pexp <= 0.69 ) {
11264 extc3ah6(xcur, ycur, zcur);
11265 }
11266 }
11267 }
11268 /* examine reaction with diffusing gypsum to form ettringite */
11269 /* Only allow reaction with diffusing gypsum */
11270 else if ( ( check == DIFFGYP ) && ( p2diff < C3AGYP ) ) {
11271 /* convert diffusing gypsum to ettringite */
11272 mic [ xnew ] [ ynew ] [ znew ] = ETTR;
11273 count [ ETTR ] += 1;
11274 /* decrement counts of diffusing gypsum */
11275 count [ DIFFGYP ] -= 1;
11276 action = 0;
11277
11278 /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11279 pexp = ran1(seed);
11280 nexp = 2;
11281 if ( pexp <= 0.40 ) {
11282 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
11283 count [ ETTR ] += 1;
11284 count [ DIFFC3A ] -= 1;
11285 nexp = 1;
11286 } else {
11287 /* indicate that diffusing species remains in current location */
11288 action = 7;
11289 nexp = 2;
11290 }
11291
11292 /* Perform expansion that occurs when ettringite is formed */
11293 /* xexp, yexp and zexp are the coordinates of the last ettringite */
11294 /* pixel to be added */
11295 xexp = xnew;
11296 yexp = ynew;
11297 zexp = znew;
11298 for ( iexp = 1; iexp <= nexp; iexp++ ) {
11299 newact = extettr(xexp, yexp, zexp, 0);
11300 /* update xexp, yexp and zexp */
11301 switch ( newact ) {
11302 case 1:
11303 xexp -= 1;
11304 if ( xexp < 0 ) {
11305 xexp = ( SYSIZEM1 );
11306 }
11307
11308 break;
11309 case 2:
11310 xexp += 1;
11311 if ( xexp >= SYSIZE ) {
11312 xexp = 0;
11313 }
11314
11315 break;
11316 case 3:
11317 yexp -= 1;
11318 if ( yexp < 0 ) {
11319 yexp = ( SYSIZEM1 );
11320 }
11321
11322 break;
11323 case 4:
11324 yexp += 1;
11325 if ( yexp >= SYSIZE ) {
11326 yexp = 0;
11327 }
11328
11329 break;
11330 case 5:
11331 zexp -= 1;
11332 if ( zexp < 0 ) {
11333 zexp = ( SYSIZEM1 );
11334 }
11335
11336 break;
11337 case 6:
11338 zexp += 1;
11339 if ( zexp >= SYSIZE ) {
11340 zexp = 0;
11341 }
11342
11343 break;
11344 default:
11345 break;
11346 }
11347 }
11348
11349 /* probabilistic-based expansion for last ettringite pixel */
11350 pexp = ran1(seed);
11351 if ( pexp <= 0.30 ) {
11352 newact = extettr(xexp, yexp, zexp, 0);
11353 }
11354 }
11355 /* examine reaction with diffusing hemihydrate to form ettringite */
11356 /* Only allow reaction with diffusing hemihydrate */
11357 else if ( ( check == DIFFHEM ) && ( p2diff < C3AGYP ) ) {
11358 /* convert diffusing hemihydrate to ettringite */
11359 mic [ xnew ] [ ynew ] [ znew ] = ETTR;
11360 count [ ETTR ] += 1;
11361 /* decrement counts of diffusing hemihydrate */
11362 count [ DIFFHEM ] -= 1;
11363 action = 0;
11364
11365 /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11366 pexp = ran1(seed);
11367 nexp = 3;
11368 if ( pexp <= 0.5583 ) {
11369 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
11370 count [ ETTR ] += 1;
11371 count [ DIFFC3A ] -= 1;
11372 nexp = 2;
11373 } else {
11374 /* indicate that diffusing species remains in current location */
11375 action = 7;
11376 nexp = 3;
11377 }
11378
11379 /* Perform expansion that occurs when ettringite is formed */
11380 /* xexp, yexp and zexp are the coordinates of the last ettringite */
11381 /* pixel to be added */
11382 xexp = xnew;
11383 yexp = ynew;
11384 zexp = znew;
11385 for ( iexp = 1; iexp <= nexp; iexp++ ) {
11386 newact = extettr(xexp, yexp, zexp, 0);
11387 /* update xexp, yexp and zexp */
11388 switch ( newact ) {
11389 case 1:
11390 xexp -= 1;
11391 if ( xexp < 0 ) {
11392 xexp = ( SYSIZEM1 );
11393 }
11394
11395 break;
11396 case 2:
11397 xexp += 1;
11398 if ( xexp >= SYSIZE ) {
11399 xexp = 0;
11400 }
11401
11402 break;
11403 case 3:
11404 yexp -= 1;
11405 if ( yexp < 0 ) {
11406 yexp = ( SYSIZEM1 );
11407 }
11408
11409 break;
11410 case 4:
11411 yexp += 1;
11412 if ( yexp >= SYSIZE ) {
11413 yexp = 0;
11414 }
11415
11416 break;
11417 case 5:
11418 zexp -= 1;
11419 if ( zexp < 0 ) {
11420 zexp = ( SYSIZEM1 );
11421 }
11422
11423 break;
11424 case 6:
11425 zexp += 1;
11426 if ( zexp >= SYSIZE ) {
11427 zexp = 0;
11428 }
11429
11430 break;
11431 default:
11432 break;
11433 }
11434 }
11435
11436 /* probabilistic-based expansion for last ettringite pixel */
11437 pexp = ran1(seed);
11438 if ( pexp <= 0.6053 ) {
11439 newact = extettr(xexp, yexp, zexp, 0);
11440 }
11441 }
11442 /* examine reaction with diffusing anhydrite to form ettringite */
11443 /* Only allow reaction with diffusing anhydrite */
11444 else if ( ( check == DIFFANH ) && ( p2diff < C3AGYP ) ) {
11445 /* convert diffusing anhydrite to ettringite */
11446 mic [ xnew ] [ ynew ] [ znew ] = ETTR;
11447 count [ ETTR ] += 1;
11448 /* decrement counts of diffusing anhydrite */
11449 count [ DIFFANH ] -= 1;
11450 action = 0;
11451
11452 /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11453 pexp = ran1(seed);
11454 nexp = 3;
11455 if ( pexp <= 0.569 ) {
11456 mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
11457 count [ ETTR ] += 1;
11458 count [ DIFFC3A ] -= 1;
11459 nexp = 2;
11460 } else {
11461 /* indicate that diffusing species remains in current location */
11462 action = 7;
11463 nexp = 3;
11464 }
11465
11466 /* Perform expansion that occurs when ettringite is formed */
11467 /* xexp, yexp and zexp are the coordinates of the last ettringite */
11468 /* pixel to be added */
11469 xexp = xnew;
11470 yexp = ynew;
11471 zexp = znew;
11472 for ( iexp = 1; iexp <= nexp; iexp++ ) {
11473 newact = extettr(xexp, yexp, zexp, 0);
11474 /* update xexp, yexp and zexp */
11475 switch ( newact ) {
11476 case 1:
11477 xexp -= 1;
11478 if ( xexp < 0 ) {
11479 xexp = ( SYSIZEM1 );
11480 }
11481
11482 break;
11483 case 2:
11484 xexp += 1;
11485 if ( xexp >= SYSIZE ) {
11486 xexp = 0;
11487 }
11488
11489 break;
11490 case 3:
11491 yexp -= 1;
11492 if ( yexp < 0 ) {
11493 yexp = ( SYSIZEM1 );
11494 }
11495
11496 break;
11497 case 4:
11498 yexp += 1;
11499 if ( yexp >= SYSIZE ) {
11500 yexp = 0;
11501 }
11502
11503 break;
11504 case 5:
11505 zexp -= 1;
11506 if ( zexp < 0 ) {
11507 zexp = ( SYSIZEM1 );
11508 }
11509
11510 break;
11511 case 6:
11512 zexp += 1;
11513 if ( zexp >= SYSIZE ) {
11514 zexp = 0;
11515 }
11516
11517 break;
11518 default:
11519 break;
11520 }
11521 }
11522
11523 /* probabilistic-based expansion for last ettringite pixel */
11524 pexp = ran1(seed);
11525 if ( pexp <= 0.6935 ) {
11526 newact = extettr(xexp, yexp, zexp, 0);
11527 }
11528 }
11529 /* examine reaction with diffusing CaCl2 to form FREIDEL */
11530 /* Only allow reaction with diffusing CaCl2 */
11531 else if ( check == DIFFCACL2 ) {
11532 /* convert diffusing C3A to Freidel's salt */
11533 mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
11534 count [ FREIDEL ] += 1;
11535 /* decrement counts of diffusing C3A and CaCl2 */
11536 count [ DIFFC3A ] -= 1;
11537 action = 0;
11538
11539 /* convert diffusing CACL2 to solid FREIDEL or else leave as a diffusing CACL2 */
11540 pexp = ran1(seed);
11541 nexp = 2;
11542 if ( pexp <= 0.5793 ) {
11543 mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
11544 count [ FREIDEL ] += 1;
11545 count [ DIFFCACL2 ] -= 1;
11546 nexp = 1;
11547 } else {
11548 nexp = 2;
11549 }
11550
11551 /* Perform expansion that occurs when Freidel's salt is formed */
11552 /* xexp, yexp and zexp are the coordinates of the last FREIDEL */
11553 /* pixel to be added */
11554 xexp = xnew;
11555 yexp = ynew;
11556 zexp = znew;
11557 for ( iexp = 1; iexp <= nexp; iexp++ ) {
11558 newact = extfreidel(xexp, yexp, zexp);
11559 /* update xexp, yexp and zexp */
11560 switch ( newact ) {
11561 case 1:
11562 xexp -= 1;
11563 if ( xexp < 0 ) {
11564 xexp = ( SYSIZEM1 );
11565 }
11566
11567 break;
11568 case 2:
11569 xexp += 1;
11570 if ( xexp >= SYSIZE ) {
11571 xexp = 0;
11572 }
11573
11574 break;
11575 case 3:
11576 yexp -= 1;
11577 if ( yexp < 0 ) {
11578 yexp = ( SYSIZEM1 );
11579 }
11580
11581 break;
11582 case 4:
11583 yexp += 1;
11584 if ( yexp >= SYSIZE ) {
11585 yexp = 0;
11586 }
11587
11588 break;
11589 case 5:
11590 zexp -= 1;
11591 if ( zexp < 0 ) {
11592 zexp = ( SYSIZEM1 );
11593 }
11594
11595 break;
11596 case 6:
11597 zexp += 1;
11598 if ( zexp >= SYSIZE ) {
11599 zexp = 0;
11600 }
11601
11602 break;
11603 default:
11604 break;
11605 }
11606 }
11607
11608 /* probabilistic-based expansion for last FREIDEL pixel */
11609 pexp = ran1(seed);
11610 if ( pexp <= 0.3295 ) {
11611 newact = extfreidel(xexp, yexp, zexp);
11612 }
11613 }
11614 /* examine reaction with diffusing CAS2 to form STRAT */
11615 /* Only allow reaction with diffusing (not solid) CAS2 */
11616 else if ( check == DIFFCAS2 ) {
11617 /* convert diffusing CAS2 to stratlingite */
11618 mic [ xnew ] [ ynew ] [ znew ] = STRAT;
11619 count [ STRAT ] += 1;
11620 /* decrement counts of diffusing C3A and CAS2 */
11621 count [ DIFFCAS2 ] -= 1;
11622 action = 0;
11623
11624 /* convert diffusing C3A to solid STRAT or else leave as a diffusing C3A */
11625 pexp = ran1(seed);
11626 nexp = 3;
11627 if ( pexp <= 0.886 ) {
11628 mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
11629 count [ STRAT ] += 1;
11630 count [ DIFFC3A ] -= 1;
11631 nexp = 2;
11632 } else {
11633 action = 7;
11634 nexp = 3;
11635 }
11636
11637 /* Perform expansion that occurs when stratlingite is formed */
11638 /* xexp, yexp and zexp are the coordinates of the last STRAT */
11639 /* pixel to be added */
11640 xexp = xnew;
11641 yexp = ynew;
11642 zexp = znew;
11643 for ( iexp = 1; iexp <= nexp; iexp++ ) {
11644 newact = extstrat(xexp, yexp, zexp);
11645 /* update xexp, yexp and zexp */
11646 switch ( newact ) {
11647 case 1:
11648 xexp -= 1;
11649 if ( xexp < 0 ) {
11650 xexp = ( SYSIZEM1 );
11651 }
11652
11653 break;
11654 case 2:
11655 xexp += 1;
11656 if ( xexp >= SYSIZE ) {
11657 xexp = 0;
11658 }
11659
11660 break;
11661 case 3:
11662 yexp -= 1;
11663 if ( yexp < 0 ) {
11664 yexp = ( SYSIZEM1 );
11665 }
11666
11667 break;
11668 case 4:
11669 yexp += 1;
11670 if ( yexp >= SYSIZE ) {
11671 yexp = 0;
11672 }
11673
11674 break;
11675 case 5:
11676 zexp -= 1;
11677 if ( zexp < 0 ) {
11678 zexp = ( SYSIZEM1 );
11679 }
11680
11681 break;
11682 case 6:
11683 zexp += 1;
11684 if ( zexp >= SYSIZE ) {
11685 zexp = 0;
11686 }
11687
11688 break;
11689 default:
11690 break;
11691 }
11692 }
11693
11694 /* probabilistic-based expansion for last STRAT pixel */
11695 pexp = ran1(seed);
11696 if ( pexp <= 0.286 ) {
11697 newact = extstrat(xexp, yexp, zexp);
11698 }
11699 }
11700
11701 /* check for reaction with diffusing or solid ettringite to form AFm */
11702 /* reaction at solid ettringite only possible if ettringite is soluble */
11703 /* and even then on a limited bases to avoid a great formation of AFm */
11704 /* when ettringite first becomes soluble */
11705 pgrow = ran1(seed);
11706 if ( ( check == DIFFETTR ) || ( ( check == ETTR ) && ( soluble [ ETTR ] == 1 ) && ( pgrow <= C3AETTR ) ) ) {
11707 /* convert diffusing or solid ettringite to AFm */
11708 mic [ xnew ] [ ynew ] [ znew ] = AFM;
11709 count [ AFM ] += 1;
11710 /* decrement count of ettringite */
11711 count [ check ] -= 1;
11712 action = 0;
11713
11714 /* convert diffusing C3A to AFm or leave as diffusing C3A */
11715 pexp = ran1(seed);
11716 if ( pexp <= 0.2424 ) {
11717 mic [ xcur ] [ ycur ] [ zcur ] = AFM;
11718 count [ AFM ] += 1;
11719 count [ DIFFC3A ] -= 1;
11720 pafm = ( -0.1 );
11721 } else {
11722 action = 7;
11723 pafm = 0.04699;
11724 }
11725
11726 /* probabilistic-based expansion for new AFm pixel */
11727 pexp = ran1(seed);
11728 if ( pexp <= pafm ) {
11729 extafm(xnew, ynew, znew);
11730 }
11731 }
11732
11733 if ( ( action != 0 ) && ( action != 7 ) ) {
11734 /* if diffusion is possible, execute it */
11735 if ( check == POROSITY ) {
11736 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
11737 mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
11738 } else {
11739 /* indicate that diffusing C3A remained */
11740 /* at original location */
11741 action = 7;
11742 }
11743 }
11744 }
11745
11746 return ( action );
11747
11748 ( void ) sumgarb;
11749}
11750
11751/* routine to move a diffusing C4A species */
11752/* from location (xcur,ycur,zcur) with nucleation probability of nucprob */
11753/* Called by hydrate */
11754/* Calls extc3ah6, moveone, extettr, and extafm */
11755int CemhydMatStatus :: movec4a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
11756{
11757 int check, xnew, ynew, znew, action, sumgarb, sumold;
11758 int xexp, yexp, zexp, nexp, iexp, newact;
11759 float pgen, pexp, pafm, pgrow, p2diff;
11760
11761 /* First be sure that a diffusing C4A species is at (xcur,ycur,zcur) */
11762 if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFC4A ) {
11763 action = 0;
11764 return ( action );
11765 }
11766
11767 /* Check for nucleation into solid C3AH6 */
11768 pgen = ran1(seed);
11769 p2diff = ran1(seed);
11770
11771 if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
11772 action = 0;
11773 mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11774 count [ C3AH6 ] += 1;
11775 /* decrement count of diffusing C3A species */
11776 count [ DIFFC4A ] -= 1;
11777 /* allow for probabilistic-based expansion of C3AH6 */
11778 /* crystal to account for volume stoichiometry */
11779 pexp = ran1(seed);
11780 if ( pexp <= 0.69 ) {
11781 extc3ah6(xcur, ycur, zcur);
11782 }
11783 } else {
11784 /* determine new coordinates (using periodic boundaries) */
11785 xnew = xcur;
11786 ynew = ycur;
11787 znew = zcur;
11788 action = 0;
11789 sumold = 1;
11790 sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
11791 if ( action == 0 ) {
11792 printf("Error in value of action in movec4a \n");
11793 }
11794
11795 check = mic [ xnew ] [ ynew ] [ znew ];
11796
11797 /* check for growth of C3AH6 crystal */
11798 if ( check == C3AH6 ) {
11799 pgrow = ran1(seed);
11800 /* Try to slow down growth of C3AH6 crystals to */
11801 /* promote ettringite and Afm formation */
11802 if ( pgrow <= C3AH6GROW ) {
11803 mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11804 count [ C3AH6 ] += 1;
11805 count [ DIFFC4A ] -= 1;
11806 action = 0;
11807 /* allow for probabilistic-based expansion of C3AH6 */
11808 /* crystal to account for volume stoichiometry */
11809 pexp = ran1(seed);
11810 if ( pexp <= 0.69 ) {
11811 extc3ah6(xcur, ycur, zcur);
11812 }
11813 }
11814 }
11815 /* examine reaction with diffusing gypsum to form ettringite */
11816 /* Only allow reaction with diffusing gypsum */
11817 else if ( ( check == DIFFGYP ) && ( p2diff < C3AGYP ) ) {
11818 /* convert diffusing gypsum to ettringite */
11819 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
11820 count [ ETTRC4AF ] += 1;
11821 /* decrement counts of diffusing gypsum */
11822 count [ DIFFGYP ] -= 1;
11823 action = 0;
11824
11825 /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11826 pexp = ran1(seed);
11827 nexp = 2;
11828 if ( pexp <= 0.40 ) {
11829 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
11830 count [ ETTRC4AF ] += 1;
11831 count [ DIFFC4A ] -= 1;
11832 nexp = 1;
11833 } else {
11834 /* indicate that diffusing species remains in current location */
11835 action = 7;
11836 nexp = 2;
11837 }
11838
11839 /* Perform expansion that occurs when ettringite is formed */
11840 /* xexp, yexp and zexp are the coordinates of the last ettringite */
11841 /* pixel to be added */
11842 xexp = xnew;
11843 yexp = ynew;
11844 zexp = znew;
11845 for ( iexp = 1; iexp <= nexp; iexp++ ) {
11846 newact = extettr(xexp, yexp, zexp, 1);
11847 /* update xexp, yexp and zexp */
11848 switch ( newact ) {
11849 case 1:
11850 xexp -= 1;
11851 if ( xexp < 0 ) {
11852 xexp = ( SYSIZEM1 );
11853 }
11854
11855 break;
11856 case 2:
11857 xexp += 1;
11858 if ( xexp >= SYSIZE ) {
11859 xexp = 0;
11860 }
11861
11862 break;
11863 case 3:
11864 yexp -= 1;
11865 if ( yexp < 0 ) {
11866 yexp = ( SYSIZEM1 );
11867 }
11868
11869 break;
11870 case 4:
11871 yexp += 1;
11872 if ( yexp >= SYSIZE ) {
11873 yexp = 0;
11874 }
11875
11876 break;
11877 case 5:
11878 zexp -= 1;
11879 if ( zexp < 0 ) {
11880 zexp = ( SYSIZEM1 );
11881 }
11882
11883 break;
11884 case 6:
11885 zexp += 1;
11886 if ( zexp >= SYSIZE ) {
11887 zexp = 0;
11888 }
11889
11890 break;
11891 default:
11892 break;
11893 }
11894 }
11895
11896 /* probabilistic-based expansion for last ettringite pixel */
11897 pexp = ran1(seed);
11898 if ( pexp <= 0.30 ) {
11899 newact = extettr(xexp, yexp, zexp, 1);
11900 }
11901 }
11902 /* examine reaction with diffusing hemi to form ettringite */
11903 /* Only allow reaction with diffusing hemihydrate */
11904 else if ( ( check == DIFFHEM ) && ( p2diff < C3AGYP ) ) {
11905 /* convert diffusing hemihydrate to ettringite */
11906 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
11907 count [ ETTRC4AF ] += 1;
11908 /* decrement counts of diffusing hemihydrate */
11909 count [ DIFFHEM ] -= 1;
11910 action = 0;
11911
11912 /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11913 pexp = ran1(seed);
11914 nexp = 3;
11915 if ( pexp <= 0.5583 ) {
11916 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
11917 count [ ETTRC4AF ] += 1;
11918 count [ DIFFC4A ] -= 1;
11919 nexp = 2;
11920 } else {
11921 /* indicate that diffusing species remains in current location */
11922 action = 7;
11923 nexp = 3;
11924 }
11925
11926 /* Perform expansion that occurs when ettringite is formed */
11927 /* xexp, yexp and zexp are the coordinates of the last ettringite */
11928 /* pixel to be added */
11929 xexp = xnew;
11930 yexp = ynew;
11931 zexp = znew;
11932 for ( iexp = 1; iexp <= nexp; iexp++ ) {
11933 newact = extettr(xexp, yexp, zexp, 1);
11934 /* update xexp, yexp and zexp */
11935 switch ( newact ) {
11936 case 1:
11937 xexp -= 1;
11938 if ( xexp < 0 ) {
11939 xexp = ( SYSIZEM1 );
11940 }
11941
11942 break;
11943 case 2:
11944 xexp += 1;
11945 if ( xexp >= SYSIZE ) {
11946 xexp = 0;
11947 }
11948
11949 break;
11950 case 3:
11951 yexp -= 1;
11952 if ( yexp < 0 ) {
11953 yexp = ( SYSIZEM1 );
11954 }
11955
11956 break;
11957 case 4:
11958 yexp += 1;
11959 if ( yexp >= SYSIZE ) {
11960 yexp = 0;
11961 }
11962
11963 break;
11964 case 5:
11965 zexp -= 1;
11966 if ( zexp < 0 ) {
11967 zexp = ( SYSIZEM1 );
11968 }
11969
11970 break;
11971 case 6:
11972 zexp += 1;
11973 if ( zexp >= SYSIZE ) {
11974 zexp = 0;
11975 }
11976
11977 break;
11978 default:
11979 break;
11980 }
11981 }
11982
11983 /* probabilistic-based expansion for last ettringite pixel */
11984 pexp = ran1(seed);
11985 if ( pexp <= 0.6053 ) {
11986 newact = extettr(xexp, yexp, zexp, 1);
11987 }
11988 }
11989 /* examine reaction with diffusing anhydrite to form ettringite */
11990 /* Only allow reaction with diffusing anhydrite */
11991 else if ( ( check == DIFFANH ) && ( p2diff < C3AGYP ) ) {
11992 /* convert diffusing anhydrite to ettringite */
11993 mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
11994 count [ ETTRC4AF ] += 1;
11995 /* decrement counts of diffusing anhydrite */
11996 count [ DIFFANH ] -= 1;
11997 action = 0;
11998
11999 /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
12000 pexp = ran1(seed);
12001 nexp = 3;
12002 if ( pexp <= 0.569 ) {
12003 mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
12004 count [ ETTRC4AF ] += 1;
12005 count [ DIFFC4A ] -= 1;
12006 nexp = 2;
12007 } else {
12008 /* indicate that diffusing species remains in current location */
12009 action = 7;
12010 nexp = 3;
12011 }
12012
12013 /* Perform expansion that occurs when ettringite is formed */
12014 /* xexp, yexp and zexp are the coordinates of the last ettringite */
12015 /* pixel to be added */
12016 xexp = xnew;
12017 yexp = ynew;
12018 zexp = znew;
12019 for ( iexp = 1; iexp <= nexp; iexp++ ) {
12020 newact = extettr(xexp, yexp, zexp, 1);
12021 /* update xexp, yexp and zexp */
12022 switch ( newact ) {
12023 case 1:
12024 xexp -= 1;
12025 if ( xexp < 0 ) {
12026 xexp = ( SYSIZEM1 );
12027 }
12028
12029 break;
12030 case 2:
12031 xexp += 1;
12032 if ( xexp >= SYSIZE ) {
12033 xexp = 0;
12034 }
12035
12036 break;
12037 case 3:
12038 yexp -= 1;
12039 if ( yexp < 0 ) {
12040 yexp = ( SYSIZEM1 );
12041 }
12042
12043 break;
12044 case 4:
12045 yexp += 1;
12046 if ( yexp >= SYSIZE ) {
12047 yexp = 0;
12048 }
12049
12050 break;
12051 case 5:
12052 zexp -= 1;
12053 if ( zexp < 0 ) {
12054 zexp = ( SYSIZEM1 );
12055 }
12056
12057 break;
12058 case 6:
12059 zexp += 1;
12060 if ( zexp >= SYSIZE ) {
12061 zexp = 0;
12062 }
12063
12064 break;
12065 default:
12066 break;
12067 }
12068 }
12069
12070 /* probabilistic-based expansion for last ettringite pixel */
12071 pexp = ran1(seed);
12072 if ( pexp <= 0.6935 ) {
12073 newact = extettr(xexp, yexp, zexp, 1);
12074 }
12075 }
12076 /* examine reaction with diffusing CaCl2 to form FREIDEL */
12077 /* Only allow reaction with diffusing CaCl2 */
12078 else if ( check == DIFFCACL2 ) {
12079 /* convert diffusing C3A to Freidel's salt */
12080 mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
12081 count [ FREIDEL ] += 1;
12082 /* decrement counts of diffusing C3A and CaCl2 */
12083 count [ DIFFC4A ] -= 1;
12084 action = 0;
12085
12086 /* convert diffusing CACL2 to solid FREIDEL or else leave as a diffusing CACL2 */
12087 pexp = ran1(seed);
12088 nexp = 2;
12089 if ( pexp <= 0.5793 ) {
12090 mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
12091 count [ FREIDEL ] += 1;
12092 count [ DIFFCACL2 ] -= 1;
12093 nexp = 1;
12094 } else {
12095 nexp = 2;
12096 }
12097
12098 /* Perform expansion that occurs when Freidel's salt is formed */
12099 /* xexp, yexp and zexp are the coordinates of the last FREIDEL */
12100 /* pixel to be added */
12101 xexp = xnew;
12102 yexp = ynew;
12103 zexp = znew;
12104 for ( iexp = 1; iexp <= nexp; iexp++ ) {
12105 newact = extfreidel(xexp, yexp, zexp);
12106 /* update xexp, yexp and zexp */
12107 switch ( newact ) {
12108 case 1:
12109 xexp -= 1;
12110 if ( xexp < 0 ) {
12111 xexp = ( SYSIZEM1 );
12112 }
12113
12114 break;
12115 case 2:
12116 xexp += 1;
12117 if ( xexp >= SYSIZE ) {
12118 xexp = 0;
12119 }
12120
12121 break;
12122 case 3:
12123 yexp -= 1;
12124 if ( yexp < 0 ) {
12125 yexp = ( SYSIZEM1 );
12126 }
12127
12128 break;
12129 case 4:
12130 yexp += 1;
12131 if ( yexp >= SYSIZE ) {
12132 yexp = 0;
12133 }
12134
12135 break;
12136 case 5:
12137 zexp -= 1;
12138 if ( zexp < 0 ) {
12139 zexp = ( SYSIZEM1 );
12140 }
12141
12142 break;
12143 case 6:
12144 zexp += 1;
12145 if ( zexp >= SYSIZE ) {
12146 zexp = 0;
12147 }
12148
12149 break;
12150 default:
12151 break;
12152 }
12153 }
12154
12155 /* probabilistic-based expansion for last FREIDEL pixel */
12156 pexp = ran1(seed);
12157 if ( pexp <= 0.3295 ) {
12158 newact = extfreidel(xexp, yexp, zexp);
12159 }
12160 }
12161 /* examine reaction with diffusing CAS2 to form STRAT */
12162 /* Only allow reaction with diffusing (not solid) CAS2 */
12163 else if ( check == DIFFCAS2 ) {
12164 /* convert diffusing CAS2 to stratlingite */
12165 mic [ xnew ] [ ynew ] [ znew ] = STRAT;
12166 count [ STRAT ] += 1;
12167 /* decrement counts of diffusing CAS2 */
12168 count [ DIFFCAS2 ] -= 1;
12169 action = 0;
12170
12171 /* convert diffusing C3A to solid STRAT or else leave as a diffusing C3A */
12172 pexp = ran1(seed);
12173 nexp = 3;
12174 if ( pexp <= 0.886 ) {
12175 mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
12176 count [ STRAT ] += 1;
12177 count [ DIFFC4A ] -= 1;
12178 nexp = 2;
12179 } else {
12180 action = 7;
12181 nexp = 3;
12182 }
12183
12184 /* Perform expansion that occurs when stratlingite is formed */
12185 /* xexp, yexp and zexp are the coordinates of the last STRAT */
12186 /* pixel to be added */
12187 xexp = xnew;
12188 yexp = ynew;
12189 zexp = znew;
12190 for ( iexp = 1; iexp <= nexp; iexp++ ) {
12191 newact = extstrat(xexp, yexp, zexp);
12192 /* update xexp, yexp and zexp */
12193 switch ( newact ) {
12194 case 1:
12195 xexp -= 1;
12196 if ( xexp < 0 ) {
12197 xexp = ( SYSIZEM1 );
12198 }
12199
12200 break;
12201 case 2:
12202 xexp += 1;
12203 if ( xexp >= SYSIZE ) {
12204 xexp = 0;
12205 }
12206
12207 break;
12208 case 3:
12209 yexp -= 1;
12210 if ( yexp < 0 ) {
12211 yexp = ( SYSIZEM1 );
12212 }
12213
12214 break;
12215 case 4:
12216 yexp += 1;
12217 if ( yexp >= SYSIZE ) {
12218 yexp = 0;
12219 }
12220
12221 break;
12222 case 5:
12223 zexp -= 1;
12224 if ( zexp < 0 ) {
12225 zexp = ( SYSIZEM1 );
12226 }
12227
12228 break;
12229 case 6:
12230 zexp += 1;
12231 if ( zexp >= SYSIZE ) {
12232 zexp = 0;
12233 }
12234
12235 break;
12236 default:
12237 break;
12238 }
12239 }
12240
12241 /* probabilistic-based expansion for last STRAT pixel */
12242 pexp = ran1(seed);
12243 if ( pexp <= 0.286 ) {
12244 newact = extstrat(xexp, yexp, zexp);
12245 }
12246 }
12247
12248 /* check for reaction with diffusing or solid ettringite to form AFm */
12249 /* reaction at solid ettringite only possible if ettringite is soluble */
12250 /* and even then on a limited bases to avoid a great formation of AFm */
12251 /* when ettringite first becomes soluble */
12252 pgrow = ran1(seed);
12253 if ( ( check == DIFFETTR ) || ( ( check == ETTR ) && ( soluble [ ETTR ] == 1 ) && ( pgrow <= C3AETTR ) ) ) {
12254 /* convert diffusing or solid ettringite to AFm */
12255 mic [ xnew ] [ ynew ] [ znew ] = AFM;
12256 count [ AFM ] += 1;
12257 /* decrement count of ettringite */
12258 count [ check ] -= 1;
12259 action = 0;
12260
12261 /* convert diffusing C4A to AFm or leave as diffusing C4A */
12262 pexp = ran1(seed);
12263 if ( pexp <= 0.2424 ) {
12264 mic [ xcur ] [ ycur ] [ zcur ] = AFM;
12265 count [ AFM ] += 1;
12266 count [ DIFFC4A ] -= 1;
12267 pafm = ( -0.1 );
12268 } else {
12269 action = 7;
12270 pafm = 0.04699;
12271 }
12272
12273 /* probabilistic-based expansion for new AFm pixel */
12274 pexp = ran1(seed);
12275 if ( pexp <= pafm ) {
12276 extafm(xnew, ynew, znew);
12277 }
12278 }
12279
12280 if ( ( action != 0 ) && ( action != 7 ) ) {
12281 /* if diffusion is possible, execute it */
12282 if ( check == POROSITY ) {
12283 mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
12284 mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
12285 } else {
12286 /* indicate that diffusing C4A remained */
12287 /* at original location */
12288 action = 7;
12289 }
12290 }
12291 }
12292
12293 return ( action );
12294
12295 ( void ) sumgarb;
12296}
12297
12298/* routine to oversee hydration by updating position of all */
12299/* remaining diffusing species */
12300/* Calls movech, movec3a, movefh3, moveettr, movecsh, and movegyp */
12301
12302void CemhydMatStatus :: hydrate(int fincyc, int stepmax, float chpar1, float chpar2, float hgpar1, float hgpar2, float fhpar1, float fhpar2, float gypar1, float gypar2)
12303{
12304 int xpl, ypl, zpl, phpl, agepl, xpnew, ypnew, zpnew;
12305 float chprob, c3ah6prob, fh3prob, gypprob;
12306 long int nleft, ntodo, ndale;
12307 int istep, termflag, reactf = -1;
12308 float beterm;
12309 struct ants *curant, *antgone;
12310
12311 ntodo = nmade;
12312 nleft = nmade;
12313 termflag = 0;
12314
12315 /* Perform diffusion until all reacted or max. # of diffusion steps reached */
12316 for ( istep = 1; ( ( istep <= stepmax ) && ( nleft > 0 ) ); istep++ ) {
12317 if ( ( fincyc == 1 ) && ( istep == stepmax ) ) {
12318 termflag = 1;
12319 }
12320
12321 nleft = 0;
12322 ndale = 0;
12323
12324 /* determine probabilities for CH and C3AH6 nucleation */
12325 beterm = exp(-( double ) ( count [ DIFFCH ] ) * 1000000. / SYSIZE_POW3 / chpar2); //fixed
12326 chprob = chpar1 * ( 1. - beterm );
12327 beterm = exp(-( double ) ( count [ DIFFC3A ] ) * 1000000. / SYSIZE_POW3 / hgpar2); //fixed
12328 c3ah6prob = hgpar1 * ( 1. - beterm );
12329 beterm = exp(-( double ) ( count [ DIFFFH3 ] ) * 1000000. / SYSIZE_POW3 / fhpar2); //fixed
12330 fh3prob = fhpar1 * ( 1. - beterm );
12331 beterm = exp(-( double ) ( count [ DIFFANH ] + count [ DIFFHEM ] ) * 1000000. / SYSIZE_POW3 / gypar2); //fixed
12332 gypprob = gypar1 * ( 1. - beterm );
12333
12334 /* Process each diffusing species in turn */
12335 curant = headant->nextant;
12336 while ( curant != NULL ) {
12337 ndale += 1;
12338 xpl = curant->x;
12339 ypl = curant->y;
12340 zpl = curant->z;
12341 phpl = curant->id;
12342 agepl = curant->cycbirth;
12343
12344 /* based on ID, call appropriate routine to process diffusing species */
12345 if ( phpl == DIFFCSH ) {
12346 /* printf("Calling movecsh \n");
12347 * fflush(stdout); */
12348 reactf = movecsh(xpl, ypl, zpl, termflag, agepl);
12349 } else if ( phpl == DIFFANH ) {
12350 /* printf("Calling moveanh \n");
12351 * fflush(stdout); */
12352 reactf = moveanh(xpl, ypl, zpl, termflag, gypprob);
12353 } else if ( phpl == DIFFHEM ) {
12354 /* printf("Calling movehem \n");
12355 * fflush(stdout); */
12356 reactf = movehem(xpl, ypl, zpl, termflag, gypprob);
12357 } else if ( phpl == DIFFCH ) {
12358 /* printf("Calling movech \n");
12359 * fflush(stdout); */
12360 reactf = movech(xpl, ypl, zpl, termflag, chprob);
12361 } else if ( phpl == DIFFFH3 ) {
12362 /* printf("Calling movefh3 \n");
12363 * fflush(stdout); */
12364 reactf = movefh3(xpl, ypl, zpl, termflag, fh3prob);
12365 } else if ( phpl == DIFFGYP ) {
12366 /* printf("Calling movegyp \n");
12367 * fflush(stdout); */
12368 reactf = movegyp(xpl, ypl, zpl, termflag);
12369 } else if ( phpl == DIFFC3A ) {
12370 /* printf("Calling movec3a \n");
12371 * fflush(stdout); */
12372 reactf = movec3a(xpl, ypl, zpl, termflag, c3ah6prob);
12373 } else if ( phpl == DIFFC4A ) {
12374 /* printf("Calling movec4a \n");
12375 * fflush(stdout); */
12376 reactf = movec4a(xpl, ypl, zpl, termflag, c3ah6prob);
12377 } else if ( phpl == DIFFETTR ) {
12378 /* printf("Calling moveettr \n");
12379 * fflush(stdout); */
12380 reactf = moveettr(xpl, ypl, zpl, termflag);
12381 } else if ( phpl == DIFFCACL2 ) {
12382 /* printf("Calling movecacl2 \n");
12383 * fflush(stdout); */
12384 reactf = movecacl2(xpl, ypl, zpl, termflag);
12385 } else if ( phpl == DIFFCAS2 ) {
12386 /* printf("Calling movecas2 \n");
12387 * fflush(stdout); */
12388 reactf = movecas2(xpl, ypl, zpl, termflag);
12389 } else if ( phpl == DIFFAS ) {
12390 /* printf("Calling moveas \n");
12391 * fflush(stdout); */
12392 reactf = moveas(xpl, ypl, zpl, termflag);
12393 } else if ( phpl == DIFFCACO3 ) {
12394 /* printf("Calling movecaco3 \n");
12395 * fflush(stdout); */
12396 reactf = movecaco3(xpl, ypl, zpl, termflag);
12397 } else {
12398 printf("Error in ID of phase \n");
12399 }
12400
12401 /* if no reaction */
12402 if ( reactf != 0 ) {
12403 nleft += 1;
12404 xpnew = xpl;
12405 ypnew = ypl;
12406 zpnew = zpl;
12407
12408 /* update location of diffusing species */
12409 switch ( reactf ) {
12410 case 1:
12411 xpnew -= 1;
12412 if ( xpnew < 0 ) {
12413 xpnew = ( SYSIZEM1 );
12414 }
12415
12416 break;
12417 case 2:
12418 xpnew += 1;
12419 if ( xpnew >= SYSIZE ) {
12420 xpnew = 0;
12421 }
12422
12423 break;
12424 case 3:
12425 ypnew -= 1;
12426 if ( ypnew < 0 ) {
12427 ypnew = ( SYSIZEM1 );
12428 }
12429
12430 break;
12431 case 4:
12432 ypnew += 1;
12433 if ( ypnew >= SYSIZE ) {
12434 ypnew = 0;
12435 }
12436
12437 break;
12438 case 5:
12439 zpnew -= 1;
12440 if ( zpnew < 0 ) {
12441 zpnew = ( SYSIZEM1 );
12442 }
12443
12444 break;
12445 case 6:
12446 zpnew += 1;
12447 if ( zpnew >= SYSIZE ) {
12448 zpnew = 0;
12449 }
12450
12451 break;
12452 default:
12453 break;
12454 }
12455
12456 /* store new location of diffusing species */
12457 curant->x = xpnew;
12458 curant->y = ypnew;
12459 curant->z = zpnew;
12460 curant->id = phpl;
12461 curant = curant->nextant;
12462 } /* end of reactf!=0 loop */
12463 /* else remove ant from list */
12464 else {
12465 if ( ndale == 1 ) {
12466 headant->nextant = curant->nextant;
12467 } else {
12468 ( curant->prevant )->nextant = curant->nextant;
12469 }
12470
12471 if ( curant->nextant != NULL ) {
12472 ( curant->nextant )->prevant = curant->prevant;
12473 } else {
12474 tailant = curant->prevant;
12475 }
12476
12477 antgone = curant;
12478 curant = curant->nextant;
12479 //printf("DEMEM antgone addr %p\n", (const void *)antgone);
12480 free(antgone);
12481 ngoing -= 1;
12482 }
12483 }
12484
12485 /* end of curant loop */
12486 ntodo = nleft;
12487 }
12488
12489 /* end of istep loop */
12490 ( void ) ntodo;
12491}
12492
12493
12494void CemhydMatStatus :: laguer(fcomplex_cem a[], int m, fcomplex_cem *x, float eps, int polish)
12495{
12496 int j, iter;
12497 float err, dxold, cdx, abx;
12498 fcomplex_cem sq, h, gp, gm, g2, g, b, d, dx, f, x1;
12499
12500 dxold = Cabs(* x);
12501 for ( iter = 1; iter <= MAXIT; iter++ ) {
12502 b = a [ m ];
12503 err = Cabs(b);
12504 d = f = ComplexCemhyd(0.0, 0.0);
12505 abx = Cabs(* x);
12506 for ( j = m - 1; j >= 0; j-- ) {
12507 f = Cadd(Cmul(* x, f), d);
12508 d = Cadd(Cmul(* x, d), b);
12509 b = Cadd(Cmul(* x, b), a [ j ]);
12510 err = Cabs(b) + abx * err;
12511 }
12512
12513 err *= EPSS;
12514 if ( Cabs(b) <= err ) {
12515 return;
12516 }
12517
12518 g = Cdiv(d, b);
12519 g2 = Cmul(g, g);
12520 h = Csub( g2, RCmul( 2.0, Cdiv(f, b) ) );
12521 sq = Csqrt( RCmul( ( float ) ( m - 1 ), Csub(RCmul( ( float ) m, h ), g2) ) );
12522 gp = Cadd(g, sq);
12523 gm = Csub(g, sq);
12524 if ( Cabs(gp) < Cabs(gm) ) {
12525 gp = gm;
12526 }
12527
12528 dx = Cdiv(ComplexCemhyd( ( float ) m, 0.0 ), gp);
12529 x1 = Csub(* x, dx);
12530 if ( x->r == x1.r && x->i == x1.i ) {
12531 return;
12532 }
12533
12534 * x = x1;
12535 cdx = Cabs(dx);
12536 if ( iter > 6 && cdx >= dxold ) {
12537 return;
12538 }
12539
12540 dxold = cdx;
12541 if ( !polish ) {
12542 if ( cdx <= eps * Cabs(* x) ) {
12543 return;
12544 }
12545 }
12546 }
12547
12548 nrerror("Too many iterations in routine CemhydMat - LAGUER\n");
12549}
12550
12551
12552
12553void CemhydMatStatus :: zroots(fcomplex_cem a[], int m, fcomplex_cem roots[], int polish)
12554{
12555 int jj, j, i;
12556 fcomplex_cem x, b, c;
12557 fcomplex_cem *ad;
12558 //void laguer();fixed-no influence
12559 ad = new fcomplex_cem [ MAXM ];
12560
12561 for ( j = 0; j <= m; j++ ) {
12562 ad [ j ] = a [ j ];
12563 }
12564
12565 for ( j = m; j >= 1; j-- ) {
12566 x = ComplexCemhyd(0.0, 0.0);
12567 laguer(ad, j, & x, EPSP, 0);
12568 if ( fabs(x.i) <= ( 2.0 * EPSP * fabs(x.r) ) ) {
12569 x.i = 0.0;
12570 }
12571
12572 roots [ j ] = x;
12573 b = ad [ j ];
12574 for ( jj = j - 1; jj >= 0; jj-- ) {
12575 c = ad [ jj ];
12576 ad [ jj ] = b;
12577 b = Cadd(Cmul(x, b), c);
12578 }
12579 }
12580
12581 if ( polish ) {
12582 for ( j = 1; j <= m; j++ ) {
12583 laguer(a, m, & roots [ j ], EPSP, 1);
12584 }
12585 }
12586
12587 for ( j = 2; j <= m; j++ ) {
12588 x = roots [ j ];
12589 for ( i = j - 1; i >= 1; i-- ) {
12590 if ( roots [ i ].r <= x.r ) {
12591 break;
12592 }
12593
12594 roots [ i + 1 ] = roots [ i ];
12595 }
12596
12597 roots [ i + 1 ] = x;
12598 }
12599
12600 delete [] ad;
12601}
12602
12603
12604
12605void CemhydMatStatus :: pHpred()
12606{ //dangerous function - can lead to zero division etc.
12607 int j, syngen_change = 0, syn_old = 0, counter = 0;
12608 double concnaplus, conckplus;
12609 double concohminus = 0., A, B, C, conctest, concsulfate1;
12610 double volpore, grams_cement;
12611 double releasedna, releasedk, activitySO4, activityK, test_precip;
12612 double activityCa, activityOH, Istrength, Anow, Bnow, Inew;
12613 double conductivity = 0.0;
12614 fcomplex_cem coef [ 5 ], roots [ 5 ];
12615 float sumbest, sumtest, pozzreact, KspCH;
12616
12617 /* Update CH activity product based on current system temperature */
12618 /* Factors derived from fitting CH solubility vs. temperature */
12619 /* data in Taylor book (p. 117) */
12620 KspCH = KspCH25C * ( 1.534385 - 0.02057 * temp_cur );
12621
12622 if ( conccaplus > 1.0 ) {
12623 conccaplus = 0.0;
12624 }
12625
12626 /* Calculate volume of pore solution in the concrete in Liters */
12627 volpore = ( double ) count [ POROSITY ] + 0.38 * ( double ) count [ CSH ] + 0.20 * ( double ) count [ POZZCSH ] + 0.20 * count [ SLAGCSH ]; //relative amount, no need to rescale
12628 /* Convert from pixels (cubic micrometers) to liters (cubic decimeters) */
12629 volpore *= VOLFACTOR;
12630 volpore *= VOLFACTOR;
12631 volpore *= VOLFACTOR;
12632 /* Compute pore volume per gram of cement */
12633 grams_cement = cemmasswgyp * MASSFACTOR * MASSFACTOR * MASSFACTOR;
12634 /* Compute pore volume per gram of cement */
12635 volpore /= grams_cement;
12636 /* Compute grams of pozzolan which have reacted */
12637 pozzreact = ( ( float ) npr / 1.35 ) * MASSFACTOR * MASSFACTOR * MASSFACTOR * specgrav [ POZZ ];
12638
12639 /* Compute moles of released potassium and sodium per gram of cement*/
12640 if ( time_cur > 1.0 ) {
12641 releasedk = ( 2. * ( rspotassium + ( totpotassium - rspotassium ) * alpha_cur ) );
12642 releasedk /= MMK2O;
12643 releasedna = ( 2. * ( rssodium + ( totsodium - rssodium ) * alpha_cur ) );
12644 releasedna /= MMNa2O;
12645 } else {
12646 /* Proportion the early time release over the first hour */
12647 /* 90% immediately and the remaining 10% over the first hour */
12648 /* based on limited data from Davide Zampini (MBT) */
12649 releasedk = ( 2. * ( ( 0.9 + 0.1 * time_cur ) * ( rspotassium ) + ( totpotassium - rspotassium ) * alpha_cur ) );
12650 releasedk /= MMK2O;
12651 releasedna = ( 2. * ( ( 0.9 + 0.1 * time_cur ) * ( rssodium ) + ( totsodium - rssodium ) * alpha_cur ) );
12652 releasedna /= MMNa2O;
12653 }
12654
12655 /* Compute concentrations of K+ and Na+ in pore solution currently */
12656 /* Remember to decrease K+ by KperSyn*moles of syngenite precipitated */
12657 /* Units must be in moles/gram for both */
12658 conckplus = ( ( releasedk - moles_syn_precip * KperSyn ) / ( volpore + BK * alpha_cur + BprimeK * pozzreact ) );
12659 concnaplus = ( releasedna ) / ( volpore + BNa * alpha_cur + BprimeNa * pozzreact );
12660
12661 do { /* while Syngenite precipitating loop */
12662 /* Now compute the activities (estimated) of Ca++ and OH- */
12663 activityCa = activityOH = activitySO4 = activityK = 1.0;
12664 Inew = 0.0;
12665 if ( ( ( concnaplus + conckplus ) > 0.0 ) && ( soluble [ ETTR ] == 0 ) ) {
12666 /* Factor of 1000 to convert from M to mmol/L */
12667 Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12668 if ( Istrength < 1.0 ) {
12669 Istrength = 1.0;
12670 }
12671
12672 while ( ( fabs(Istrength - Inew) / Istrength ) > 0.10 ) {
12673 Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12674 if ( Istrength < 1.0 ) {
12675 Istrength = 1.0;
12676 }
12677
12678 Anow = activeA0 * 295. * sqrt(295.) / ( ( temp_cur + 273.15 ) * sqrt(temp_cur + 273.15) );
12679 Bnow = activeB0 * sqrt(295.) / ( sqrt(temp_cur + 273.15) );
12680 /* Equations from papers of Marchand et al. */
12681 activityCa = ( -Anow * zCa * zCa * sqrt(Istrength) ) / ( 1. + aCa * Bnow * sqrt(Istrength) );
12682 activityCa += ( 0.2 - 0.0000417 * Istrength ) * Anow * zCa * zCa * Istrength / sqrt(1000.);
12683 activityCa = exp(activityCa);
12684 activityOH = ( -Anow * zOH * zOH * sqrt(Istrength) ) / ( 1. + aOH * Bnow * sqrt(Istrength) );
12685 activityOH += ( 0.2 - 0.0000417 * Istrength ) * Anow * zOH * zOH * Istrength / sqrt(1000.);
12686 activityOH = exp(activityOH);
12687 activityK = ( -Anow * zK * zK * sqrt(Istrength) ) / ( 1. + aK * Bnow * sqrt(Istrength) );
12688 activityK += ( 0.2 - 0.0000417 * Istrength ) * Anow * zK * zK * Istrength / sqrt(1000.);
12689 activityK = exp(activityK);
12690 activitySO4 = ( -Anow * zSO4 * zSO4 * sqrt(Istrength) ) / ( 1. + aSO4 * Bnow * sqrt(Istrength) );
12691 activitySO4 += ( 0.2 - 0.0000417 * Istrength ) * Anow * zSO4 * zSO4 * Istrength / sqrt(1000.);
12692 activitySO4 = exp(activitySO4);
12693 /* Now try to find roots of fourth degree polynomial */
12694 /* to determine sulfate, OH-, and calcium ion concentrations */
12695 /* A=(-KspCH); */
12696 /* Now with activities */
12697 A = ( -KspCH / ( activityCa * activityOH * activityOH ) );
12698 B = conckplus + concnaplus;
12699 C = ( -2. * KspGypsum / ( activityCa * activitySO4 ) );
12700 concohminus = conckplus + concnaplus;
12701 coef [ 0 ] = ComplexCemhyd(C, 0.0);
12702 coef [ 1 ] = ComplexCemhyd( ( A + 2. * B * C ) / C, 0.0 );
12703 coef [ 2 ] = ComplexCemhyd(B * B / C + 4., 0.0);
12704 coef [ 3 ] = ComplexCemhyd(4. * B / C, 0.0);
12705 coef [ 4 ] = ComplexCemhyd(4. / C, 0.0);
12706 /* printf("coef 0 is (%f,%f)\n",coef[0].r,coef[0].i);
12707 * printf("coef 1 is (%f,%f)\n",coef[1].r,coef[1].i);
12708 * printf("coef 2 is (%f,%f)\n",coef[2].r,coef[2].i);
12709 * printf("coef 3 is (%f,%f)\n",coef[3].r,coef[3].i);
12710 * printf("coef 4 is (%f,%f)\n",coef[4].r,coef[4].i); */
12711 roots [ 1 ] = ComplexCemhyd(0.0, 0.0);
12712 roots [ 2 ] = ComplexCemhyd(0.0, 0.0);
12713 roots [ 3 ] = ComplexCemhyd(0.0, 0.0);
12714 roots [ 4 ] = ComplexCemhyd(0.0, 0.0);
12715 zroots(coef, 4, roots, 1);
12716 sumbest = 100;
12717 /* Find the best real root for electoneutrality */
12718 for ( j = 1; j <= 4; j++ ) {
12719 //printf("pH root %d is (%f,%f)\n",j,roots[j].r,roots[j].i);
12720 fflush(stdout);
12721 if ( ( ( roots [ j ].i ) == 0.0 ) && ( ( roots [ j ].r ) > 0.0 ) ) {
12722 conctest = sqrt( KspCH / ( roots [ j ].r * activityCa * activityOH * activityOH ) );
12723 concsulfate1 = KspGypsum / ( roots [ j ].r * activityCa * activitySO4 );
12724 sumtest = concnaplus + conckplus + 2. * roots [ j ].r - conctest - 2. * concsulfate1;
12725 if ( fabs(sumtest) < sumbest ) {
12726 sumbest = fabs(sumtest);
12727 concohminus = conctest;
12728 conccaplus = roots [ j ].r;
12729 concsulfate = concsulfate1;
12730 }
12731 }
12732 }
12733
12734 /* Update ionic strength */
12735 Inew = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12736 }
12737
12738 /* end of while loop for Istrength-Inew */
12739 } else {
12740 /* Factor of 1000 to convert from M to mmol/L */
12741 Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12742 if ( Istrength < 1.0 ) {
12743 Istrength = 1.0;
12744 }
12745
12746 while ( ( fabs(Istrength - Inew) / Istrength ) > 0.10 && counter < 4 ) {
12747 //add counter to limit to 3 iterations, normally it suffices but when high wcr it hangs - smilauer@cml.fsv.cvut.cz
12748 Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12749 Anow = activeA0 * 295. * sqrt(295.) / ( ( temp_cur + 273.15 ) * sqrt(temp_cur + 273.15) );
12750 Bnow = activeB0 * sqrt(295.) / ( sqrt(temp_cur + 273.15) );
12751 /* Equations from papers of Marchand et al. */
12752 activityCa = ( -Anow * zCa * zCa * sqrt(Istrength) ) / ( 1. + aCa * Bnow * sqrt(Istrength) );
12753 activityCa += ( 0.2 - 0.0000417 * Istrength ) * Anow * zCa * zCa * Istrength / sqrt(1000.);
12754 activityCa = exp(activityCa);
12755 activityOH = ( -Anow * zOH * zOH * sqrt(Istrength) ) / ( 1. + aOH * Bnow * sqrt(Istrength) );
12756 activityOH += ( 0.2 - 0.0000417 * Istrength ) * Anow * zOH * zOH * Istrength / sqrt(1000.);
12757 activityOH = exp(activityOH);
12758 activityK = ( -Anow * zK * zK * sqrt(Istrength) ) / ( 1. + aK * Bnow * sqrt(Istrength) );
12759 activityK += ( 0.2 - 0.0000417 * Istrength ) * Anow * zK * zK * Istrength / sqrt(1000.);
12760 activityK = exp(activityK);
12761 /* Calculate pH assuming simply that OH- balances sum of Na+ and K+ */
12762 concohminus = conckplus + concnaplus;
12763 if ( ( conccaplus ) > ( 0.1 * ( concohminus ) ) ) {
12764 concohminus += ( 2. * conccaplus );
12765 }
12766
12767 conccaplus = ( KspCH / ( activityCa * activityOH * activityOH * concohminus * concohminus ) );
12768 concsulfate = 0.0;
12769 /* Update ionic strength */
12770 Inew = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12771 counter++;
12772 }
12773
12774 /* end of while loop for Istrength-Inew */
12775 }
12776
12777 /* Check for syngenite precipitation */
12778 syngen_change = 0;
12779 if ( syn_old != 2 ) {
12780 test_precip = conckplus * conckplus * activityK * activityK;
12781 test_precip *= conccaplus * activityCa;
12782 test_precip *= concsulfate * concsulfate * activitySO4 * activitySO4;
12783 if ( test_precip > KspSyngenite ) {
12784#ifdef PRINTF
12785 printf("Syngenite precipitating at cycle %d\n", icyc);
12786#endif
12787 syngen_change = syn_old = 1;
12788 /* Units of moles_syn_precip are moles per gram of cement */
12789 if ( conckplus > 0.002 ) {
12790 conckplus -= 0.001;
12791 moles_syn_precip += 0.001 * volpore / KperSyn;
12792 } else if ( conckplus > 0.0002 ) {
12793 conckplus -= 0.0001;
12794 moles_syn_precip += 0.0001 * volpore / KperSyn;
12795 } else {
12796 moles_syn_precip += conckplus * volpore / KperSyn;
12797 conckplus = 0.0;
12798 }
12799 }
12800
12801 /* Check for syngenite dissolution */
12802 /* How to control dissolution rates??? */
12803 /* Have 0.001*KperSyn increase in conckplus each cycle */
12804 /* Only one dissolution per cycle --- purpose of syn_old */
12805 /* and no dissolution if some precipitation in that cycle */
12806 if ( ( syn_old == 0 ) && ( moles_syn_precip > 0.0 ) ) {
12807 syngen_change = syn_old = 2;
12808 /* conckplus+=(moles_syn_precip/10.0)/volpore; */
12809 if ( ( moles_syn_precip / volpore ) > 0.001 ) {
12810 conckplus += 0.001 * KperSyn;
12811 moles_syn_precip -= ( 0.001 * volpore );
12812 } else {
12813 conckplus += ( moles_syn_precip * KperSyn / volpore );
12814 moles_syn_precip = 0.0;
12815 }
12816 }
12817 }
12818 } while ( syngen_change != 0 );
12819
12820 if ( concohminus < ( 0.0000001 ) ) {
12821 concohminus = 0.0000001;
12822 conccaplus = ( KspCH / ( activityCa * activityOH * activityOH * concohminus * concohminus ) );
12823 }
12824
12825 pH_cur = 14.0 + log10(concohminus * activityOH);
12826 /* Calculation of solution conductivity (Snyder and Feng basis) */
12827 /* First convert ionic strength back to M units */
12828 Istrength /= 1000.;
12829 conductivity += zCa * conccaplus * ( lambdaCa_0 / ( 1. + GCa * sqrt(Istrength) ) );
12830 conductivity += zOH * concohminus * ( lambdaOH_0 / ( 1. + GOH * sqrt(Istrength) ) );
12831 conductivity += zNa * concnaplus * ( lambdaNa_0 / ( 1. + GNa * sqrt(Istrength) ) );
12832 conductivity += zK * conckplus * ( lambdaK_0 / ( 1. + GK * sqrt(Istrength) ) );
12833 conductivity += zSO4 * concsulfate * ( lambdaSO4_0 / ( 1. + GSO4 * sqrt(Istrength) ) );
12834 conductivity *= cm2perL2m;
12835
12836 /* Output results to logging file */
12837#ifdef OUTFILES
12838 fprintf(pHfile, "%d %.4f %f %.4f %f %f %f %f %f %.4f %.4f %.4f %.4f %f\n", cyccnt - 1, time_cur, alpha_cur, pH_cur, conductivity, concnaplus, conckplus, conccaplus, concsulfate, activityCa, activityOH, activitySO4, activityK, moles_syn_precip);
12839 fflush(pHfile);
12840#endif
12841}
12842
12843
12844int CemhydMatStatus :: IsSolidPhase(int phase)
12845{
12846 if ( ( phase >= C3S && phase <= ABSGYP ) || ( phase == HDCSH ) ) {
12847 return 1;
12848 } else {
12849 return 0;
12850 }
12851}
12852
12853void CemhydMatStatus :: burn_phases(int d1, int d2, int d3)
12854{
12855 long int icur, inew, ncur, nnew;
12856 int i, j, k, cnt_perc, cnt_tot, kh;
12857 int *nmatx, *nmaty, *nmatz;
12858 int xl, xh, j1, k1, px, py, pz, qx, qy, qz;
12859 int xcn, ycn, zcn, x1, y1, z1, igood;
12860 int *nnewx, *nnewy, *nnewz;
12861 int jnew;
12862 int phase_temp [ 51 ];
12863 char ***newmat;
12864
12865
12866 alloc_char_3D(newmat, SYSIZE);
12867 nmatx = new int [ SIZESET ];
12868 nmaty = new int [ SIZESET ];
12869 nmatz = new int [ SIZESET ];
12870 nnewx = new int [ SIZESET ];
12871 nnewy = new int [ SIZESET ];
12872 nnewz = new int [ SIZESET ];
12873
12874 last = NULL;
12875
12876 /* counters for number of pixels of phase accessible from surface #1 */
12877 /* and number which are part of a percolated pathway to surface #2 */
12878 /* create copy of original microstructure to newmat[][][]*/
12879 /* array mic_CSH[][][] will not be changed through this routine */
12880 /* phase_temp[] and phase[] are for phases storage in percolated pathway */
12881 // ntop=0;
12882 // nthrough=0;
12883 for ( k = 0; k < SYSIZE; k++ ) {
12884 for ( j = 0; j < SYSIZE; j++ ) {
12885 for ( i = 0; i < SYSIZE; i++ ) {
12886 newmat [ i ] [ j ] [ k ] = mic_CSH [ i ] [ j ] [ k ];
12887 //assign 0 or EMPTYP to ArrPerc[][][]
12888 if ( mic_CSH [ i ] [ j ] [ k ] == EMPTYP ) {
12889 ArrPerc [ i ] [ j ] [ k ] = EMPTYP;
12890 } else {
12891 ArrPerc [ i ] [ j ] [ k ] = 0;
12892 }
12893 }
12894 }
12895 }
12896
12897 for ( k = 0; k < 51; k++ ) {
12898 phase [ k ] = 0;
12899 }
12900
12901 /* percolation is assessed from top to bottom only */
12902 /* in transformed coordinates */
12903 /* and burning algorithm is periodic in other two directions */
12904 i = 0;
12905
12906 for ( k = 0; k < SYSIZE; k++ ) {
12907 for ( j = 0; j < SYSIZE; j++ ) {
12908 igood = 0;
12909 ncur = 0;
12910 for ( kh = 0; kh < 51; kh++ ) {
12911 phase_temp [ kh ] = 0;
12912 }
12913
12914
12915 //delete all array in case of next cycle
12916 while ( last != NULL ) { //go through all voxel coordinates
12917 current = last;
12918 last = last->prev;
12919 /*deallocate memory*/
12920 delete current;
12921 }
12922
12923 /* Transform coordinates */
12924 px = cx(i, j, k, d1, d2, d3);
12925 py = cy(i, j, k, d1, d2, d3);
12926 pz = cz(i, j, k, d1, d2, d3);
12927 /* start from any solid phase */
12928 if ( IsSolidPhase(newmat [ px ] [ py ] [ pz ]) == 1 ) {
12929 /* Start a burn front */
12930 phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
12931
12932 //store in unnamed list
12933 WriteUnsortedList(px, py, pz);
12934 newmat [ px ] [ py ] [ pz ] = BURNT;
12935 ncur += 1;
12936
12937
12938
12939 /* burn front is stored in matrices nmat* */
12940 /* and nnew* */
12941 nmatx [ ncur ] = i;
12942 nmaty [ ncur ] = j;
12943 nmatz [ ncur ] = k;
12944 /* Burn as long as new (fuel) pixels are found */
12945 do {
12946 nnew = 0;
12947 for ( inew = 1; inew <= ncur; inew++ ) {
12948 xcn = nmatx [ inew ];
12949 ycn = nmaty [ inew ];
12950 zcn = nmatz [ inew ];
12951 /* Convert to directional coordinates */
12952 qx = cx(xcn, ycn, zcn, d1, d2, d3);
12953 qy = cy(xcn, ycn, zcn, d1, d2, d3);
12954 qz = cz(xcn, ycn, zcn, d1, d2, d3);
12955
12956 /* Check all six neighbors */
12957 for ( jnew = 1; jnew <= 6; jnew++ ) {
12958 x1 = xcn;
12959 y1 = ycn;
12960 z1 = zcn;
12961 if ( jnew == 1 ) {
12962 x1 -= 1;
12963 }
12964
12965 if ( jnew == 2 ) {
12966 x1 += 1;
12967 }
12968
12969 if ( jnew == 3 ) {
12970 y1 -= 1;
12971 }
12972
12973 if ( jnew == 4 ) {
12974 y1 += 1;
12975 }
12976
12977 if ( jnew == 5 ) {
12978 z1 -= 1;
12979 }
12980
12981 if ( jnew == 6 ) {
12982 z1 += 1;
12983 }
12984
12985 /* Periodic in y and */
12986 if ( y1 >= SYSIZE ) {
12987 y1 -= SYSIZE;
12988 } else if ( y1 < 0 ) {
12989 y1 += SYSIZE;
12990 }
12991
12992 /* Periodic in z direction */
12993 if ( z1 >= SYSIZE ) {
12994 z1 -= SYSIZE;
12995 } else if ( z1 < 0 ) {
12996 z1 += SYSIZE;
12997 }
12998
12999 /* Nonperiodic so be sure to remain in the 3-D box */
13000 if ( ( x1 >= 0 ) && ( x1 < SYSIZE ) ) {
13001 px = cx(x1, y1, z1, d1, d2, d3);
13002 py = cy(x1, y1, z1, d1, d2, d3);
13003 pz = cz(x1, y1, z1, d1, d2, d3);
13004 /* Conditions for propagation of burning */
13005 /* 1) new pixel is any solid except clinker phases */
13006
13007 if ( ( IsSolidPhase(newmat [ px ] [ py ] [ pz ]) == 1 ) &&
13008 ( newmat [ px ] [ py ] [ pz ] != C3S ) &&
13009 ( newmat [ px ] [ py ] [ pz ] != C2S ) &&
13010 ( newmat [ px ] [ py ] [ pz ] != C3A ) &&
13011 ( newmat [ px ] [ py ] [ pz ] != C4AF ) ) {
13012 /*
13013 * if((newmat[px][py][pz]==CSH)||(newmat[px][py][pz]==ETTRC4AF)||(newmat[px][py][pz]==ETTR)){
13014 */
13015 phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
13016 WriteUnsortedList(px, py, pz);
13017 newmat [ px ] [ py ] [ pz ] = BURNT;
13018 nnew += 1;
13019 if ( nnew >= SIZESET ) {
13020 printf("error in size of nnew %ld\n", nnew);
13021 }
13022
13023 nnewx [ nnew ] = x1;
13024 nnewy [ nnew ] = y1;
13025 nnewz [ nnew ] = z1;
13026 }
13027 /* 2) old pixel is solid except clinker and new pixel is one of cement clinker phases */
13028 else if ( ( ( IsSolidPhase(mic_CSH [ qx ] [ qy ] [ qz ]) == 1 ) &&
13029 ( mic_CSH [ qx ] [ qy ] [ qz ] != C3S ) &&
13030 ( mic_CSH [ qx ] [ qy ] [ qz ] != C2S ) &&
13031 ( mic_CSH [ qx ] [ qy ] [ qz ] != C3A ) &&
13032 ( mic_CSH [ qx ] [ qy ] [ qz ] != C4AF ) ) &&
13033 ( ( newmat [ px ] [ py ] [ pz ] == C3S ) ||
13034 ( newmat [ px ] [ py ] [ pz ] == C2S ) ||
13035 ( newmat [ px ] [ py ] [ pz ] == C3A ) ||
13036 ( newmat [ px ] [ py ] [ pz ] == C4AF ) ) ) {
13037 phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
13038 WriteUnsortedList(px, py, pz);
13039 newmat [ px ] [ py ] [ pz ] = BURNT;
13040 nnew += 1;
13041 if ( nnew >= SIZESET ) {
13042 printf("error in size of nnew %ld\n", nnew);
13043 }
13044
13045 nnewx [ nnew ] = x1;
13046 nnewy [ nnew ] = y1;
13047 nnewz [ nnew ] = z1;
13048 }
13049 /* 3) old and new pixels belong to one of cement clinker phases and */
13050 /* are contained in the same initial cement particle */
13051 else if ( ( micpart [ qx ] [ qy ] [ qz ] == micpart [ px ] [ py ] [ pz ] ) &&
13052 ( ( newmat [ px ] [ py ] [ pz ] == C3S ) ||
13053 ( newmat [ px ] [ py ] [ pz ] == C2S ) ||
13054 ( newmat [ px ] [ py ] [ pz ] == C3A ) ||
13055 ( newmat [ px ] [ py ] [ pz ] == C4AF ) ) &&
13056 ( ( mic_CSH [ qx ] [ qy ] [ qz ] == C3S ) ||
13057 ( mic_CSH [ qx ] [ qy ] [ qz ] == C2S ) ||
13058 ( mic_CSH [ qx ] [ qy ] [ qz ] == C3A ) ||
13059 ( mic_CSH [ qx ] [ qy ] [ qz ] == C4AF ) ) ) {
13060 // ntot+=1;
13061 phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
13062 WriteUnsortedList(px, py, pz);
13063 newmat [ px ] [ py ] [ pz ] = BURNT;
13064 nnew += 1;
13065 if ( nnew >= SIZESET ) {
13066 printf("error in size of nnew %ld\n", nnew);
13067 }
13068
13069 nnewx [ nnew ] = x1;
13070 nnewy [ nnew ] = y1;
13071 nnewz [ nnew ] = z1;
13072 }
13073 }
13074
13075 /* nonperiodic if delimiter */
13076 }
13077
13078 /* neighbors loop */
13079 }
13080
13081 /* propagators loop */
13082 if ( nnew > 0 ) {
13083 ncur = nnew;
13084 /* update the burn front matrices */
13085 for ( icur = 1; icur <= ncur; icur++ ) {
13086 nmatx [ icur ] = nnewx [ icur ];
13087 nmaty [ icur ] = nnewy [ icur ];
13088 nmatz [ icur ] = nnewz [ icur ];
13089 }
13090 }
13091 } while ( nnew > 0 );
13092
13093 // ntop+=ntot;
13094 xl = 0;
13095 xh = SYSIZE - 1;
13096 /* Check for percolated path through system */
13097 for ( j1 = 0; j1 < SYSIZE; j1++ ) {
13098 for ( k1 = 0; k1 < SYSIZE; k1++ ) {
13099 px = cx(xl, j1, k1, d1, d2, d3);
13100 py = cy(xl, j1, k1, d1, d2, d3);
13101 pz = cz(xl, j1, k1, d1, d2, d3);
13102 qx = cx(xh, j1, k1, d1, d2, d3);
13103 qy = cy(xh, j1, k1, d1, d2, d3);
13104 qz = cz(xh, j1, k1, d1, d2, d3);
13105 if ( ( newmat [ px ] [ py ] [ pz ] == BURNT ) && ( newmat [ qx ] [ qy ] [ qz ] == BURNT ) ) {
13106 igood = 2;
13107 }
13108
13109 if ( newmat [ px ] [ py ] [ pz ] == BURNT ) {
13110 newmat [ px ] [ py ] [ pz ] = BURNT + 1;
13111 }
13112
13113 if ( newmat [ qx ] [ qy ] [ qz ] == BURNT ) {
13114 newmat [ qx ] [ qy ] [ qz ] = BURNT + 1;
13115 }
13116 }
13117 }
13118
13119 if ( igood == 2 ) {
13120 // nthrough+=ntot;
13121
13122 while ( last != NULL ) { //go through all voxel coordinates
13123 ArrPerc [ last->x ] [ last->y ] [ last->z ] = mic_CSH [ last->x ] [ last->y ] [ last->z ];
13124 // printf("AAA%d %d %d\n", last->x, last->y, last->z);
13125 current = last;
13126 last = last->prev;
13127 /*deallocate memory*/
13128 delete current;
13129 }
13130
13131
13132 for ( kh = 0; kh < 51; kh++ ) {
13133 phase [ kh ] += phase_temp [ kh ];
13134 }
13135 }
13136 }
13137
13138 //if(IsSolidPhase(newmat [px] [py] [pz])==1)
13139 }
13140
13141 //loop j
13142 }
13143
13144 //loop k
13145
13146 //GenerateConnNumbers();//only for FEM analysis
13147
13148 //output only solid phases in percolation path
13149#ifdef IMAGEFILES
13151#endif
13152
13153 cnt_perc = 0;
13154 for ( kh = 0; kh < 51; kh++ ) {
13155 cnt_perc += phase [ kh ];
13156 }
13157
13158#ifdef OUTFILES
13159 fprintf(perc_phases, "%d %f %f %d ", cyccnt, time_cur, alpha_cur, cnt_perc);
13160#endif
13161 cnt_tot = 0;
13162 phase [ EMPTYP ] = count [ EMPTYP ];
13163
13164 /* calculate sum of all solid phases*/
13165 for ( kh = 1; kh <= HDCSH; kh++ ) {
13166 if ( ( kh >= DIFFCSH && kh <= EMPTYP ) || kh == HDCSH ) {
13167 continue;
13168 }
13169
13170 cnt_tot += count [ kh ];
13171 }
13172
13173#ifdef OUTFILES
13174 fprintf(perc_phases, "%d %f | ", cnt_tot, ( double ) cnt_perc / cnt_tot);
13175 for ( kh = 0; kh <= HDCSH; kh++ ) {
13176 if ( kh > ABSGYP && kh < EMPTYP ) {
13177 continue;
13178 }
13179
13180 //assign EMPTYP to percolated path (used in homogenization)
13181 phase [ EMPTYP ] = count [ EMPTYP ];
13182 fprintf(perc_phases, "%ld %ld ",
13183 phase [ kh ], kh == CSH ? ( count [ CSH ] - count [ HDCSH ] ) : count [ kh ]);
13184 }
13185
13186 fprintf(perc_phases, "\n");
13187 fflush(perc_phases);
13188#endif
13189
13190 dealloc_char_3D(newmat, SYSIZE);
13191 delete [] nmatx;
13192 delete [] nmaty;
13193 delete [] nmatz;
13194 delete [] nnewx;
13195 delete [] nnewy;
13196 delete [] nnewz;
13197}
13198
13199
13200/*Check whether two adjacent voxels by side are/aren't connected
13201 * i.e. if they are in the percolated pathway.
13202 * Return function will always terminate loops.
13203 * Return 0 if one of phases is not solid.
13204 * Return 1 if phases are solid and are disconnected.
13205 * Return 2 if phases are solid and connected.
13206 */
13207
13208int CemhydMatStatus :: IsConnected(int cx, int cy, int cz, int dx, int dy, int dz)
13209{
13210 int CentPhase, NeighPhase;
13211
13212 CentPhase = ArrPerc [ AdjCoord(cx) ] [ AdjCoord(cy) ] [ AdjCoord(cz) ];
13213 if ( IsSolidPhase(CentPhase) ) { //is non-zero
13214 NeighPhase = ArrPerc [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ];
13215
13216 //skip non-solid phases
13217 if ( IsSolidPhase(NeighPhase) ) { //is non-zero
13218 /* 1) old voxel is any solid, new voxel is any
13219 * solid except clinker phases */
13220 if ( ( NeighPhase != C3S ) &&
13221 NeighPhase != C2S &&
13222 NeighPhase != C3A &&
13223 NeighPhase != C4AF ) {
13224 return 2;
13225 }
13226 /*2) old voxel is solid except clinker and new voxel is one
13227 * of cement clinker phases */
13228 else if ( ( CentPhase != C3S &&
13229 CentPhase != C2S &&
13230 CentPhase != C3A &&
13231 CentPhase != C4AF ) &&
13232 ( NeighPhase == C3S ||
13233 NeighPhase == C2S ||
13234 NeighPhase == C3A ||
13235 NeighPhase == C4AF ) ) {
13236 return 2;
13237 }
13238 /* 3) old and new voxels belong to one of cement clinker phases and
13239 * are contained in the same initial cement particle
13240 * one-voxel particles have also non-zero ID number*/
13241 else if ( ( micpart [ AdjCoord(cx) ] [ AdjCoord(cy) ] [ AdjCoord(cz) ] ==
13242 micpart [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ] ) &&
13243 ( CentPhase == C3S ||
13244 CentPhase == C2S ||
13245 CentPhase == C3A ||
13246 CentPhase == C4AF ) &&
13247 ( NeighPhase == C3S ||
13248 NeighPhase == C2S ||
13249 NeighPhase == C3A ||
13250 NeighPhase == C4AF ) ) {
13251 return 2;
13252 } else {
13253 return 1;
13254 }
13255 }
13256
13257 //IsSolidPhase(NeighPhase)
13258 return 0;
13259 }
13260
13261 //IsSolidPhase(CentPhase)
13262 return 0;
13263}
13264
13265
13266
13267/*Routine to perform check of connected and disconnected phases
13268 * on percolated microstructure stored in ArrPerc[dx][dy][dz].
13269 * Can not be executed during percolation algorithm since whole microstructure
13270 * is unknown.
13271 * Each vertex has possible 8x multiple node.
13272 * Voxel coordinates are the closest to the vertex coordinates
13273 * in the positive octant.
13274 * Disconnected node is added to the array as the sum of vertexes
13275 * by the following scheme (Big Voxel):
13276 *
13277 * ---------4096
13278 * /. /|
13279 * / . 32|
13280 * / . 4 / 256
13281 * / . / 2 |
13282 ***|--16---512 |
13283 | .....|...2048
13284 | . 8 /
13285 | . 1 | 128
13286 ||||. | /
13287 * ----64---1024
13288 *
13289 * e.g. if number 1 is present, that means that solid voxel below is disconnected
13290 * number 1024 means that voxel in front, right and down is solid and disconnected
13291 *
13292 * z^
13293 |
13294 |
13295 * ----->y
13296 * /
13297 * /x
13298 * coordinates transformation is irrelevant, used x,y,z loop
13299 */
13300void CemhydMatStatus :: GenerateConnNumbers()
13301{
13302 int cx, cy, cz;
13303 int CentPhase;
13304
13305
13306 for ( cz = 0; cz < SYSIZE; cz++ ) {
13307 for ( cy = 0; cy < SYSIZE; cy++ ) {
13308 for ( cx = 0; cx < SYSIZE; cx++ ) {
13309 //set zero values
13310 ConnNumbers [ cx ] [ cy ] [ cz ] = 0;
13311
13312 //if voxel is any solid phase
13313 CentPhase = ArrPerc [ cx ] [ cy ] [ cz ];
13314 if ( IsSolidPhase(CentPhase) ) { //is non-zero value
13315 /*Each vertex has 7 surrouning neighbors, go through them
13316 * Return 0 if one of phases is not solid.
13317 * Return 1 if phases are solid and are disconnected.
13318 * Return 2 if phases are solid and connected.*/
13319
13320 //(1) x+1
13321 if ( IsConnected(cx, cy, cz, 1, 0, 0) == 1 ) {
13322 ConnNumbers [ cx ] [ cy ] [ cz ] += 1;
13323 }
13324
13325 //(2) y+1
13326 if ( IsConnected(cx, cy, cz, 0, 1, 0) == 1 ) {
13327 ConnNumbers [ cx ] [ cy ] [ cz ] += 2;
13328 }
13329
13330 //(4) z+1
13331 if ( IsConnected(cx, cy, cz, 0, 0, 1) == 1 ) {
13332 ConnNumbers [ cx ] [ cy ] [ cz ] += 4;
13333 }
13334
13335 /*(8) x+1, y+1, 2 possible ways of connection
13336 * voxel may not be connected to master (CentPhase), i.e.
13337 * not connected in first way && not connected in second way
13338 */
13339 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz) ]) ) {
13340 if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13341 IsConnected(cx + 1, cy, cz, 0, 1, 0) != 2 ) &&
13342 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13343 IsConnected(cx, cy + 1, cz, 1, 0, 0) != 2 ) ) {
13344 ConnNumbers [ cx ] [ cy ] [ cz ] += 8;
13345 }
13346 }
13347
13348 /*(16) x+1, z+1, 2 possible ways of connection
13349 * voxel may not be connected to master (CentPhase), i.e.
13350 * not connected in first way && not connected in second way
13351 */
13352 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy) ] [ AdjCoord(cz + 1) ]) ) {
13353 if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13354 IsConnected(cx + 1, cy, cz, 0, 0, 1) != 2 ) &&
13355 ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13356 IsConnected(cx, cy, cz + 1, 1, 0, 0) != 2 ) ) {
13357 ConnNumbers [ cx ] [ cy ] [ cz ] += 16;
13358 }
13359 }
13360
13361 /*(32) y+1, z+1, 2 possible ways of connection
13362 * voxel may not be connected to master (CentPhase), i.e.
13363 * not connected in first way && not connected in second way
13364 */
13365 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz + 1) ]) ) {
13366 if ( ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13367 IsConnected(cx, cy + 1, cz, 0, 0, 1) != 2 ) &&
13368 ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13369 IsConnected(cx, cy, cz + 1, 0, 1, 0) != 2 ) ) {
13370 ConnNumbers [ cx ] [ cy ] [ cz ] += 32;
13371 }
13372 }
13373
13374 /*(64) x+1, z-1, 2 possible ways of connection
13375 * AdjCoord MUST be present at z direction
13376 * voxel may not be connected to master (CentPhase), i.e.
13377 * not connected in first way && not connected in second way
13378 */
13379 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy) ] [ AdjCoord(cz - 1) ]) ) {
13380 if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13381 IsConnected(cx + 1, cy, cz, 0, 0, -1) != 2 ) &&
13382 ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13383 IsConnected(cx, cy, cz - 1, 1, 0, 0) != 2 ) ) {
13384 ConnNumbers [ cx ] [ cy ] [ cz ] += 64;
13385 }
13386 }
13387
13388 /*(128) y+1, z-1, 2 possible ways of connection
13389 * AdjCoord MUST be present at z direction
13390 * voxel may not be connected to master (CentPhase), i.e.
13391 * not connected in first way && not connected in second way
13392 */
13393 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz - 1) ]) ) {
13394 if ( ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13395 IsConnected(cx, cy + 1, cz, 0, 0, -1) != 2 ) &&
13396 ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13397 IsConnected(cx, cy, cz - 1, 0, 1, 0) != 2 ) ) {
13398 ConnNumbers [ cx ] [ cy ] [ cz ] += 128;
13399 }
13400 }
13401
13402
13403 /*(256) x-1, y+1, 2 possible ways of connection
13404 * AdjCoord MUST be present at x direction
13405 * voxel may not be connected to master (CentPhase), i.e.
13406 * not connected in first way && not connected in second way
13407 */
13408 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx - 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz) ]) ) {
13409 if ( ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13410 IsConnected(cx, cy + 1, cz, -1, 0, 0) != 2 ) &&
13411 ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13412 IsConnected(cx - 1, cy, cz, 0, 1, 0) != 2 ) ) {
13413 ConnNumbers [ cx ] [ cy ] [ cz ] += 256;
13414 }
13415 }
13416
13417 /*(512) x+1, y+1, z+1, 6 possible ways of connection
13418 * voxel may not be connected to master (CentPhase), i.e.
13419 * not connected in first way && not connected in second way && not in
13420 * third way
13421 */
13422 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz + 1) ]) ) {
13423 // printf("%d %d %d\n", IsConnected(cx, cy, cz, 1, 0, 0), IsConnected(cx+1, cy, cz, 1, 0, 1), IsConnected(cx+1, cy, cz+1, 1, 1, 1));
13424
13425 if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13426 IsConnected(cx + 1, cy, cz, 0, 0, 1) != 2 ||
13427 IsConnected(cx + 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13428 ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13429 IsConnected(cx + 1, cy, cz, 0, 1, 0) != 2 ||
13430 IsConnected(cx + 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13431
13432 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13433 IsConnected(cx, cy + 1, cz, 1, 0, 0) != 2 ||
13434 IsConnected(cx + 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13435 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13436 IsConnected(cx, cy + 1, cz, 0, 0, 1) != 2 ||
13437 IsConnected(cx, cy + 1, cz + 1, 1, 0, 0) != 2 ) &&
13438
13439 ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13440 IsConnected(cx, cy, cz + 1, 1, 0, 0) != 2 ||
13441 IsConnected(cx + 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13442 ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13443 IsConnected(cx, cy, cz + 1, 0, 1, 0) != 2 ||
13444 IsConnected(cx, cy + 1, cz + 1, 1, 0, 0) != 2 ) ) {
13445 ConnNumbers [ cx ] [ cy ] [ cz ] += 512;
13446 }
13447 }
13448
13449
13450 /*(1024) x+1, y+1, z-1, 6 possible ways of connection
13451 * voxel may not be connected to master (CentPhase), i.e.
13452 * not connected in first way && not connected in second way && not in
13453 * third way
13454 */
13455 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz - 1) ]) ) {
13456 if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13457 IsConnected(cx + 1, cy, cz, 0, 0, -1) != 2 ||
13458 IsConnected(cx + 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13459 ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13460 IsConnected(cx + 1, cy, cz, 0, 1, 0) != 2 ||
13461 IsConnected(cx + 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13462
13463 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13464 IsConnected(cx, cy + 1, cz, 1, 0, 0) != 2 ||
13465 IsConnected(cx + 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13466 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13467 IsConnected(cx, cy + 1, cz, 0, 0, -1) != 2 ||
13468 IsConnected(cx, cy + 1, cz - 1, 1, 0, 0) != 2 ) &&
13469
13470 ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13471 IsConnected(cx, cy, cz - 1, 1, 0, 0) != 2 ||
13472 IsConnected(cx + 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13473 ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13474 IsConnected(cx, cy, cz - 1, 0, 1, 0) != 2 ||
13475 IsConnected(cx, cy + 1, cz - 1, 1, 0, 0) != 2 ) ) {
13476 ConnNumbers [ cx ] [ cy ] [ cz ] += 1024;
13477 }
13478 }
13479
13480
13481 /*(2048) x-1, y+1, z-1, 6 possible ways of connection
13482 * voxel may not be connected to master (CentPhase), i.e.
13483 * not connected in first way && not connected in second way && not in
13484 * third way
13485 */
13486 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx - 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz - 1) ]) ) {
13487 if ( ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13488 IsConnected(cx - 1, cy, cz, 0, 0, -1) != 2 ||
13489 IsConnected(cx - 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13490 ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13491 IsConnected(cx - 1, cy, cz, 0, 1, 0) != 2 ||
13492 IsConnected(cx - 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13493
13494 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13495 IsConnected(cx, cy + 1, cz, -1, 0, 0) != 2 ||
13496 IsConnected(cx - 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13497 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13498 IsConnected(cx, cy + 1, cz, 0, 0, -1) != 2 ||
13499 IsConnected(cx, cy + 1, cz - 1, -1, 0, 0) != 2 ) &&
13500
13501 ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13502 IsConnected(cx, cy, cz - 1, -1, 0, 0) != 2 ||
13503 IsConnected(cx - 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13504 ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13505 IsConnected(cx, cy, cz - 1, 0, 1, 0) != 2 ||
13506 IsConnected(cx, cy + 1, cz - 1, -1, 0, 0) != 2 ) ) {
13507 ConnNumbers [ cx ] [ cy ] [ cz ] += 2048;
13508 }
13509 }
13510
13511 /*(4096) x-1, y+1, z+1, 6 possible ways of connection
13512 * voxel may not be connected to master (CentPhase), i.e.
13513 * not connected in first way && not connected in second way && not in
13514 * third way
13515 */
13516 if ( IsSolidPhase(ArrPerc [ AdjCoord(cx - 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz + 1) ]) ) {
13517 if ( ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13518 IsConnected(cx - 1, cy, cz, 0, 0, 1) != 2 ||
13519 IsConnected(cx - 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13520 ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13521 IsConnected(cx - 1, cy, cz, 0, 1, 0) != 2 ||
13522 IsConnected(cx - 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13523
13524 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13525 IsConnected(cx, cy + 1, cz, -1, 0, 0) != 2 ||
13526 IsConnected(cx - 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13527 ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13528 IsConnected(cx, cy + 1, cz, 0, 0, 1) != 2 ||
13529 IsConnected(cx, cy + 1, cz + 1, -1, 0, 0) != 2 ) &&
13530
13531 ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13532 IsConnected(cx, cy, cz + 1, -1, 0, 0) != 2 ||
13533 IsConnected(cx - 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13534 ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13535 IsConnected(cx, cy, cz + 1, 0, 1, 0) != 2 ||
13536 IsConnected(cx, cy + 1, cz + 1, -1, 0, 0) != 2 ) ) {
13537 ConnNumbers [ cx ] [ cy ] [ cz ] += 4096;
13538 }
13539 }
13540 }
13541
13542 //IsSolidPhase(CentPhase)
13543 }
13544
13545 //loop cx
13546 }
13547
13548 //loop cy
13549 }
13550
13551 //loop cz
13552}
13553
13554void CemhydMatStatus :: outputImageFilePerc()
13555{
13556 FILE *perc_img;
13557 char extension [ 10 ];
13558 //char outputname[80];
13559 char *prefix;
13560 prefix = ( char * ) malloc(80);
13561
13562 //mkdir("perc", 0777);//make directory (every time)
13563 //system("mk perc");
13564 //system("mkdir perc 2> /dev/null");
13565 fprintf(infoperc, "%d %.4f %.3f\n", icyc, alpha_cur, time_cur);
13566 fflush(infoperc);
13567 sprintf(extension, "%04d", icyc);
13568 strcpy(prefix, "perc/out5."); //see line with mkdir in order to be the same
13569 strcat(prefix, extension);
13570 strcat(prefix, ".p.img");
13571#ifdef PRINTF
13572 printf("Name of percolated output file is %s\n", prefix);
13573#endif
13574
13575
13576 if ( ( perc_img = fopen(prefix, "w") ) == NULL ) {
13577 printf("\nFile %s can not be opened\n", prefix);
13578 free(prefix);
13579 return;
13580 }
13581
13582 for ( int dz = 0; dz < SYSIZE; dz++ ) {
13583 for ( int dy = 0; dy < SYSIZE; dy++ ) {
13584 for ( int dx = 0; dx < SYSIZE; dx++ ) {
13585 //fprintf(perc_img, "%d %d\n", ArrPerc[dx][dy][dz], ConnNumbers[dx][dy][dz]);
13586 fprintf(perc_img, "%d\n", ArrPerc [ dx ] [ dy ] [ dz ]);
13587 }
13588 }
13589 }
13590
13591 fclose(perc_img);
13592#ifdef PRINTF
13593 printf("Percolated file %s wrote\n", prefix);
13594#endif
13595 free(prefix);
13596}
13597
13598
13599
13600void CemhydMatStatus :: WriteUnsortedList(int px, int py, int pz)
13601{
13602 current = new percolatedpath;
13603 if ( last != NULL ) {
13604 last->next = current;
13605 } else {
13606 current->prev = NULL;
13607 }
13608
13609 current->x = px;
13610 current->y = py;
13611 current->z = pz;
13612 current->prev = last;
13613 last = current;
13614}
13615
13616
13617
13618inline int CemhydMatStatus :: AdjCoord(int coord)
13619{
13620 if ( coord < 0 ) {
13621 coord += SYSIZE;
13622 }
13623
13624 if ( coord >= SYSIZE ) {
13625 coord -= SYSIZE;
13626 }
13627
13628 return coord;
13629}
13630
13631
13632int CemhydMatStatus :: NumSol(int cx, int cy, int cz)
13633{
13634 int cnt = 0;
13635 int *p_arr;
13636
13637 /*check if box is eligible for CSH transformation*/
13638 for ( int dx = -BoxSize; dx <= BoxSize; dx++ ) {
13639 for ( int dy = -BoxSize; dy <= BoxSize; dy++ ) {
13640 for ( int dz = -BoxSize; dz <= BoxSize; dz++ ) {
13641 if ( mic_CSH [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ] != POROSITY && mic_CSH [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ] != EMPTYP ) {
13642 cnt++;
13643 }
13644 }
13645 }
13646 }
13647
13648 /*update count*/
13649 CSH_vicinity [ cnt ]++;
13650
13651
13652 /*if enough phases found, change all CSH in the box to HDCSH*/
13653 if ( cnt >= SolidLimit ) {
13654 cnt = 0;
13655
13656 for ( int dx = -BoxSize; dx <= BoxSize; dx++ ) {
13657 for ( int dy = -BoxSize; dy <= BoxSize; dy++ ) {
13658 for ( int dz = -BoxSize; dz <= BoxSize; dz++ ) {
13659 p_arr = & mic_CSH [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ];
13660 //printf("%d at %d %d %d \n", *p_arr, dx, dy, dz);
13661 if ( * p_arr == CSH ) {
13662 * p_arr = HDCSH;
13663 cnt++;
13664 // printf("ph %d\n", mic_CSH[AdjCoord(cx+dx)][AdjCoord(cy+dy)][AdjCoord(cz+dz)]);
13665 }
13666 }
13667 }
13668 }
13669 } else {
13670 cnt = 0;
13671 }
13672
13673 return cnt;
13674}
13675
13676/*use pointer to array as argument*/
13677/*CSH_vicinity[(2*BoxSize+1)*(2*BoxSize+1)*(2*BoxSize+1)]*/
13678
13679void CemhydMatStatus :: CSHbox(unsigned int *CSH_vicinity)
13680{
13681 int TotPhase = 0;
13682 int cx, cy, cz;
13683
13684 for ( int i = 0; i <= ( ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) ); i++ ) {
13685 CSH_vicinity [ i ] = 0;
13686 }
13687
13688 /*make copy of microstructure*/
13689 for ( cx = 0; cx < SYSIZE; cx++ ) {
13690 for ( cy = 0; cy < SYSIZE; cy++ ) {
13691 for ( cz = 0; cz < SYSIZE; cz++ ) {
13692 mic_CSH [ cx ] [ cy ] [ cz ] = mic [ cx ] [ cy ] [ cz ];
13693 }
13694 }
13695 }
13696
13697
13698 /*routine to scan microstructure and find eligible voxels*/
13699 for ( cx = 0; cx < SYSIZE; cx++ ) {
13700 for ( cy = 0; cy < SYSIZE; cy++ ) {
13701 for ( cz = 0; cz < SYSIZE; cz++ ) {
13702 /*CSH may be already in the CSHbox*/
13703 if ( mic_CSH [ cx ] [ cy ] [ cz ] == CSH || mic_CSH [ cx ] [ cy ] [ cz ] == HDCSH ) {
13704 TotPhase += NumSol(cx, cy, cz);
13705 }
13706 }
13707 }
13708 }
13709
13710 // printf("TotPhase:%d", TotPhase);
13711 count [ HDCSH ] = TotPhase;
13712}
13713
13714
13715
13716void CemhydMatStatus :: nrerror(const char *error_text)
13717{
13718 printf("\nNumerical Recipes run-time error...\n");
13719 printf("%s\n", error_text);
13720 printf("...now exiting to system...\n");
13721 exit(1);
13722}
13723
13724
13725float *CemhydMatStatus :: vector(int nl, int nh)
13726{
13727 float *v;
13728
13729 v = ( float * ) malloc( ( unsigned ) ( nh - nl + 1 ) * sizeof( float ) );
13730 if ( !v ) {
13731 nrerror("allocation failure in vector()");
13732 }
13733
13734 return v - nl;
13735}
13736
13737int *CemhydMatStatus :: ivector(int nl, int nh)
13738{
13739 int *v;
13740
13741 v = ( int * ) malloc( ( unsigned ) ( nh - nl + 1 ) * sizeof( int ) );
13742 if ( !v ) {
13743 nrerror("allocation failure in ivector()");
13744 }
13745
13746 return v - nl;
13747}
13748
13749double *CemhydMatStatus :: dvector(int nl, int nh)
13750{
13751 double *v;
13752
13753 v = ( double * ) malloc( ( unsigned ) ( nh - nl + 1 ) * sizeof( double ) );
13754 if ( !v ) {
13755 nrerror("allocation failure in dvector()");
13756 }
13757
13758 return v - nl;
13759}
13760
13761
13762
13763//float** CemhydMat::matrix(int nrl,int nrh,int ncl,int nch){
13764float **CemhydMatStatus :: matrix_cem(int nrl, int nrh, int ncl, int nch)
13765{
13766 int i;
13767 float **m;
13768
13769 m = ( float ** ) malloc( ( unsigned ) ( nrh - nrl + 1 ) * sizeof( float * ) );
13770 if ( !m ) {
13771 nrerror("allocation failure 1 in matrix_cem()");
13772 }
13773
13774 m -= nrl;
13775
13776 for ( i = nrl; i <= nrh; i++ ) {
13777 m [ i ] = ( float * ) malloc( ( unsigned ) ( nch - ncl + 1 ) * sizeof( float ) );
13778 if ( !m [ i ] ) {
13779 nrerror("allocation failure 2 in matrix_cem()");
13780 }
13781
13782 m [ i ] -= ncl;
13783 }
13784
13785 return m;
13786}
13787
13788double **CemhydMatStatus :: dmatrix(int nrl, int nrh, int ncl, int nch)
13789{
13790 int i;
13791 double **m;
13792
13793 m = ( double ** ) malloc( ( unsigned ) ( nrh - nrl + 1 ) * sizeof( double * ) );
13794 if ( !m ) {
13795 nrerror("allocation failure 1 in dmatrix()");
13796 }
13797
13798 m -= nrl;
13799
13800 for ( i = nrl; i <= nrh; i++ ) {
13801 m [ i ] = ( double * ) malloc( ( unsigned ) ( nch - ncl + 1 ) * sizeof( double ) );
13802 if ( !m [ i ] ) {
13803 nrerror("allocation failure 2 in dmatrix()");
13804 }
13805
13806 m [ i ] -= ncl;
13807 }
13808
13809 return m;
13810}
13811
13812int **CemhydMatStatus :: imatrix(int nrl, int nrh, int ncl, int nch)
13813{
13814 int i, **m;
13815
13816 m = ( int ** ) malloc( ( unsigned ) ( nrh - nrl + 1 ) * sizeof( int * ) );
13817 if ( !m ) {
13818 nrerror("allocation failure 1 in imatrix()");
13819 }
13820
13821 m -= nrl;
13822
13823 for ( i = nrl; i <= nrh; i++ ) {
13824 m [ i ] = ( int * ) malloc( ( unsigned ) ( nch - ncl + 1 ) * sizeof( int ) );
13825 if ( !m [ i ] ) {
13826 nrerror("allocation failure 2 in imatrix()");
13827 }
13828
13829 m [ i ] -= ncl;
13830 }
13831
13832 return m;
13833}
13834
13835
13836
13837float **CemhydMatStatus :: submatrix(float **a, int oldrl, int oldrh, int oldcl, int, int newrl, int newcl)
13838{
13839 int i, j;
13840 float **m;
13841
13842 m = ( float ** ) malloc( ( unsigned ) ( oldrh - oldrl + 1 ) * sizeof( float * ) );
13843 if ( !m ) {
13844 nrerror("allocation failure in submatrix()");
13845 }
13846
13847 m -= newrl;
13848
13849 for ( i = oldrl, j = newrl; i <= oldrh; i++, j++ ) {
13850 m [ j ] = a [ i ] + oldcl - newcl;
13851 }
13852
13853 return m;
13854}
13855
13856
13857void free_vector(float *v, int nl) { free( ( char * ) ( v + nl ) ); }
13858
13859void free_ivector(int *v, int nl) { free( ( char * ) ( v + nl ) ); }
13860
13861void free_dvector(double *v, int nl) { free( ( char * ) ( v + nl ) ); }
13862
13863
13864void free_matrix(float **m, int nrl, int nrh, int ncl)
13865{
13866 int i;
13867
13868 for ( i = nrh; i >= nrl; i-- ) {
13869 free( ( char * ) ( m [ i ] + ncl ) );
13870 }
13871
13872 free( ( char * ) ( m + nrl ) );
13873}
13874
13875void free_dmatrix(double **m, int nrl, int nrh, int ncl)
13876{
13877 int i;
13878
13879 for ( i = nrh; i >= nrl; i-- ) {
13880 free( ( char * ) ( m [ i ] + ncl ) );
13881 }
13882
13883 free( ( char * ) ( m + nrl ) );
13884}
13885
13886void free_imatrix(int **m, int nrl, int nrh, int ncl)
13887{
13888 int i;
13889
13890 for ( i = nrh; i >= nrl; i-- ) {
13891 free( ( char * ) ( m [ i ] + ncl ) );
13892 }
13893
13894 free( ( char * ) ( m + nrl ) );
13895}
13896
13897void free_submatrix(float *b, int nrl)
13898{
13899 free( ( char * ) ( b + nrl ) );
13900}
13901
13902float **CemhydMatStatus :: convert_matrix(float *a, int nrl, int nrh, int ncl, int nch)
13903{
13904 int i, j, nrow, ncol;
13905 float **m;
13906
13907 nrow = nrh - nrl + 1;
13908 ncol = nch - ncl + 1;
13909 m = ( float ** ) malloc( ( unsigned ) ( nrow ) * sizeof( float * ) );
13910 if ( !m ) {
13911 nrerror("allocation failure in convert_matrix()");
13912 }
13913
13914 m -= nrl;
13915 for ( i = 0, j = nrl; i <= nrow - 1; i++, j++ ) {
13916 m [ j ] = a + ncol * i - ncl;
13917 }
13918
13919 return m;
13920}
13921
13922void free_convert_matrix(float **b, int nrl)
13923{
13924 free( ( char * ) ( b + nrl ) );
13925}
13926
13927fcomplex_cem CemhydMatStatus :: Cadd(fcomplex_cem a, fcomplex_cem b)
13928{
13929 fcomplex_cem c;
13930 c.r = a.r + b.r;
13931 c.i = a.i + b.i;
13932 return c;
13933}
13934
13935fcomplex_cem CemhydMatStatus :: Csub(fcomplex_cem a, fcomplex_cem b)
13936{
13937 fcomplex_cem c;
13938 c.r = a.r - b.r;
13939 c.i = a.i - b.i;
13940 return c;
13941}
13942
13943fcomplex_cem CemhydMatStatus :: Cmul(fcomplex_cem a, fcomplex_cem b)
13944{
13945 fcomplex_cem c;
13946 c.r = a.r * b.r - a.i * b.i;
13947 c.i = a.i * b.r + a.r * b.i;
13948 return c;
13949}
13950
13951fcomplex_cem CemhydMatStatus :: ComplexCemhyd(float re, float im)
13952{
13953 fcomplex_cem c;
13954 c.r = re;
13955 c.i = im;
13956 return c;
13957}
13958
13959fcomplex_cem CemhydMatStatus :: Conjg(fcomplex_cem z)
13960{
13961 fcomplex_cem c;
13962 c.r = z.r;
13963 c.i = -z.i;
13964 return c;
13965}
13966
13967fcomplex_cem CemhydMatStatus :: Cdiv(fcomplex_cem a, fcomplex_cem b)
13968{
13969 fcomplex_cem c;
13970 float r, den;
13971 if ( fabs(b.r) >= fabs(b.i) ) {
13972 r = b.i / b.r;
13973 den = b.r + r * b.i;
13974 c.r = ( a.r + r * a.i ) / den;
13975 c.i = ( a.i - r * a.r ) / den;
13976 } else {
13977 r = b.r / b.i;
13978 den = b.i + r * b.r;
13979 c.r = ( a.r * r + a.i ) / den;
13980 c.i = ( a.i * r - a.r ) / den;
13981 }
13982
13983 return c;
13984}
13985
13986float CemhydMatStatus :: Cabs(fcomplex_cem z)
13987{
13988 float x, y, ans, temp;
13989 x = fabs(z.r);
13990 y = fabs(z.i);
13991 if ( x == 0.0 ) {
13992 ans = y;
13993 } else if ( y == 0.0 ) {
13994 ans = x;
13995 } else if ( x > y ) {
13996 temp = y / x;
13997 ans = x * sqrt(1.0 + temp * temp);
13998 } else {
13999 temp = x / y;
14000 ans = y * sqrt(1.0 + temp * temp);
14001 }
14002
14003 return ans;
14004}
14005
14006fcomplex_cem CemhydMatStatus :: Csqrt(fcomplex_cem z)
14007{
14008 fcomplex_cem c;
14009 float x, y, w, r;
14010 if ( ( z.r == 0.0 ) && ( z.i == 0.0 ) ) {
14011 c.r = 0.0;
14012 c.i = 0.0;
14013 return c;
14014 } else {
14015 x = fabs(z.r);
14016 y = fabs(z.i);
14017 if ( x >= y ) {
14018 r = y / x;
14019 w = sqrt(x) * sqrt( 0.5 * ( 1.0 + sqrt(1.0 + r * r) ) );
14020 } else {
14021 r = x / y;
14022 w = sqrt(y) * sqrt( 0.5 * ( r + sqrt(1.0 + r * r) ) );
14023 }
14024
14025 if ( z.r >= 0.0 ) {
14026 c.r = w;
14027 c.i = z.i / ( 2.0 * w );
14028 } else {
14029 c.i = ( z.i >= 0 ) ? w : -w;
14030 c.r = z.i / ( 2.0 * c.i );
14031 }
14032
14033 return c;
14034 }
14035}
14036
14037fcomplex_cem CemhydMatStatus :: RCmul(float x, fcomplex_cem a)
14038{
14039 fcomplex_cem c;
14040 c.r = x * a.r;
14041 c.i = x * a.i;
14042 return c;
14043}
14044
14045
14046//public function to call the routine for HDCSH creation
14047void CemhydMatStatus :: CreateHDCSH()
14048{
14050}
14051
14052//public function to call the routine for solid percolation
14053void CemhydMatStatus :: PercolateForOutput()
14054{
14055 burn_phases(1, 0, 0);
14056}
14057
14058//public function to access w/c ratio
14059double CemhydMatStatus :: GiveWcr()
14060{
14061 return w_to_c;
14062}
14063
14064/*function read into the string
14065 * int rand_seed_num, double fineness, double dihydrate, double hemihydrate, double anhydrite, double C3S_mass, double C2S_mass, double C3A_mass, double C4AF_mass, double wcr, int satur_sealed
14066 */
14067
14068void CemhydMatStatus :: GetInputParams(char *my_string)
14069{
14070 sprintf(my_string, "%d", iseed);
14071}
14072
14073long CemhydMatStatus :: cx(int x, int y, int z, int a, int b, int c)
14074{
14075 return ( 1 - b - c ) * x + ( 1 - a - c ) * y + ( 1 - a - b ) * z;
14076}
14077
14078
14079long CemhydMatStatus :: cy(int x, int y, int z, int a, int b, int c)
14080{
14081 return ( 1 - a - b ) * x + ( 1 - b - c ) * y + ( 1 - a - c ) * z;
14082}
14083
14084long CemhydMatStatus :: cz(int x, int y, int z, int a, int b, int c)
14085{
14086 return ( 1 - a - c ) * x + ( 1 - a - b ) * y + ( 1 - b - c ) * z;
14087}
14088
14089//homogenization of plain cement paste without filler
14090void CemhydMatStatus :: AnalyticHomogenizationPaste(double &E, double &nu, int perc_unperc_flag)
14091{
14092 //flag 0 - percolated phases are is in phase[]
14093 //flag 1 - unpercolated phases are in count[]
14094 int index, x, i;
14095 double sum = 0.;
14096 FloatMatrix PhaseMatrix(32, 3), LevelI(2, 3);
14097 double E_CSH_hmg, nu_CSH_hmg;
14098 Homogenize CSH_level, Paste_level;
14099
14100
14101 //determine phase fractions
14102 //0-23, PhaseFrac[0] = none, [1]=POROSITY, [2]=C3S .. [31]=EMPTYP [32]=HDCSH
14103 for ( x = 0; x < 34; x++ ) {
14104 PhaseFrac [ x ] = 0.;
14105 }
14106
14107 for ( x = 0; x < 51; x++ ) {
14108 index = x;
14109 if ( x == HDCSH ) {
14110 index = 31;
14111 } else if ( x == EMPTYP ) { //EMPTYP
14112 index = 30;
14113 } else if ( x >= DIFFCSH ) { //all dissolved phases
14114 continue;
14115 }
14116
14117
14118 if ( perc_unperc_flag == 0 ) { //percolated
14119 PhaseFrac [ index + 1 ] += phase [ x ];
14120 } else { //unpercolated
14121 if ( x == CSH ) {
14122 PhaseFrac [ index + 1 ] += ( count [ CSH ] - count [ HDCSH ] );
14123 } else {
14124 PhaseFrac [ index + 1 ] += count [ x ];
14125 }
14126 }
14127 }
14128
14129 for ( x = 2; x < 34; x++ ) {
14130 PhaseFrac [ x ] /= SYSIZE_POW3;
14131 sum += PhaseFrac [ x ];
14132 }
14133
14134
14135 //water-filled porosity is what is missing
14136 PhaseFrac [ 1 ] = 1 - sum;
14137
14138 for ( x = 0; x < 34; x++ ) { //34
14139 //printf("Phase %d PhaseFrac %f\n", x, PhaseFrac[x]);
14140 //printf("Phase %d perc / unper %ld %ld\n", x, phase[x], count[x]);
14141 }
14142
14143 PhaseMatrix(0, 0) = PhaseFrac [ 1 ]; //POROSITY 0
14144 PhaseMatrix(0, 1) = 0.001;
14145 PhaseMatrix(0, 2) = 0.499924;
14146 PhaseMatrix(1, 0) = PhaseFrac [ 2 ]; //C3S 1
14147 PhaseMatrix(1, 1) = 135.0;
14148 PhaseMatrix(1, 2) = 0.300000;
14149 PhaseMatrix(2, 0) = PhaseFrac [ 3 ]; //C2S 2
14150 PhaseMatrix(2, 1) = 130.0;
14151 PhaseMatrix(2, 2) = 0.300000;
14152 PhaseMatrix(3, 0) = PhaseFrac [ 4 ]; //C3A 3
14153 PhaseMatrix(3, 1) = 145.0;
14154 PhaseMatrix(3, 2) = 0.300000;
14155 PhaseMatrix(4, 0) = PhaseFrac [ 5 ]; //C4AF 4
14156 PhaseMatrix(4, 1) = 125.0;
14157 PhaseMatrix(4, 2) = 0.300000;
14158 PhaseMatrix(5, 0) = PhaseFrac [ 6 ]; //GYPSUM 5
14159 PhaseMatrix(5, 1) = 30.00;
14160 PhaseMatrix(5, 2) = 0.300000;
14161 PhaseMatrix(6, 0) = PhaseFrac [ 7 ]; //HEMIHYD 6
14162 PhaseMatrix(6, 1) = 62.90;
14163 PhaseMatrix(6, 2) = 0.300000;
14164 PhaseMatrix(7, 0) = PhaseFrac [ 8 ]; //ANHYDRITE 7
14165 PhaseMatrix(7, 1) = 73.60;
14166 PhaseMatrix(7, 2) = 0.275000;
14167 PhaseMatrix(8, 0) = PhaseFrac [ 9 ]; //POZZ,SiO2 8
14168 PhaseMatrix(8, 1) = 72.80;
14169 PhaseMatrix(8, 2) = 0.167000;
14170 PhaseMatrix(9, 0) = PhaseFrac [ 10 ]; //INERT 9
14171 PhaseMatrix(9, 1) = 79.60;
14172 PhaseMatrix(9, 2) = 0.309900;
14173 PhaseMatrix(10, 0) = PhaseFrac [ 11 ]; //SLAG 10
14174 PhaseMatrix(10, 1) = 72.80;
14175 PhaseMatrix(10, 2) = 0.16700;
14176 PhaseMatrix(11, 0) = PhaseFrac [ 12 ]; //ASG 11
14177 PhaseMatrix(11, 1) = 72.80;
14178 PhaseMatrix(11, 2) = 0.16700;
14179 PhaseMatrix(12, 0) = PhaseFrac [ 13 ]; //CAS2 slag 12
14180 PhaseMatrix(12, 1) = 72.80;
14181 PhaseMatrix(12, 2) = 0.16700;
14182 PhaseMatrix(13, 0) = PhaseFrac [ 14 ]; //CH 13
14183 PhaseMatrix(13, 1) = 38.00;
14184 PhaseMatrix(13, 2) = 0.30500;
14185 PhaseMatrix(14, 0) = -10.; //CSH upsc. 14
14186 PhaseMatrix(14, 1) = -10.0;
14187 PhaseMatrix(14, 2) = -10.000;
14188 PhaseMatrix(15, 0) = PhaseFrac [ 16 ]; //C3AH6 15
14189 PhaseMatrix(15, 1) = 22.40;
14190 PhaseMatrix(15, 2) = 0.25000;
14191 PhaseMatrix(16, 0) = PhaseFrac [ 17 ]; //ETTR 16
14192 PhaseMatrix(16, 1) = 22.40;
14193 PhaseMatrix(16, 2) = 0.25000;
14194 PhaseMatrix(17, 0) = PhaseFrac [ 18 ]; //ETTRC4AF 17
14195 PhaseMatrix(17, 1) = 22.40;
14196 PhaseMatrix(17, 2) = 0.25000;
14197 PhaseMatrix(18, 0) = PhaseFrac [ 19 ]; //AFM 18
14198 PhaseMatrix(18, 1) = 42.30;
14199 PhaseMatrix(18, 2) = 0.32380;
14200 PhaseMatrix(19, 0) = PhaseFrac [ 20 ]; //FH3 19
14201 PhaseMatrix(19, 1) = 22.40;
14202 PhaseMatrix(19, 2) = 0.24590;
14203 PhaseMatrix(20, 0) = PhaseFrac [ 21 ]; //POZZCSH 20
14204 PhaseMatrix(20, 1) = 22.40;
14205 PhaseMatrix(20, 2) = 0.24590;
14206 PhaseMatrix(21, 0) = PhaseFrac [ 22 ]; //SLAGCSH 21
14207 PhaseMatrix(21, 1) = 22.40;
14208 PhaseMatrix(21, 2) = 0.24590;
14209 PhaseMatrix(22, 0) = PhaseFrac [ 23 ]; //CACL2 22
14210 PhaseMatrix(22, 1) = 42.30;
14211 PhaseMatrix(22, 2) = 0.32380;
14212 PhaseMatrix(23, 0) = PhaseFrac [ 24 ]; //FREIDEL 23
14213 PhaseMatrix(23, 1) = 22.40;
14214 PhaseMatrix(23, 2) = 0.24590;
14215 PhaseMatrix(24, 0) = PhaseFrac [ 25 ]; //STRAT 24
14216 PhaseMatrix(24, 1) = 22.40;
14217 PhaseMatrix(24, 2) = 0.25000;
14218 PhaseMatrix(25, 0) = PhaseFrac [ 26 ]; //GYPSUMS 25
14219 PhaseMatrix(25, 1) = 30.00;
14220 PhaseMatrix(25, 2) = 0.30000;
14221 PhaseMatrix(26, 0) = PhaseFrac [ 27 ]; //CaCO3 26
14222 PhaseMatrix(26, 1) = 60.00;
14223 PhaseMatrix(26, 2) = 0.30000;
14224 PhaseMatrix(27, 0) = PhaseFrac [ 28 ]; //AFMC 27
14225 PhaseMatrix(27, 1) = 42.30;
14226 PhaseMatrix(27, 2) = 0.32380;
14227 PhaseMatrix(28, 0) = PhaseFrac [ 29 ]; //INERTAGG 28
14228 PhaseMatrix(28, 1) = 79.60;
14229 PhaseMatrix(28, 2) = 0.30990;
14230 PhaseMatrix(29, 0) = PhaseFrac [ 30 ]; //ABSGYP 29
14231 PhaseMatrix(29, 1) = 30.00;
14232 PhaseMatrix(29, 2) = 0.30000;
14233 PhaseMatrix(30, 0) = PhaseFrac [ 31 ]; //EMPTYP 30
14234 PhaseMatrix(30, 1) = 0.001;
14235 PhaseMatrix(30, 2) = 0.00100;
14236
14237 //CSH level
14238 if ( PhaseFrac [ 15 ] == 0. && PhaseFrac [ 32 ] == 0. ) { //beginning of hydration
14239 LevelI(0, 0) = 1.;
14240 LevelI(1, 0) = 0.;
14241 } else {
14242 LevelI(0, 0) = PhaseFrac [ 15 ] / ( PhaseFrac [ 15 ] + PhaseFrac [ 32 ] ); //LDCSH
14243 LevelI(1, 0) = PhaseFrac [ 32 ] / ( PhaseFrac [ 15 ] + PhaseFrac [ 32 ] ); //HDCSH
14244 }
14245
14246 LevelI(0, 1) = 21.7; //21.7 LDCSH
14247 LevelI(0, 2) = 0.24;
14248
14249 LevelI(1, 1) = 29.4; //29.4 HDCSH
14250 LevelI(1, 2) = 0.24;
14251
14252 //constructor without parameters
14253 CSH_level.moriTanaka(LevelI, 0);
14254
14255 //fill actual values into PhaseMatrix
14256 for ( i = 0; i < 31; i++ ) {
14257 PhaseMatrix(i, 0) = PhaseFrac [ i + 1 ];
14258 }
14259
14260 //cement paste level
14261
14262 PhaseMatrix(14, 0) = PhaseFrac [ 15 ] + PhaseFrac [ 32 ];
14263 PhaseMatrix(14, 1) = CSH_level.E_hmg;
14264 PhaseMatrix(14, 2) = CSH_level.nu_hmg;
14265
14266 E_CSH_hmg = CSH_level.E_hmg; //E from CSH level
14267 nu_CSH_hmg = CSH_level.nu_hmg; //nu from CSH level
14268
14269 Paste_level.selfConsistent(PhaseMatrix);
14270
14271 E = Paste_level.E_hmg;
14272 nu = Paste_level.nu_hmg;
14274 ( void ) E_CSH_hmg;
14275 ( void ) nu_CSH_hmg;
14276}
14277
14278//use results from cement paste level and add SCM, inert filler, entrained air, ITZ, FA, CA
14279void CemhydMatStatus :: AnalyticHomogenizationConcrete(double E_paste_inp, double nu_paste_inp, double *E_paste, double *nu_paste, double *E_mortar, double *nu_mortar, double &E_concrete, double &nu_concrete)
14280{
14281 Homogenize Paste_level, Mortar_level, Concrete_level;
14282
14283 //CEMENT PASTE LEVEL - homogenize cement paste with SCM, inert filler, entrained and entrapped air using Mori-Tanaka with cement paste as reference via MT scheme
14285 FloatMatrix PhaseMatrix(4, 3), Mortar(4, 3), Concrete(4, 3);
14286
14287 PhaseMatrix(0, 0) = ( Vol_cement_clinker_gypsum + Vol_water ) / vol_tot_paste; //cement paste (reference medium)
14288 PhaseMatrix(0, 1) = E_paste_inp;
14289 PhaseMatrix(0, 2) = nu_paste_inp;
14290 PhaseMatrix(1, 0) = Vol_cement_SCM / vol_tot_paste; //SCM
14291 PhaseMatrix(1, 1) = Young_SCM;
14292 PhaseMatrix(1, 2) = Poisson_SCM;
14293 PhaseMatrix(2, 0) = Vol_inert_filler / vol_tot_paste; //inert filler
14294 PhaseMatrix(2, 1) = Young_inert;
14295 PhaseMatrix(2, 2) = Poisson_inert;
14296 PhaseMatrix(3, 0) = Vol_entrained_entrapped_air / vol_tot_paste; //entrained + entrapped air
14297 PhaseMatrix(3, 1) = 0.001;
14298 PhaseMatrix(3, 2) = 0.001;
14299
14300 Paste_level.moriTanaka(PhaseMatrix, 0);
14301 * E_paste = Paste_level.E_hmg;
14302 * nu_paste = Paste_level.nu_hmg;
14303
14304 //MORTAR LEVEL - homogenize cement paste with fine aggregates including ITZ via Herve-Zaoui scheme
14305 //ITZ covers all aggregates, therefore its fraction associated with mortar and concrete has to be determined
14306 //ITZ occupies additional space
14307 double n_FA, n_CA, vol_ITZ_FA, vol_ITZ_CA;
14308 n_FA = Vol_FA / ( 4. / 3. * M_PI * pow(0.01 * Grain_average_FA / 2., 3.) ); //amount of FA particles
14309 vol_ITZ_FA = n_FA * 4. / 3. * M_PI * ( pow(0.01 * Grain_average_FA / 2. + 0.00001 * ITZ_thickness, 3) - pow(0.01 * Grain_average_FA / 2., 3) ); //volume occupied by ITZ in FA [l]
14310 n_CA = Vol_CA / ( 4. / 3. * M_PI * pow(0.01 * Grain_average_CA / 2., 3) ); //amount of CA particles
14311 vol_ITZ_CA = n_CA * 4. / 3. * M_PI * ( pow(0.01 * Grain_average_CA / 2. + 0.00001 * ITZ_thickness, 3) - pow(0.01 * Grain_average_CA / 2., 3) ); //volume occupied by ITZ in CA [l]
14312 double vol_tot_mortar = vol_tot_paste + Vol_FA;
14313
14314 Mortar(0, 0) = Vol_FA / vol_tot_mortar; //Fine aggregates
14315 Mortar(0, 1) = Young_FA;
14316 Mortar(0, 2) = Poisson_FA;
14317 Mortar(1, 0) = vol_ITZ_FA / vol_tot_mortar; //ITZ
14318 Mortar(1, 1) = * E_paste * ITZ_Young_red;
14319 Mortar(1, 2) = * nu_paste;
14320 Mortar(2, 0) = ( vol_tot_paste - vol_ITZ_FA ) / vol_tot_mortar; //cement paste
14321 Mortar(2, 1) = * E_paste;
14322 Mortar(2, 2) = * nu_paste;
14323 Mortar(3, 0) = 0.; //vol. fraction must be zero - reference medium
14324 Mortar(3, 1) = 10.; //arbitrary value
14325 Mortar(3, 2) = 0.3; //arbitrary value
14326
14327 Mortar_level.herveZaoui(Mortar);
14328 * E_mortar = Mortar_level.E_hmg;
14329 * nu_mortar = Mortar_level.nu_hmg;
14330
14331 //CONCRETE LEVEL
14332 double vol_tot_concrete = vol_tot_mortar + Vol_CA;
14333
14334 Concrete(0, 0) = Vol_CA / vol_tot_concrete; //Coarse aggregates
14335 Concrete(0, 1) = Young_CA;
14336 Concrete(0, 2) = Poisson_CA;
14337 Concrete(1, 0) = vol_ITZ_CA / vol_tot_concrete; //ITZ
14338 Concrete(1, 1) = * E_paste * ITZ_Young_red;
14339 Concrete(1, 2) = * nu_paste;
14340 Concrete(2, 0) = ( vol_tot_mortar - vol_ITZ_CA ) / vol_tot_concrete; //mortar
14341 Concrete(2, 1) = * E_mortar;
14342 Concrete(2, 2) = * nu_mortar;
14343 Concrete(3, 0) = 0.; //vol. fraction must be zero - reference medium
14344 Concrete(3, 1) = 10.; //arbitrary value
14345 Concrete(3, 2) = 0.3; //arbitrary value
14346
14347 Concrete_level.herveZaoui(Concrete);
14348 E_concrete = Concrete_level.E_hmg;
14349 nu_concrete = Concrete_level.nu_hmg;
14350}
14351
14352//at least one cycle has to pass, volume fraction
14353void CemhydMatStatus :: GetInitClinkerPhases(double &c3s, double &c2s, double &c3a, double &c4af, double &gypsum, double &hemi, double &anh)
14354{
14355 double sum = c3sinit + c2sinit + c3ainit + c4afinit + ncsbar + heminit + anhinit;
14356
14357 if ( icyc > 1 ) {
14358 c3s = ( double ) c3sinit / sum;
14359 c2s = ( double ) c2sinit / sum;
14360 c3a = ( double ) c3ainit / sum;
14361 c4af = ( double ) c4afinit / sum;
14362 gypsum = ( double ) ncsbar / sum;
14363 hemi = ( double ) heminit / sum;
14364 anh = ( double ) anhinit / sum;
14365 }
14366}
14367
14368
14369#ifdef __TM_MODULE //transport module for OOFEM
14370void
14371CemhydMatStatus :: updateYourself(TimeStep *tStep)
14372{
14373 TransportMaterialStatus :: updateYourself(tStep);
14374 if(!tStep->isIcApply()){//not very efficient here due to averaging in each call
14375 CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
14376 cemhydmat->clearWeightTemperatureProductVolume(this->gp->giveElement());
14377 cemhydmat->storeWeightTemperatureProductVolume(this->gp->giveElement(), tStep);
14378 cemhydmat->averageTemperature();
14379 }
14380};
14381
14382double CemhydMatStatus :: giveAverageTemperature()
14383{
14384 CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
14385 CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( cemhydmat->giveStatus(gp) );
14386 double ret;
14387
14388 if ( !cemhydmat->eachGP ) {
14389 ret = cemhydmat->MasterCemhydMatStatus->averageTemperature;
14390 } else {
14391 ret = ms->giveField();
14392 }
14393
14394 return ret;
14395}
14396
14397
14398void
14399CemhydMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) const
14400{
14401 CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
14402 const auto ms = cemhydmat->MasterCemhydMatStatus ? cemhydmat->MasterCemhydMatStatus : this;
14403
14404 TransportMaterialStatus :: printOutputAt(file, tStep);
14405 fprintf(file, " status {");
14406 fprintf( file, "cyc %d time %e DoH %f conductivity %f capacity %f density %f", cemhydmat->giveCycleNumber(this->gp), 3600 * cemhydmat->giveTimeOfCycle(this->gp), cemhydmat->giveDoHActual(this->gp), cemhydmat->giveIsotropicConductivity(this->gp,tStep), cemhydmat->giveConcreteCapacity(this->gp, tStep), cemhydmat->giveConcreteDensity(this->gp, tStep) );
14407 if ( ms->Calculate_elastic_homogenization ) {
14408 fprintf(file, " EVirginPaste %f NuVirginPaste %f EConcrete %f NuConcrete %f", ms->last_values [ 2 ], ms->last_values [ 3 ], ms->last_values [ 4 ], ms->last_values [ 5 ]);
14409 }
14410
14411
14412 if ( !cemhydmat->eachGP ) {
14413 if ( cemhydmat->giveStatus(gp) == cemhydmat->MasterCemhydMatStatus ) {
14414 fprintf( file, " master material %d", cemhydmat->giveNumber() );
14415 } else {
14416 fprintf( file, " slave of material %d", cemhydmat->giveNumber() );
14417 }
14418 } else {
14419 fprintf( file, " independent microstructure %p from material %d", this, cemhydmat->giveNumber() );
14420 }
14421
14422 fprintf(file, "}\n");
14423}
14424#endif
14425
14426
14427#ifdef CEMPY
14428// constructors
14429CemhydMatStatus :: CemhydMatStatus()
14430{
14431 PartHeat = 0.;
14432 temp_cur = 0.;
14433 #ifdef PRINTF
14434 printf("Constructor of CemhydMatStatus called\n");
14435 fflush(stdout);
14436 #endif
14437}
14438
14439
14440void
14441CemhydMatStatus :: InitializePy(const char *inp)
14442{
14443 initializeMicrostructure();
14444 readInputFileAndInitialize(inp, ( bool ) 1);
14445}
14446
14447#endif //CEMPY
14448} //end of namespace oofem
14449
14450
14451
14452#ifdef CEMPY
14453 #include <boost/python.hpp>
14454BOOST_PYTHON_MODULE(cemhydmodule)
14455{
14456 //boost::python::class_< oofem::CemhydMatStatus >("cemhydmatstatus", init<std::string>() ) - does not work, why ?
14457 boost :: python :: class_< oofem :: CemhydMatStatus >("cemhydmatstatus") //use default class constructor instead
14458 .def("InitializePy", & oofem :: CemhydMatStatus :: InitializePy)
14459 .def("MoveCycles", & oofem :: CemhydMatStatus :: MoveCycles)
14460 ;
14461}
14462#endif
#define _IFT_CemhydMat_nowarnings
Definition cemhydmat.h:64
#define _IFT_CemhydMat_scaling
Definition cemhydmat.h:65
#define _IFT_CemhydMat_eachgp
Definition cemhydmat.h:63
#define _IFT_CemhydMat_capacitytype
Definition cemhydmat.h:61
#define _IFT_CemhydMat_densitytype
Definition cemhydmat.h:62
#define _IFT_CemhydMat_inputFileName
Definition cemhydmat.h:67
#define _IFT_CemhydMat_conductivitytype
Definition cemhydmat.h:60
#define _IFT_CemhydMat_reinforcementDegree
Definition cemhydmat.h:66
#define E(a, b)
#define REGISTER_Material(class)
void QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, int &val)
Definition cemhydmat.C:1127
int movech(int xcur, int ycur, int zcur, int finalstep, float nucprob)
double Vol_cement_clinker_gypsum
Definition cemhydmat.h:770
int extfreidel(int xpres, int ypres, int zpres)
Definition cemhydmat.C:9471
void dissolve(int cycle)
Definition cemhydmat.C:4869
long int volume[50]
Definition cemhydmat.h:552
unsigned int * CSH_vicinity
Definition cemhydmat.h:670
short int *** faces
Definition cemhydmat.h:669
int IsConnected(int cx, int cy, int cz, int dx, int dy, int dz)
int movefh3(int xcur, int ycur, int zcur, int finalstep, float nucprob)
CemhydMatStatus(GaussPoint *gp, CemhydMatStatus *CemStat, CemhydMat *cemhydmat, bool withMicrostructure)
Definition cemhydmat.C:453
int edgecnt(int xck, int yck, int zck, int ph1, int ph2, int ph3)
Definition cemhydmat.C:8303
void rand3d(int phasein, int phaseout, float xpt)
Definition cemhydmat.C:3361
void makeinert(long int ndesire)
Definition cemhydmat.C:4652
void zroots(fcomplex_cem a[], int m, fcomplex_cem roots[], int polish)
int IsSolidPhase(int phase)
int countem(int xp, int yp, int zp, int phin)
Definition cemhydmat.C:2848
long cy(int x, int y, int z, int a, int b, int c)
void laguer(fcomplex_cem a[], int m, fcomplex_cem *x, float eps, int polish)
void nrerror(const char *error_text)
int burn3d(int npix, int d1, int d2, int d3)
Definition cemhydmat.C:7599
int movecacl2(int xcur, int ycur, int zcur, int finalstep)
Definition cemhydmat.C:9918
void addrand(int randid, long int nneed)
Definition cemhydmat.C:6211
long int *** micpart
Definition cemhydmat.h:499
GaussPoint * gp
Stores GP of the CemhydMatStatus.
Definition cemhydmat.h:251
void hydrate(int fincyc, int stepmax, float chpar1, float chpar2, float hgpar1, float hgpar2, float fhpar1, float fhpar2, float gypar1, float gypar2)
long int *** cement
Definition cemhydmat.h:515
double GiveCycTime(void)
Definition cemhydmat.C:7587
double GivePower(double GiveTemp, double TargTime)
Definition cemhydmat.C:7367
int movec3a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
void alloc_int_3D(int ***(&mask), long SYSIZE)
Definition cemhydmat.C:1035
int chksph(int xin, int yin, int zin, int radd, int wflg, int phasein, int phase2)
Definition cemhydmat.C:1534
int movecaco3(int xcur, int ycur, int zcur, int finalstep)
fcomplex_cem Csub(fcomplex_cem a, fcomplex_cem b)
int loccsh(int xcur, int ycur, int zcur, int extent)
Definition cemhydmat.C:4464
fcomplex_cem Csqrt(fcomplex_cem z)
void drawfloc(int xin, int yin, int zin, int radd, int phasein, int phase2)
Definition cemhydmat.C:1896
int Calculate_elastic_homogenization
Flag to proceed percolation filtering and elastic homogenization.
Definition cemhydmat.h:247
fcomplex_cem ComplexCemhyd(float re, float im)
int movegyp(int xcur, int ycur, int zcur, int finalstep)
Definition cemhydmat.C:9633
double IPVolume
Volume associated to master IP of one CemhydMat.
Definition cemhydmat.h:210
int movec4a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
double giveAverageTemperature(void)
void QueryStringAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, char *chars)
Definition cemhydmat.C:1207
void WriteUnsortedList(int px, int py, int pz)
double ran1(int *idum)
Definition cemhydmat.C:1447
void extc3ah6(int xpres, int ypres, int zpres)
int surfpix(int xin, int yin, int zin)
Definition cemhydmat.C:2749
float rhcalc(int phin)
Definition cemhydmat.C:2817
double GiveDoHActual(void)
Return degree of hydration of the receiver.
Definition cemhydmat.C:7564
void setAverageTemperatureVolume(double temperature, double volume)
Auxiliary function for temperature averaging over GPs.
Definition cemhydmat.h:215
void outputImageFilePerc(void)
int gsphere(int numgen, long int *numeach, int *sizeeach, int *pheach)
Definition cemhydmat.C:1611
long cz(int x, int y, int z, int a, int b, int c)
void disrealnew(double GiveTemp, double TargTime, int flag)
Definition cemhydmat.C:7124
void alloc_shortint_3D(short int ***(&mic), long SYSIZE)
Definition cemhydmat.C:1065
float Cabs(fcomplex_cem z)
short int *** cshage
Definition cemhydmat.h:667
struct percolatedpath * current
Definition cemhydmat.h:755
fcomplex_cem Cdiv(fcomplex_cem a, fcomplex_cem b)
struct ants * tailant
Definition cemhydmat.h:733
void dealloc_shortint_3D(short int ***(&mic), long SYSIZE)
Definition cemhydmat.C:1080
double * last_values
Array for storing temporary values (elastic properties etc.).
Definition cemhydmat.h:245
int icyc
Cycle of celular automata.
Definition cemhydmat.h:243
void outputImageFileUnperc(char ***m)
Definition cemhydmat.C:6369
long int nsolid[1500]
Definition cemhydmat.h:555
void alloc_long_3D(long ***(&mic), long SYSIZE)
Definition cemhydmat.C:1005
int maketemp(int size)
Definition cemhydmat.C:2679
void PercolateForOutput(void)
double averageTemperature
Average temperature through integration points.
Definition cemhydmat.h:208
double init_material_time
Inital material time for growing problems.
Definition cemhydmat.h:212
double PartHeat
The last incremental heat returned from a GP.
Definition cemhydmat.h:239
int chckedge(int xck, int yck, int zck)
Definition cemhydmat.C:4317
void extfh3(int xpres, int ypres, int zpres)
Definition cemhydmat.C:8553
void extgyps(int xpres, int ypres, int zpres)
Definition cemhydmat.C:8821
void AnalyticHomogenizationPaste(double &E, double &nu, int perc_unperc_flag)
int procair(int nsearch)
Definition cemhydmat.C:2995
struct percolatedpath * last
Definition cemhydmat.h:755
void passone(int low, int high, int cycid, int cshexflag)
Definition cemhydmat.C:4366
int moveanh(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
Definition cemhydmat.C:8900
int movecas2(int xcur, int ycur, int zcur, int finalstep)
void extafm(int xpres, int ypres, int zpres)
int procsol(int nsearch)
Definition cemhydmat.C:2968
void dealloc_int_3D(int ***(&mask), long SYSIZE)
Definition cemhydmat.C:1050
void disrealnew_init(void)
Definition cemhydmat.C:6966
double Vol_entrained_entrapped_air
Definition cemhydmat.h:770
void extslagcsh(int xpres, int ypres, int zpres)
Definition cemhydmat.C:4776
double Concrete_thermal_conductivity
Definition cemhydmat.h:691
int movehem(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
Definition cemhydmat.C:9186
void dealloc_long_3D(long ***(&mic), long SYSIZE)
Definition cemhydmat.C:1020
void CSHbox(unsigned int *CSH_vicinity)
int extstrat(int xpres, int ypres, int zpres)
Definition cemhydmat.C:9552
int moveettr(int xcur, int ycur, int zcur, int finalstep)
fcomplex_cem Cmul(fcomplex_cem a, fcomplex_cem b)
int countbox(int boxsize, int qx, int qy, int qz)
Definition cemhydmat.C:4538
int movepix(int ntomove, int ph1, int ph2)
Definition cemhydmat.C:3020
long int surface[50]
Definition cemhydmat.h:552
long int *** cemreal
Definition cemhydmat.h:517
int moveone(int *xloc, int *yloc, int *zloc, int *act, int sumold)
Definition cemhydmat.C:8192
void sysinit(int ph1, int ph2)
Definition cemhydmat.C:2891
double MoveCycles(double GiveTemp, int cycles)
Definition cemhydmat.C:7455
void alloc_double_3D(double ***(&mic), long SYSIZE)
Definition cemhydmat.C:1095
long int volpart[47]
Definition cemhydmat.h:524
long int nair[1500]
Definition cemhydmat.h:555
struct ants * headant
Definition cemhydmat.h:733
void initializeMicrostructure(void)
Definition cemhydmat.C:558
int movecsh(int xcur, int ycur, int zcur, int finalstep, int cycorig)
Definition cemhydmat.C:8415
int chkfloc(int xin, int yin, int zin, int radd)
Definition cemhydmat.C:1954
void AnalyticHomogenizationConcrete(double E_paste_inp, double nu_paste_inp, double *E_paste, double *nu_paste, double *E_mortar, double *nu_mortar, double &E_concrete, double &nu_concrete)
struct cluster ** clust
Definition cemhydmat.h:530
void alloc_char_3D(char ***(&mic), long SYSIZE)
Definition cemhydmat.C:976
XMLDocument * xmlFile
Definition cemhydmat.h:463
void dealloc_double_3D(double ***(&mic), long SYSIZE)
Definition cemhydmat.C:1110
void dealloc_char_3D(char ***(&mic), long SYSIZE)
Definition cemhydmat.C:990
int readInputFileAndInitialize(const char *inp, bool generateMicrostructure)
Definition cemhydmat.C:1243
fcomplex_cem Cadd(fcomplex_cem a, fcomplex_cem b)
int AdjCoord(int coord)
void burn_phases(int d1, int d2, int d3)
fcomplex_cem RCmul(float x, fcomplex_cem a)
void extpozz(int xpres, int ypres, int zpres)
void sysscan(int ph1, int ph2)
Definition cemhydmat.C:2943
int NumSol(int cx, int cy, int cz)
int countboxc(int boxsize, int qx, int qy, int qz)
Definition cemhydmat.C:4594
int extettr(int xpres, int ypres, int zpres, int etype)
Definition cemhydmat.C:8634
long cx(int x, int y, int z, int a, int b, int c)
int moveas(int xcur, int ycur, int zcur, int finalstep)
FloatArray scaling
Array containing scaling factors for density, conductivity and capacity.
Definition cemhydmat.h:134
virtual int giveCycleNumber(GaussPoint *gp)
Returns cycle number at the closest cycle after the target time.
Definition cemhydmat.C:133
int conductivityType
Use different methods to evaluate material parameters.
Definition cemhydmat.h:130
virtual double giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) const
Returns concrete thermal capacity depending on chosen type.
Definition cemhydmat.C:197
virtual double giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) const
Returns concrete density depending on chosen type.
Definition cemhydmat.C:228
int eachGP
Assign a separate microstructure in each integration point.
Definition cemhydmat.h:138
virtual void storeWeightTemperatureProductVolume(Element *element, TimeStep *tStep)
Store temperatures multiplied with volume around GPs - need before temperature averaging.
Definition cemhydmat.C:383
virtual double giveTimeOfCycle(GaussPoint *gp)
Returns time of the CEMHYD3D at the first cycle after the target time.
Definition cemhydmat.C:143
std::string XMLfileName
XML input file name for CEMHYD3D.
Definition cemhydmat.h:140
double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const override
Returns concrete heat conductivity depending on chosen type.
Definition cemhydmat.C:166
virtual double giveDoHActual(GaussPoint *gp)
Returns DoH of the closest CEMHYD3D cycle after the target time.
Definition cemhydmat.C:155
virtual void clearWeightTemperatureProductVolume(Element *element)
Clear temperatures multiplied with volume around GPs - need before temperature averaging.
Definition cemhydmat.C:373
int reinforcementDegree
Degree of reinforcement, if defined, reinforcement effect for conductivity and capacity is accounted ...
Definition cemhydmat.h:136
virtual void averageTemperature()
Perform averaging on a master CemhydMatStatus.
Definition cemhydmat.C:397
IntArray nowarnings
Array containing warnings supression for density, conductivity, capacity, high temperature.
Definition cemhydmat.h:132
CemhydMatStatus * MasterCemhydMatStatus
Definition cemhydmat.h:146
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Definition element.C:1298
virtual double computeVolumeAround(GaussPoint *gp)
Definition element.h:530
int giveNumber() const
Definition femcmpnn.h:104
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double nu_hmg
Effective Poisson's ratio.
Definition homogenize.h:131
void herveZaoui(FloatMatrix &PhaseMatrix)
Definition homogenize.C:341
void selfConsistent(FloatMatrix &PhaseMatrix)
Definition homogenize.C:243
double E_hmg
Effective Young's modulus or the lower bound.
Definition homogenize.h:125
void moriTanaka(FloatMatrix &PhaseMatrix, int refRow)
Definition homogenize.C:174
int & at(std::size_t i)
Definition intarray.h:104
IsotropicHeatTransferMaterial(int n, Domain *d)
Definition isoheatmat.C:45
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
double castingTime
Definition material.h:115
double giveTargetTime()
Returns target time.
Definition timestep.h:164
bool isIcApply()
Definition timestep.C:154
double giveField() const
Return last field.
#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 IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define M_PI
Definition mathfem.h:52
void free_convert_matrix(float **b, int nrl)
void free_submatrix(float *b, int nrl)
void free_dvector(double *v, int nl)
void free_matrix(float **m, int nrl, int nrh, int ncl)
void free_dmatrix(double **m, int nrl, int nrh, int ncl)
void free_imatrix(int **m, int nrl, int nrh, int ncl)
void free_ivector(int *v, int nl)
double sum(const FloatArray &x)
struct oofem::FCOMPLEX fcomplex_cem
void free_vector(float *v, int nl)

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