OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
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 - 2013 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 "cemhydmat.h"
55 #include "homogenize.h"
56 #include "mathfem.h"
57 
58 #ifdef __TM_MODULE //OOFEM transport module
59  #include "classfactory.h"
60  #include "domain.h"
61  #include "floatmatrix.h"
62  #include "gausspoint.h"
63 #endif
64 
65 namespace oofem {
66 /* This software was developed at the National Institute of */
67 /* Standards and Technology by employees of the Federal */
68 /* Government in the course of their official duties. Pursuant */
69 /* to title 17 Section 105 of the United States Code this */
70 /* software is not subject to copyright protection and is in */
71 /* the public domain. CEMHYD3D is an experimental system. NIST */
72 /* assumes no responsibility whatsoever for its use by other */
73 /* parties, and makes no guarantees, expressed or implied, */
74 /* about its quality, reliability, or any other characteristic. */
75 /* We would appreciate acknowledgement if the software is used. */
76 /* This software can be redistributed and/or modified freely */
77 /* provided that any derivative works bear some notice that */
78 /* they are derived from it, and any modified versions bear */
79 /* some notice that they have been modified. */
80 /* Modified 3/97 to allow placement of pozzolanic, inert and fly ash particles */
81 /* Modified 9/98 to allow placement of various forms of gypsum */
82 /* Documented version produced 1/00 */
83 /* Modified by smilauer@cml.fsv.cvut.cz to include 1 voxel particles 16.6.2005
84  * Dynamical allocation of memory arrays (possible in input file)
85  */
86 
87 //#define OUTFILES //if defined, output files are generated
88 //#define IMAGEFILES //if defined, output percolated and unpercolated images in each cycle (directories perc/ and unperc/)
89 //#define PRINTF //if defined, printf results simultaneously on screen
90 
91 #ifdef __TM_MODULE //OOFEM transport module
92 
93 REGISTER_Material(CemhydMat);
94 
96 {
97  MasterCemhydMatStatus = NULL;
98 }
99 
101 { }
102 
103 //returns hydration power [W/m3 of concrete]
104 void
106 {
107  double averageTemperature;
108  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
109  val.resize(1);
110 
111  if ( eachGP || ms == MasterCemhydMatStatus ) {
112  averageTemperature = ms->giveAverageTemperature();
113  if ( mode == VM_Total || mode == VM_TotalIntrinsic ) {
114  //for nonlinear solver, return the last value even no time has elapsed
115  if ( tStep->giveTargetTime() != ms->LastCallTime ) {
116  val.at(1) = ms->GivePower( averageTemperature, tStep->giveTargetTime() );
117  } else {
118  val.at(1) = ms->PartHeat;
119  }
120  } else {
121  OOFEM_ERROR( "Undefined mode %s\n", __ValueModeTypeToString(mode) );
122  }
123  } else { //return released heat from the master
124  if ( mode == VM_Total || mode == VM_TotalIntrinsic ) {
126  } else {
127  OOFEM_ERROR( "Undefined mode %s\n", __ValueModeTypeToString(mode) );
128  }
129  }
130 
131  //val.at(1) = 1500;//constant source
132 }
133 
134 
136 {
137  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
138  if ( MasterCemhydMatStatus ) {
140  }
141 
142  return ms->GiveCycNum();
143 }
144 
146 {
147  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
148  if ( MasterCemhydMatStatus ) {
150  }
151 
152  return ms->GiveCycTime();
153 }
154 
155 
156 
158 {
159  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
160  if ( MasterCemhydMatStatus ) {
162  }
163 
164  return ms->GiveDoHActual();
165 }
166 
167 //standard units are [Wm-1K-1]
169 {
170  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
171  double conduct = 0.0;
172 
173  if ( MasterCemhydMatStatus ) {
175  }
176 
177  if ( conductivityType == 0 ) { //given from OOFEM input file
178  conduct = IsotropicHeatTransferMaterial :: give('k', gp, tStep);
179  } 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
180  conduct = IsotropicHeatTransferMaterial :: give('k', gp, tStep) * ( 1.33 - 0.33 * ms->GiveDoHActual() );
181  } else {
182  OOFEM_ERROR("Unknown conductivityType %d\n", conductivityType);
183  }
184 
185 
186  //Parallel Voigt model, 20 W/m/K for steel
187  conduct = conduct * ( 1. - this->reinforcementDegree ) + 20. * this->reinforcementDegree;
188 
189  if ( !this->nowarnings.at(2) && ( conduct < 0.3 || conduct > 5 ) ) {
190  OOFEM_WARNING("Weird concrete thermal conductivity %f W/m/K\n", conduct);
191  }
192 
193  conduct *= this->scaling.at(2);
194 
195  return conduct;
196 }
197 
198 //normally it returns J/kg/K of concrete
200 {
201  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
202  double capacityConcrete = 0.0;
203 
204  if ( MasterCemhydMatStatus ) {
206  }
207 
208  if ( capacityType == 0 ) { //given from OOFEM input file
209  capacityConcrete = IsotropicHeatTransferMaterial :: give('c', gp, tStep);
210  } else if ( capacityType == 1 ) { //compute from CEMHYD3D according to Bentz
211  capacityConcrete = ms->computeConcreteCapacityBentz();
212  } else if ( capacityType == 2 ) { //compute from CEMHYD3D directly
213  capacityConcrete = 1000 * ms->GiveCp();
214  } else {
215  OOFEM_ERROR("Unknown capacityType %d\n", capacityType);
216  }
217 
218  //Parallel Voigt model, 500 J/kg/K for steel
219  capacityConcrete = capacityConcrete * ( 1. - this->reinforcementDegree ) + 500. * this->reinforcementDegree;
220 
221  if ( !this->nowarnings.at(3) && ( capacityConcrete < 500 || capacityConcrete > 2000 ) ) {
222  OOFEM_WARNING("Weird concrete heat capacity %f J/kg/K\n", capacityConcrete);
223  }
224 
225  capacityConcrete *= this->scaling.at(3);
226 
227  return capacityConcrete;
228 }
229 
231 {
232  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
233  double concreteBulkDensity = 0.0;
234 
235  if ( MasterCemhydMatStatus ) {
237  }
238 
239  if ( densityType == 0 ) { //get from OOFEM input file
240  concreteBulkDensity = IsotropicHeatTransferMaterial :: give('d', gp, tStep);
241  } else if ( densityType == 1 ) { //get from XML input file
242  concreteBulkDensity = ms->GiveDensity();
243  } else {
244  OOFEM_ERROR("Unknown densityType %d\n", densityType);
245  }
246 
247  //Parallel Voigt model, 7850 kg/m3 for steel
248  concreteBulkDensity = concreteBulkDensity * ( 1. - this->reinforcementDegree ) + 7850. * this->reinforcementDegree;
249 
250  if ( !this->nowarnings.at(1) && ( concreteBulkDensity < 1000 || concreteBulkDensity > 4000 ) ) {
251  OOFEM_WARNING("Weird concrete density %f kg/m3\n", concreteBulkDensity);
252  }
253 
254  concreteBulkDensity *= this->scaling.at(1);
255 
256  return concreteBulkDensity;
257 }
258 
259 double
261 {
262  if ( mode == Capacity ) {
263  return ( giveConcreteCapacity(gp, tStep) * giveConcreteDensity(gp, tStep) );
264  } else if ( mode == IntSource ) { //for nonlinear solver, return dHeat/dTemperature
265  TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) );
266  //it suffices to compute derivative of Arrhenius equation
267  //double actualTemperature = status->giveTempField().at(1);
268  double lastEquilibratedTemperature = status->giveField().at(1);
269  //double dt = tStep->giveTimeIncrement();
270  double krate, EaOverR, val;
271  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
272  if ( MasterCemhydMatStatus ) {
274  }
275 
276  EaOverR = 1000. * ms->E_act / 8.314;
277 
278  if ( ms->icyc > 1 ) {
279  krate = exp( -EaOverR * ( 1. / ( ms->temp_cur + 273.15 ) - 1. / ( lastEquilibratedTemperature + 273.15 ) ) );
280  //use PartHeat from the last cycle as a corrector tangent, at least one cycle has elapsed
281  // if( fabs(3600*ms->time_cur - ms->PrevHydrTime) > 1.e-3 ){
282  // power = ms->heat_new-ms->PrevCycHeat / (3600*ms->time_cur - ms->PrevHydrTime);//[J/s = W] per gram of cement
283  // power *= 1000 * ms->Mass_cement_concrete;//W/m3/s
284  // } else {
285  // power = 1.e-6;
286  // }
287  } else {
288  krate = 1.;
289  }
290 
291  val = EaOverR * krate / ( ms->temp_cur + 273.15 ) / ( ms->temp_cur + 273.15 );
292 
293  return val;
294  } else {
295  OOFEM_ERROR("unknown mode (%s)\n", __MatResponseModeToString(mode) );
296  }
297 
298  return 0.;
299 }
300 
301 
302 int
304 {
305  CemhydMatStatus *ms;
306  if ( MasterCemhydMatStatus ) {
308  } else {
309  ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
310  }
311 
312  if ( type == IST_HydrationDegree ) {
313  answer.resize(1);
314  answer.at(1) = this->giveDoHActual(gp);
315  return 1;
316  } else if ( type == IST_Density ) {
317  answer.resize(1);
318  answer.at(1) = this->giveConcreteDensity(gp,tStep);
319  return 1;
320  } else if ( type == IST_ThermalConductivityIsotropic ) {
321  answer.resize(1);
322  answer.at(1) = this->giveIsotropicConductivity(gp, tStep);
323  return 1;
324  } else if ( type == IST_HeatCapacity ) {
325  answer.resize(1);
326  answer.at(1) = this->giveConcreteCapacity(gp,tStep);
327  return 1;
328  } else if ( type == IST_AverageTemperature ) {
329  answer.resize(1);
330  answer.at(1) = ms->giveAverageTemperature();
331  return 1;
332  } else if ( type == IST_YoungModulusVirginPaste ) {
333  answer.resize(1);
334  answer.at(1) = ms->last_values [ 2 ];
335  return 1;
336  } else if ( type == IST_PoissonRatioVirginPaste ) {
337  answer.resize(1);
338  answer.at(1) = ms->last_values [ 3 ];
339  return 1;
340  } else if ( type == IST_YoungModulusConcrete ) {
341  answer.resize(1);
342  answer.at(1) = ms->last_values [ 4 ];
343  return 1;
344  } else if ( type == IST_PoissonRatioConcrete ) {
345  answer.resize(1);
346  answer.at(1) = ms->last_values [ 5 ];
347  return 1;
348  } else {
349  return TransportMaterial :: giveIPValue(answer, gp, type, tStep);
350  }
351 }
352 
353 int
355 {
356  for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) {
357  CemhydMatStatus *ms;
358  if ( !MasterCemhydMatStatus && !eachGP ) {
359  ms = new CemhydMatStatus(1, domain, gp, NULL, this, 1);
361  } else if ( eachGP ) {
362  ms = new CemhydMatStatus(1, domain, gp, MasterCemhydMatStatus, this, 1);
363  } else {
364  ms = new CemhydMatStatus(1, domain, gp, NULL, this, 0);
365  }
366 
367 // if(!gp->giveMaterialStatus()){
368  gp->setMaterialStatus( ms, this->giveNumber() );
369 // }
370  }
371 
372  return 1;
373 }
374 
376 {
377  CemhydMatStatus *ms;
378 
379  for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) {
380  ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) );
381  ms->setAverageTemperatureVolume(0.0, 0.0);
382  }
383 }
384 
386 {
387  FloatArray vecTemperature;
388 
389  if ( !eachGP ) {
390  for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) {
391  //when more GPs are lumped to a master GP
392  double dV = element->computeVolumeAround(gp);
393  element->giveIPValue(vecTemperature, gp, IST_Temperature, tStep);
395  }
396  }
397 }
398 
400 {
401  //printf("%f ", MasterCemhydMatStatus->giveAverageTemperature());
402  if ( !eachGP ) {
404  }
405 }
406 
408 {
409  IRResultType result; // Required by IR_GIVE_FIELD macro
410  castingTime = 0.;
411 
412  result = IsotropicHeatTransferMaterial :: initializeFrom(ir); //read d,k,c
413  if ( result != IRRT_OK ) return result;
414 
415  conductivityType = 0;
416  capacityType = 0;
417  densityType = 0;
418  eachGP = 0;
419  nowarnings.resize(4);
420  nowarnings.zero();
421  scaling.resize(3);
422  for ( int i = 1; i <= scaling.giveSize(); i++ ) {
423  scaling.at(i) = 1.;
424  }
425 
426  reinforcementDegree = 0.;
427  //if you want computation of material properties directly from CEMHYD3D, sum up 1 for density, 2 for conductivity, 4 for capacity
433  if ( nowarnings.giveSize() != 4 ) {
434  OOFEM_ERROR("Incorrect size %d of nowarnings", nowarnings.giveSize() );
435  }
436 
438  if ( scaling.giveSize() != 3 ) {
439  OOFEM_ERROR("Incorrect size %d of scaling", nowarnings.giveSize() );
440  }
441 
444 
445  return IRRT_OK;
446 }
447 
448 
451 {
452  OOFEM_ERROR("Use function CemhydMat :: initMaterial instead");
453  return NULL;
454 }
455 
456 
457 //constructor allowing to copy a microstructure from another CemhydMatStatus
458 //particular instance of CemhydMat in an integration point
459 CemhydMatStatus :: CemhydMatStatus(int n, Domain *d, GaussPoint *gp, CemhydMatStatus *CemStat, CemhydMat *cemhydmat, bool withMicrostructure) : TransportMaterialStatus(n, d, gp)
460 {
461  int i, j, k;
462  PartHeat = 0.;
463  //to be sure, set all pointers to NULL
464  mic = NULL;
465  mic_CSH = NULL;
466  micorig = NULL;
467  micpart = NULL;
468  mask = NULL;
469  ArrPerc = NULL;
470  ConnNumbers = NULL;
471  cshage = NULL;
472  faces = NULL;
473  PhaseFrac = NULL;
474  last_values = NULL;
475  phase = NULL;
476 
477  adiafile = NULL;
478  thfile = NULL;
479  elasfile = NULL;
480  heatfile = NULL;
481  chsfile = NULL;
482  ptmpfile = NULL;
483  movfile = NULL;
484  pHfile = NULL;
485  micfile = NULL;
486  fileperc = NULL;
487  percfile = NULL;
488  disprobfile = NULL;
489  phasfile = NULL;
490  perc_phases = NULL;
491  CSHfile = NULL;
492  infoperc = NULL;
493  infoUnperc = NULL;
494 
495  mic = NULL;
496  micorig = NULL;
497  micpart = NULL;
498  cement = NULL;
499  cemreal = NULL;
500  clust = NULL;
501  mask = NULL;
502  curvature = NULL;
503  mic_CSH = NULL;
504  ArrPerc = NULL;
505  ConnNumbers = NULL;
506  faces = NULL;
507 
508  #ifdef TINYXML
509  xmlFile = NULL;
510  #endif
511 
512  headant = NULL;
513  tailant = NULL;
514  soluble = NULL;
515  creates = NULL;
516  CSH_vicinity = NULL;
517  molarvcsh = NULL;
518  watercsh = NULL;
519  xsph = NULL;
520  ysph = NULL;
521  zsph = NULL;
522  iv = NULL;
523  discount = NULL;
524  count = NULL;
525  disprob = NULL;
526  disbase = NULL;
527  specgrav = NULL;
528  molarv = NULL;
529  heatf = NULL;
530  waterc = NULL;
531  pHeffect = NULL;
532  soluble = NULL;
533  creates = NULL;
534 
535 
536  //set common variables in constructor
537  #ifdef PRINTF
538  printf("Constructor of CemhydMatStatus on GP %p, withMicrostructure %d, copy from CemhydMatStatus %p\n", gp, withMicrostructure, CemStat);
539  fflush(stdout);
540  #endif
541  this->gp = gp;
542  if ( withMicrostructure ) {
543  this->initializeMicrostructure();
544  if ( !CemStat ) {
545  this->readInputFileAndInitialize(cemhydmat->XMLfileName.c_str(), 1);
546  } else { //copy 3D microstructure
547  this->readInputFileAndInitialize(cemhydmat->XMLfileName.c_str(), 0); //read input but do not reconstruct 3D microstructure
548  for ( k = 0; k < SYSIZE; k++ ) {
549  for ( j = 0; j < SYSIZE; j++ ) {
550  for ( i = 0; i < SYSIZE; i++ ) {
551  micpart [ i ] [ j ] [ k ] = CemStat->micpart [ i ] [ j ] [ k ];
552  micorig [ i ] [ j ] [ k ] = CemStat->micorig [ i ] [ j ] [ k ];
553  mic [ i ] [ j ] [ k ] = micorig [ i ] [ j ] [ k ];
554  }
555  }
556  }
557  }
558  }
559 }
560 #endif //__TM_MODULE
561 
562 
564 {
565  icyc = 1; //set the cycle counter
566  time_cur = 0.; //hydration time [h]
567  heat_new = 0.;
568  heat_cf = 0.;
569  Cp_now = 0.900; //initial guess [J/g of concrete], which is later updated
570 
571  averageTemperature = 0.;
572  IPVolume = 0.;
573  init_material_time = 0.;
574 
575  xoff [ 0 ] = 1;
576  xoff [ 1 ] = 0;
577  xoff [ 2 ] = 0;
578  xoff [ 3 ] = -1;
579  xoff [ 4 ] = 0;
580  xoff [ 5 ] = 0;
581  xoff [ 6 ] = 1;
582  xoff [ 7 ] = 1;
583  xoff [ 8 ] = -1;
584  xoff [ 9 ] = -1;
585  xoff [ 10 ] = 0;
586  xoff [ 11 ] = 0;
587  xoff [ 12 ] = 0;
588  xoff [ 13 ] = 0;
589  xoff [ 14 ] = 1;
590  xoff [ 15 ] = 1;
591  xoff [ 16 ] = -1;
592  xoff [ 17 ] = -1;
593  xoff [ 18 ] = 1;
594  xoff [ 19 ] = 1;
595  xoff [ 20 ] = 1;
596  xoff [ 21 ] = 1;
597  xoff [ 22 ] = -1;
598  xoff [ 23 ] = -1;
599  xoff [ 24 ] = -1;
600  xoff [ 25 ] = -1;
601  xoff [ 26 ] = 0;
602 
603  yoff [ 0 ] = 0;
604  yoff [ 1 ] = 1;
605  yoff [ 2 ] = 0;
606  yoff [ 3 ] = 0;
607  yoff [ 4 ] = -1;
608  yoff [ 5 ] = 0;
609  yoff [ 6 ] = 1;
610  yoff [ 7 ] = -1;
611  yoff [ 8 ] = 1;
612  yoff [ 9 ] = -1;
613  yoff [ 10 ] = 1;
614  yoff [ 11 ] = -1;
615  yoff [ 12 ] = 1;
616  yoff [ 13 ] = -1;
617  yoff [ 14 ] = 0;
618  yoff [ 15 ] = 0;
619  yoff [ 16 ] = 0;
620  yoff [ 17 ] = 0;
621  yoff [ 18 ] = 1;
622  yoff [ 19 ] = -1;
623  yoff [ 20 ] = 1;
624  yoff [ 21 ] = -1;
625  yoff [ 22 ] = 1;
626  yoff [ 23 ] = 1;
627  yoff [ 24 ] = -1;
628  yoff [ 25 ] = -1;
629  yoff [ 26 ] = 0;
630 
631  zoff [ 0 ] = 0;
632  zoff [ 1 ] = 0;
633  zoff [ 2 ] = 1;
634  zoff [ 3 ] = 0;
635  zoff [ 4 ] = 0;
636  zoff [ 5 ] = -1;
637  zoff [ 6 ] = 0;
638  zoff [ 7 ] = 0;
639  zoff [ 8 ] = 0;
640  zoff [ 9 ] = 0;
641  zoff [ 10 ] = 1;
642  zoff [ 11 ] = 1;
643  zoff [ 12 ] = -1;
644  zoff [ 13 ] = -1;
645  zoff [ 14 ] = 1;
646  zoff [ 15 ] = -1;
647  zoff [ 16 ] = 1;
648  zoff [ 17 ] = -1;
649  zoff [ 18 ] = 1;
650  zoff [ 19 ] = 1;
651  zoff [ 20 ] = -1;
652  zoff [ 21 ] = -1;
653  zoff [ 22 ] = 1;
654  zoff [ 23 ] = -1;
655  zoff [ 24 ] = 1;
656  zoff [ 25 ] = -1;
657  zoff [ 26 ] = 0;
658 
659  iy = 0; //random generator ran1()
660  LastCallTime = -1.e6; //start from begining (the LastCall in the beginning is -1.e6)
661  alpha_cur = 0.0;
662  alpha_last = 0.; //last degree of hydration
663  LastTargTime = 0.; //stores last call of TargTime
664  TargDoHelas = 0.; //stores DoH at which to perform analytic homogenization
665  //definitions originally from CemhydMat.h
666 
667  //for generation of microstructures
668  CEM = 100; /* and greater */
669  CEMID = 1; /* phase identifier for cement */
670  C2SID = 2; /* phase identified for C2S cement */
671  GYPID = 5; /* phase identifier for gypsum */
672  HEMIHYDRATE = 6; /* phase identifier for hemihydrate */
673  POZZID = 8; /* phase identifier for pozzolanic material - REACTIVE */
674  INERTID = 9; /* phase identifier for inert material - UNREACTIVE */
675  SLAGID = 10; /* phase identifier for slag - REACTIVE */
676  AGG = 28; /* phase identifier for flat aggregate - UNREACTIVE */
677  FLYASH = 30; /* phase identifier for all fly ash components - UNREACTIVE*/
678 
679  //for hydration part
680  POROSITY = 0;
681  C3S = 1;
682  C2S = 2;
683  C3A = 3;
684  C4AF = 4;
685  GYPSUM = 5;
686  HEMIHYD = 6;
687  ANHYDRITE = 7;
688  POZZ = 8;
689  INERT = 9;
690  SLAG = 10;
691  ASG = 11; /* aluminosilicate glass */
692  CAS2 = 12;
693  CH = 13;
694  CSH = 14;
695  C3AH6 = 15;
696  ETTR = 16;
697  ETTRC4AF = 17; /* Iron-rich stable ettringite phase */
698  AFM = 18;
699  FH3 = 19;
700  POZZCSH = 20;
701  SLAGCSH = 21; /* Slag gel-hydration product */
702  CACL2 = 22;
703  FREIDEL = 23; /* Freidel's salt */
704  STRAT = 24; /* stratlingite (C2ASH8) */
705  GYPSUMS = 25; /* Gypsum formed from hemihydrate and anhydrite */
706  CACO3 = 26;
707  AFMC = 27;
708  INERTAGG = 28;
709  ABSGYP = 29;
710  DIFFCSH = 30;
711  DIFFCH = 31;
712  DIFFGYP = 32;
713  DIFFC3A = 33;
714  DIFFC4A = 34;
715  DIFFFH3 = 35;
716  DIFFETTR = 36;
717  DIFFCACO3 = 37;
718  DIFFAS = 38;
719  DIFFANH = 39;
720  DIFFHEM = 40;
721  DIFFCAS2 = 41;
722  DIFFCACL2 = 42;
723  EMPTYP = 45; /*Empty porosity due to self desiccation*/
724  HDCSH = 46;
725  OFFSET = 50; /*Offset for highlighted potentially soluble pixel*/
726 
727  NEIGHBORS = 26; /* number of neighbors to consider (6, 18, or 26) in dissolution */
728  BoxSize = 1; /*int describing vicinity of CSH*/
729  SolidLimit = 27; /*how many solid phase voxels must be in a box (max. <=(2*BoxSize+1)^3)*/
730  MAXTRIES = 150000; /* maximum number of random tries for sphere placement */
731  MAXCYC_SEAL = 30000; /* Maximum number of cycles of sealed hydration (originally MAXCYC in disrealnew.c */
732  NUMSIZES = 100; /* maximum number of different particle sizes */
733  MAXSPH = 10000; /* maximum number of elements in a spherical template */
734 
735  Cp_pozz = 0.75;
736  Cp_CH = 0.75;
737  Cp_h2o = 4.18; /* Cp for free water */
738  Cp_bh2o = 2.2; /* Cp for bound water */
739  WN = 0.23; /* water bound per gram of cement during hydration */
740  WCHSH = 0.06; /* water imbibed per gram of cement during chemical shrinkage (estimate) */
741  CUBEMIN = 3; /* Minimum cube size for checking pore size */
742 
743  DISBIAS = 30.0; /* Dissolution bias- to change all dissolution rates */
744  DISMIN = 0.001; /* Minimum dissolution for C3S dissolution */
745  DISMIN2 = 0.00025; /* Minimum dissolution for C2S dissolution */
746  DISMINSLAG = 0.0001; /* Minimum dissolution for SLAG dissolution */
747  DISMINASG = 0.0005; /* Minimum dissolution for ASG dissolution */
748  DISMINCAS2 = 0.0005; /* Minimum dissolution for CAS2 dissolution */
749  DISMIN_C3A_0 = 0.002; /* Minimum dissolution for C3A dissolution */
750  DISMIN_C4AF_0 = 0.0005; /* Minimum dissolution for C4AF dissolution */
751 
752  C3AH6GROW = 0.01; /* Probability for C3AH6 growth */
753  CHGROW = 1.0; /* Probability for CH growth */
754  CHGROWAGG = 1.0; /* Probability for CH growth on aggregate surface */
755  ETTRGROW = 0.002; /* Probability for ettringite growth */
756  C3AETTR = 0.001; /* Probability for reaction of diffusing C3A with ettringite */
757  C3AGYP = 0.001; /* Probability for diffusing C3A to react with diffusing gypsum */
758  SOLIDC3AGYP = 0.5; /* Probability of solid C3A to react with diffusing sulfate */
759  SOLIDC4AFGYP = 0.1; /* Probability of solid C4AF to react with diffusing sulfate */
760  PPOZZ = 0.05; /* base probability for pozzolanic reaction */
761  PCSH2CSH = 0.002; /* probability for CSH dissolution */
762  A0_CHSOL = 1.325; /* Parameters for variation of CH solubility with */
763  A1_CHSOL = 0.008162; /* temperature (data from Taylor- Cement Chemistry) */
764 
765  BURNT = 70; /* label for a burnt pixel <255 (in char type arrays) */
766  SIZE2D = 49000; /* size of matrices for holding burning locations */
767 
768  SIZESET = 100000;
769  AGRATE = 0.25; /* Probability of gypsum absorption by CSH */
770  VOLFACTOR = 0.00001; /* dm per pixel Note- dm*dm*dm = Liters */
771  MASSFACTOR = 0.0001; /* cm per pixel - specific gravities in g/cm^3 */
772  MMNa = 22.9898;
773  MMK = 39.102;
774  MMNa2O = 61.979;
775  MMK2O = 94.203;
776  BNa = 0.00031; /* From Taylor paper in liters (31 mL/1000/ 100 g) */
777  BK = 0.00020; /* From Taylor paper in liters (20 mL/1000/ 100 g) */
778  BprimeNa = 0.0030; /* From Taylor paper in liters (3 mL/1000/ 1 g POZZ) */
779  BprimeK = 0.0033; /* From Taylor paper in liters (3.3 mL/1000/ 1 g POZZ) */
780  KspCH25C = 0.00000646;
781  KspGypsum = 0.0000263;
782  KspSyngenite = 0.00000010;
783  SpecgravSyngenite = 2.607; /* Source Taylor, H.F.W., Cement Chemistry */
784  KperSyn = 2.0; /* moles of K+ per mole of syngenite */
785  activeA0 = 0.0366; /* A at 295 K (from Ken) */
786  activeB0 = 0.01035; /* B at 295 K (from Ken) */
787  zCa = 2.;
788  zSO4 = 2.;
789  zOH = 1.;
790  zNa = 1.;
791  zK = 1.;
792  aK = 1.33;
793  aCa = 1.;
794  aOH = 3.;
795  aNa = 3.;
796  aSO4 = 4.5; /* Estimate as S ionic radii + O ionic diameter */
797  lambdaOH_0 = 198.0; /* Units: S cm-cm eq.^(-1) */
798  lambdaNa_0 = 50.1;
799  lambdaK_0 = 73.5;
800  lambdaSO4_0 = 39.5;
801  lambdaCa_0 = 29.5; /* Note that CRC has 60./2 for this */
802  GOH = 0.353; /* Units: (eq.^2 mol/L)^(-0.5) */
803  GK = 0.548;
804  GNa = 0.733;
805  GCa = 0.771;
806  GSO4 = 0.877;
807  cm2perL2m = 0.1; /* Conversion from cm2/Liter to 1/m */
808  EPSS = 6.e-8;
809  MAXIT = 100;
810  EPSP = 2.0e-6;
811  MAXM = 100;
812 
813  /*random generator*/
814  IA = 16807;
815  IM = 2147483647;
816  IQ = 127773;
817  IR = 2836;
818  NTAB = 32;
819  EPS = 1.2E-07;
820 
821  PhaseFrac = new double [ 34 ];
822  last_values = new double [ 6 ];
823  last_values [ 2 ] = 0.001; //Young's modulus of virgin paste
824  last_values [ 3 ] = 0.499924; //Poisson's ratio of virgin paste
825  last_values [ 4 ] = 0.001; //Young's modulus of concrete
826  last_values [ 5 ] = 0.499924; //Poisson's ratio of concrete
827  phase = new long int [ 51 ];
828 
829  CSH_vicinity = new unsigned int [ ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) + 1 ];
830  molarvcsh = new float [ MAXCYC_SEAL ];
831  watercsh = new float [ MAXCYC_SEAL ];
832  xsph = new int [ MAXSPH ];
833  ysph = new int [ MAXSPH ];
834  zsph = new int [ MAXSPH ];
835 
836  iv = new int [ NTAB ];
837 
838  discount = new long int [ EMPTYP + 1 ];
839  count = new long int [ HDCSH + 1 ];
840  disprob = new float [ HDCSH + 1 ];
841  disbase = new float [ EMPTYP + 1 ];
842  specgrav = new float [ EMPTYP + 1 ];
843  molarv = new float [ EMPTYP + 1 ];
844  heatf = new float [ EMPTYP + 1 ];
845  waterc = new float [ EMPTYP + 1 ];
846  pHeffect = new float [ EMPTYP + 1 ];
847 
848  //set zero to arrays
849  for ( int i = 0; i <= EMPTYP; i++ ) {
850  heatf [ i ] = 0.;
851  waterc [ i ] = 0.;
852  }
853 
854  for ( int i = 0; i <= HDCSH; i++ ) {
855  disprob [ i ] = 0.;
856  }
857 
858  soluble = new int [ EMPTYP + 1 ];
859  creates = new int [ EMPTYP + 1 ];
860 }
861 
862 
863 
864 // destructor
866 {
867 #ifdef OUTFILES
868  if ( fileperc != NULL ) {
869  fclose(fileperc);
870  }
871 
872  if ( disprobfile != NULL ) {
873  fclose(disprobfile);
874  }
875 
876  //fclose(percfile);
877  if ( heatfile != NULL ) {
878  fclose(heatfile);
879  }
880 
881  if ( pHfile != NULL ) {
882  fclose(pHfile);
883  }
884 
885  if ( phasfile != NULL ) {
886  fclose(phasfile);
887  }
888 
889  if ( perc_phases != NULL ) {
890  fclose(perc_phases);
891  }
892 
893  if ( adiafile != NULL ) {
894  fclose(adiafile);
895  }
896 
897  if ( elasfile != NULL ) {
898  fclose(elasfile);
899  }
900 
901  if ( CSHfile != NULL ) {
902  fclose(CSHfile);
903  }
904 
905  if ( infoperc != NULL ) {
906  fclose(infoperc);
907  }
908 
909  if ( infoUnperc != NULL ) {
910  fclose(infoUnperc);
911  }
912 
913 #endif
914  delete [] PhaseFrac;
915  delete [] last_values;
916  delete [] phase;
917 
918 #ifdef CMLFILE
919  delete F; //delete cmlfile
920 #endif
921 #ifdef TINYXML
922  if ( xmlFile != NULL ) {
923  delete xmlFile;
924  }
925 #endif
926 
927  delete [] CSH_vicinity;
928  delete [] molarvcsh;
929  delete [] watercsh;
930 
931  delete [] xsph;
932  delete [] ysph;
933  delete [] zsph;
934  delete [] iv;
935  delete [] discount;
936  delete [] count;
937  delete [] disprob;
938  delete [] disbase;
939  delete [] specgrav;
940  delete [] molarv;
941  delete [] heatf;
942  delete [] waterc;
943  delete [] pHeffect;
944  delete [] soluble;
945  delete [] creates;
946 
947  /* Eliminate the whole list */
948  struct ants *curant;
949 
950  if ( headant != NULL ) { //if hydration did not start sucessfully
951  while ( headant->nextant != NULL ) {
952  curant = headant->nextant;
953  free(headant);
954  headant = curant;
955 #ifdef PRINTF
956  printf("Deallocating headant\n");
957 #endif
958  }
959  }
960 
961  if ( tailant != NULL ) { //if hydration did not start sucessfully
962  free(tailant);
963  }
964 
965 #ifdef PRINTF
966  printf("Deallocating arrays\n");
967  fflush(stdout);
968 #endif
969 
974  dealloc_int_3D(mask, SYSIZE + 1);
979 }
980 
982 {
983  mic = new char ** [ SYSIZE ];
984  for ( int x = 0; x < SYSIZE; x++ ) {
985  mic [ x ] = new char * [ SYSIZE ];
986  for ( int y = 0; y < SYSIZE; y++ ) {
987  mic [ x ] [ y ] = new char [ SYSIZE ];
988  if ( mic [ x ] [ y ] == NULL ) {
989  printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
990  }
991  }
992  }
993 }
994 
996 {
997  if ( mic != NULL ) {
998  for ( int x = 0; x < SYSIZE; x++ ) {
999  for ( int y = 0; y < SYSIZE; y++ ) {
1000  delete [] mic [ x ] [ y ];
1001  }
1002 
1003  delete [] mic [ x ];
1004  }
1005 
1006  delete [] mic;
1007  }
1008 }
1009 
1011 {
1012  mic = new long ** [ SYSIZE ];
1013  for ( int x = 0; x < SYSIZE; x++ ) {
1014  mic [ x ] = new long * [ SYSIZE ];
1015  for ( int y = 0; y < SYSIZE; y++ ) {
1016  mic [ x ] [ y ] = new long [ SYSIZE ];
1017  if ( mic [ x ] [ y ] == NULL ) {
1018  printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1019  }
1020  }
1021  }
1022 }
1023 
1024 
1026 {
1027  if ( mic != NULL ) {
1028  for ( int x = 0; x < SYSIZE; x++ ) {
1029  for ( int y = 0; y < SYSIZE; y++ ) {
1030  delete [] mic [ x ] [ y ];
1031  }
1032 
1033  delete [] mic [ x ];
1034  }
1035 
1036  delete [] mic;
1037  }
1038 }
1039 
1041 {
1042  mic = new int ** [ SYSIZE ];
1043  for ( int x = 0; x < SYSIZE; x++ ) {
1044  mic [ x ] = new int * [ SYSIZE ];
1045  for ( int y = 0; y < SYSIZE; y++ ) {
1046  mic [ x ] [ y ] = new int [ SYSIZE ];
1047  if ( mic [ x ] [ y ] == NULL ) {
1048  printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1049  }
1050  }
1051  }
1052 }
1053 
1054 
1056 {
1057  if ( mic != NULL ) {
1058  for ( int x = 0; x < SYSIZE; x++ ) {
1059  for ( int y = 0; y < SYSIZE; y++ ) {
1060  delete [] mic [ x ] [ y ];
1061  }
1062 
1063  delete [] mic [ x ];
1064  }
1065 
1066  delete [] mic;
1067  }
1068 }
1069 
1070 void CemhydMatStatus :: alloc_shortint_3D(short int ***( &mic ), long SYSIZE)
1071 {
1072  mic = new short int ** [ SYSIZE ];
1073  for ( int x = 0; x < SYSIZE; x++ ) {
1074  mic [ x ] = new short int * [ SYSIZE ];
1075  for ( int y = 0; y < SYSIZE; y++ ) {
1076  mic [ x ] [ y ] = new short int [ SYSIZE ];
1077  if ( mic [ x ] [ y ] == NULL ) {
1078  printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1079  }
1080  }
1081  }
1082 }
1083 
1084 
1086 {
1087  if ( mic != NULL ) {
1088  for ( int x = 0; x < SYSIZE; x++ ) {
1089  for ( int y = 0; y < SYSIZE; y++ ) {
1090  delete [] mic [ x ] [ y ];
1091  }
1092 
1093  delete [] mic [ x ];
1094  }
1095 
1096  delete [] mic;
1097  }
1098 }
1099 
1101 {
1102  mic = new double ** [ SYSIZE ];
1103  for ( int x = 0; x < SYSIZE; x++ ) {
1104  mic [ x ] = new double * [ SYSIZE ];
1105  for ( int y = 0; y < SYSIZE; y++ ) {
1106  mic [ x ] [ y ] = new double [ SYSIZE ];
1107  if ( mic [ x ] [ y ] == NULL ) {
1108  printf("Cannot allocate memory (file %s, line %d)\n", __FILE__, __LINE__);
1109  }
1110  }
1111  }
1112 }
1113 
1114 
1116 {
1117  if ( mic != NULL ) {
1118  for ( int x = 0; x < SYSIZE; x++ ) {
1119  for ( int y = 0; y < SYSIZE; y++ ) {
1120  delete [] mic [ x ] [ y ];
1121  }
1122 
1123  delete [] mic [ x ];
1124  }
1125 
1126  delete [] mic;
1127  }
1128 }
1129 
1130 #ifdef TINYXML
1131 //functions to read int, double and string with error checking
1132 void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, int &val)
1133 {
1134  int success;
1135  char key [ 256 ];
1136  XMLHandle docHandle = XMLHandle(xmlFile);
1137  XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1138  if ( elemSelected == NULL ) {
1139  printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1140  exit(0);
1141  }
1142 
1143  sprintf(key, "key%d", position);
1144  success = elemSelected->QueryIntAttribute(key, & val);
1145  if ( success != XML_SUCCESS ) {
1146  printf("Cannot read int value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1147  exit(0);
1148  }
1149 }
1150 
1151 void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, long int &val)
1152 {
1153  int temp;
1154  QueryNumAttributeExt(xmlFile, elementName, position, temp);
1155  val = static_cast< long int >(temp);
1156 }
1157 
1158 void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, const char *key, int &val)
1159 {
1160  int success;
1161  XMLHandle docHandle = XMLHandle(xmlFile);
1162  XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1163  if ( elemSelected == NULL ) {
1164  printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1165  exit(0);
1166  }
1167 
1168  success = elemSelected->QueryIntAttribute(key, & val);
1169  if ( success != XML_SUCCESS ) {
1170  printf("Cannot read int value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1171  exit(0);
1172  }
1173 }
1174 
1175 
1176 void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, double &val)
1177 {
1178  int success;
1179  char key [ 256 ];
1180  XMLHandle docHandle = XMLHandle(xmlFile);
1181  XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1182  if ( elemSelected == NULL ) {
1183  printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1184  exit(0);
1185  }
1186 
1187  sprintf(key, "key%d", position);
1188  success = elemSelected->QueryDoubleAttribute(key, & val);
1189  if ( success != XML_SUCCESS ) {
1190  printf("Cannot read double value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1191  exit(0);
1192  }
1193 }
1194 
1195 void CemhydMatStatus :: QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, const char *key, double &val)
1196 {
1197  int success;
1198  XMLHandle docHandle = XMLHandle(xmlFile);
1199  XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1200  if ( elemSelected == NULL ) {
1201  printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1202  exit(0);
1203  }
1204 
1205  success = elemSelected->QueryDoubleAttribute(key, & val);
1206  if ( success != XML_SUCCESS ) {
1207  printf("Cannot read double value or attribute %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1208  exit(0);
1209  }
1210 }
1211 
1212 void CemhydMatStatus :: QueryStringAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, char *chars)
1213 {
1214  int success;
1215  char key [ 256 ];
1216  XMLHandle docHandle = XMLHandle(xmlFile);
1217  std :: string str1;
1218  XMLElement *elemSelected = docHandle.FirstChildElement("cemhyd").FirstChildElement(elementName).ToElement();
1219  if ( elemSelected == NULL ) {
1220  printf("Cannot find entry %s, terminating, file %s, line %d\n", elementName, __FILE__, __LINE__);
1221  exit(0);
1222  }
1223 
1224  sprintf(key, "key%d", position);
1225  //success = elemSelected->QueryStringAttribute(key, & str1);
1226  // Since ubuntu/debian is still stuck at 2.5.3, lacking QueryStringAttribute.
1227  // Change with above whenever packages are updated.
1228  const char *cstr = elemSelected->Attribute(key);
1229  if ( cstr ) {
1230  success = XML_SUCCESS;
1231  } else {
1232  success = XML_NO_ATTRIBUTE;
1233  }
1234  if ( success != XML_SUCCESS ) {
1235  printf("Cannot read string value or key %s from the entry %s, terminating, file %s, line %d\n", key, elementName, __FILE__, __LINE__);
1236  exit(0);
1237  }
1238  str1 = std :: string(cstr);
1239 
1240  strcpy( chars, str1.c_str() );
1241 }
1242 #endif
1243 
1244 /* read input parameters in file, use XML or cmlfile construction
1245  * allocate necessary arrays (especially those dependent on SYSIZE)
1246  * returns (1) if generation of particles in the Representative Volume Element (RVE) was unsuccessful
1247  */
1248 int CemhydMatStatus :: readInputFileAndInitialize(const char *inp, bool generateMicrostructure)
1249 {
1250  int read_micr;
1251 #ifdef CMLFILE
1252  F = new cmlfile(inp);
1253  // set number of keywords
1254  F->set_labels(54);
1255  F->set_label_string(0, "Rand_seed_num");
1256  F->set_label_string(1, "Input_img_file");
1257  F->set_label_string(2, "Input_id_file");
1258  F->set_label_string(3, "Saturated_sealed");
1259  F->set_label_string(4, "Induction_time");
1260  F->set_label_string(5, "Ea_cement");
1261  F->set_label_string(6, "Ea_pozz");
1262  F->set_label_string(7, "Ea_slag");
1263  F->set_label_string(8, "Beta");
1264  F->set_label_string(9, "Mass_SCM_FA_CA_inert_frac");
1265  F->set_label_string(10, "Mass_cem");
1266  F->set_label_string(11, "Cp_SCM_FA_CA_inert");
1267  F->set_label_string(12, "Cp_cem");
1268  F->set_label_string(13, "Given_microstructure");
1269  F->set_label_string(14, "Output_initial_microstructure");
1270  F->set_label_string(15, "Output_initial_microstructure_img_file");
1271  F->set_label_string(16, "Output_initial_microstructure_id_file");
1272  F->set_label_string(17, "Cycle_freq_perc_pore");
1273  F->set_label_string(18, "Cycle_freq_perc_sol");
1274  F->set_label_string(19, "Total_sodium");
1275  F->set_label_string(20, "Total_potassium");
1276  F->set_label_string(21, "Readily_soluble_sodium");
1277  F->set_label_string(22, "Readily_soluble_potassium");
1278  F->set_label_string(23, "Diffusion_steps_per_cycle");
1279  F->set_label_string(24, "CH_nucleation_probability");
1280  F->set_label_string(25, "CH_scale_factor");
1281  F->set_label_string(26, "Gypsum_nucleation_probability");
1282  F->set_label_string(27, "Gypsum_scale_factor");
1283  F->set_label_string(28, "C3AH6_nucleation_probability");
1284  F->set_label_string(29, "C3AH6_scale_factor");
1285  F->set_label_string(30, "FH3_nucleation_probability");
1286  F->set_label_string(31, "FH3_scale_factor");
1287  F->set_label_string(32, "Microstructure_size");
1288  F->set_label_string(33, "Adiabatic_conditions");
1289  F->set_label_string(34, "Vol_cement_clinker_gypsum");
1290  F->set_label_string(35, "Vol_cement_SCM");
1291  F->set_label_string(36, "Vol_water");
1292  F->set_label_string(37, "Vol_FA");
1293  F->set_label_string(38, "Vol_CA");
1294  F->set_label_string(39, "Vol_inert_filler");
1295  F->set_label_string(40, "Vol_entrained_entrapped_air");
1296  F->set_label_string(41, "Grain_average_FA");
1297  F->set_label_string(42, "Grain_average_CA");
1298  F->set_label_string(43, "ITZ_thickness");
1299  F->set_label_string(44, "ITZ_Young_red");
1300  F->set_label_string(45, "Young_SCM");
1301  F->set_label_string(46, "Poisson_SCM");
1302  F->set_label_string(47, "Young_FA");
1303  F->set_label_string(48, "Poisson_FA");
1304  F->set_label_string(49, "Young_CA");
1305  F->set_label_string(50, "Poisson_CA");
1306  F->set_label_string(51, "Young_inert");
1307  F->set_label_string(52, "Poisson_inert");
1308  F->set_label_string(53, "Calculate_elastic_homogenization");
1309 
1310  // these keywords with #id will be required
1311  F->require(0);
1312  //F->require( 1 ) ;
1313  //F->require( 2 ) ;
1314  F->require(3);
1315  F->require(4);
1316  F->require(5);
1317  F->require(6);
1318  F->require(7);
1319  F->require(8);
1320  F->require(9);
1321  F->require(10);
1322  F->require(11);
1323  F->require(12);
1324  F->require(13);
1325  F->require(14);
1326  F->require(17);
1327  F->require(18);
1328  F->require(19);
1329  F->require(20);
1330  F->require(21);
1331  F->require(22);
1332  F->require(23);
1333  F->require(24);
1334  F->require(27);
1335  F->require(28);
1336  F->require(29);
1337  F->require(30);
1338  F->require(31);
1339  F->require(32);
1340  F->require(33);
1341  F->require(34);
1342  F->require(35);
1343  F->require(36);
1344  F->require(37);
1345  F->require(38);
1346  F->require(39);
1347  F->require(40);
1348  F->require(41);
1349  F->require(42);
1350  F->require(43);
1351  F->require(44);
1352  F->require(45);
1353  F->require(46);
1354  F->require(47);
1355  F->require(48);
1356  F->require(49);
1357  F->require(50);
1358  F->require(51);
1359  F->require(52);
1360  F->require(53);
1361  // set number and names of sections
1362  F->set_sections(1);
1363  F->set_section_string(0, "CEMHYD_generate_particles");
1364 
1365  F->check_requirements();
1366 
1367  if ( F->error_in_requirements() ) {
1368  printf("Cemhyd input file %s is not complete (file %s, line %d)\n", inp, __FILE__, __LINE__);
1369  exit(0);
1370  }
1371 
1372  F->get_value(0, ( long & )iseed);
1373 #endif
1374 #ifdef TINYXML
1375  xmlFile = new XMLDocument();
1376  countKey = 0;
1377  int errorId = xmlFile->LoadFile(inp);
1378  if ( errorId != XML_SUCCESS ) {
1379  printf("\nError reading XML file %s or nonletter symbols used, error id = %d\n", inp, errorId);
1380  exit(0);
1381  }
1382 
1383  QueryNumAttributeExt(xmlFile, "Rand_seed_num", 0, iseed);
1384  QueryNumAttributeExt(xmlFile, "Microstructure_size", 0, SYSSIZE);
1385  QueryNumAttributeExt(xmlFile, "Given_microstructure", 0, read_micr);
1386 #endif
1387 
1388  nseed = iseed;
1389  seed = ( & nseed );
1390  //printf("iseed = %d", iseed);
1391 
1392  //read SYSSIZE of microstructure and allocate arrays
1393 #ifdef CMLFILE
1394  F->get_value(32, ( long & )SYSSIZE);
1395 #endif
1396  if ( SYSSIZE < 10 ) {
1397  printf("Can not run small microstructure %d (< 10 voxels a side), file %s, line %d)\n", SYSSIZE, __FILE__, __LINE__);
1398  exit(0);
1399  }
1400 
1401  SYSIZE = SYSSIZE;
1402  SYSIZEM1 = ( SYSIZE - 1 ); /* System size -1 */
1403  SYSIZE_POW3 = ( SYSIZE * SYSIZE * SYSIZE );
1404  NPARTC = ( long ) ( 700000 * ( double ) SYSIZE_POW3 / 1000000. );
1405  BURNTG = ( NPARTC > 100 ? NPARTC : 100 );
1406  CUBEMAX = ( SYSIZE > 6 ? 7 : 3 );
1407  DETTRMAX = ( 1200. * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of ettringite diffusing species */
1408  DGYPMAX = ( 2000. * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of gypsum diffusing species */
1409  DCACO3MAX = ( 1000 * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of CaCO3 diffusing species */
1410  DCACL2MAX = ( 2000 * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of CaCl2 diffusing species */
1411  DCAS2MAX = ( 2000 * SYSIZE_POW3 / 1000000. ); /* Maximum allowed # of CAS2 diffusing species */
1412  CHCRIT = ( 50. * SYSIZE_POW3 / 1000000. ); /* Scale parameter to adjust CH dissolution probability */
1413  C3AH6CRIT = ( 10. * SYSIZE_POW3 / 1000000. ); /* Scale par. to adjust C3AH6 dissolution prob. */
1414  CSHSCALE = ( 70000. * SYSIZE_POW3 / 1000000. ); /*scale factor for CSH controlling induction */
1415  C3AH6_SCALE = ( 2000. * SYSIZE_POW3 / 1000000. ); /*scale factor for C3AH6 controlling induction of aluminates */
1416 
1421  alloc_int_3D(mask, SYSIZE + 1);
1426 
1427 #ifdef CMLFILE
1428  F->get_value(13, ( long & )read_micr);
1429 #endif
1430 
1431  if ( !read_micr && generateMicrostructure == 1 ) { //generate new microstructure
1432  if ( genpartnew() == 1 ) { //read input file for RVE generation, if unsuccessful microstructure generation, return
1433  return 1;
1434  }
1435 
1436 #ifdef PRINTF
1437  printf("MONOPHASE microstructure created\n");
1438 #endif
1439  distrib3d(); //read autocorrelation functions and distribute clinker phases in RVE
1440  }
1441 
1442  readhydrparam(); //read hydration parameters
1443 
1444  return 0;
1445 }
1446 
1447 
1448 /* Random number generator ran1 from Computers in Physics */
1449 /* Volume 6 No. 5, 1992, 522-524, Press and Teukolsky */
1450 /* To generate real random numbers 0.0-1.0 */
1451 /* Should be seeded with a negative integer */
1452 double CemhydMatStatus :: ran1(int *idum)
1453 /* Calls: no routines */
1454 /* Called by: gsphere,makefloc */
1455 {
1456  int j, k;
1457  NDIV = 1.0 / ( 1.0 + ( IM - 1.0 ) / NTAB );
1458  RNMX = ( 1.0 - EPS );
1459  AM = ( 1.0 / IM );
1460 
1461  if ( ( * idum <= 0 ) || ( iy == 0 ) ) {
1462  * idum = ( -* idum > * idum ) ? -* idum : * idum; //MAX(-*idum>*idum);
1463  for ( j = NTAB + 7; j >= 0; j-- ) {
1464  k = * idum / IQ;
1465  * idum = IA * ( * idum - k * IQ ) - IR * k;
1466  if ( * idum < 0 ) {
1467  * idum += IM;
1468  }
1469 
1470  if ( j < NTAB ) {
1471  iv [ j ] = * idum;
1472  }
1473  }
1474 
1475  iy = iv [ 0 ];
1476  }
1477 
1478  k = * idum / IQ;
1479  * idum = IA * ( * idum - k * IQ ) - IR * k;
1480  if ( * idum < 0 ) {
1481  * idum += IM;
1482  }
1483 
1484  j = ( int ) ( iy * NDIV );
1485  iy = iv [ j ];
1486  iv [ j ] = * idum;
1487  return AM * iy < RNMX ? AM * iy : RNMX; //MIN(AM*iy,RNMX);
1488 }
1489 
1490 
1491 /* routine to add a flat plate aggregate in the microstructure */
1493 /* Calls: no other routines */
1494 /* Called by: main program */
1495 {
1496  int ix, iy, iz;
1497  int agglo, agghi;
1498 
1499  /* Be sure aggregate size is an even integer */
1500  do {
1501  printf("Enter thickness of aggregate to place (an even integer) \n");
1502 #ifdef CMLFILE
1503  F->get_next_line_in_section(0, ( long & )aggsize);
1504 #endif
1505 #ifdef TINYXML
1506  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, aggsize);
1507 #endif
1508 
1509  //fscanf(in, "%d",&aggsize);
1510 #ifdef PRINTF
1511  printf("%d\n", aggsize);
1512 #endif
1513  } while ( ( ( aggsize % 2 ) != 0 ) || ( aggsize > ( SYSSIZE - 2 ) ) );
1514 
1515  if ( aggsize != 0 ) {
1516  agglo = ( SYSSIZE / 2 ) - ( ( aggsize - 2 ) / 2 );
1517  agghi = ( SYSSIZE / 2 ) + ( aggsize / 2 );
1518 
1519  /* Aggregate is placed in yz plane */
1520  for ( ix = agglo; ix <= agghi; ix++ ) {
1521  for ( iy = 1; iy <= SYSSIZE; iy++ ) {
1522  for ( iz = 1; iz <= SYSSIZE; iz++ ) {
1523  /* Mark aggregate in both particle and microstructure images */
1524  cement [ ix ] [ iy ] [ iz ] = AGG;
1525  cemreal [ ix ] [ iy ] [ iz ] = AGG;
1526  }
1527  }
1528  }
1529  }
1530 }
1531 
1532 
1533 
1534 /* routine to check or perform placement of sphere of ID phasein */
1535 /* centered at location (xin,yin,zin) of radius radd */
1536 /* wflg=1 check for fit of sphere */
1537 /* wflg=2 place the sphere */
1538 /* phasein and phase2 are phases to assign to cement and cemreal images resp. */
1539 int CemhydMatStatus :: chksph(int xin, int yin, int zin, int radd, int wflg, int phasein, int phase2)
1540 /* Calls: no other routines */
1541 /* Called by: gsphere */
1542 {
1543  int nofits, xp, yp, zp, i, j, k;
1544  float dist, xdist, ydist, zdist, ftmp;
1545 
1546  nofits = 0; /* Flag indicating if placement is possible */
1547  /* Check all pixels within the digitized sphere volume */
1548  for ( i = xin - radd; ( ( i <= xin + radd ) && ( nofits == 0 ) ); i++ ) {
1549  xp = i;
1550  /* use periodic boundary conditions for sphere placement */
1551  if ( xp < 1 ) {
1552  xp += SYSSIZE;
1553  } else if ( xp > SYSSIZE ) {
1554  xp -= SYSSIZE;
1555  }
1556 
1557  ftmp = ( float ) ( i - xin );
1558  xdist = ftmp * ftmp;
1559  for ( j = yin - radd; ( ( j <= yin + radd ) && ( nofits == 0 ) ); j++ ) {
1560  yp = j;
1561  /* use periodic boundary conditions for sphere placement */
1562  if ( yp < 1 ) {
1563  yp += SYSSIZE;
1564  } else if ( yp > SYSSIZE ) {
1565  yp -= SYSSIZE;
1566  }
1567 
1568  ftmp = ( float ) ( j - yin );
1569  ydist = ftmp * ftmp;
1570  for ( k = zin - radd; ( ( k <= zin + radd ) && ( nofits == 0 ) ); k++ ) {
1571  zp = k;
1572  /* use periodic boundary conditions for sphere placement */
1573  if ( zp < 1 ) {
1574  zp += SYSSIZE;
1575  } else if ( zp > SYSSIZE ) {
1576  zp -= SYSSIZE;
1577  }
1578 
1579  ftmp = ( float ) ( k - zin );
1580  zdist = ftmp * ftmp;
1581 
1582  /* Compute distance from center of sphere to this pixel */
1583  dist = sqrt(xdist + ydist + zdist);
1584  if ( ( dist - 0.5 ) <= ( float ) radd ) {
1585  /* Perform placement */
1586  if ( wflg == 2 ) {
1587  cement [ xp ] [ yp ] [ zp ] = phasein;
1588  cemreal [ xp ] [ yp ] [ zp ] = phase2;
1589  }
1590  /* or check placement */
1591  else if ( ( wflg == 1 ) && ( cement [ xp ] [ yp ] [ zp ] != POROSITY ) ) {
1592  nofits = 1;
1593  }
1594  }
1595 
1596  /* Check for overlap with aggregate */
1597  if ( ( wflg == 1 ) && ( ( fabs( xp - ( ( float ) ( SYSSIZE + 1 ) / 2.0 ) ) ) < ( ( float ) aggsize / 2.0 ) ) ) {
1598  nofits = 1;
1599  }
1600  }
1601  }
1602  }
1603 
1604  /* return flag indicating if sphere will fit */
1605  return ( nofits );
1606 }
1607 
1608 
1609 
1610 /* routine to place spheres of various sizes and phases at random */
1611 /* locations in 3-D microstructure */
1612 /* numgen is number of different size spheres to place */
1613 /* numeach holds the number of each size class */
1614 /* sizeeach holds the radius of each size class */
1615 /* pheach holds the phase of each size class */
1616 int CemhydMatStatus :: gsphere(int numgen, long int *numeach, int *sizeeach, int *pheach)
1617 {
1618  /* Calls: makesph, ran1 */
1619  /* Called by: create */
1620  int count, x, y, z, radius, ig, tries, phnow;
1621  long int jg, i;
1622  float testgyp, typegyp;
1623 
1624  /* Generate spheres of each size class in turn (largest first) */
1625  for ( ig = 0; ig < numgen; ig++ ) {
1626  phnow = pheach [ ig ]; /* phase for this class */
1627  radius = sizeeach [ ig ]; /* radius for this class */
1628  /* loop for each sphere in this size class */
1629  for ( jg = 1; jg <= numeach [ ig ]; jg++ ) {
1630  tries = 0;
1631  /* Stop after MAXTRIES random tries */
1632  do {
1633  tries += 1;
1634  /* generate a random center location for the sphere */
1635  x = ( int ) ( ( float ) SYSSIZE * ran1(seed) ) + 1;
1636  y = ( int ) ( ( float ) SYSSIZE * ran1(seed) ) + 1;
1637  z = ( int ) ( ( float ) SYSSIZE * ran1(seed) ) + 1;
1638  /* See if the sphere will fit at x,y,z */
1639  /* Include dispersion distance when checking */
1640  /* to insure requested separation between spheres */
1641  count = chksph(x, y, z, radius + dispdist, 1, npart + CEM, 0);
1642  if ( ( tries > MAXTRIES ) && ( dispdist == 2 ) ) {
1643  tries = 0;
1644  dispdist += 1;
1645  }
1646 
1647  if ( tries > MAXTRIES ) {
1648  printf("Could not place sphere %d after %ld random attempts \n", npart, MAXTRIES);
1649  printf("Skipping this microstructure parameters\n");
1650  for ( i = 1; i <= npart; i++ ) {
1651  free(clust [ i ]);
1652  }
1653 
1654  return ( 1 );
1655  }
1656  } while ( count != 0 );
1657 
1658  /* place the sphere at x,y,z */
1659  npart += 1;
1660  if ( npart >= NPARTC ) {
1661  printf("Too many spheres being generated \n");
1662  printf("User needs to increase value of NPARTC at top of C-code\n");
1663  printf("Skipping this microstructure parameters\n");
1664  return ( 1 );
1665  }
1666 
1667  /* Allocate space for new particle info */
1668  clust [ npart ] = ( struct cluster * ) malloc( sizeof( struct cluster ) );
1669  clust [ npart ]->partid = npart;
1670  clust [ npart ]->clustid = npart;
1671  /* Default to cement placement */
1672  clust [ npart ]->partphase = CEMID;
1673  clust [ npart ]->x = x;
1674  clust [ npart ]->y = y;
1675  clust [ npart ]->z = z;
1676  clust [ npart ]->r = radius;
1677  clusleft += 1;
1678  if ( phnow == 1 ) {
1679  testgyp = ran1(seed);
1680  /* Do not use dispersion distance when placing particle */
1681  if ( ( ( testgyp > probgyp ) && ( ( target_sulfate - n_sulfate ) < ( target_total - n_total ) ) ) || ( n_sulfate > target_sulfate ) || ( volpart [ radius ] > ( target_sulfate - n_sulfate ) ) || ( numeach [ ig ] <= 2 ) ) {
1682  count = chksph(x, y, z, radius, 2, npart + CEM - 1, CEMID);
1683  n_total += volpart [ radius ];
1684  } else {
1685  /* Place particle as gypsum */
1686  typegyp = ran1(seed);
1687  n_total += volpart [ radius ];
1688  n_sulfate += volpart [ radius ];
1689  if ( ( probanh >= 1.0 ) || ( ( typegyp < probanh ) && ( n_anhydrite < target_anhydrite ) && ( volpart [ radius ] <= ( target_anhydrite - n_anhydrite ) ) ) ) {
1690  /* Place particle as anhydrite */
1691  n_anhydrite += volpart [ radius ];
1692  count = chksph(x, y, z, radius, 2, npart + CEM - 1, ANHYDRITE);
1693  clust [ npart ]->partphase = ANHYDRITE;
1694  } else if ( ( ( probanh + probhem ) >= 1.0 ) || ( ( typegyp < ( probanh + probhem ) ) && ( n_hemi < target_hemi ) && ( volpart [ radius ] <= ( target_hemi - n_hemi ) ) ) ) {
1695  /* Place particle as hemihydrate */
1696  n_hemi += volpart [ radius ];
1697  count = chksph(x, y, z, radius, 2, npart + CEM - 1, HEMIHYDRATE);
1699  } else {
1700  count = chksph(x, y, z, radius, 2, npart + CEM - 1, GYPID);
1701  /* Correct phase ID of particle */
1702  clust [ npart ]->partphase = GYPID;
1703  }
1704  }
1705  }
1706  /* place as inert, CaCO3, C2S, slag, or pozzolanic material */
1707  else {
1708  count = chksph(x, y, z, radius, 2, npart + CEM - 1, phnow);
1709  /* Correct phase ID of particle */
1710  clust [ npart ]->partphase = phnow;
1711  }
1712 
1713  clust [ npart ]->nextpart = NULL;
1714  }
1715  }
1716 
1717  //deallocate
1718  for ( i = 1; i <= npart; i++ ) {
1719  free(clust [ i ]);
1720  //printf("Dealloc clust %ld of %d", i,npart);
1721  }
1722 
1723  return ( 0 );
1724 }
1725 
1726 
1727 /* routine to obtain user input and create a starting microstructure */
1729 {
1730  /* Calls: gsphere */
1731  /* Called by: main program */
1732  int numsize;
1733  int *sphrad, *sphase;
1734  long int *sphnum;
1735  long int inval1;
1736  int isph, inval;
1737 
1738  sphrad = new int [ NUMSIZES ];
1739  sphase = new int [ NUMSIZES ];
1740  sphnum = new long int [ NUMSIZES ];
1741 
1742 
1743  do {
1744 #ifdef PRINTF
1745  printf("Enter number of different size spheres to use(max. is %d) \n", NUMSIZES);
1746 #endif
1747 #ifdef CMLFILE
1748  F->get_next_line_in_section(0, ( long & )numsize);
1749 #endif
1750 #ifdef TINYXML
1751  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, numsize);
1752 #endif
1753  //fscanf(in, "%d",&numsize);
1754 #ifdef PRINTF
1755  printf("%d \n", numsize);
1756 #endif
1757  } while ( ( numsize > NUMSIZES ) || ( numsize < 0 ) );
1758 
1759  do {
1760 #ifdef PRINTF
1761  printf("Enter dispersion factor (separation distance in pixels) for spheres (0-2) \n");
1762  printf("0 corresponds to totally random placement \n");
1763 #endif
1764 #ifdef CMLFILE
1765  F->get_next_line_in_section(0, ( long & )dispdist);
1766 #endif
1767 #ifdef TINYXML
1768  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, dispdist);
1769 #endif
1770  //fscanf(in, "%d",&dispdist);
1771 #ifdef PRINTF
1772  printf("%d \n", dispdist);
1773 #endif
1774  } while ( ( dispdist < 0 ) || ( dispdist > 2 ) );
1775 
1776  do {
1777 #ifdef PRINTF
1778  printf("Enter probability for gypsum particles on a random particle basis (0.0-1.0) \n");
1779 #endif
1780 #ifdef CMLFILE
1781  F->get_next_line_in_section(0, probgyp);
1782 #endif
1783 #ifdef TINYXML
1784  QueryNumAttributeExt(xmlFile, "Generate_microstructure", "dihydrate", probgyp);
1785 #endif
1786  //fscanf(in, "%f",&probgyp);
1787 #ifdef PRINTF
1788  printf("%f \n", probgyp);
1789 #endif
1790  } while ( ( probgyp < 0.0 ) || ( probgyp > 1.0 ) );
1791 
1792  do {
1793 #ifdef PRINTF
1794  printf("Enter probabilities for hemihydrate and anhydrite forms of gypsum (0.0-1.0) \n");
1795 #endif
1796 #ifdef CMLFILE
1797  F->get_next_line_in_section(0, probhem);
1798  F->get_next_line_in_section(0, probanh);
1799 #endif
1800 #ifdef TINYXML
1801  QueryNumAttributeExt(xmlFile, "Generate_microstructure", "hemihydrate", probhem);
1802  QueryNumAttributeExt(xmlFile, "Generate_microstructure", "anhydrite", probanh);
1803 #endif
1804  //fscanf(in, "%f %f",&probhem,&probanh);
1805 #ifdef PRINTF
1806  printf("%f %f\n", probhem, probanh);
1807 #endif
1808  } while ( ( probhem < 0.0 ) || ( probhem > 1.0 ) || ( probanh < 0.0 ) || ( probanh > 1.0 ) || ( ( probanh + probhem ) > 1.001 ) );
1809 
1810  if ( ( numsize > 0 ) && ( numsize < ( NUMSIZES + 1 ) ) ) {
1811 #ifdef PRINTF
1812  printf("Enter number, radius, and phase ID for each sphere class (largest radius 1st) \n");
1813  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);
1814 #endif
1815  /* Obtain input for each size class of spheres */
1816  for ( isph = 0; isph < numsize; isph++ ) {
1817 #ifdef PRINTF
1818  printf("Enter number of spheres of class %d \n", isph + 1);
1819 #endif
1820 #ifdef CMLFILE
1821  F->get_next_line_in_section(0, inval1);
1822 #endif
1823 #ifdef TINYXML
1824  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, inval1);
1825  //inval1 = static_cast<long int>(inval);
1826 #endif
1827  //fscanf(in, "%ld",&inval1);
1828 #ifdef PRINTF
1829  printf("%ld \n", inval1);
1830 #endif
1831  sphnum [ isph ] = inval1;
1832 
1833  // do{
1834 #ifdef PRINTF
1835  printf("Enter radius of spheres of class %d \n", isph + 1);
1836  printf("(Integer <=%d please) \n", SYSSIZE / 3);
1837 #endif
1838 #ifdef CMLFILE
1839  F->get_next_line_in_section(0, ( long & )inval);
1840 #endif
1841 #ifdef TINYXML
1842  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, inval);
1843 #endif
1844  //fscanf(in, "%d",&inval);
1845  if ( inval > ( SYSSIZE / 3 ) ) {
1846  printf("Given radius %d exceeded maximum radius of %d, terminating\n", inval, SYSSIZE / 3);
1847  exit(0);
1848  }
1849 
1850 #ifdef PRINTF
1851  printf("%d \n", inval);
1852 #endif
1853  //} while ((inval<0)||(inval>(SYSSIZE/3)));
1854 
1855  sphrad [ isph ] = inval;
1856  do {
1857 #ifdef PRINTF
1858  printf("Enter phase of spheres of class %d \n", isph + 1);
1859 #endif
1860 #ifdef CMLFILE
1861  F->get_next_line_in_section(0, ( long & )inval);
1862 #endif
1863 #ifdef TINYXML
1864  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, inval);
1865 #endif
1866  //fscanf(in, "%d",&inval);
1867 #ifdef PRINTF
1868  printf("%d \n", inval);
1869 #endif
1870  } 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 ) );
1871 
1872  sphase [ isph ] = inval;
1873  if ( inval == CEMID ) {
1874  target_total += sphnum [ isph ] * volpart [ sphrad [ isph ] ];
1875  }
1876  }
1877 
1878  /* Determine target pixel counts for calcium sulfate forms */
1879  target_sulfate = ( int ) ( ( float ) target_total * probgyp );
1880  target_anhydrite = ( int ) ( ( float ) target_total * probgyp * probanh );
1881  target_hemi = ( int ) ( ( float ) target_total * probgyp * probhem );
1882  if ( gsphere(numsize, sphnum, sphrad, sphase) == 1 ) { //unsuccessful generation of microstructure due to excessive amount of particles or too dense
1883  delete [] sphrad;
1884  delete [] sphase;
1885  delete [] sphnum;
1886  return ( 1 );
1887  }
1888  }
1889 
1890  delete [] sphrad;
1891  delete [] sphase;
1892  delete [] sphnum;
1893 
1894 
1895  return ( 0 );
1896 }
1897 
1898 
1899 /* Routine to draw a particle during flocculation routine */
1900 /* See routine chksph for definition of parameters */
1901 void CemhydMatStatus :: drawfloc(int xin, int yin, int zin, int radd, int phasein, int phase2)
1902 {
1903  /* Calls: no other routines */
1904  /* Called by: makefloc */
1905  int xp, yp, zp, i, j, k;
1906  float dist, xdist, ydist, zdist, ftmp;
1907 
1908  /* Check all pixels within the digitized sphere volume */
1909  for ( i = xin - radd; ( i <= xin + radd ); i++ ) {
1910  xp = i;
1911  /* use periodic boundary conditions for sphere placement */
1912  if ( xp < 1 ) {
1913  xp += SYSSIZE;
1914  } else if ( xp > SYSSIZE ) {
1915  xp -= SYSSIZE;
1916  }
1917 
1918  ftmp = ( float ) ( i - xin );
1919  xdist = ftmp * ftmp;
1920  for ( j = yin - radd; ( j <= yin + radd ); j++ ) {
1921  yp = j;
1922  /* use periodic boundary conditions for sphere placement */
1923  if ( yp < 1 ) {
1924  yp += SYSSIZE;
1925  } else if ( yp > SYSSIZE ) {
1926  yp -= SYSSIZE;
1927  }
1928 
1929  ftmp = ( float ) ( j - yin );
1930  ydist = ftmp * ftmp;
1931  for ( k = zin - radd; ( k <= zin + radd ); k++ ) {
1932  zp = k;
1933  /* use periodic boundary conditions for sphere placement */
1934  if ( zp < 1 ) {
1935  zp += SYSSIZE;
1936  } else if ( zp > SYSSIZE ) {
1937  zp -= SYSSIZE;
1938  }
1939 
1940  ftmp = ( float ) ( k - zin );
1941  zdist = ftmp * ftmp;
1942 
1943  /* Compute distance from center of sphere to this pixel */
1944  dist = sqrt(xdist + ydist + zdist);
1945  if ( ( dist - 0.5 ) <= ( float ) radd ) {
1946  /* Update both cement and cemreal images */
1947  cement [ xp ] [ yp ] [ zp ] = phasein;
1948  cemreal [ xp ] [ yp ] [ zp ] = phase2;
1949  }
1950  }
1951  }
1952  }
1953 }
1954 
1955 
1956 /* Routine to check particle placement during flocculation */
1957 /* for particle of size radd centered at (xin,yin,zin) */
1958 /* Returns flag indicating if placement is possible */
1959 int CemhydMatStatus :: chkfloc(int xin, int yin, int zin, int radd)
1960 {
1961  /* Calls: no other routines */
1962  /* Called by: makefloc */
1963  int nofits, xp, yp, zp, i, j, k;
1964  float dist, xdist, ydist, zdist, ftmp;
1965 
1966  nofits = 0; /* Flag indicating if placement is possible */
1967 
1968  /* Check all pixels within the digitized sphere volume */
1969  for ( i = xin - radd; ( ( i <= xin + radd ) && ( nofits == 0 ) ); i++ ) {
1970  xp = i;
1971  /* use periodic boundary conditions for sphere placement */
1972  if ( xp < 1 ) {
1973  xp += SYSSIZE;
1974  } else if ( xp > SYSSIZE ) {
1975  xp -= SYSSIZE;
1976  }
1977 
1978  ftmp = ( float ) ( i - xin );
1979  xdist = ftmp * ftmp;
1980  for ( j = yin - radd; ( ( j <= yin + radd ) && ( nofits == 0 ) ); j++ ) {
1981  yp = j;
1982  /* use periodic boundary conditions for sphere placement */
1983  if ( yp < 1 ) {
1984  yp += SYSSIZE;
1985  } else if ( yp > SYSSIZE ) {
1986  yp -= SYSSIZE;
1987  }
1988 
1989  ftmp = ( float ) ( j - yin );
1990  ydist = ftmp * ftmp;
1991  for ( k = zin - radd; ( ( k <= zin + radd ) && ( nofits == 0 ) ); k++ ) {
1992  zp = k;
1993  /* use periodic boundary conditions for sphere placement */
1994  if ( zp < 1 ) {
1995  zp += SYSSIZE;
1996  } else if ( zp > SYSSIZE ) {
1997  zp -= SYSSIZE;
1998  }
1999 
2000  ftmp = ( float ) ( k - zin );
2001  zdist = ftmp * ftmp;
2002 
2003  /* Compute distance from center of sphere to this pixel */
2004  dist = sqrt(xdist + ydist + zdist);
2005  if ( ( dist - 0.5 ) <= ( float ) radd ) {
2006  if ( ( cement [ xp ] [ yp ] [ zp ] != POROSITY ) ) {
2007  /* Record ID of particle hit */
2008  nofits = cement [ xp ] [ yp ] [ zp ];
2009  }
2010  }
2011 
2012  /* Check for overlap with aggregate */
2013  if ( ( fabs( xp - ( ( float ) ( SYSSIZE + 1 ) / 2.0 ) ) ) < ( ( float ) aggsize / 2.0 ) ) {
2014  nofits = AGG;
2015  }
2016  }
2017  }
2018  }
2019 
2020  /* return flag indicating if sphere will fit */
2021  return ( nofits );
2022 }
2023 
2024 
2025 /* routine to perform flocculation of particles */
2027 /* Calls: drawfloc, chkfloc, ran1 */
2028 /* Called by: main program */
2029 {
2030  int partdo, numfloc;
2031  int nstart;
2032  int nleft = 0, ckall;
2033  int xm, ym, zm, moveran;
2034  int xp, yp, zp, rp, clushit, valkeep;
2035  int iclus;
2036  int *cluspart;
2037  struct cluster *parttmp, *partpoint, *partkeep = NULL;
2038 
2039  cluspart = new int [ NPARTC ];
2040 
2041 
2042  nstart = npart; /* Counter of number of flocs remaining */
2043  for ( iclus = 1; iclus <= npart; iclus++ ) {
2044  cluspart [ iclus ] = iclus;
2045  }
2046 
2047  do {
2048 #ifdef PRINTF
2049  printf("Enter number of flocs desired at end of routine (>0) \n");
2050 #endif
2051 #ifdef CMLFILE
2052  F->get_next_line_in_section(0, ( long & )numfloc);
2053 #endif
2054 #ifdef TINYXML
2055  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, numfloc);
2056 #endif
2057  //fscanf(in, "%d",&numfloc);
2058 #ifdef PRINTF
2059  printf("%d\n", numfloc);
2060 #endif
2061  } while ( numfloc <= 0 );
2062 
2063  while ( nstart > numfloc ) {
2064  nleft = 0;
2065 
2066  /* Try to move each cluster in turn */
2067  for ( iclus = 1; iclus <= npart; iclus++ ) {
2068  if ( clust [ iclus ] == NULL ) {
2069  nleft += 1;
2070  } else {
2071  xm = ym = zm = 0;
2072  /* Generate a random move in one of 6 principal directions */
2073  moveran = ( int ) ( 6. * ran1(seed) );
2074  switch ( moveran ) {
2075  case 0:
2076  xm = 1;
2077  break;
2078  case 1:
2079  xm = ( -1 );
2080  break;
2081  case 2:
2082  ym = 1;
2083  break;
2084  case 3:
2085  ym = ( -1 );
2086  break;
2087  case 4:
2088  zm = 1;
2089  break;
2090  case 5:
2091  zm = ( -1 );
2092  break;
2093  default:
2094  break;
2095  }
2096 
2097  /* First erase all particles in cluster */
2098  partpoint = clust [ iclus ];
2099  while ( partpoint != NULL ) {
2100  xp = partpoint->x;
2101  yp = partpoint->y;
2102  zp = partpoint->z;
2103  rp = partpoint->r;
2104  drawfloc(xp, yp, zp, rp, 0, 0);
2105  partpoint = partpoint->nextpart;
2106  }
2107 
2108  ckall = 0;
2109  /* Now try to draw cluster at new location */
2110  partpoint = clust [ iclus ];
2111  while ( ( partpoint != NULL ) && ( ckall == 0 ) ) {
2112  xp = partpoint->x + xm;
2113  yp = partpoint->y + ym;
2114  zp = partpoint->z + zm;
2115  rp = partpoint->r;
2116  ckall = chkfloc(xp, yp, zp, rp);
2117  partpoint = partpoint->nextpart;
2118  }
2119 
2120  if ( ckall == 0 ) {
2121  /* Place cluster particles at new location */
2122  partpoint = clust [ iclus ];
2123  while ( partpoint != NULL ) {
2124  xp = partpoint->x + xm;
2125  yp = partpoint->y + ym;
2126  zp = partpoint->z + zm;
2127  rp = partpoint->r;
2128  valkeep = partpoint->partphase;
2129  partdo = partpoint->partid;
2130  drawfloc(xp, yp, zp, rp, partdo + CEM - 1, valkeep);
2131  /* Update particle location */
2132  partpoint->x = xp;
2133  partpoint->y = yp;
2134  partpoint->z = zp;
2135  partpoint = partpoint->nextpart;
2136  }
2137  } else {
2138  /* A cluster or aggregate was hit */
2139  /* Draw particles at old location */
2140  partpoint = clust [ iclus ];
2141  /* partkeep stores pointer to last particle in list */
2142  while ( partpoint != NULL ) {
2143  xp = partpoint->x;
2144  yp = partpoint->y;
2145  zp = partpoint->z;
2146  rp = partpoint->r;
2147  valkeep = partpoint->partphase;
2148  partdo = partpoint->partid;
2149  drawfloc(xp, yp, zp, rp, partdo + CEM - 1, valkeep);
2150  partkeep = partpoint;
2151  partpoint = partpoint->nextpart;
2152  }
2153 
2154  /* Determine the cluster hit */
2155  if ( ckall != AGG ) {
2156  clushit = cluspart [ ckall - CEM + 1 ];
2157  /* Move all of the particles from cluster clushit to cluster iclus */
2158  parttmp = clust [ clushit ];
2159  /* Attach new cluster to old one */
2160  partkeep->nextpart = parttmp;
2161  while ( parttmp != NULL ) {
2162  cluspart [ parttmp->partid ] = iclus;
2163  /* Relabel all particles added to this cluster */
2164  parttmp->clustid = iclus;
2165  parttmp = parttmp->nextpart;
2166  }
2167 
2168  /* Disengage the cluster that was hit */
2169  clust [ clushit ] = NULL;
2170  nstart -= 1;
2171  }
2172  }
2173  }
2174  }
2175 
2176  printf("Number left was %d but number of clusters is %d \n", nleft, nstart);
2177  }
2178 
2179  /* end of while loop */
2180  clusleft = nleft;
2181 
2182  delete [] cluspart;
2183 }
2184 
2185 
2186 /* routine to assess global phase fractions present in 3-D system */
2188 /* Calls: no other routines */
2189 /* Called by: main program */
2190 {
2191  long int npor, nc2s, ngyp, ncem, nagg, npozz, ninert, nflyash, nanh, nhem, ncaco3, nslag;
2192  int i, j, k, valph;
2193 
2194  /* counters for the various phase fractions */
2195  npor = 0;
2196  ngyp = 0;
2197  ncem = 0;
2198  nagg = 0;
2199  ninert = 0;
2200  nslag = 0;
2201  nc2s = 0;
2202  npozz = 0;
2203  nflyash = 0;
2204  nanh = 0;
2205  nhem = 0;
2206  ncaco3 = 0;
2207 
2208  /* Check all pixels in 3-D microstructure */
2209  for ( i = 1; i <= SYSSIZE; i++ ) {
2210  for ( j = 1; j <= SYSSIZE; j++ ) {
2211  for ( k = 1; k <= SYSSIZE; k++ ) {
2212  valph = cemreal [ i ] [ j ] [ k ];
2213  if ( valph == POROSITY ) {
2214  npor += 1;
2215  } else if ( valph == CEMID ) {
2216  ncem += 1;
2217  } else if ( valph == C2SID ) {
2218  nc2s += 1;
2219  } else if ( valph == GYPID ) {
2220  ngyp += 1;
2221  } else if ( valph == ANHYDRITE ) {
2222  nanh += 1;
2223  } else if ( valph == HEMIHYDRATE ) {
2224  nhem += 1;
2225  } else if ( valph == AGG ) {
2226  nagg += 1;
2227  } else if ( valph == POZZID ) {
2228  npozz += 1;
2229  } else if ( valph == SLAGID ) {
2230  nslag += 1;
2231  } else if ( valph == INERTID ) {
2232  ninert += 1;
2233  } else if ( valph == FLYASH ) {
2234  nflyash += 1;
2235  } else if ( valph == CACO3 ) {
2236  ncaco3 += 1;
2237  }
2238  }
2239  }
2240  }
2241 
2242  /* Output results */
2243  printf("\n Phase counts are: \n");
2244  printf("Porosity= %ld \n", npor);
2245  printf("Cement= %ld \n", ncem);
2246  printf("C2S= %ld \n", nc2s);
2247  printf("Gypsum= %ld \n", ngyp);
2248  printf("Anhydrite= %ld \n", nanh);
2249  printf("Hemihydrate= %ld \n", nhem);
2250  printf("Pozzolan= %ld \n", npozz);
2251  printf("Inert= %ld \n", ninert);
2252  printf("Slag= %ld \n", nslag);
2253  printf("CaCO3= %ld \n", ncaco3);
2254  printf("Fly Ash= %ld \n", nflyash);
2255  printf("Aggregate= %ld \n", nagg);
2256 }
2257 
2258 
2259 /* Routine to measure phase fractions as a function of distance from */
2260 /* aggregate surface*/
2262 /* Calls: no other routines */
2263 /* Called by: main program */
2264 {
2265  int phase [ 40 ], ptot;
2266  int icnt, ixlo, ixhi, iy, iz, phid, idist;
2267  FILE *aggfile;
2268 
2269  /* By default, results are sent to output file called agglist.out */
2270  aggfile = fopen("agglist.out", "w");
2271  printf("Distance Porosity Cement C2S Gypsum Anhydrite Hemihydrate Pozzolan Inert Slag CaCO3 Fly Ash\n");
2272  fprintf(aggfile, "Distance Porosity Cement C2S Gypsum Anhydrite Hemihydrate Pozzolan Inert Slag CaCO3 Fly Ash\n");
2273 
2274  /* Increase distance from aggregate in increments of one */
2275  for ( idist = 1; idist <= ( SYSSIZE - aggsize ) / 2; idist++ ) {
2276  /* Pixel left of aggregate surface */
2277  ixlo = ( ( SYSSIZE - aggsize + 2 ) / 2 ) - idist;
2278  /* Pixel right of aggregate surface */
2279  ixhi = ( ( SYSSIZE + aggsize ) / 2 ) + idist;
2280 
2281  /* Initialize phase counts for this distance */
2282  for ( icnt = 0; icnt < 39; icnt++ ) {
2283  phase [ icnt ] = 0;
2284  }
2285 
2286  ptot = 0;
2287 
2288  /* Check all pixels which are this distance from aggregate surface */
2289  for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2290  for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2291  phid = cemreal [ ixlo ] [ iy ] [ iz ];
2292  ptot += 1;
2293  if ( phid <= FLYASH ) {
2294  phase [ phid ] += 1;
2295  }
2296 
2297  phid = cemreal [ ixhi ] [ iy ] [ iz ];
2298  ptot += 1;
2299  if ( phid <= FLYASH ) {
2300  phase [ phid ] += 1;
2301  }
2302  }
2303  }
2304 
2305  /* Output results for this distance from surface */
2306  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 ]);
2307  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 ]);
2308  }
2309 
2310  fclose(aggfile);
2311 }
2312 
2313 
2314 /* routine to assess the connectivity (percolation) of a single phase */
2315 /* Two matrices are used here: one for the current burnt locations */
2316 /* the other to store the newly found burnt locations */
2318 /* Calls: no other routines */
2319 /* Called by: main program */
2320 {
2321  long int inew, ntop, nthrough, ncur, nnew, ntot;
2322  int i, j, k, nmatx [ 29000 ], nmaty [ 29000 ], nmatz [ 29000 ];
2323  int xcn, ycn, zcn, npix, x1, y1, z1, igood, nnewx [ 29000 ], nnewy [ 29000 ], nnewz [ 29000 ];
2324  int jnew, icur;
2325 
2326  do {
2327  printf("Enter phase to analyze 0) pores 1) Cement \n");
2328 #ifdef CMLFILE
2329  F->get_next_line_in_section(0, ( long & )npix);
2330 #endif
2331 #ifdef TINYXML
2332  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, npix);
2333 #endif
2334  //fscanf(in, "%d",&npix);
2335  printf("%d \n", npix);
2336  } while ( ( npix != 0 ) && ( npix != 1 ) );
2337 
2338  /* counters for number of pixels of phase accessible from top surface */
2339  /* and number which are part of a percolated pathway */
2340  ntop = 0;
2341  nthrough = 0;
2342 
2343  /* percolation is assessed from top to bottom only */
2344  /* and burning algorithm is periodic in x and y directions */
2345  k = 1;
2346  for ( i = 1; i <= SYSSIZE; i++ ) {
2347  for ( j = 1; j <= SYSSIZE; j++ ) {
2348  ncur = 0;
2349  ntot = 0;
2350  igood = 0; /* Indicates if bottom has been reached */
2351  if ( ( ( cement [ i ] [ j ] [ k ] == npix ) && ( ( cement [ i ] [ j ] [ SYSSIZE ] == npix ) ||
2352  ( cement [ i ] [ j ] [ SYSSIZE ] == ( npix + BURNTG ) ) ) ) ||
2353  ( ( cement [ i ] [ j ] [ SYSSIZE ] >= CEM ) &&
2354  ( cement [ i ] [ j ] [ k ] >= CEM ) && ( cement [ i ] [ j ] [ k ] < BURNTG ) && ( npix == 1 ) ) ) {
2355  /* Start a burn front */
2356  cement [ i ] [ j ] [ k ] += BURNTG;
2357  ntot += 1;
2358  ncur += 1;
2359  /* burn front is stored in matrices nmat* */
2360  /* and nnew* */
2361  nmatx [ ncur ] = i;
2362  nmaty [ ncur ] = j;
2363  nmatz [ ncur ] = 1;
2364  /* Burn as long as new (fuel) pixels are found */
2365  do {
2366  nnew = 0;
2367  for ( inew = 1; inew <= ncur; inew++ ) {
2368  xcn = nmatx [ inew ];
2369  ycn = nmaty [ inew ];
2370  zcn = nmatz [ inew ];
2371 
2372  /* Check all six neighbors */
2373  for ( jnew = 1; jnew <= 6; jnew++ ) {
2374  x1 = xcn;
2375  y1 = ycn;
2376  z1 = zcn;
2377  if ( jnew == 1 ) {
2378  x1 -= 1;
2379  if ( x1 < 1 ) {
2380  x1 += SYSSIZE;
2381  }
2382  } else if ( jnew == 2 ) {
2383  x1 += 1;
2384  if ( x1 > SYSSIZE ) {
2385  x1 -= SYSSIZE;
2386  }
2387  } else if ( jnew == 3 ) {
2388  y1 -= 1;
2389  if ( y1 < 1 ) {
2390  y1 += SYSSIZE;
2391  }
2392  } else if ( jnew == 4 ) {
2393  y1 += 1;
2394  if ( y1 > SYSSIZE ) {
2395  y1 -= SYSSIZE;
2396  }
2397  } else if ( jnew == 5 ) {
2398  z1 -= 1;
2399  } else if ( jnew == 6 ) {
2400  z1 += 1;
2401  }
2402 
2403  /* Nonperiodic in z direction so be sure to remain in the 3-D box */
2404  if ( ( z1 >= 1 ) && ( z1 <= SYSSIZE ) ) {
2405  if ( ( cement [ x1 ] [ y1 ] [ z1 ] == npix ) || ( ( cement [ x1 ] [ y1 ] [ z1 ] >= CEM ) &&
2406  ( cement [ x1 ] [ y1 ] [ z1 ] < BURNTG ) && ( npix == 1 ) ) ) {
2407  ntot += 1;
2408  cement [ x1 ] [ y1 ] [ z1 ] += BURNTG;
2409  nnew += 1;
2410  if ( nnew >= 29000 ) {
2411  printf("error in size of nnew \n");
2412  }
2413 
2414  nnewx [ nnew ] = x1;
2415  nnewy [ nnew ] = y1;
2416  nnewz [ nnew ] = z1;
2417  /* See if bottom of system has been reached */
2418  if ( z1 == SYSSIZE ) {
2419  igood = 1;
2420  }
2421  }
2422  }
2423  }
2424  }
2425 
2426  if ( nnew > 0 ) {
2427  ncur = nnew;
2428  /* update the burn front matrices */
2429  for ( icur = 1; icur <= ncur; icur++ ) {
2430  nmatx [ icur ] = nnewx [ icur ];
2431  nmaty [ icur ] = nnewy [ icur ];
2432  nmatz [ icur ] = nnewz [ icur ];
2433  }
2434  }
2435  } while ( nnew > 0 );
2436 
2437  ntop += ntot;
2438  if ( igood == 1 ) {
2439  nthrough += ntot;
2440  }
2441  }
2442  }
2443  }
2444 
2445  printf("Phase ID= %d \n", npix);
2446  printf("Number accessible from top= %ld \n", ntop);
2447  printf("Number contained in through pathways= %ld \n", nthrough);
2448 
2449  /* return the burnt sites to their original phase values */
2450  for ( i = 1; i <= SYSSIZE; i++ ) {
2451  for ( j = 1; j <= SYSSIZE; j++ ) {
2452  for ( k = 1; k <= SYSSIZE; k++ ) {
2453  if ( cement [ i ] [ j ] [ k ] >= BURNTG ) {
2454  cement [ i ] [ j ] [ k ] -= BURNTG;
2455  }
2456  }
2457  }
2458  }
2459 }
2460 
2461 
2462 /* Routine to output final microstructure to file */
2464 /* Calls: no other routines */
2465 /* Called by: main program */
2466 {
2467  FILE *outfile, *partfile;
2468  char filen [ 80 ], filepart [ 80 ];
2469  int ix, iy, iz, valout;
2470 
2471 #ifdef PRINTF
2472  printf("Enter name of file to save microstructure to \n");
2473 #endif
2474 #ifdef CMLFILE
2475  F->get_next_line_in_section(0, filen);
2476 #endif
2477 #ifdef TINYXML
2478  QueryStringAttributeExt(xmlFile, "Generate_microstructure", countKey++, filen);
2479 #endif
2480  //fscanf(in, "%s",filen);
2481  printf("%s\n", filen);
2482 
2483  outfile = fopen(filen, "w");
2484 
2485 #ifdef PRINTF
2486  printf("Enter name of file to save particle IDs to \n");
2487 #endif
2488 #ifdef CMLFILE
2489  F->get_next_line_in_section(0, filepart);
2490 #endif
2491 #ifdef TINYXML
2492  QueryStringAttributeExt(xmlFile, "Generate_microstructure", countKey++, filepart);
2493 #endif
2494  //fscanf(in, "%s",filepart);
2495 #ifdef PRINTF
2496  printf("%s\n", filepart);
2497 #endif
2498 
2499  partfile = fopen(filepart, "w");
2500 
2501  for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2502  for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2503  for ( ix = 1; ix <= SYSSIZE; ix++ ) {
2504  valout = cemreal [ ix ] [ iy ] [ iz ];
2505  fprintf(outfile, "%1d\n", valout); //img file
2506  valout = cement [ ix ] [ iy ] [ iz ];
2507  if ( valout < 0 ) {
2508  valout = 0;
2509  }
2510 
2511  fprintf(partfile, "%d\n", valout); //id file
2512  }
2513  }
2514  }
2515 
2516  fclose(outfile);
2517  fclose(partfile);
2518 }
2519 
2520 
2522 {
2523  int userc; /* User choice from menu */
2524  int ig, jg, kg;
2525 
2526  n_sulfate = 0;
2527  target_sulfate = 0;
2528  n_total = 0;
2529  target_total = 0;
2530  n_anhydrite = 0;
2531  target_anhydrite = 0;
2532  n_hemi = 0;
2533  target_hemi = 0;
2534 
2535  alloc_long_3D(cement, SYSIZE + 1);
2537 
2538  clust = new cluster * [ NPARTC ];
2539 
2540  /* Initialize volume array */
2541  volpart [ 0 ] = 1;
2542  volpart [ 1 ] = 19;
2543  volpart [ 2 ] = 81;
2544  volpart [ 3 ] = 179;
2545  volpart [ 4 ] = 389;
2546  volpart [ 5 ] = 739;
2547  volpart [ 6 ] = 1189;
2548  volpart [ 7 ] = 1791;
2549  volpart [ 8 ] = 2553;
2550  volpart [ 9 ] = 3695;
2551  volpart [ 10 ] = 4945;
2552  volpart [ 11 ] = 6403;
2553  volpart [ 12 ] = 8217;
2554  volpart [ 13 ] = 10395;
2555  volpart [ 14 ] = 12893;
2556  volpart [ 15 ] = 15515;
2557  volpart [ 16 ] = 18853;
2558  volpart [ 17 ] = 22575;
2559  volpart [ 18 ] = 26745;
2560  volpart [ 19 ] = 31103;
2561  volpart [ 20 ] = 36137;
2562  volpart [ 21 ] = 41851;
2563  volpart [ 22 ] = 47833;
2564  volpart [ 23 ] = 54435;
2565  volpart [ 24 ] = 61565;
2566  volpart [ 25 ] = 69599;
2567  volpart [ 26 ] = 78205;
2568  volpart [ 27 ] = 87271;
2569  volpart [ 28 ] = 97233;
2570  volpart [ 29 ] = 107783;
2571  volpart [ 30 ] = 119009;
2572  volpart [ 31 ] = 131155;
2573  volpart [ 32 ] = 143761;
2574  volpart [ 33 ] = 157563;
2575  volpart [ 34 ] = 172317;
2576  volpart [ 35 ] = 187511;
2577  volpart [ 36 ] = 203965;
2578 
2579  //printf("Enter random number seed value (a negative integer) \n");
2580  //fscanf(in, "%d",&iseed);
2581  //printf("%d \n",iseed);
2582  nseed = iseed;
2583  seed = & nseed;
2584 
2585  /* Initialize counters and system parameters */
2586  npart = 0;
2587  aggsize = 0;
2588  clusleft = 0;
2589 
2590  /* clear the 3-D system to all porosity to start */
2591  for ( ig = 1; ig <= SYSSIZE; ig++ ) {
2592  for ( jg = 1; jg <= SYSSIZE; jg++ ) {
2593  for ( kg = 1; kg <= SYSSIZE; kg++ ) {
2594  cement [ ig ] [ jg ] [ kg ] = POROSITY; //particle ID
2595  cemreal [ ig ] [ jg ] [ kg ] = POROSITY; //microstructure
2596  }
2597  }
2598  }
2599 
2600  /* present menu and execute user choice */
2601  do {
2602 #ifdef PRINTF
2603  printf(" \n Input User Choice \n");
2604  printf("1) Exit \n");
2605  printf("2) Add spherical particles (cement,gypsum, pozzolans, etc.) to microstructure \n");
2606  printf("3) Flocculate system by reducing number of particle clusters \n");
2607  printf("4) Measure global phase fractions \n");
2608  printf("5) Add an aggregate to the microstructure \n");
2609  printf("6) Measure single phase connectivity (pores or solids) \n");
2610  printf("7) Measure phase fractions vs. distance from aggregate surface \n");
2611  printf("8) Output current microstructure to file \n");
2612 #endif
2613 #ifdef CMLFILE
2614  F->get_next_line_in_section(0, ( long & )userc);
2615 #endif
2616 #ifdef TINYXML
2617  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, userc);
2618 #endif
2619  //fscanf(in, "%d",&userc);
2620  //printf("%d \n",userc);
2621  fflush(stdout);
2622 
2623  switch ( userc ) {
2624  case 2:
2625  if ( create() == 1 ) { //unsuccessful generation of microstructure due to excessive amount of particles or too dense
2626  delete [] clust;
2629  return ( 1 );
2630  }
2631 
2632  break;
2633  case 3:
2634  makefloc();
2635  break;
2636  case 4:
2637  measure();
2638  break;
2639  case 5:
2640  addagg();
2641  break;
2642  case 6:
2643  connect();
2644  break;
2645  case 7:
2646  if ( aggsize != 0 ) {
2647  measagg();
2648  } else {
2649  printf("No aggregate present. \n");
2650  }
2651 
2652  break;
2653  case 8:
2654  outmic();
2655  break;
2656  default:
2657  break;
2658  }
2659  } while ( userc != 1 );
2660 
2661  //store ID in an array
2662  for ( ig = 0; ig < SYSSIZE; ig++ ) {
2663  for ( jg = 0; jg < SYSSIZE; jg++ ) {
2664  for ( kg = 0; kg < SYSSIZE; kg++ ) {
2665  micpart [ ig ] [ jg ] [ kg ] = cement [ ig + 1 ] [ jg + 1 ] [ kg + 1 ];
2666  }
2667  }
2668  }
2669 
2671  delete [] clust;
2672  return ( 0 );
2673 }
2674 
2675 
2676 /*************************************************************************/
2677 /****************************DISTRIB3D************************************/
2678 /*************************************************************************/
2679 
2680 /* routine to create a template for the sphere of interest of radius size */
2681 /* to be used in curvature evaluation */
2682 /* Called by: runsint */
2683 /* Calls no other routines */
2685 {
2686  int icirc, xval, yval, zval;
2687  float xtmp, ytmp;
2688  float dist;
2689 
2690  /* determine and store the locations of all pixels in the 3-D sphere */
2691  icirc = 0;
2692  for ( xval = ( -size ); xval <= size; xval++ ) {
2693  xtmp = ( float ) ( xval * xval );
2694  for ( yval = ( -size ); yval <= size; yval++ ) {
2695  ytmp = ( float ) ( yval * yval );
2696  for ( zval = ( -size ); zval <= size; zval++ ) {
2697  dist = sqrt( xtmp + ytmp + ( float ) ( zval * zval ) );
2698  if ( dist <= ( ( float ) size + 0.5 ) ) {
2699  icirc += 1;
2700  if ( icirc >= MAXSPH ) {
2701  printf("Too many elements in sphere \n");
2702  printf("Must change value of MAXSPH parameter \n");
2703  printf("Currently set at %ld \n", MAXSPH);
2704  exit(1);
2705  }
2706 
2707  xsph [ icirc ] = xval;
2708  ysph [ icirc ] = yval;
2709  zsph [ icirc ] = zval;
2710  }
2711  }
2712  }
2713  }
2714 
2715  /* return the number of pixels contained in sphere of radius (size+0.5) */
2716  return ( icirc );
2717 }
2718 
2719 /* routine to count phase fractions (porosity and solids) */
2720 /* Called by main routine */
2721 /* Calls no other routines */
2723 {
2724  long int npore, nsolid [ 37 ];
2725  int ix, iy, iz;
2726 
2727  npore = 0;
2728  for ( ix = 1; ix < 37; ix++ ) {
2729  nsolid [ ix ] = 0;
2730  }
2731 
2732  /* check all pixels in the 3-D system */
2733  for ( ix = 1; ix <= SYSSIZE; ix++ ) {
2734  for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2735  for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2736  if ( mask [ ix ] [ iy ] [ iz ] == 0 ) {
2737  npore += 1;
2738  } else {
2739  nsolid [ mask [ ix ] [ iy ] [ iz ] ] += 1;
2740  }
2741  }
2742  }
2743  }
2744 
2745  printf("Pores are: %ld \n", npore);
2746  printf("Solids are: %ld %ld %ld %ld %ld %ld\n", nsolid [ 1 ], nsolid [ 2 ],
2747  nsolid [ 3 ], nsolid [ 4 ], nsolid [ 5 ], nsolid [ 6 ]);
2748 }
2749 
2750 /* routine to return number of surface faces exposed to porosity */
2751 /* for pixel located at (xin,yin,zin) */
2752 /* Called by rhcalc */
2753 /* Calls no other routines */
2754 int CemhydMatStatus :: surfpix(int xin, int yin, int zin)
2755 {
2756  int npix, ix1, iy1, iz1;
2757 
2758  npix = 0;
2759 
2760  /* check each of the six immediate neighbors */
2761  /* using periodic boundary conditions */
2762  ix1 = xin - 1;
2763  if ( ix1 < 1 ) {
2764  ix1 += SYSSIZE;
2765  }
2766 
2767  if ( mask [ ix1 ] [ yin ] [ zin ] == 0 ) {
2768  npix += 1;
2769  }
2770 
2771  ix1 = xin + 1;
2772  if ( ix1 > SYSSIZE ) {
2773  ix1 -= SYSSIZE;
2774  }
2775 
2776  if ( mask [ ix1 ] [ yin ] [ zin ] == 0 ) {
2777  npix += 1;
2778  }
2779 
2780  iy1 = yin - 1;
2781  if ( iy1 < 1 ) {
2782  iy1 += SYSSIZE;
2783  }
2784 
2785  if ( mask [ xin ] [ iy1 ] [ zin ] == 0 ) {
2786  npix += 1;
2787  }
2788 
2789  iy1 = yin + 1;
2790  if ( iy1 > SYSSIZE ) {
2791  iy1 -= SYSSIZE;
2792  }
2793 
2794  if ( mask [ xin ] [ iy1 ] [ zin ] == 0 ) {
2795  npix += 1;
2796  }
2797 
2798  iz1 = zin - 1;
2799  if ( iz1 < 1 ) {
2800  iz1 += SYSSIZE;
2801  }
2802 
2803  if ( mask [ xin ] [ yin ] [ iz1 ] == 0 ) {
2804  npix += 1;
2805  }
2806 
2807  iz1 = zin + 1;
2808  if ( iz1 > SYSSIZE ) {
2809  iz1 -= SYSSIZE;
2810  }
2811 
2812  if ( mask [ xin ] [ yin ] [ iz1 ] == 0 ) {
2813  npix += 1;
2814  }
2815 
2816  return ( npix );
2817 }
2818 
2819 /* routine to return the current hydraulic radius for phase phin */
2820 /* Calls surfpix */
2821 /* Called by runsint */
2823 {
2824  int ix, iy, iz;
2825  long int porc, surfc;
2826  float rhval;
2827 
2828  porc = surfc = 0;
2829 
2830  /* Check all pixels in the 3-D volume */
2831  for ( ix = 1; ix <= SYSSIZE; ix++ ) {
2832  for ( iy = 1; iy <= SYSSIZE; iy++ ) {
2833  for ( iz = 1; iz <= SYSSIZE; iz++ ) {
2834  if ( mask [ ix ] [ iy ] [ iz ] == phin ) {
2835  porc += 1;
2836  surfc += surfpix(ix, iy, iz);
2837  }
2838  }
2839  }
2840  }
2841 
2842  printf("Phase area count is %ld \n", porc);
2843  printf("Phase surface count is %ld \n", surfc);
2844  rhval = ( float ) porc * 6. / ( 4. * ( float ) surfc );
2845  printf("Hydraulic radius is %f \n", rhval);
2846  return ( rhval );
2847 }
2848 
2849 /* routine to return count of pixels in a spherical template which are phase */
2850 /* phin or porosity (phase=0) */
2851 /* Calls no other routines */
2852 /* Called by sysinit */
2853 int CemhydMatStatus :: countem(int xp, int yp, int zp, int phin)
2854 {
2855  int xc, yc, zc;
2856  int cumnum, ic;
2857 
2858  cumnum = 0;
2859  for ( ic = 1; ic <= nsph; ic++ ) {
2860  xc = xp + xsph [ ic ];
2861  yc = yp + ysph [ ic ];
2862  zc = zp + zsph [ ic ];
2863  /* Use periodic boundaries */
2864  if ( xc < 1 ) {
2865  xc += SYSSIZE;
2866  } else if ( xc > SYSSIZE ) {
2867  xc -= SYSSIZE;
2868  }
2869 
2870  if ( yc < 1 ) {
2871  yc += SYSSIZE;
2872  } else if ( yc > SYSSIZE ) {
2873  yc -= SYSSIZE;
2874  }
2875 
2876  if ( zc < 1 ) {
2877  zc += SYSSIZE;
2878  } else if ( zc > SYSSIZE ) {
2879  zc -= SYSSIZE;
2880  }
2881 
2882  if ( ( xc != xp ) || ( yc != yp ) || ( zc != zp ) ) {
2883  if ( ( mask [ xc ] [ yc ] [ zc ] == phin ) || ( mask [ xc ] [ yc ] [ zc ] == 0 ) ) {
2884  cumnum += 1;
2885  }
2886  }
2887  }
2888 
2889  return ( cumnum );
2890 }
2891 
2892 /* routine to initialize system by determining local curvature */
2893 /* of all phase 1 and phase 2 pixels */
2894 /* Calls countem */
2895 /* Called by runsint */
2896 void CemhydMatStatus :: sysinit(int ph1, int ph2)
2897 {
2898  int count, xl, yl, zl;
2899 
2900  count = 0;
2901  /* process all pixels in the 3-D box */
2902  for ( xl = 1; xl <= SYSSIZE; xl++ ) {
2903  for ( yl = 1; yl <= SYSSIZE; yl++ ) {
2904  for ( zl = 1; zl <= SYSSIZE; zl++ ) {
2905  /* determine local curvature */
2906  /* For phase 1 want to determine number of porosity pixels */
2907  /* (phase=0) in immediate neighborhood */
2908  if ( mask [ xl ] [ yl ] [ zl ] == ph1 ) {
2909  count = countem(xl, yl, zl, 0);
2910  }
2911 
2912  /* For phase 2 want to determine number of porosity or phase */
2913  /* 2 pixels in immediate neighborhood */
2914  if ( mask [ xl ] [ yl ] [ zl ] == ph2 ) {
2915  count = countem(xl, yl, zl, ph2);
2916  }
2917 
2918  if ( ( count < 0 ) || ( count >= nsph ) ) {
2919  printf("Error count is %d \n", count);
2920  printf("xl %d yl %d zl %d \n", xl, yl, zl);
2921  }
2922 
2923  /* case where we have a phase 1 surface pixel */
2924  /* with non-zero local curvature */
2925  if ( ( count >= 0 ) && ( mask [ xl ] [ yl ] [ zl ] == ph1 ) ) {
2926  curvature [ xl ] [ yl ] [ zl ] = count;
2927  /* update solid curvature histogram */
2928  nsolid [ count ] += 1;
2929  }
2930 
2931  /* case where we have a phase 2 surface pixel */
2932  if ( ( count >= 0 ) && ( mask [ xl ] [ yl ] [ zl ] == ph2 ) ) {
2933  curvature [ xl ] [ yl ] [ zl ] = count;
2934  /* update air curvature histogram */
2935  nair [ count ] += 1;
2936  }
2937  }
2938  }
2939  }
2940 
2941  /* end of xl loop */
2942 }
2943 
2944 /* routine to scan system and determine nsolid (ph2) and nair (ph1) */
2945 /* histograms based on values in phase and curvature arrays */
2946 /* Calls no other routines */
2947 /* Called by runsint */
2948 void CemhydMatStatus :: sysscan(int ph1, int ph2)
2949 {
2950  int xd, yd, zd, curvval;
2951 
2952  /* Scan all pixels in 3-D system */
2953  for ( xd = 1; xd <= SYSSIZE; xd++ ) {
2954  for ( yd = 1; yd <= SYSSIZE; yd++ ) {
2955  for ( zd = 1; zd <= SYSSIZE; zd++ ) {
2956  curvval = curvature [ xd ] [ yd ] [ zd ];
2957 
2958  if ( mask [ xd ] [ yd ] [ zd ] == ph2 ) {
2959  nair [ curvval ] += 1;
2960  } else if ( mask [ xd ] [ yd ] [ zd ] == ph1 ) {
2961  nsolid [ curvval ] += 1;
2962  }
2963  }
2964  }
2965  }
2966 }
2967 
2968 /* routine to return how many cells of solid curvature histogram to use */
2969 /* to accomodate nsearch pixels moving */
2970 /* want to use highest values first */
2971 /* Calls no other routines */
2972 /* Called by movepix */
2974 {
2975  int valfound, i, stop;
2976  long int nsofar;
2977 
2978  /* search histogram from top down until cumulative count */
2979  /* exceeds nsearch */
2980  valfound = nsph - 1;
2981  nsofar = 0;
2982  stop = 0;
2983  for ( i = ( nsph - 1 ); ( ( i >= 0 ) && ( stop == 0 ) ); i-- ) {
2984  nsofar += nsolid [ i ];
2985  if ( nsofar > nsearch ) {
2986  valfound = i;
2987  stop = 1;
2988  }
2989  }
2990 
2991  return ( valfound );
2992 }
2993 
2994 /* routine to determine how many cells of air curvature histogram to use */
2995 /* to accomodate nsearch moving pixels */
2996 /* want to use lowest values first */
2997 /* Calls no other routines */
2998 /* Called by movepix */
2999 
3001 {
3002  int valfound, i, stop;
3003  long int nsofar;
3004 
3005  /* search histogram from bottom up until cumulative count */
3006  /* exceeds nsearch */
3007  valfound = 0;
3008  nsofar = 0;
3009  stop = 0;
3010  for ( i = 0; ( ( i < nsph ) && ( stop == 0 ) ); i++ ) {
3011  nsofar += nair [ i ];
3012  if ( nsofar > nsearch ) {
3013  valfound = i;
3014  stop = 1;
3015  }
3016  }
3017 
3018  return ( valfound );
3019 }
3020 
3021 /* routine to move requested number of pixels (ntomove) from highest */
3022 /* curvature phase 1 (ph1) sites to lowest curvature phase 2 (ph2) sites */
3023 /* Calls procsol and procair */
3024 /* Called by runsint */
3025 int CemhydMatStatus :: movepix(int ntomove, int ph1, int ph2)
3026 {
3027  int count1, count2, ntot, countc, i, xp, yp, zp;
3028  int cmin, cmax, cfg;
3029  int alldone;
3030  long int nsolc, nairc, nsum, nsolm, nairm, nst1, nst2, next1, next2;
3031  float pck, plsol, plair;
3032 
3033  alldone = 0;
3034  /* determine critical values for removal and placement */
3035  count1 = procsol(ntomove);
3036  nsum = 0;
3037  cfg = 0;
3038  cmax = count1;
3039  for ( i = nsph; i > count1; i-- ) {
3040  if ( ( nsolid [ i ] > 0 ) && ( cfg == 0 ) ) {
3041  cfg = 1;
3042  cmax = i;
3043  }
3044 
3045  nsum += nsolid [ i ];
3046  }
3047 
3048  /* Determine movement probability for last cell */
3049  plsol = ( float ) ( ntomove - nsum ) / ( float ) nsolid [ count1 ];
3050  next1 = ntomove - nsum;
3051  nst1 = nsolid [ count1 ];
3052 
3053  count2 = procair(ntomove);
3054  nsum = 0;
3055  cmin = count2;
3056  cfg = 0;
3057  for ( i = 0; i < count2; i++ ) {
3058  if ( ( nair [ i ] > 0 ) && ( cfg == 0 ) ) {
3059  cfg = 1;
3060  cmin = i;
3061  }
3062 
3063  nsum += nair [ i ];
3064  }
3065 
3066  /* Determine movement probability for last cell */
3067  plair = ( float ) ( ntomove - nsum ) / ( float ) nair [ count2 ];
3068  next2 = ntomove - nsum;
3069  nst2 = nair [ count2 ];
3070 
3071  /* Check to see if equilibrium has been reached --- */
3072  /* no further increase in hydraulic radius is possible */
3073  if ( cmin >= cmax ) {
3074  alldone = 1;
3075  printf("Stopping - at equilibrium \n");
3076  printf("cmin- %d cmax- %d \n", cmin, cmax);
3077  return ( alldone );
3078  }
3079 
3080  /* initialize counters for performing sintering */
3081  ntot = 0;
3082  nsolc = 0;
3083  nairc = 0;
3084  nsolm = 0;
3085  nairm = 0;
3086 
3087  /* Now process each pixel in turn */
3088  for ( xp = 1; xp <= SYSSIZE; xp++ ) {
3089  for ( yp = 1; yp <= SYSSIZE; yp++ ) {
3090  for ( zp = 1; zp <= SYSSIZE; zp++ ) {
3091  countc = curvature [ xp ] [ yp ] [ zp ];
3092  /* handle phase 1 case first */
3093  if ( mask [ xp ] [ yp ] [ zp ] == ph1 ) {
3094  if ( countc > count1 ) {
3095  /* convert from phase 1 to phase 2 */
3096  mask [ xp ] [ yp ] [ zp ] = ph2;
3097 
3098  /* update appropriate histogram cells */
3099  nsolid [ countc ] -= 1;
3100  nair [ countc ] += 1;
3101  /* store the location of the modified pixel */
3102  ntot += 1;
3103  }
3104 
3105  if ( countc == count1 ) {
3106  nsolm += 1;
3107  /* generate probability for pixel being removed */
3108  pck = ran1(seed);
3109  if ( ( pck < 0 ) || ( pck > 1.0 ) ) {
3110  pck = 1.0;
3111  }
3112 
3113  if ( ( ( pck < plsol ) && ( nsolc < next1 ) ) || ( ( nst1 - nsolm ) < ( next1 - nsolc ) ) ) {
3114  nsolc += 1;
3115  /* convert phase 1 pixel to phase 2 */
3116  mask [ xp ] [ yp ] [ zp ] = ph2;
3117 
3118  /* update appropriate histogram cells */
3119  nsolid [ count1 ] -= 1;
3120  nair [ count1 ] += 1;
3121  /* store the location of the modified pixel */
3122  ntot += 1;
3123  }
3124  }
3125  }
3126  /* handle phase 2 case here */
3127  else if ( mask [ xp ] [ yp ] [ zp ] == ph2 ) {
3128  if ( countc < count2 ) {
3129  /* convert phase 2 pixel to phase 1 */
3130  mask [ xp ] [ yp ] [ zp ] = ph1;
3131 
3132  nsolid [ countc ] += 1;
3133  nair [ countc ] -= 1;
3134  ntot += 1;
3135  }
3136 
3137  if ( countc == count2 ) {
3138  nairm += 1;
3139  pck = ran1(seed);
3140  if ( ( pck < 0 ) || ( pck > 1.0 ) ) {
3141  pck = 1.0;
3142  }
3143 
3144  if ( ( ( pck < plair ) && ( nairc < next2 ) ) || ( ( nst2 - nairm ) < ( next2 - nairc ) ) ) {
3145  nairc += 1;
3146  /* convert phase 2 to phase 1 */
3147  mask [ xp ] [ yp ] [ zp ] = ph1;
3148 
3149  nsolid [ count2 ] += 1;
3150  nair [ count2 ] -= 1;
3151  ntot += 1;
3152  }
3153  }
3154  }
3155  }
3156 
3157  /* end of zp loop */
3158  }
3159 
3160  /* end of yp loop */
3161  }
3162 
3163  /* end of xloop */
3164  printf("ntot is %d \n", ntot);
3165  return ( alldone );
3166 }
3167 
3168 /* routine to execute user input number of cycles of sintering algorithm */
3169 /* Calls maketemp, rhcalc, sysinit, sysscan, and movepix */
3170 /* Called by main routine */
3171 void CemhydMatStatus :: sinter3d(int ph1id, int ph2id, float rhtarget)
3172 {
3173  int natonce, i, rade, j, rflag;
3174  int keepgo;
3175  long int curvsum1, curvsum2, pixsum1, pixsum2;
3176  float rhnow, avecurv1, avecurv2;
3177 
3178  /* initialize the solid and air count histograms */
3179  for ( i = 0; i <= 499; i++ ) {
3180  nsolid [ i ] = 0;
3181  nair [ i ] = 0;
3182  }
3183 
3184  /* Obtain needed user input */
3185  natonce = 200;
3186  rade = 3;
3187  rflag = 0; /* always initialize system */
3188 
3189  nsph = maketemp(rade);
3190  printf("nsph is %d \n", nsph);
3191  if ( rflag == 0 ) {
3192  sysinit(ph1id, ph2id);
3193  } else {
3194  sysscan(ph1id, ph2id);
3195  }
3196 
3197  i = 0;
3198  rhnow = rhcalc(ph1id);
3199  while ( ( rhnow < rhtarget ) && ( i < MAXCYC_SEAL ) ) {
3200  printf("Now: %f Target: %f \n", rhnow, rhtarget);
3201  i += 1;
3202 #ifdef PRINTF
3203  printf("Cycle: %d \n", i);
3204 #endif
3205  keepgo = movepix(natonce, ph1id, ph2id);
3206  /* If equilibrium is reached, then return to calling routine */
3207  if ( keepgo == 1 ) {
3208  return;
3209  }
3210 
3211  curvsum1 = 0;
3212  curvsum2 = 0;
3213  pixsum1 = 0;
3214  pixsum2 = 0;
3215  /* Determine average curvatures for phases 1 and 2 */
3216  for ( j = 0; j <= nsph; j++ ) {
3217  pixsum1 += nsolid [ j ];
3218  curvsum1 += ( j * nsolid [ j ] );
3219  pixsum2 += nair [ j ];
3220  curvsum2 += ( j * nair [ j ] );
3221  }
3222 
3223  avecurv1 = ( float ) curvsum1 / ( float ) pixsum1;
3224  avecurv2 = ( float ) curvsum2 / ( float ) pixsum2;
3225  printf("Ave. solid curvature: %f \n", avecurv1);
3226  printf("Ave. air curvature: %f \n", avecurv2);
3227  rhnow = rhcalc(ph1id);
3228  }
3229 }
3230 
3232 {
3233  int valin, ix, iy, iz;
3234  int ix1, iy1, iz1, k;
3235  long int voltot, surftot;
3236 
3237  for ( ix = 0; ix <= 42; ix++ ) {
3238  volume [ ix ] = surface [ ix ] = 0;
3239  }
3240 
3241  /* Read in image and accumulate volume totals */
3242  for ( iz = 1; iz <= SYSIZE; iz++ ) {
3243  for ( iy = 1; iy <= SYSIZE; iy++ ) {
3244  for ( ix = 1; ix <= SYSIZE; ix++ ) {
3245  valin = mask [ ix ] [ iy ] [ iz ];
3246  volume [ valin ] += 1;
3247  }
3248  }
3249  }
3250 
3251 
3252  for ( iz = 1; iz <= SYSIZE; iz++ ) {
3253  for ( iy = 1; iy <= SYSIZE; iy++ ) {
3254  for ( ix = 1; ix <= SYSIZE; ix++ ) {
3255  if ( mask [ ix ] [ iy ] [ iz ] != 0 ) {
3256  valin = mask [ ix ] [ iy ] [ iz ];
3257  /* Check six neighboring pixels for porosity */
3258  for ( k = 1; k <= 6; k++ ) {
3259  switch ( k ) {
3260  case 1:
3261  ix1 = ix - 1;
3262  if ( ix1 < 1 ) {
3263  ix1 += SYSIZE;
3264  }
3265 
3266  iy1 = iy;
3267  iz1 = iz;
3268  break;
3269  case 2:
3270  ix1 = ix + 1;
3271  if ( ix1 > SYSIZE ) {
3272  ix1 -= SYSIZE;
3273  }
3274 
3275  iy1 = iy;
3276  iz1 = iz;
3277  break;
3278  case 3:
3279  iy1 = iy - 1;
3280  if ( iy1 < 1 ) {
3281  iy1 += SYSIZE;
3282  }
3283 
3284  ix1 = ix;
3285  iz1 = iz;
3286  break;
3287  case 4:
3288  iy1 = iy + 1;
3289  if ( iy1 > SYSIZE ) {
3290  iy1 -= SYSIZE;
3291  }
3292 
3293  ix1 = ix;
3294  iz1 = iz;
3295  break;
3296  case 5:
3297  iz1 = iz - 1;
3298  if ( iz1 < 1 ) {
3299  iz1 += SYSIZE;
3300  }
3301 
3302  iy1 = iy;
3303  ix1 = ix;
3304  break;
3305  case 6:
3306  iz1 = iz + 1;
3307  if ( iz1 > SYSIZE ) {
3308  iz1 -= SYSIZE;
3309  }
3310 
3311  iy1 = iy;
3312  ix1 = ix;
3313  break;
3314  default:
3315  break;
3316  }
3317 
3318  if ( ( ix1 < 1 ) || ( iy1 < 1 ) || ( iz1 < 1 ) || ( ix1 > SYSIZE ) || ( iy1 > SYSIZE ) || ( iz1 > SYSIZE ) ) {
3319  printf("%d %d %d \n", ix1, iy1, iz1);
3320  exit(1);
3321  }
3322 
3323  if ( mask [ ix1 ] [ iy1 ] [ iz1 ] == 0 ) {
3324  surface [ valin ] += 1;
3325  }
3326  }
3327  }
3328  }
3329  }
3330  }
3331 
3332 #ifdef PRINTF
3333  printf("Phase Volume Surface Volume Surface \n");
3334  printf(" ID count count fraction fraction \n");
3335 #endif
3336  /* Only include clinker phases in surface area fraction calculation */
3337  surftot = surface [ 1 ] + surface [ 2 ] + surface [ 3 ] + surface [ 4 ];
3338  voltot = volume [ 1 ] + volume [ 2 ] + volume [ 3 ] + volume [ 4 ];
3339  k = 0;
3340 #ifdef PRINTF
3341  printf(" %d %8ld %8ld \n", k, volume [ 0 ], surface [ 0 ]);
3342 
3343  for ( k = 1; k <= 4; k++ ) {
3344  printf(" %d %8ld %8ld %.5f %.5f\n", k, volume [ k ], surface [ k ],
3345  ( float ) volume [ k ] / ( float ) voltot, ( float ) surface [ k ] / ( float ) surftot);
3346  }
3347 
3348  printf("Total %8ld %8ld\n\n\n", voltot, surftot);
3349 
3350  for ( k = 5; k <= 11; k++ ) {
3351  printf(" %d %8ld %8ld\n", k, volume [ k ], surface [ k ]);
3352  }
3353 
3354  printf(" 20 %8ld %8ld\n", volume [ 20 ], surface [ 20 ]);
3355 
3356  for ( k = 24; k <= 27; k++ ) {
3357  printf(" %d %8ld %8ld\n", k, volume [ k ], surface [ k ]);
3358  }
3359 
3360  printf(" 28 %8ld %8ld\n", volume [ 28 ], surface [ 28 ]);
3361 #endif
3362  ( void ) surftot;
3363  ( void ) voltot;
3364 }
3365 
3366 void CemhydMatStatus :: rand3d(int phasein, int phaseout, float xpt)
3367 {
3368  float s2, ss, sdiff, xtmp, ytmp;
3369  //static float normm[SYSIZE+1][SYSIZE+1][SYSIZE+1];
3370  //static float res[SYSIZE+1][SYSIZE+1][SYSIZE+1];
3371  double ***normm, ***res;
3372  //static float filter [32][32][32];
3373  double ***filter;
3374  int done, r [ 61 ];
3375  //static float s[61],xr[61],sum[502];
3376  float *s, *xr, *sum;
3377  double val2;
3378  double t1, t2, x1, x2, u1, u2, xrad, resmax, resmin;
3379  float xtot, filval, radius, sect, sumtot, vcrit;
3380  int valin, r1, r2, i1, i2, i3, i, j, k, j1, k1;
3381  int ido, iii, jjj, ix, iy, iz, index;
3382 #ifdef CMLFILE
3383  char tempstr [ 256 ];
3384 #endif
3385 
3386  alloc_double_3D(normm, SYSIZE + 1);
3387  alloc_double_3D(res, SYSIZE + 1);
3388  alloc_double_3D(filter, 32);
3389 
3390  s = new float [ 61 ];
3391  xr = new float [ 61 ];
3392  sum = new float [ 502 ];
3393 
3394  /* Create the Gaussian noise image */
3395  i1 = i2 = i3 = 1;
3396  for ( i = 1; i <= ( ( SYSIZE * SYSIZE * SYSIZE ) / 2 ); i++ ) {
3397  u1 = ran1(seed);
3398  u2 = ran1(seed);
3399  t1 = 2. * M_PI * u2;
3400  t2 = sqrt( -2. * log(u1) );
3401  x1 = cos(t1) * t2;
3402  x2 = sin(t1) * t2;
3403  normm [ i1 ] [ i2 ] [ i3 ] = x1;
3404  i1 += 1;
3405  if ( i1 > SYSIZE ) {
3406  i1 = 1;
3407  i2 += 1;
3408  if ( i2 > SYSIZE ) {
3409  i2 = 1;
3410  i3 += 1;
3411  }
3412  }
3413 
3414  normm [ i1 ] [ i2 ] [ i3 ] = x2;
3415  i1 += 1;
3416  if ( i1 > SYSIZE ) {
3417  i1 = 1;
3418  i2 += 1;
3419  if ( i2 > SYSIZE ) {
3420  i2 = 1;
3421  i3 += 1;
3422  }
3423  }
3424  }
3425 
3426  /* Now perform the convolution */
3427 #ifdef CMLFILE
3428  F->get_next_line_in_section(0, ( long & )ido);
3429 #endif
3430  //fscanf(in,"%d",&ido);
3431 #ifdef TINYXML
3432  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, ido);
3433 #endif
3434 
3435 #ifdef PRINTF
3436  printf("Number of points in correlation file is %d \n", ido);
3437 #endif
3438 
3439  for ( i = 1; i <= ido; i++ ) {
3440 #ifdef CMLFILE
3441  F->get_next_line_in_section(0, tempstr);
3442  sscanf(tempstr, "%d %f", & valin, & val2);
3443 #endif
3444 #ifdef TINYXML
3445  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, valin);
3446  QueryNumAttributeExt(xmlFile, "Generate_microstructure", countKey++, val2);
3447 #endif
3448  //fscanf(in,"%d %f",&valin,&val2);
3449  r [ i ] = valin;
3450  s [ i ] = ( float ) val2;
3451  xr [ i ] = ( float ) r [ i ];
3452  }
3453 
3454  ss = s [ 1 ];
3455  s2 = ss * ss;
3456  /* Load up the convolution matrix */
3457  sdiff = ss - s2;
3458  for ( i = 0; i < 31; i++ ) {
3459  iii = i * i;
3460  for ( j = 0; j < 31; j++ ) {
3461  jjj = j * j;
3462  for ( k = 0; k < 31; k++ ) {
3463  xtmp = ( float ) ( iii + jjj + k * k );
3464  radius = sqrt(xtmp);
3465  r1 = ( int ) radius + 1;
3466  r2 = r1 + 1;
3467  if ( s [ r1 ] < 0.0 ) {
3468  printf("%d and %d %f and %f with xtmp of %f\n", r1, r2, s [ r1 ], s [ r2 ], xtmp);
3469  fflush(stdout);
3470  exit(1);
3471  }
3472 
3473  xrad = radius + 1 - r1;
3474  filval = s [ r1 ] + ( s [ r2 ] - s [ r1 ] ) * xrad;
3475  filter [ i + 1 ] [ j + 1 ] [ k + 1 ] = ( filval - s2 ) / sdiff;
3476  }
3477  }
3478  }
3479 
3480  /* Now filter the image maintaining periodic boundaries */
3481  /*fixed for periodic boundaries (small microstructures) - smilauer 4.12.2006*/
3482  resmax = 0.0;
3483  resmin = 1.0;
3484  for ( i = 1; i <= SYSIZE; i++ ) {
3485  for ( j = 1; j <= SYSIZE; j++ ) {
3486  for ( k = 1; k <= SYSIZE; k++ ) {
3487  res [ i ] [ j ] [ k ] = 0.0;
3488  if ( ( float ) mask [ i ] [ j ] [ k ] == phasein ) {
3489  for ( ix = 1; ix <= 31; ix++ ) {
3490  i1 = i + ix - 1;
3491  while ( i1 < 1 ) { //if(i1<1){i1+=SYSIZE;}
3492  i1 += SYSIZE;
3493  }
3494 
3495  while ( i1 > SYSIZE ) { //else if(i1>SYSIZE){
3496  i1 -= SYSIZE;
3497  }
3498 
3499  for ( iy = 1; iy <= 31; iy++ ) {
3500  j1 = j + iy - 1;
3501  while ( j1 < 1 ) { //if(j1<1){j1+=SYSIZE;}
3502  j1 += SYSIZE;
3503  }
3504 
3505  while ( j1 > SYSIZE ) { //else if(j1>SYSIZE){
3506  j1 -= SYSIZE;
3507  }
3508 
3509  for ( iz = 1; iz <= 31; iz++ ) {
3510  k1 = k + iz - 1;
3511  while ( k1 < 1 ) { //if(k1<1){k1+=SYSIZE;}
3512  k1 += SYSIZE;
3513  }
3514 
3515  while ( k1 > SYSIZE ) { //else if(k1>SYSIZE){
3516  k1 -= SYSIZE;
3517  }
3518 
3519  res [ i ] [ j ] [ k ] += normm [ i1 ] [ j1 ] [ k1 ] * filter [ ix ] [ iy ] [ iz ];
3520  }
3521  }
3522  }
3523 
3524  if ( res [ i ] [ j ] [ k ] > resmax ) {
3525  resmax = res [ i ] [ j ] [ k ];
3526  }
3527 
3528  if ( res [ i ] [ j ] [ k ] < resmin ) {
3529  resmin = res [ i ] [ j ] [ k ];
3530  }
3531  }
3532  }
3533 
3534 #ifdef PRINTF
3535  printf(".");
3536 #endif
3537  }
3538 
3539 #ifdef PRINTF
3540  printf("%d out of %d\n", i, SYSIZE);
3541 #endif
3542  }
3543 
3544 #ifdef PRINTF
3545  printf("\n");
3546 #endif
3547  /* Now threshold the image */
3548  sect = ( resmax - resmin ) / 500.;
3549  for ( i = 1; i <= 500; i++ ) {
3550  sum [ i ] = 0.0;
3551  }
3552 
3553  xtot = 0.0;
3554  for ( i = 1; i <= SYSIZE; i++ ) {
3555  for ( j = 1; j <= SYSIZE; j++ ) {
3556  for ( k = 1; k <= SYSIZE; k++ ) {
3557  if ( ( float ) mask [ i ] [ j ] [ k ] == phasein ) {
3558  xtot += 1.0;
3559  index = 1 + ( int ) ( ( res [ i ] [ j ] [ k ] - resmin ) / sect );
3560  if ( index > 500 ) {
3561  index = 500;
3562  }
3563 
3564  sum [ index ] += 1.0;
3565  }
3566  }
3567  }
3568  }
3569 
3570  /* Determine which bin to choose for correct thresholding */
3571  sumtot = vcrit = 0.0;
3572  done = 0;
3573  for ( i = 1; ( ( i <= 500 ) && ( done == 0 ) ); i++ ) {
3574  sumtot += sum [ i ] / xtot;
3575  if ( sumtot > xpt ) {
3576  ytmp = ( float ) i;
3577  vcrit = resmin + ( resmax - resmin ) * ( ytmp - 0.5 ) / 500.;
3578  done = 1;
3579  }
3580  }
3581 
3582 #ifdef PRINTF
3583  printf("Critical volume fraction is %f\n", vcrit);
3584 #endif
3585 
3586  for ( k = 1; k <= SYSIZE; k++ ) {
3587  for ( j = 1; j <= SYSIZE; j++ ) {
3588  for ( i = 1; i <= SYSIZE; i++ ) {
3589  if ( ( float ) mask [ i ] [ j ] [ k ] == phasein ) {
3590  if ( res [ i ] [ j ] [ k ] > vcrit ) {
3591  mask [ i ] [ j ] [ k ] = phaseout;
3592  }
3593  }
3594  }
3595  }
3596  }
3597 
3598  dealloc_double_3D(normm, SYSIZE + 1);
3599  dealloc_double_3D(res, SYSIZE + 1);
3600  dealloc_double_3D(filter, 32);
3601 
3602  delete [] s;
3603  delete [] xr;
3604  delete [] sum;
3605 }
3606 
3607 
3608 /*disabled sintering*/
3610 {
3611  int i, j, k, alumval, alum2, valin;
3612  int output_img;
3613  double volin, volf [ 5 ], surff [ 5 ], rhtest, rdesire;
3614  char filen [ 80 ];
3615  //char fileout[80],filecem[80]
3616  FILE *infile;
3617  FILE *outfile_img = NULL, *outfile_id = NULL;
3618 
3620 
3621  /* Seed the random number generator */
3622  //printf("Enter random number seed (negative integer) \n");
3623  //fscanf(in, "%d",&nseed);
3624  //printf("%d\n",nseed);
3625  nseed = iseed;
3626 #ifdef PRINTF
3627  printf("%d\n", * seed);
3628 #endif
3629 
3630  /* Read in the parameters to use */
3631  //printf("Enter name of cement microstructure image file\n");
3632  //fscanf(in, "%s",filen);
3633  //printf("%s\n",filen);
3634 
3635 
3636  /* Set up the correlation filenames
3637  * printf("Enter name of sil correlation files\n");
3638  * fscanf(in, "%s",filesil);
3639  * printf("%s\n",filesil);
3640  * printf("Enter name of c3s correlation files\n");
3641  * fscanf(in, "%s",filec3s);
3642  * printf("%s\n",filec3s);
3643  * printf("Enter name of c4af correlation files\n");
3644  * fscanf(in, "%s",filealum);
3645  * printf("%s\n",filealum);
3646  */
3647 
3648  alumval = 4;
3649 
3650  //assume always C4AF
3651  /*
3652  * testfile=fopen(filealum,"r");
3653  * if(testfile==NULL){
3654  * alumflag=0;
3655  * sprintf(filealum,"%s",filecem);
3656  * strcat(filealum,".c3a");
3657  * alumval=3;
3658  * }
3659  * else{
3660  * fclose(testfile);
3661  * }
3662  */
3663  //printf("Enter name of new cement microstructure image file\n");
3664  //fscanf(in, "%s",fileout);
3665  // printf("%s\n",fileout);
3666  for ( i = 1; i <= 4; i++ ) {
3667 #ifdef CMLFILE
3668  F->get_next_line_in_section(0, volin);
3669 #endif
3670 #ifdef TINYXML
3671  if ( i == 1 ) {
3672  QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C3S_unit_frac", volin);
3673  }
3674 
3675  if ( i == 2 ) {
3676  QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C2S_unit_frac", volin);
3677  }
3678 
3679  if ( i == 3 ) {
3680  QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C3A_unit_frac", volin);
3681  }
3682 
3683  if ( i == 4 ) {
3684  QueryNumAttributeExt(xmlFile, "Generate_microstructure", "C4AF_unit_frac", volin);
3685  }
3686 
3687 #endif
3688  //fscanf(in, "%f",&volin);
3689  volf [ i ] = volin;
3690 #ifdef PRINTF
3691  printf("Volume %f\n", volf [ i ]);
3692 #endif
3693  //fscanf(in, "%f",&volin);
3694  surff [ i ] = volin;
3695 #ifdef PRINTF
3696  printf("Surface %f\n", surff [ i ]);
3697 #endif
3698  }
3699 
3700  /* Read in the original microstructure image file */
3701  if ( ( infile = fopen(filen, "r") ) != NULL ) {
3702  for ( k = 1; k <= SYSIZE; k++ ) {
3703  for ( j = 1; j <= SYSIZE; j++ ) {
3704  for ( i = 1; i <= SYSIZE; i++ ) {
3705  if ( fscanf(infile, "%d", & valin) != 1 ) {
3706  OOFEM_ERROR("distrib3d reading error");
3707  }
3708 
3709  mask [ i ] [ j ] [ k ] = valin;
3710  curvature [ i ] [ j ] [ k ] = 0;
3711  }
3712  }
3713  }
3714 
3715  fclose(infile);
3716  } else {
3717  for ( k = 1; k <= SYSIZE; k++ ) {
3718  for ( j = 1; j <= SYSIZE; j++ ) {
3719  for ( i = 1; i <= SYSIZE; i++ ) {
3720  mask [ i ] [ j ] [ k ] = cemreal [ i ] [ j ] [ k ];
3721  }
3722  }
3723  }
3724  }
3725 
3726  stat3d();
3727 
3728  /* First filtering */
3729  volin = volf [ 1 ] + volf [ 2 ];
3730  if ( volin < 1.0 ) {
3731  rand3d(1, alumval, volin);
3732 
3733  /* First sintering */
3734  stat3d();
3735  rdesire = ( surff [ 1 ] + surff [ 2 ] ) * ( float ) ( surface [ 1 ] + surface [ alumval ] );
3736  if ( rdesire != 0.0 ) {
3737  if ( ( int ) rdesire < surface [ 1 ] ) {
3738  rhtest = ( 6. / 4. ) * ( float ) ( volume [ 1 ] ) / rdesire;
3739  //sinter3d(1,alumval,rhtest);
3740  } else {
3741  rdesire = ( surff [ 3 ] + surff [ 4 ] ) * ( float ) ( surface [ 1 ] + surface [ alumval ] );
3742  if ( rdesire != 0.0 ) {
3743  rhtest = ( 6. / 4. ) * ( float ) ( volume [ alumval ] ) / rdesire;
3744  //sinter3d(alumval,1,rhtest);
3745  }
3746  }
3747  }
3748  }
3749 
3750  /* Second filtering */
3751  if ( ( volf [ 1 ] + volf [ 2 ] ) > 0.0 ) {
3752  volin = volf [ 1 ] / ( volf [ 1 ] + volf [ 2 ] );
3753  if ( volin < 1.0 ) {
3754  rand3d(1, 2, volin);
3755 
3756  /* Second sintering */
3757  stat3d();
3758  rdesire = ( surff [ 1 ] / ( surff [ 1 ] + surff [ 2 ] ) ) * ( float ) ( surface [ 1 ] + surface [ 2 ] );
3759  if ( rdesire != 0.0 ) {
3760  if ( ( int ) rdesire < surface [ 1 ] ) {
3761  rhtest = ( 6. / 4. ) * ( float ) ( volume [ 1 ] ) / rdesire;
3762  //sinter3d(1,2,rhtest);
3763  } else {
3764  rdesire = ( surff [ 2 ] / ( surff [ 1 ] + surff [ 2 ] ) ) * ( float ) ( surface [ 1 ] + surface [ 2 ] );
3765  if ( rdesire != 0.0 ) {
3766  rhtest = ( 6. / 4. ) * ( float ) ( volume [ 2 ] ) / rdesire;
3767  //sinter3d(2,1,rhtest);
3768  }
3769  }
3770  }
3771  }
3772  }
3773 
3774  /* Third (final) filtering */
3775  if ( alumval == 4 ) {
3776  volin = volf [ 4 ] / ( volf [ 4 ] + volf [ 3 ] );
3777  alum2 = 3;
3778  } else {
3779  volin = volf [ 3 ] / ( volf [ 4 ] + volf [ 3 ] );
3780  alum2 = 4;
3781  }
3782 
3783  if ( volin < 1.0 ) {
3784  rand3d(alumval, alum2, volin);
3785 
3786  /* Third (final) sintering */
3787  stat3d();
3788  if ( alumval == 4 ) {
3789  rdesire = ( surff [ 4 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3790  if ( rdesire != 0.0 ) {
3791  if ( ( int ) rdesire < surface [ 4 ] ) {
3792  rhtest = ( 6. / 4. ) * ( float ) ( volume [ 4 ] ) / rdesire;
3793  //sinter3d(alumval,alum2,rhtest);
3794  } else {
3795  rdesire = ( surff [ 3 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3796  if ( rdesire != 0.0 ) {
3797  rhtest = ( 6. / 4. ) * ( float ) ( volume [ 3 ] ) / rdesire;
3798  //sinter3d(alum2,alumval,rhtest);
3799  }
3800  }
3801  }
3802  } else {
3803  rdesire = ( surff [ 3 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3804  if ( rdesire != 0.0 ) {
3805  if ( ( int ) rdesire < surface [ 3 ] ) {
3806  rhtest = ( 6. / 4. ) * ( float ) ( volume [ 3 ] ) / rdesire;
3807  //sinter3d(alumval,alum2,rhtest);
3808  } else {
3809  rdesire = ( surff [ 4 ] / ( surff [ 3 ] + surff [ 4 ] ) ) * ( float ) ( surface [ 3 ] + surface [ 4 ] );
3810  if ( rdesire != 0.0 ) {
3811  rhtest = ( 6. / 4. ) * ( float ) ( volume [ 4 ] ) / rdesire;
3812  //sinter3d(alum2,alumval,rhtest);
3813  }
3814  }
3815  }
3816  }
3817  }
3818 
3819  /* Output final microstructure */
3820 
3821  //check whether to save it into img and id files
3822 #ifdef CMLFILE
3823  F->get_value(14, ( long & )output_img);
3824 #endif
3825 #ifdef TINYXML
3826  QueryNumAttributeExt(xmlFile, "Output_initial_microstructure", 0, output_img);
3827 #endif
3828 
3829 
3830  if ( output_img ) {
3831 #ifdef CMLFILE
3832  F->get_value(15, filen);
3833 #endif
3834 #ifdef TINYXML
3835  QueryStringAttributeExt(xmlFile, "Output_initial_microstructure_img_file", 0, filen);
3836 #endif
3837  if ( ( outfile_img = fopen(filen, "w") ) == NULL ) {
3838  printf("Output img file %s can not be created (file %s, line %d)\n", filen, __FILE__, __LINE__);
3839  exit(1);
3840  }
3841 
3842 #ifdef CMLFILE
3843  F->get_value(16, filen);
3844 #endif
3845 #ifdef TINYXML
3846  QueryStringAttributeExt(xmlFile, "Output_initial_microstructure_id_file", 0, filen);
3847 #endif
3848  if ( ( outfile_id = fopen(filen, "w") ) == NULL ) {
3849  printf("Output id file %s can not be created (file %s, line %d)\n", filen, __FILE__, __LINE__);
3850  exit(1);
3851  }
3852  }
3853 
3854  for ( k = 0; k < SYSIZE; k++ ) {
3855  for ( j = 0; j < SYSIZE; j++ ) {
3856  for ( i = 0; i < SYSIZE; i++ ) {
3857  mic [ i ] [ j ] [ k ] = mask [ i + 1 ] [ j + 1 ] [ k + 1 ];
3858  micorig [ i ] [ j ] [ k ] = mic [ i ] [ j ] [ k ];
3859  if ( output_img ) {
3860  fprintf(outfile_img, "%d\n", mic [ i ] [ j ] [ k ]);
3861  fprintf(outfile_id, "%ld\n", micpart [ i ] [ j ] [ k ]);
3862  }
3863  }
3864  }
3865  }
3866 
3867  if ( output_img ) {
3868  fclose(outfile_img);
3869  fclose(outfile_id);
3870  }
3871 
3872  //deallocate curvature
3873  dealloc_int_3D(curvature, SYSIZE + 1);
3874 
3875  //deallocate cemreal[][][]
3876  dealloc_long_3D(cemreal, SYSIZE + 1);
3877  ( void ) rhtest;
3878 }
3879 
3880 
3881 /**********************************************************/
3882 /*************DISREALNEW***********************************/
3883 /**********************************************************/
3884 
3886 {
3887  int i;
3888  double slagin, CHperslag;
3889  FILE *slagfile;
3890 
3891  for ( i = 0; i <= EMPTYP; i++ ) {
3892  creates [ i ] = 0;
3893  soluble [ i ] = 0;
3894  disprob [ i ] = 0.0;
3895  disbase [ i ] = 0.0;
3896  pHeffect [ i ] = 0.0;
3897  }
3898 
3899  /* soluble [x] - flag indicating if phase x is soluble */
3900  /* disprob [x] - probability of dissolution (relative diss. rate) */
3901  gypabsprob = 0.01; /* One sulfate absorbed per 100 CSH units */
3902  /* Source is from Taylor's Cement Chemistry for K and Na absorption */
3903  /* Note that for the first cycle, of the clinker phases only the */
3904  /* aluminates and gypsum are soluble */
3905  soluble [ C4AF ] = 1;
3906  disprob [ C4AF ] = disbase [ C4AF ] = 0.067 / DISBIAS;
3907  creates [ C4AF ] = POROSITY;
3908  pHeffect [ C4AF ] = 1.0;
3909  soluble [ C3S ] = 0;
3910  disprob [ C3S ] = disbase [ C3S ] = 0.7 / DISBIAS;
3911  creates [ C3S ] = DIFFCSH;
3912  pHeffect [ C3S ] = 1.0;
3913  soluble [ C2S ] = 0;
3914  disprob [ C2S ] = disbase [ C2S ] = 0.1 / DISBIAS;
3915  creates [ C2S ] = DIFFCSH;
3916  pHeffect [ C2S ] = 1.0;
3917  soluble [ C3A ] = 1;
3918  /* increased back to 0.4 from 0.25 7/8/99 */
3919  disprob [ C3A ] = disbase [ C3A ] = 0.4 / DISBIAS;
3920  creates [ C3A ] = POROSITY;
3921  pHeffect [ C3A ] = 1.0;
3922  soluble [ GYPSUM ] = 1;
3923  /* Changed from 0.05 to 0.015 9/29/98 */
3924  /* Changed to 0.040 10/15/98 */
3925  /* back to 0.05 from 0.10 7/8/99 */
3926  /* from 0.05 to 0.02 4/4/00 */
3927  /* from 0.02 to 0.025 8/13/01 */
3928  disprob [ GYPSUM ] = disbase [ GYPSUM ] = 0.025; /*geaendert am 04.04.00, urspr. 0.05*/
3929  /* dissolved gypsum distributed at random throughout microstructure */
3930  creates [ GYPSUM ] = POROSITY;
3931  soluble [ GYPSUMS ] = 1;
3932  pHeffect [ GYPSUM ] = 0.0;
3933  /* Changed from 0.05 to 0.015 9/29/98 */
3934  /* Changed to 0.020 10/15/98 */
3935  /* and also changed all sulfate based dissolution rates */
3936  disprob [ GYPSUMS ] = disbase [ GYPSUMS ] = disprob [ GYPSUM ];
3937  creates [ GYPSUMS ] = POROSITY;
3938  pHeffect [ GYPSUMS ] = 0.0;
3939  soluble [ ANHYDRITE ] = 1;
3940  /* set anhydrite dissolution at 4/5ths of that of gypsum */
3941  /* Source: Uchikawa et al., CCR, 1984 */
3942  disprob [ ANHYDRITE ] = disbase [ ANHYDRITE ] = 0.8 * disprob [ GYPSUM ];
3943  /* dissolved anhydrite distributed at random throughout microstructure */
3944  creates [ ANHYDRITE ] = POROSITY;
3945  pHeffect [ ANHYDRITE ] = 0.0;
3946  soluble [ HEMIHYD ] = 1;
3947  /* set hemihydrate dissolution at 3 times that of gypsum */
3948  /* Source: Uchikawa et al., CCR, 1984 */
3949  /* Changed to 1.5 times that of gypsum 6/1/00 */
3950  disprob [ HEMIHYD ] = disbase [ HEMIHYD ] = 1.5 * disprob [ GYPSUM ]; /* ge�ndert am 01.06.00, urspr. 3.0 */
3951  /* dissolved hemihydrate distributed at random throughout microstructure */
3952  creates [ HEMIHYD ] = POROSITY;
3953  pHeffect [ HEMIHYD ] = 0.0;
3954  /* CH soluble to allow for Ostwald ripening of crystals */
3955  soluble [ CH ] = 1;
3956  disprob [ CH ] = disbase [ CH ] = 0.5 / DISBIAS;
3957  creates [ CH ] = DIFFCH;
3958  pHeffect [ CH ] = 0.0;
3959  /* CaCO3 is only mildly soluble */
3960  soluble [ CACO3 ] = 1;
3961  disprob [ CACO3 ] = disbase [ CACO3 ] = 0.10 / DISBIAS;
3962  creates [ CACO3 ] = DIFFCACO3;
3963  pHeffect [ CACO3 ] = 0.0;
3964  /* Slag is not truly soluble, but use its dissolution probability for reaction probability */
3965  soluble [ SLAG ] = 0;
3966  disprob [ SLAG ] = disbase [ SLAG ] = 0.005 / DISBIAS;
3967  creates [ SLAG ] = 0;
3968  pHeffect [ SLAG ] = 1.0;
3969  soluble [ C3AH6 ] = 1;
3970  disprob [ C3AH6 ] = disbase [ C3AH6 ] = 0.01 / DISBIAS; /* changed from 0.5 to 0.01 06.09.00 */
3971  creates [ C3AH6 ] = POROSITY;
3972  pHeffect [ C3AH6 ] = 0.0;
3973  /* Ettringite is initially insoluble */
3974  soluble [ ETTR ] = 0;
3975  /* Changed to 0.008 from 0.020 3/11/99 */
3976  disprob [ ETTR ] = disbase [ ETTR ] = 0.008 / DISBIAS;
3977  creates [ ETTR ] = DIFFETTR;
3978  pHeffect [ ETTR ] = 0.0;
3979  /* Iron-rich ettringite is always insoluble */
3980  soluble [ ETTRC4AF ] = 0;
3981  disprob [ ETTRC4AF ] = disbase [ ETTRC4AF ] = 0.0;
3982  creates [ ETTRC4AF ] = ETTRC4AF;
3983  pHeffect [ ETTRC4AF ] = 0.0;
3984  /* calcium chloride is soluble */
3985  soluble [ CACL2 ] = 1;
3986  disprob [ CACL2 ] = disbase [ CACL2 ] = 0.1 / DISBIAS;
3987  creates [ CACL2 ] = DIFFCACL2;
3988  pHeffect [ CACL2 ] = 0.0;
3989  /* aluminosilicate glass is soluble */
3990  soluble [ ASG ] = 1;
3991  disprob [ ASG ] = disbase [ ASG ] = 0.2 / DISBIAS;
3992  creates [ ASG ] = DIFFAS;
3993  pHeffect [ ASG ] = 1.0;
3994  /* calcium aluminodisilicate is soluble */
3995  soluble [ CAS2 ] = 1;
3996  disprob [ CAS2 ] = disbase [ CAS2 ] = 0.2 / DISBIAS;
3997  creates [ CAS2 ] = DIFFCAS2;
3998  pHeffect [ CAS2 ] = 1.0;
3999 
4000  /* establish molar volumes and heats of formation */
4001  /* molar volumes are in cm^3/mole */
4002  /* heats of formation are in kJ/mole */
4003  /* See paper by Fukuhara et al., Cem. & Conc. Res., 11, 407-14, 1981. */
4004  /* values for Porosity are those of water */
4005  molarv [ POROSITY ] = 18.068;
4006  heatf [ POROSITY ] = ( -285.83 );
4007  waterc [ POROSITY ] = 1.0;
4008  specgrav [ POROSITY ] = 0.99707;
4009 
4010  molarv [ C3S ] = 71.129;
4011  heatf [ C3S ] = ( -2927.82 );
4012  waterc [ C3S ] = 0.0;
4013  specgrav [ C3S ] = 3.21;
4014  /* For improvement in chemical shrinkage correspondence */
4015  /* Changed molar volume of C(1.7)-S-H(4.0) to 108 5/24/95 */
4016  molarv [ CSH ] = 108.;
4017  heatf [ CSH ] = ( -3283.0 );
4018  waterc [ CSH ] = 4.0;
4019  specgrav [ CSH ] = 2.11;
4020 
4021  molarv [ CH ] = 33.1;
4022  heatf [ CH ] = ( -986.1 );
4023  waterc [ CH ] = 1.0;
4024  specgrav [ CH ] = 2.24;
4025 
4026  //uncomment to have the same values as in Pignat's thesis
4027  /*
4028  * molarv[C3S]=72.381;//changed 18.5.05
4029  * specgrav[C3S]=3.15;//changed 18.5.05
4030  * molarv[CSH]=113.5;//changed 18.5.05
4031  * specgrav[CSH]=2.0;//changed 18.5.05
4032  * molarv[CH]=33.036;//changed 18.5.05
4033  */
4034 
4035  /* Assume that calcium carbonate is in the calcite form */
4036  molarv [ CACO3 ] = 36.93;
4037  waterc [ CACO3 ] = 0.0;
4038  specgrav [ CACO3 ] = 2.71;
4039  heatf [ CACO3 ] = ( -1206.92 );
4040 
4041  molarv [ AFMC ] = 261.91;
4042  waterc [ AFMC ] = 11.0;
4043  specgrav [ AFMC ] = 2.17;
4044  /* Need to fill in heat of formation at a later date */
4045  heatf [ AFMC ] = ( 0.0 );
4046 
4047  molarv [ C2S ] = 52.513;
4048  heatf [ C2S ] = ( -2311.6 );
4049  waterc [ C2S ] = 0.0;
4050  specgrav [ C2S ] = 3.28;
4051 
4052  molarv [ C3A ] = 88.94;
4053  heatf [ C3A ] = ( -3587.8 );
4054  waterc [ C3A ] = 0.0;
4055  specgrav [ C3A ] = 3.038;
4056 
4057  molarv [ GYPSUM ] = 74.21;
4058  heatf [ GYPSUM ] = ( -2022.6 );
4059  waterc [ GYPSUM ] = 0.0;
4060  specgrav [ GYPSUM ] = 2.32;
4061  molarv [ GYPSUMS ] = 74.21;
4062  heatf [ GYPSUMS ] = ( -2022.6 );
4063  waterc [ GYPSUMS ] = 0.0;
4064  specgrav [ GYPSUMS ] = 2.32;
4065 
4066  molarv [ ANHYDRITE ] = 52.16;
4067  heatf [ ANHYDRITE ] = ( -1424.6 );
4068  waterc [ ANHYDRITE ] = 0.0;
4069  specgrav [ ANHYDRITE ] = 2.61;
4070 
4071  molarv [ HEMIHYD ] = 52.973;
4072  heatf [ HEMIHYD ] = ( -1574.65 );
4073  waterc [ HEMIHYD ] = 0.0;
4074  specgrav [ HEMIHYD ] = 2.74;
4075 
4076  molarv [ C4AF ] = 130.29;
4077  heatf [ C4AF ] = ( -5090.3 );
4078  waterc [ C4AF ] = 0.0;
4079  specgrav [ C4AF ] = 3.73;
4080 
4081  molarv [ C3AH6 ] = 150.12;
4082  heatf [ C3AH6 ] = ( -5548. );
4083  waterc [ C3AH6 ] = 6.0;
4084  specgrav [ C3AH6 ] = 2.52;
4085 
4086  /* Changed molar volume of FH3 to 69.8 (specific gravity of 3.06) 5/23/95 */
4087  molarv [ FH3 ] = 69.803;
4088  heatf [ FH3 ] = ( -823.9 );
4089  waterc [ FH3 ] = 3.0;
4090  specgrav [ FH3 ] = 3.062;
4091 
4092  molarv [ ETTRC4AF ] = 735.01;
4093  heatf [ ETTRC4AF ] = ( -17539.0 );
4094  waterc [ ETTRC4AF ] = 26.0;
4095  specgrav [ ETTRC4AF ] = 1.7076;
4096  /* Changed molar volue of ettringite to 735 (spec. gr.=1.7076) 5/24/95 */
4097  molarv [ ETTR ] = 735.01;
4098  heatf [ ETTR ] = ( -17539.0 );
4099  waterc [ ETTR ] = 26.0;
4100  specgrav [ ETTR ] = 1.7076;
4101 
4102  molarv [ AFM ] = 312.82;
4103  heatf [ AFM ] = ( -8778.0 );
4104  /* Each mole of AFM which forms requires 12 moles of water, */
4105  /* two of which are supplied by gypsum in forming ETTR */
4106  /* leaving 10 moles to be incorporated from free water */
4107  waterc [ AFM ] = 10.0;
4108  specgrav [ AFM ] = 1.99;
4109 
4110  molarv [ CACL2 ] = 51.62;
4111  heatf [ CACL2 ] = ( -795.8 );
4112  waterc [ CACL2 ] = 0;
4113  specgrav [ CACL2 ] = 2.15;
4114 
4115  molarv [ FREIDEL ] = 296.662;
4116  /* No data available for heat of formation */
4117  heatf [ FREIDEL ] = ( 0.0 );
4118  /* 10 moles of H2O per mole of Freidel's salt */
4119  waterc [ FREIDEL ] = 10.0;
4120  specgrav [ FREIDEL ] = 1.892;
4121 
4122  /* Basic reaction is 2CH + ASG + 6H --> C2ASH8 (Stratlingite) */
4123  molarv [ ASG ] = 49.9;
4124  /* No data available for heat of formation */
4125  heatf [ ASG ] = 0.0;
4126  waterc [ ASG ] = 0.0;
4127  specgrav [ ASG ] = 3.247;
4128 
4129  molarv [ CAS2 ] = 100.62;
4130  /* No data available for heat of formation */
4131  heatf [ CAS2 ] = 0.0;
4132  waterc [ CAS2 ] = 0.0;
4133  specgrav [ CAS2 ] = 2.77;
4134 
4135  molarv [ STRAT ] = 215.63;
4136  /* No data available for heat of formation */
4137  heatf [ STRAT ] = 0.0;
4138  /* 8 moles of water per mole of stratlingite */
4139  waterc [ STRAT ] = 8.0;
4140  specgrav [ STRAT ] = 1.94;
4141 
4142  molarv [ POZZ ] = 27.0;
4143  /* Use heat of formation of SiO2 (quartz) for unreacted pozzolan */
4144  /* Source- Handbook of Chemistry and Physics */
4145  heatf [ POZZ ] = -907.5;
4146  waterc [ POZZ ] = 0.0;
4147  specgrav [ POZZ ] = 2.22;
4148 
4149  /* Data for Pozzolanic CSH based on work of Atlassi, DeLarrard, */
4150  /* and Jensen */
4151  /* gives a chemical shrinkage of 0.2 g H2O/g CSF */
4152  /* heat of formation estimated based on heat release of */
4153  /* 780 J/g Condensed Silica Fume */
4154  /* Changed stoichiometry to be C(1.1)SH(3.9) to see effect on */
4155  /* results 1/22/97 */
4156  /* MW is 191.8 g/mole */
4157  /* Changed molar volume to 101.81 3/10/97 */
4158  molarv [ POZZCSH ] = 101.81;
4159  waterc [ POZZCSH ] = 3.9;
4160  specgrav [ POZZCSH ] = 1.884;
4161  heatf [ POZZCSH ] = ( -2.1 );
4162 
4163  /* Assume inert filler has same specific gravity and molar volume as SiO2 */
4164  molarv [ INERT ] = 27.0;
4165  heatf [ INERT ] = 0.0;
4166  waterc [ INERT ] = 0.0;
4167  specgrav [ INERT ] = 2.2;
4168 
4169  molarv [ ABSGYP ] = 74.21;
4170  heatf [ ABSGYP ] = ( -2022.6 );
4171  waterc [ ABSGYP ] = 0.0;
4172  specgrav [ ABSGYP ] = 2.32;
4173 
4174  molarv [ EMPTYP ] = 18.068;
4175  heatf [ EMPTYP ] = ( -285.83 );
4176  waterc [ EMPTYP ] = 0.0;
4177  specgrav [ EMPTYP ] = 0.99707;
4178 
4179  /* Read in values for alkali characteristics and */
4180  /* convert them to fractions from percentages */
4181  // First define non-zero values due to divisions
4182  //totsodium=0.2/100;
4183  //totpotassium=0.5/100;
4184  //rssodium=0.03/100;
4185  //rspotassium=0.25/100;
4186  specgrav [ SLAG ] = 2.87;
4187  specgrav [ SLAGCSH ] = 2.35;
4188  molarv [ SLAG ] = 945.72;
4189  molarv [ SLAGCSH ] = 1717.53;
4190  slagcasi = 1.433;
4191  slaghydcasi = 1.35;
4192  siperslag = 15.0;
4193  waterc [ SLAGCSH ] = 5.533 * siperslag;
4194  slagc3a = 1.0;
4195  slagreact = 1.0;
4196 
4197 #ifdef CMLFILE
4198  F->get_value(19, totsodium);
4199  F->get_value(20, totpotassium);
4200  F->get_value(21, rssodium);
4201  F->get_value(22, rspotassium);
4202 #endif
4203 #ifdef TINYXML
4204  QueryNumAttributeExt(xmlFile, "Total_sodium", 0, totsodium);
4205  QueryNumAttributeExt(xmlFile, "Total_potassium", 0, totpotassium);
4206  QueryNumAttributeExt(xmlFile, "Readily_soluble_sodium", 0, rssodium);
4207  QueryNumAttributeExt(xmlFile, "Readily_soluble_potassium", 0, rspotassium);
4208 #endif
4209 
4210  /*fscanf(alkalifile,"%f",&totsodium);
4211  * fscanf(alkalifile,"%f",&totpotassium);
4212  * fscanf(alkalifile,"%f",&rssodium);
4213  * fscanf(alkalifile,"%f",&rspotassium);
4214  */
4215 
4216  totsodium /= 100.;
4217  totpotassium /= 100.;
4218  rssodium /= 100.;
4219  rspotassium /= 100.;
4220 
4221 
4222  if ( pHactive ) {
4223  /* Read in values for slag characteristics */
4224 
4225  if ( ( slagfile = fopen("slagchar.dat", "r") ) == NULL ) {
4226  OOFEM_ERROR("Slag file can not be opened");
4227  }
4228 
4229 
4230  if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4231  OOFEM_ERROR("slagfile reading error");
4232  }
4233 
4234  if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4235  OOFEM_ERROR("slagfile reading error");
4236  }
4237 
4238  if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4239  OOFEM_ERROR("slagfile reading error");
4240  }
4241 
4242  specgrav [ SLAG ] = slagin;
4243  if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4244  OOFEM_ERROR("slagfile reading error");
4245  }
4246 
4247  specgrav [ SLAGCSH ] = slagin;
4248  if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4249  OOFEM_ERROR("slagfile reading error");
4250  }
4251 
4252  molarv [ SLAG ] = slagin;
4253  if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4254  OOFEM_ERROR("slagfile reading error");
4255  }
4256 
4257  molarv [ SLAGCSH ] = slagin;
4258  if ( fscanf(slagfile, "%lf", & slagcasi) != 1 ) {
4259  OOFEM_ERROR("slagfile reading error");
4260  }
4261 
4262  if ( fscanf(slagfile, "%lf", & slaghydcasi) != 1 ) {
4263  OOFEM_ERROR("slagfile reading error");
4264  }
4265 
4266  if ( fscanf(slagfile, "%lf", & siperslag) != 1 ) {
4267  OOFEM_ERROR("slagfile reading error");
4268  }
4269 
4270  if ( fscanf(slagfile, "%lf", & slagin) != 1 ) {
4271  OOFEM_ERROR("slagfile reading error");
4272  }
4273 
4274  waterc [ SLAGCSH ] = slagin * siperslag;
4275  if ( fscanf(slagfile, "%lf", & slagc3a) != 1 ) {
4276  OOFEM_ERROR("slagfile reading error");
4277  }
4278 
4279  if ( fscanf(slagfile, "%lf", & slagreact) != 1 ) {
4280  OOFEM_ERROR("slagfile reading error");
4281  }
4282 
4283  waterc [ SLAG ] = 0.0;
4284  heatf [ SLAG ] = 0.0;
4285  heatf [ SLAGCSH ] = 0.0;
4286  fclose(slagfile);
4287  }
4288 
4289  //use default values
4290  specgrav [ SLAG ] = 2.87;
4291  specgrav [ SLAGCSH ] = 2.35;
4292  molarv [ SLAG ] = 945.72;
4293  molarv [ SLAGCSH ] = 1717.53;
4294  slagcasi = 1.4333;
4295  slaghydcasi = 1.35;
4296  siperslag = 15.0;
4297  waterc [ SLAGCSH ] = 5.533 * siperslag;
4298  slagc3a = 1.0;
4299  slagreact = 1.0;
4300 
4301  /* Compute slag probabilities as defined above */
4302  CHperslag = siperslag * ( slaghydcasi - slagcasi ) + 3. * slagc3a;
4303  if ( CHperslag < 0.0 ) {
4304  CHperslag = 0.0;
4305  }
4306 
4307  p2slag = ( molarv [ SLAG ] + molarv [ CH ] * CHperslag + molarv [ POROSITY ] * ( waterc [ SLAGCSH ] - CHperslag + waterc [ C3AH6 ] * slagc3a ) - molarv [ SLAGCSH ] - molarv [ C3AH6 ] * slagc3a ) / molarv [ SLAG ];
4308  p1slag = 1.0 - p2slag;
4309  p3slag = ( molarv [ SLAGCSH ] / molarv [ SLAG ] ) - p1slag;
4310  p4slag = CHperslag * molarv [ CH ] / molarv [ SLAG ];
4311  p5slag = slagc3a * molarv [ C3A ] / molarv [ SLAG ];
4312  if ( p5slag > 1.0 ) {
4313  p5slag = 1.0;
4314  printf("Error in range of C3A/slag value... reset to 1.0 \n");
4315  }
4316 }
4317 
4318 /* routine to check if a pixel located at (xck,yck,zck) is on an edge */
4319 /* (in contact with pore space) in 3-D system */
4320 /* Called by passone */
4321 /* Calls no other routines */
4322 int CemhydMatStatus :: chckedge(int xck, int yck, int zck)
4323 {
4324  int edgeback, x2, y2, z2;
4325  int ip;
4326 
4327  edgeback = 0;
4328 
4329  /* Check all six neighboring pixels */
4330  /* with periodic boundary conditions */
4331  for ( ip = 0; ( ( ip < NEIGHBORS ) && ( edgeback == 0 ) ); ip++ ) {
4332  x2 = xck + xoff [ ip ];
4333  y2 = yck + yoff [ ip ];
4334  z2 = zck + zoff [ ip ];
4335  if ( x2 >= SYSIZE ) {
4336  x2 = 0;
4337  }
4338 
4339  if ( x2 < 0 ) {
4340  x2 = SYSIZEM1;
4341  }
4342 
4343  if ( y2 >= SYSIZE ) {
4344  y2 = 0;
4345  }
4346 
4347  if ( y2 < 0 ) {
4348  y2 = SYSIZEM1;
4349  }
4350 
4351  if ( z2 >= SYSIZE ) {
4352  z2 = 0;
4353  }
4354 
4355  if ( z2 < 0 ) {
4356  z2 = SYSIZEM1;
4357  }
4358 
4359  if ( mic [ x2 ] [ y2 ] [ z2 ] == POROSITY ) {
4360  edgeback = 1;
4361  }
4362  }
4363 
4364  return ( edgeback );
4365 }
4366 
4367 /* routine for first pass through microstructure during dissolution */
4368 /* low and high indicate phase ID range to check for surface sites */
4369 /* Called by dissolve */
4370 /* Calls chckedge */
4371 void CemhydMatStatus :: passone(int low, int high, int cycid, int cshexflag)
4372 {
4373  int i, xid, yid, zid, phid, edgef, phread, cshcyc;
4374 
4375  /* gypready used to determine if any soluble gypsum remains */
4376  if ( ( low <= GYPSUM ) && ( GYPSUM <= high ) ) {
4377  gypready = 0;
4378  }
4379 
4380  /* Zero out count for the relevant phases */
4381  for ( i = low; i <= high; i++ ) {
4382  count [ i ] = 0;
4383  }
4384 
4385  /* Scan the entire 3-D microstructure */
4386  for ( xid = 0; xid < SYSIZE; xid++ ) {
4387  for ( yid = 0; yid < SYSIZE; yid++ ) {
4388  for ( zid = 0; zid < SYSIZE; zid++ ) {
4389  phread = mic [ xid ] [ yid ] [ zid ];
4390  /* Update heat data and water consumed for solid CSH */
4391  if ( ( cshexflag == 1 ) && ( phread == CSH ) ) {
4392  cshcyc = cshage [ xid ] [ yid ] [ zid ];
4393  heatsum += heatf [ CSH ] / molarvcsh [ cshcyc ];
4394  molesh2o += watercsh [ cshcyc ] / molarvcsh [ cshcyc ];
4395  }
4396 
4397  /* Identify phase and update count */
4398  phid = 60;
4399  for ( i = low; ( ( i <= high ) && ( phid == 60 ) ); i++ ) {
4400  if ( mic [ xid ] [ yid ] [ zid ] == i ) {
4401  phid = i;
4402  /* Update count for this phase */
4403  count [ i ] += 1;
4404  if ( ( i == GYPSUM ) || ( i == GYPSUMS ) ) {
4405  gypready += 1;
4406  }
4407 
4408  /* If first cycle, then accumulate initial counts */
4409  if ( cycid == 1 ) { //fixed (ncyc cancelled)
4410  if ( i == POROSITY ) {
4411  porinit += 1;
4412  }
4413  /* Ordered in terms of likely volume fractions */
4414  /* (largest to smallest) to speed execution */
4415  else if ( i == C3S ) {
4416  c3sinit += 1;
4417  } else if ( i == C2S ) {
4418  c2sinit += 1;
4419  } else if ( i == C3A ) {
4420  c3ainit += 1;
4421  } else if ( i == C4AF ) {
4422  c4afinit += 1;
4423  } else if ( i == GYPSUM ) {
4424  ncsbar += 1;
4425  } else if ( i == GYPSUMS ) {
4426  ncsbar += 1;
4427  } else if ( i == ANHYDRITE ) {
4428  anhinit += 1;
4429  } else if ( i == HEMIHYD ) {
4430  heminit += 1;
4431  } else if ( i == POZZ ) {
4432  nfill += 1;
4433  } else if ( i == SLAG ) {
4434  slaginit += 1;
4435  } else if ( i == ETTR ) {
4436  netbar += 1;
4437  } else if ( i == ETTRC4AF ) {
4438  netbar += 1;
4439  }
4440  }
4441  }
4442  }
4443 
4444  if ( phid != 60 ) {
4445  /* If phase is soluble, see if it is in contact with porosity */
4446  if ( ( cycid != 0 ) && ( soluble [ phid ] == 1 ) ) {
4447  edgef = chckedge(xid, yid, zid);
4448  if ( edgef == 1 ) {
4449  /* Surface eligible species has an ID OFFSET greater than its original value */
4450  mic [ xid ] [ yid ] [ zid ] += OFFSET;
4451  }
4452  }
4453  }
4454  }
4455 
4456  /* end of zid */
4457  }
4458 
4459  /* end of yid */
4460  }
4461 
4462  /* end of xid */
4463 }
4464 
4465 /* routine to locate a diffusing CSH species near dissolution source */
4466 /* at (xcur,ycur,zcur) */
4467 /* Called by dissolve */
4468 /* Calls no other routines */
4469 int CemhydMatStatus :: loccsh(int xcur, int ycur, int zcur, int extent)
4470 {
4471  int effort, tries, xmod, ymod, zmod;
4472  struct ants *antnew;
4473 
4474  effort = 0; /* effort indicates if appropriate location found */
4475  tries = 0;
4476  /* 500 tries in immediate vicinity */
4477  while ( ( effort == 0 ) && ( tries < 500 ) ) {
4478  tries += 1;
4479  xmod = ( -extent ) + ( int ) ( ( 2. * ( float ) extent + 1. ) * ran1(seed) );
4480  ymod = ( -extent ) + ( int ) ( ( 2. * ( float ) extent + 1. ) * ran1(seed) );
4481  zmod = ( -extent ) + ( int ) ( ( 2. * ( float ) extent + 1. ) * ran1(seed) );
4482  if ( xmod > extent ) {
4483  xmod = extent;
4484  }
4485 
4486  if ( ymod > extent ) {
4487  ymod = extent;
4488  }
4489 
4490  if ( zmod > extent ) {
4491  zmod = extent;
4492  }
4493 
4494  xmod += xcur;
4495  ymod += ycur;
4496  zmod += zcur;
4497  /* Periodic boundaries */
4498  if ( xmod >= SYSIZE ) {
4499  xmod -= SYSIZE;
4500  } else if ( xmod < 0 ) {
4501  xmod += SYSIZE;
4502  }
4503 
4504  if ( zmod >= SYSIZE ) {
4505  zmod -= SYSIZE;
4506  } else if ( zmod < 0 ) {
4507  zmod += SYSIZE;
4508  }
4509 
4510  if ( ymod < 0 ) {
4511  ymod += SYSIZE;
4512  } else if ( ymod >= SYSIZE ) {
4513  ymod -= SYSIZE;
4514  }
4515 
4516  if ( mic [ xmod ] [ ymod ] [ zmod ] == POROSITY ) {
4517  effort = 1;
4518  mic [ xmod ] [ ymod ] [ zmod ] = DIFFCSH;
4519  nmade += 1;
4520  ngoing += 1;
4521  /* Add CSH diffusing species to the linked list */
4522  antnew = ( struct ants * ) malloc( sizeof( struct ants ) );
4523  antnew->x = xmod;
4524  antnew->y = ymod;
4525  antnew->z = zmod;
4526  antnew->id = DIFFCSH;
4527  antnew->cycbirth = cyccnt;
4528  /* Now connect this ant structure to end of linked list */
4529  antnew->prevant = tailant;
4530  tailant->nextant = antnew;
4531  antnew->nextant = NULL;
4532  tailant = antnew;
4533  }
4534  }
4535 
4536  return ( effort );
4537 }
4538 
4539 /* routine to count number of pore pixels in a cube of size boxsize */
4540 /* centered at (qx,qy,qz) */
4541 /* Called by makeinert */
4542 /* Calls no other routines */
4543 int CemhydMatStatus :: countbox(int boxsize, int qx, int qy, int qz)
4544 {
4545  int nfound, ix, iy, iz, qxlo, qxhi, qylo, qyhi, qzlo, qzhi;
4546  int hx, hy, hz, boxhalf;
4547 
4548  boxhalf = boxsize / 2;
4549  nfound = 0;
4550  qxlo = qx - boxhalf;
4551  qxhi = qx + boxhalf;
4552  qylo = qy - boxhalf;
4553  qyhi = qy + boxhalf;
4554  qzlo = qz - boxhalf;
4555  qzhi = qz + boxhalf;
4556  /* Count the number of requisite pixels in the 3-D cube box */
4557  /* using periodic boundaries */
4558  for ( ix = qxlo; ix <= qxhi; ix++ ) {
4559  hx = ix;
4560  if ( hx < 0 ) {
4561  hx += SYSIZE;
4562  } else if ( hx >= SYSIZE ) {
4563  hx -= SYSIZE;
4564  }
4565 
4566  for ( iy = qylo; iy <= qyhi; iy++ ) {
4567  hy = iy;
4568  if ( hy < 0 ) {
4569  hy += SYSIZE;
4570  } else if ( hy >= SYSIZE ) {
4571  hy -= SYSIZE;
4572  }
4573 
4574  for ( iz = qzlo; iz <= qzhi; iz++ ) {
4575  hz = iz;
4576  if ( hz < 0 ) {
4577  hz += SYSIZE;
4578  } else if ( hz >= SYSIZE ) {
4579  hz -= SYSIZE;
4580  }
4581 
4582  /* Count if porosity, diffusing species, or empty porosity */
4583  if ( ( mic [ hx ] [ hy ] [ hz ] < C3S ) || ( mic [ hx ] [ hy ] [ hz ] > ABSGYP ) ) {
4584  nfound += 1;
4585  }
4586  }
4587  }
4588  }
4589 
4590  return ( nfound );
4591 }
4592 
4593 /* routine to count number of special pixels in a cube of size boxsize */
4594 /* centered at (qx,qy,qz) */
4595 /* special pixels are those not belonging to one of the cement clinker, */
4596 /* calcium sulfate, or pozzolanic mineral admixture phases */
4597 /* Called by addrand */
4598 /* Calls no other routines */
4599 int CemhydMatStatus :: countboxc(int boxsize, int qx, int qy, int qz)
4600 {
4601  int nfound, ix, iy, iz, qxlo, qxhi, qylo, qyhi, qzlo, qzhi;
4602  int hx, hy, hz, boxhalf;
4603 
4604  boxhalf = boxsize / 2;
4605  nfound = 0;
4606  qxlo = qx - boxhalf;
4607  qxhi = qx + boxhalf;
4608  qylo = qy - boxhalf;
4609  qyhi = qy + boxhalf;
4610  qzlo = qz - boxhalf;
4611  qzhi = qz + boxhalf;
4612  /* Count the number of requisite pixels in the 3-D cube box */
4613  /* using periodic boundaries */
4614  for ( ix = qxlo; ix <= qxhi; ix++ ) {
4615  hx = ix;
4616  if ( hx < 0 ) {
4617  hx += SYSIZE;
4618  } else if ( hx >= SYSIZE ) {
4619  hx -= SYSIZE;
4620  }
4621 
4622  for ( iy = qylo; iy <= qyhi; iy++ ) {
4623  hy = iy;
4624  if ( hy < 0 ) {
4625  hy += SYSIZE;
4626  } else if ( hy >= SYSIZE ) {
4627  hy -= SYSIZE;
4628  }
4629 
4630  for ( iz = qzlo; iz <= qzhi; iz++ ) {
4631  hz = iz;
4632  if ( hz < 0 ) {
4633  hz += SYSIZE;
4634  } else if ( hz >= SYSIZE ) {
4635  hz -= SYSIZE;
4636  }
4637 
4638  /* Count if not cement clinker */
4639  if ( ( mic [ hx ] [ hy ] [ hz ] < C3S ) || ( mic [ hx ] [ hy ] [ hz ] > POZZ ) ) {
4640  nfound += 1;
4641  }
4642  }
4643  }
4644  }
4645 
4646  return ( nfound );
4647 }
4648 
4649 /* routine to create ndesire pixels of empty pore space to simulate */
4650 /* self-desiccation, or external drying */
4651 /* Called by dissolve */
4652 /* Calls countbox */
4653 /* each ....togo structure contains information only at x,y,z*/
4654 /* headtogo is the first voxel where the water is taken from*/
4655 
4656 
4657 void CemhydMatStatus :: makeinert(long int ndesire) {
4658  struct togo *headtogo, *tailtogo, *newtogo, *lasttogo, *onetogo;
4659  long int idesire;
4660  int px, py, pz, placed, cntpore, cntmax;
4661 
4662  /* First allocate the first element of the linked list */
4663  headtogo = ( struct togo * ) malloc( sizeof( struct togo ) );
4664  headtogo->x = headtogo->y = headtogo->z = ( -1 );
4665  headtogo->npore = 0;
4666  headtogo->nexttogo = NULL;
4667  headtogo->prevtogo = NULL;
4668  tailtogo = headtogo;
4669  cntmax = 0;
4670 
4671 #ifdef PRINTF
4672  printf("In makeinert with %ld needed elements \n", ndesire);
4673 #endif
4674 
4675  fflush(stdout);
4676  /* Add needed number of elements to the end of the list */
4677  for ( idesire = 2; idesire <= ndesire; idesire++ ) {
4678  newtogo = ( struct togo * ) malloc( sizeof( struct togo ) );
4679  newtogo->npore = 0;
4680  newtogo->x = newtogo->y = newtogo->z = ( -1 );
4681  tailtogo->nexttogo = newtogo;
4682  newtogo->prevtogo = tailtogo;
4683  tailtogo = newtogo;
4684  }
4685 
4686  /* Now scan the microstructure and rank the sites */
4687  for ( px = 0; px < SYSIZE; px++ ) {
4688  for ( py = 0; py < SYSIZE; py++ ) {
4689  for ( pz = 0; pz < SYSIZE; pz++ ) {
4690  if ( mic [ px ] [ py ] [ pz ] == POROSITY ) {
4691  cntpore = countbox(cubesize, px, py, pz);
4692  if ( cntpore > cntmax ) {
4693  cntmax = cntpore;
4694  }
4695 
4696  /* Store this site value at appropriate place in */
4697  /* sorted linked list */
4698  if ( cntpore > ( tailtogo->npore ) ) {
4699  placed = 0;
4700  lasttogo = tailtogo;
4701  while ( placed == 0 ) {
4702  newtogo = lasttogo->prevtogo;
4703  if ( newtogo == NULL ) { //if at the beginning of the list (tailtogo->prevtogo==NULL)
4704  placed = 2;
4705  } else {
4706  if ( cntpore <= ( newtogo->npore ) ) {
4707  placed = 1;
4708  }
4709  }
4710 
4711  if ( placed == 0 ) {
4712  lasttogo = newtogo;
4713  }
4714  }
4715 
4716  onetogo = ( struct togo * ) malloc( sizeof( struct togo ) );
4717  onetogo->x = px;
4718  onetogo->y = py;
4719  onetogo->z = pz;
4720  onetogo->npore = cntpore;
4721  /* Insertion at the head of the list */
4722  if ( placed == 2 ) {
4723  onetogo->prevtogo = NULL;
4724  onetogo->nexttogo = headtogo;
4725  headtogo->prevtogo = onetogo;
4726  headtogo = onetogo;
4727  }
4728 
4729  if ( placed == 1 ) {
4730  onetogo->nexttogo = lasttogo;
4731  onetogo->prevtogo = newtogo;
4732  lasttogo->prevtogo = onetogo;
4733  newtogo->nexttogo = onetogo;
4734  }
4735 
4736  /* Eliminate the last element */
4737  lasttogo = tailtogo;
4738  tailtogo = tailtogo->prevtogo;
4739  tailtogo->nexttogo = NULL;
4740  //printf("DEMEM lasttogo1 addr %p\n", lasttogo);
4741  free(lasttogo);
4742  }
4743  }
4744  }
4745  }
4746  }
4747 
4748  /* Now remove the sites */
4749  /* starting at the head of the list */
4750  /* and deallocate all of the used memory */
4751  for ( idesire = 1; idesire <= ndesire; idesire++ ) {
4752  px = headtogo->x;
4753  py = headtogo->y;
4754  pz = headtogo->z;
4755  if ( px != ( -1 ) ) {
4756  mic [ px ] [ py ] [ pz ] = EMPTYP;
4757  count [ POROSITY ] -= 1;
4758  count [ EMPTYP ] += 1;
4759  }
4760 
4761  lasttogo = headtogo;
4762  headtogo = headtogo->nexttogo;
4763  //printf("DEMEM lasttogo2 addr %p\n", (const void *)lasttogo);
4764  free(lasttogo);
4765  }
4766 
4767  /* If only small cubes of porosity were found, then adjust */
4768  /* cubesize to have a more efficient search in the future */
4769  if ( cubesize > CUBEMIN ) {
4770  if ( ( 2 * cntmax ) < ( cubesize * cubesize * cubesize ) ) {
4771  cubesize -= 2;
4772  }
4773  }
4774 }
4775 
4776 
4777 /* routine to add extra SLAG CSH when SLAG reacts */
4778 /* SLAG located at (xpres,ypres,zpres) */
4779 /* Called by dissolve */
4780 /* Calls moveone and edgecnt */
4781 void CemhydMatStatus :: extslagcsh(int xpres, int ypres, int zpres) {
4782  int check, sump, xchr, ychr, zchr, fchr, i1, action, numnear;
4783  long int tries;
4784  int mstest = 0, mstest2 = 0;
4785 
4786  /* first try 6 neighboring locations until */
4787  /* a) successful */
4788  /* b) all 6 sites are tried or */
4789  /* c) 100 tries are made */
4790  /* try to grow slag C-S-H as plates */
4791  fchr = 0;
4792  sump = 1;
4793  for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
4794  /* determine location of neighbor (using periodic boundaries) */
4795  xchr = xpres;
4796  ychr = ypres;
4797  zchr = zpres;
4798  action = 0;
4799  sump *= moveone(& xchr, & ychr, & zchr, & action, sump);
4800  if ( action == 0 ) {
4801  printf("Error in value of action in extpozz \n");
4802  }
4803 
4804  check = mic [ xchr ] [ ychr ] [ zchr ];
4805  /* Determine the direction of the neighbor selected and */
4806  /* the plates possible for growth */
4807  if ( xchr != xpres ) {
4808  mstest = 1;
4809  mstest2 = 2;
4810  }
4811 
4812  if ( ychr != ypres ) {
4813  mstest = 2;
4814  mstest2 = 3;
4815  }
4816 
4817  if ( zchr != zpres ) {
4818  mstest = 3;
4819  mstest2 = 1;
4820  }
4821 
4822  /* if neighbor is porosity, locate the SLAG CSH there */
4823  if ( check == POROSITY ) {
4824  if ( ( faces [ xpres ] [ ypres ] [ zpres ] == 0 ) || ( mstest == faces [ xpres ] [ ypres ] [ zpres ] ) || ( mstest2 == faces [ xpres ] [ ypres ] [ zpres ] ) ) {
4825  mic [ xchr ] [ ychr ] [ zchr ] = SLAGCSH;
4826  faces [ xchr ] [ ychr ] [ zchr ] = faces [ xpres ] [ ypres ] [ zpres ];
4827  count [ SLAGCSH ] += 1;
4828  count [ POROSITY ] -= 1;
4829  fchr = 1;
4830  }
4831  }
4832  }
4833 
4834  /* if no neighbor available, locate SLAG CSH at random location */
4835  /* in pore space */
4836  tries = 0;
4837  while ( fchr == 0 ) {
4838  tries += 1;
4839  /* generate a random location in the 3-D system */
4840  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
4841  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
4842  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
4843  if ( xchr >= SYSIZE ) {
4844  xchr = 0;
4845  }
4846 
4847  if ( ychr >= SYSIZE ) {
4848  ychr = 0;
4849  }
4850 
4851  if ( zchr >= SYSIZE ) {
4852  zchr = 0;
4853  }
4854 
4855  check = mic [ xchr ] [ ychr ] [ zchr ];
4856  /* if location is porosity, locate the extra SLAG CSH there */
4857  if ( check == POROSITY ) {
4858  numnear = edgecnt(xchr, ychr, zchr, SLAG, CSH, SLAGCSH);
4859  /* Be sure that one neighboring species is CSH or */
4860  /* SLAG material */
4861  if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
4862  mic [ xchr ] [ ychr ] [ zchr ] = SLAGCSH;
4863  count [ SLAGCSH ] += 1;
4864  count [ POROSITY ] -= 1;
4865  fchr = 1;
4866  }
4867  }
4868  }
4869 }
4870 
4871 /* routine to implement a cycle of dissolution */
4872 /* Called by main program */
4873 /* Calls passone, loccsh, and makeinert */
4875 {
4876  int nc3aext, ncshext, nchext, ngypext, nanhext, plok;
4877  int nsum5, nsum4, nsum3, nsum2, nhemext, nsum6, nc4aext;
4878  int phid, phnew, plnew, cread;
4879  int i, xloop, yloop, zloop, xc, yc;
4880  int zc, cycnew;
4881  long int ctest;
4882  long int tries;
4883  int placed, cshrand, maxsulfate, msface;
4884  long int ncshgo, nsurf, suminit;
4885  long int xext, nhgd, npchext, nslagc3a = 0;
4886  float pdis, plfh3, fchext, fc3aext, fanhext, mass_now, mass_fa_now, tot_mass, heatfill;
4887  float dfact, dfact1, molesdh2o, h2oinit, heat4, fhemext, fc4aext;
4888  float pconvert, pc3scsh, pc2scsh, calcx, calcy, calcz, tdisfact;
4889  float frafm, frettr, frhyg, frtot, mc3ar, mc4ar, p3init;
4890  struct ants *antadd;
4891 
4892  /* Initialize variables */
4893  nmade = 0;
4894  npchext = ncshgo = cshrand = 0; /* counter for number of csh diffusing species to */
4895  /* be located at random locations in microstructure */
4896  heat_old = heat_new; /* new and old values for heat released */
4897 
4898  /* Initialize dissolution and phase counters */
4899  nsurf = 0;
4900  for ( i = 0; i <= EMPTYP; i++ ) {
4901  discount [ i ] = 0;
4902  count [ i ] = 0;
4903  }
4904 
4905  /* Pass one- highlight all edge points which are soluble */
4906  soluble [ C3AH6 ] = 0;
4907  heatsum = 0.0;
4908  molesh2o = 0.0;
4909  passone(0, EMPTYP, cycle, 1);
4910 #ifdef PRINTF
4911  printf("Returned from passone \n");
4912 #endif
4913  fflush(stdout);
4914 
4915  sulf_solid = count [ GYPSUM ] + count [ GYPSUMS ] + count [ HEMIHYD ] + count [ ANHYDRITE ];
4916  /* If first cycle, then determine all mixture proportions based */
4917  /* on user input and original microstructure */
4918  if ( cycle == 1 ) {
4919  /* Mass of cement in system */
4920  cemmass = ( specgrav [ C3S ] * ( float ) count [ C3S ] + specgrav [ C2S ] *
4921  ( float ) count [ C2S ] + specgrav [ C3A ] * ( float ) count [ C3A ] +
4922  specgrav [ C4AF ] * ( float ) count [ C4AF ] );
4923  /* +specgrav[GYPSUM]*
4924  * (float)count[GYPSUM]+specgrav[ANHYDRITE]*(float)
4925  * count[ANHYDRITE]+specgrav[HEMIHYD]*(float)count[HEMIHYD]); */
4926  cemmasswgyp = ( specgrav [ C3S ] * ( float ) count [ C3S ] + specgrav [ C2S ] *
4927  ( float ) count [ C2S ] + specgrav [ C3A ] * ( float ) count [ C3A ] +
4928  specgrav [ C4AF ] * ( float ) count [ C4AF ] + specgrav [ GYPSUM ] *
4929  ( float ) count [ GYPSUM ] + specgrav [ ANHYDRITE ] * ( float )
4930  count [ ANHYDRITE ] + specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] );
4931  flyashmass = ( specgrav [ ASG ] * ( float ) count [ ASG ] + specgrav [ CAS2 ] *
4932  ( float ) count [ CAS2 ] + specgrav [ POZZ ] * ( float ) count [ POZZ ] );
4933  CH_mass = specgrav [ CH ] * ( float ) count [ CH ];
4934  /* Total mass in system neglecting single aggregate */
4935  tot_mass = cemmass + ( float ) count [ POROSITY ] + specgrav [ INERT ] *
4936  ( float ) count [ INERT ] + specgrav [ CACL2 ] * ( float ) count [ CACL2 ] +
4937  specgrav [ ASG ] * ( float ) count [ ASG ] +
4938  specgrav [ SLAG ] * ( float ) count [ SLAG ] +
4939  specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] +
4940  specgrav [ ANHYDRITE ] * ( float ) count [ ANHYDRITE ] +
4941  specgrav [ CAS2 ] * ( float ) count [ CAS2 ] +
4942  specgrav [ CSH ] * ( float ) count [ CSH ] +
4943  specgrav [ GYPSUM ] * ( float ) count [ GYPSUM ] +
4944  specgrav [ ANHYDRITE ] * ( float ) count [ ANHYDRITE ] +
4945  specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] +
4946  specgrav [ GYPSUMS ] * ( float ) count [ GYPSUMS ] +
4947  specgrav [ POZZ ] * ( float ) count [ POZZ ] + CH_mass;
4948  /* water-to-cement ratio */
4949  if ( cemmass != 0.0 ) {
4950  w_to_c = ( float ) count [ POROSITY ] / ( cemmass +
4951  specgrav [ GYPSUM ] * ( float ) count [ GYPSUM ] +
4952  specgrav [ ANHYDRITE ] * ( float ) count [ ANHYDRITE ] +
4953  specgrav [ HEMIHYD ] * ( float ) count [ HEMIHYD ] );
4954  } else {
4955  w_to_c = 0.0;
4956  }
4957 
4958  /* totfract is the total cement volume count including calcium sulfates */
4959  /* fractwithfill is the total count of cement and solid fillers and */
4960  /* mineral admixtures DPB- 10/04 */
4961  totfract = count [ C3S ] + count [ C2S ];
4962  totfract += ( count [ C3A ] + count [ C4AF ] );
4963  totfract += ( count [ GYPSUM ] + count [ ANHYDRITE ] + count [ HEMIHYD ] );
4964  fractwithfill = totfract + count [ CACO3 ] + count [ SLAG ] + count [ INERT ];
4965  fractwithfill += count [ POZZ ] + count [ CAS2 ] + count [ ASG ] + count [ CACL2 ];
4966  totfract /= ( float ) SYSIZE;
4967  totfract /= ( float ) SYSIZE;
4968  totfract /= ( float ) SYSIZE;
4969  fractwithfill /= ( float ) SYSIZE;
4970  fractwithfill /= ( float ) SYSIZE;
4971  fractwithfill /= ( float ) SYSIZE;
4972  /* Adjust masses for presence of aggregates in concrete */
4973  mass_water = ( 1. - mass_agg ) * ( float ) count [ POROSITY ] / tot_mass;
4974  mass_CH = ( 1. - mass_agg ) * CH_mass / tot_mass;
4975  /* pozzolan-to-cement ratio */
4976  if ( cemmass != 0.0 ) {
4977  s_to_c = ( float ) ( count [ INERT ] * specgrav [ INERT ] +
4978  count [ CACL2 ] * specgrav [ CACL2 ] + count [ ASG ] * specgrav [ ASG ] +
4979  count [ CAS2 ] * specgrav [ CAS2 ] +
4980  count [ SLAG ] * specgrav [ SLAG ] +
4981  count [ POZZ ] * specgrav [ POZZ ] ) / cemmass;
4982  } else {
4983  s_to_c = 0.0;
4984  }
4985 
4986  /* Conversion factor to kJ/kg for heat produced */
4987  if ( cemmass != 0.0 ) {
4988  heatfill = ( float ) ( count [ INERT ] + count [ SLAG ] + count [ POZZ ] + count [ CACL2 ] + count [ ASG ] + count [ CAS2 ] ) / cemmass; //units pixels^3/g, inverse to the density
4989  } else {
4990  heatfill = 0.0;
4991  }
4992 
4993  if ( w_to_c > 0.01 ) {
4994  heat_cf = 1000. / SYSIZE_POW3 * ( 0.3125 + w_to_c + heatfill ); //heat conversion factor,1/ro_c=0.3125, fixed
4995  } else {
4996  /* Need volume per 1 gram of silica fume */
4997  heat_cf = 1000. / SYSIZE_POW3 * ( ( 1. / specgrav [ POZZ ] ) + ( float ) ( count [ POROSITY ] + count [ CH ] + count [ INERT ] ) / ( specgrav [ POZZ ] * ( float ) count [ POZZ ] ) ); //fixed
4998  }
4999 
5000  mass_fill_pozz = ( 1. - mass_agg ) * ( float ) ( count [ POZZ ] * specgrav [ POZZ ] ) / tot_mass;
5001  mass_fill = ( 1. - mass_agg ) * ( float ) ( count [ INERT ] * specgrav [ INERT ] +
5002  count [ ASG ] * specgrav [ ASG ] + count [ SLAG ] * specgrav [ SLAG ] +
5003  count [ CAS2 ] * specgrav [ CAS2 ] + count [ POZZ ] * specgrav [ POZZ ] +
5004  count [ CACL2 ] * specgrav [ CACL2 ] ) / tot_mass;
5005 #ifdef PRINTF
5006  printf("Calculated w/c is %.4f\n", w_to_c);
5007  printf("Calculated s/c is %.4f \n", s_to_c);
5008  printf("Calculated heat conversion factor is %f \n", heat_cf);
5009  printf("Calculated mass fractions of water and filler are %.4f and %.4f \n",
5011 #endif
5012  }
5013 
5014  molesdh2o = 0.0;
5015  alpha = 0.0; /* degree of hydration of clinker minerals*/
5016  /* heat4 contains measured heat release for C4AF hydration from */
5017  /* Fukuhara et al., Cem. and Conc. Res. article */
5018  heat4 = 0.0;
5019  mass_now = 0.0; /* total cement mass corrected for hydration */
5020  suminit = c3sinit + c2sinit + c3ainit + c4afinit;
5021  /* suminit=c3sinit+c2sinit+c3ainit+c4afinit+ncsbar+anhinit+heminit; */
5022  /* ctest is number of gypsum likely to form ettringite */
5023  /* 1 unit of C3A can react with 2.5 units of Gypsum */
5024  ctest = count [ DIFFGYP ];
5025 #ifdef PRINTF
5026  printf("ctest is %ld\n", ctest);
5027 #endif
5028  fflush(stdout);
5029  if ( ( float ) ctest > ( 2.5 * ( float ) ( count [ DIFFC3A ] + count [ DIFFC4A ] ) ) ) {
5030  ctest = ( long int ) ( 2.5 * ( float ) ( count [ DIFFC3A ] + count [ DIFFC4A ] ) );
5031  }
5032 
5033  for ( i = 0; i <= EMPTYP; i++ ) {
5034  if ( ( i != 0 ) && ( i <= ABSGYP ) && ( i != INERTAGG ) && ( i != CSH ) ) {
5035  heatsum += ( float ) count [ i ] * heatf [ i ] / molarv [ i ];
5036  /* Tabulate moles of H2O consumed by reactions so far */
5037  molesh2o += ( float ) count [ i ] * waterc [ i ] / molarv [ i ];
5038  }
5039 
5040  /* assume that all C3A which can, does form ettringite */
5041  if ( i == DIFFC3A ) {
5042  heatsum += ( ( float ) count [ DIFFC3A ] - ( float ) ctest / 2.5 ) * heatf [ C3A ] / molarv [ C3A ];
5043  }
5044 
5045  /* assume that all C4A which can, does form ettringite */
5046  if ( i == DIFFC4A ) {
5047  heatsum += ( ( float ) count [ DIFFC4A ] - ( float ) ctest / 2.5 ) * heatf [ C4AF ] / molarv [ C4AF ];
5048  }
5049 
5050  /* assume all gypsum which can, does form ettringite */
5051  /* rest will remain as gypsum */
5052  if ( i == DIFFGYP ) {
5053  heatsum += ( float ) ( count [ DIFFGYP ] - ctest ) * heatf [ GYPSUM ] / molarv [ GYPSUM ];
5054  /* 3.3 is the molar expansion from GYPSUM to ETTR */
5055  heatsum += ( float ) ctest * 3.30 * heatf [ ETTR ] / molarv [ ETTR ];
5056  molesdh2o += ( float ) ctest * 3.30 * waterc [ ETTR ] / molarv [ ETTR ];
5057  } else if ( i == DIFFCH ) {
5058  heatsum += ( float ) count [ DIFFCH ] * heatf [ CH ] / molarv [ CH ];
5059  molesdh2o += ( float ) count [ DIFFCH ] * waterc [ CH ] / molarv [ CH ];
5060  } else if ( i == DIFFFH3 ) {
5061  heatsum += ( float ) count [ DIFFFH3 ] * heatf [ FH3 ] / molarv [ FH3 ];
5062  molesdh2o += ( float ) count [ DIFFFH3 ] * waterc [ FH3 ] / molarv [ FH3 ];
5063  } else if ( i == DIFFCSH ) {
5064  /* use current CSH properties */
5065  heatsum += ( float ) count [ DIFFCSH ] * heatf [ CSH ] / molarvcsh [ cycle ];
5066  molesdh2o += ( float ) count [ DIFFCSH ] * watercsh [ cycle ] / molarvcsh [ cycle ];
5067  } else if ( i == DIFFETTR ) {
5068  heatsum += ( float ) count [ DIFFETTR ] * heatf [ ETTR ] / molarv [ ETTR ];
5069  molesdh2o += ( float ) count [ DIFFETTR ] * waterc [ ETTR ] / molarv [ ETTR ];
5070  } else if ( i == DIFFCACL2 ) {
5071  heatsum += ( float ) count [ DIFFCACL2 ] * heatf [ CACL2 ] / molarv [ CACL2 ];
5072  molesdh2o += ( float ) count [ DIFFCACL2 ] * waterc [ CACL2 ] / molarv [ CACL2 ];
5073  } else if ( i == DIFFAS ) {
5074  heatsum += ( float ) count [ DIFFAS ] * heatf [ ASG ] / molarv [ ASG ];
5075  molesdh2o += ( float ) count [ DIFFAS ] * waterc [ ASG ] / molarv [ ASG ];
5076  } else if ( i == DIFFCAS2 ) {
5077  heatsum += ( float ) count [ DIFFCAS2 ] * heatf [ CAS2 ] / molarv [ CAS2 ];
5078  molesdh2o += ( float ) count [ DIFFCAS2 ] * waterc [ CAS2 ] / molarv [ CAS2 ];
5079  }
5080  /* assume that all diffusing anhydrite leads to gypsum formation */
5081  else if ( i == DIFFANH ) {
5082  heatsum += ( float ) count [ DIFFANH ] * heatf [ GYPSUMS ] / molarv [ GYPSUMS ];
5083  /* 2 moles of water per mole of gypsum formed */
5084  molesdh2o += ( float ) count [ DIFFANH ] * 2.0 / molarv [ GYPSUMS ];
5085  }
5086  /* assume that all diffusing hemihydrate leads to gypsum formation */
5087  else if ( i == DIFFHEM ) {
5088  heatsum += ( float ) count [ DIFFHEM ] * heatf [ GYPSUMS ] / molarv [ GYPSUMS ];
5089  /* 1.5 moles of water per mole of gypsum formed */
5090  molesdh2o += ( float ) count [ DIFFHEM ] * 1.5 / molarv [ GYPSUMS ];
5091  } else if ( i == C3S ) {
5092  alpha += ( float ) ( c3sinit - count [ C3S ] );
5093  mass_now += specgrav [ C3S ] * ( float ) count [ C3S ];
5094  heat4 += .517 * ( float ) ( c3sinit - count [ C3S ] ) * specgrav [ C3S ];
5095  } else if ( i == C2S ) {
5096  alpha += ( float ) ( c2sinit - count [ C2S ] );
5097  mass_now += specgrav [ C2S ] * ( float ) count [ C2S ];
5098  heat4 += .262 * ( float ) ( c2sinit - count [ C2S ] ) * specgrav [ C2S ];
5099  } else if ( i == C3A ) {
5100  alpha += ( float ) ( c3ainit - count [ C3A ] );
5101  mass_now += specgrav [ C3A ] * ( float ) count [ C3A ];
5102  mc3ar = ( c3ainit - ( float ) count [ C3A ] ) / molarv [ C3A ];
5103  mc4ar = ( c4afinit - ( float ) count [ C4AF ] ) / molarv [ C4AF ];
5104  if ( ( mc3ar + mc4ar ) > 0.0 ) {
5105  frhyg = ( mc3ar / ( mc3ar + mc4ar ) ) * ( float ) count [ C3AH6 ] / molarv [ C3AH6 ];
5106  } else {
5107  frhyg = 0.0;
5108  }
5109 
5110  frettr = ( float ) count [ ETTR ] / molarv [ ETTR ];
5111  frafm = 3 * ( float ) count [ AFM ] / molarv [ AFM ];
5112  frtot = frafm + frettr + frhyg;
5113  if ( frtot > 0.0 ) {
5114  frettr /= frtot;
5115  frafm /= frtot;
5116  frhyg /= frtot;
5117  heat4 += frafm * 1.144 * ( float ) ( c3ainit - count [ C3A ] ) * specgrav [ C3A ];
5118  heat4 += frhyg * 0.908 * ( float ) ( c3ainit - count [ C3A ] ) * specgrav [ C3A ];
5119  heat4 += frettr * 1.672 * ( float ) ( c3ainit - count [ C3A ] ) * specgrav [ C3A ];
5120  }
5121  } else if ( i == C4AF ) {
5122  alpha += ( float ) ( c4afinit - count [ C4AF ] );
5123  mass_now += specgrav [ C4AF ] * ( float ) count [ C4AF ];
5124  mc3ar = ( c3ainit - ( float ) count [ C3A ] ) / molarv [ C3A ];
5125  mc4ar = ( c4afinit - ( float ) count [ C4AF ] ) / molarv [ C4AF ];
5126  if ( ( mc3ar + mc4ar ) > 0.0 ) {
5127  frhyg = ( mc4ar / ( mc3ar + mc4ar ) ) * ( float ) count [ C3AH6 ] / molarv [ C3AH6 ];
5128  } else {
5129  frhyg = 0.0;
5130  }
5131 
5132  frettr = ( float ) count [ ETTRC4AF ] / molarv [ ETTRC4AF ];
5133  frtot = frettr + frhyg;
5134  if ( frtot > 0.0 ) {
5135  frettr /= frtot;
5136  frhyg /= frtot;
5137  heat4 += frhyg * .418 * ( float ) ( c4afinit - count [ C4AF ] ) * specgrav [ C4AF ];
5138  heat4 += frettr * .725 * ( float ) ( c4afinit - count [ C4AF ] ) * specgrav [ C4AF ];
5139  }
5140  }
5141  /* else if(i==GYPSUM){
5142  * alpha+=(float)(ncsbar-count[GYPSUM]);
5143  * mass_now+=specgrav[GYPSUM]*(float)count[GYPSUM];
5144  * } */
5145  /* 0.187 kJ/g anhydrite for anhydrite --> gypsum conversion */
5146  else if ( i == ANHYDRITE ) {
5147  /* alpha+=(float)(anhinit-count[ANHYDRITE]);
5148  * mass_now+=specgrav[ANHYDRITE]*(float)count[ANHYDRITE]; */
5149  heat4 += .187 * ( float ) ( anhinit - count [ ANHYDRITE ] ) * specgrav [ ANHYDRITE ];
5150  /* 2 moles of water consumed per mole of anhydrite reacted */
5151  molesh2o += ( float ) ( anhinit - count [ ANHYDRITE ] ) * 2.0 / molarv [ ANHYDRITE ];
5152  }
5153  /* 0.132 kJ/g hemihydrate for hemihydrate-->gypsum conversion */
5154  else if ( i == HEMIHYD ) {
5155  /* alpha+=(float)(heminit-count[HEMIHYD]);
5156  * mass_now+=specgrav[HEMIHYD]*(float)count[HEMIHYD]; */
5157  heat4 += .132 * ( float ) ( heminit - count [ HEMIHYD ] ) * specgrav [ HEMIHYD ];
5158  /* 1.5 moles of water consumed per mole of anhydrite reacted */
5159  molesh2o += ( float ) ( heminit - count [ HEMIHYD ] ) * 1.5 / molarv [ HEMIHYD ];
5160  }
5161  }
5162 
5163  mass_fa_now = specgrav [ ASG ] * ( float ) count [ ASG ];
5164  mass_fa_now += specgrav [ CAS2 ] * ( float ) count [ CAS2 ];
5165  mass_fa_now += specgrav [ POZZ ] * ( float ) count [ POZZ ];
5166  if ( suminit != 0 ) {
5167  alpha = alpha / ( float ) suminit;
5168  } else {
5169  alpha = 0.0;
5170  }
5171 
5172  /* Current degree of hydration on a mass basis */
5173  if ( cemmass != 0.0 ) {
5174  alpha_cur = 1.0 - ( mass_now / cemmass );
5175  } else {
5176  alpha_cur = 0.0;
5177  }
5178 
5179  if ( flyashmass != 0.0 ) {
5180  alpha_fa_cur = 1.0 - ( mass_fa_now / flyashmass );
5181  } else {
5182  alpha_fa_cur = 0.0;
5183  }
5184 
5185  h2oinit = ( float ) porinit / molarv [ POROSITY ];
5186 
5187  /* Assume 780 J/g S for pozzolanic reaction */
5188  /* Each unit of silica fume consumes 1.35 units of CH, */
5189  /* so divide npr by 1.35 to get silca fume which has reacted */
5190  heat4 += 0.78 * ( ( float ) npr / 1.35 ) * specgrav [ POZZ ];
5191 
5192  /* Assume 800 J/g S for slag reaction */
5193  /* Seems reasonable with measurements of Biernacki and Richardson */
5194  heat4 += 0.8 * ( ( float ) nslagr ) * specgrav [ SLAG ];
5195 
5196  /* Assume 800 J/g AS for stratlingite formation (DeLarrard) */
5197  /* Each unit of AS consumes 1.3267 units of CH, */
5198  /* so divide nasr by 1.3267 to get ASG which has reacted */
5199  heat4 += 0.80 * ( ( float ) nasr / 1.3267 ) * specgrav [ ASG ];
5200 
5201  /* Should be additional code here for heat release due to CAS2 to */
5202  /* stratlingite conversion, but data unavailable at this time */
5203 
5204  /* Adjust heat sum for water left in system */
5205  water_left = ( long int ) ( ( h2oinit - molesh2o ) * molarv [ POROSITY ] + 0.5 );
5206  countkeep = count [ POROSITY ];
5207  heatsum += ( h2oinit - molesh2o - molesdh2o ) * heatf [ POROSITY ];
5208  if ( cyccnt == 0 ) {
5209 #ifdef OUTFILES
5210  fprintf(heatfile, "Cycle time(h) alpha_vol alpha_mass heat4(kJ/kg_solid) Gsratio2 G-s_ratio\n");
5211 #endif
5212  }
5213 
5214  heat_new = heat4; /* use heat4 for all adiabatic calculations */
5215  /* due to best agreement with calorimetry data */
5216 
5217  if ( cyccnt == 0 ) {
5218  //fprintf(chsfile,"Cycle time(h) alpha_mass Chemical shrinkage (ml/g cement)\n");
5219  }
5220 
5221  chs_new = ( ( float ) ( count [ EMPTYP ] + count [ POROSITY ] - water_left ) * heat_cf / 1000. );
5222  /* if((molesh2o>h2oinit)&&(sealed==1)){ */
5223  if ( ( ( water_left + water_off ) < 0 ) && ( sealed == 1 ) ) {
5224 #ifdef PRINTF
5225  printf("All water consumed at cycle %d \n", cyccnt);
5226  fflush(stdout);
5227 #endif
5228  //exit(1);the simulation can be stopped
5229  }
5230 
5231  //remove defined amount of water (outer drying)
5232  //makeinert(10);
5233 
5234  /* Attempt to create empty porosity to account for self-desiccation */
5235  if ( ( sealed == 1 ) && ( ( count [ POROSITY ] - water_left ) > 0 ) ) {
5236  poretodo = ( count [ POROSITY ] - pore_off ) - ( water_left - water_off );
5237  poretodo -= slagemptyp;
5238  if ( poretodo > 0 ) {
5240  poregone += poretodo;
5241  }
5242  }
5243 
5244  /* Output phase counts */
5245  /* phasfile for reactant and product phases */
5246 #ifdef OUTFILES
5247  if ( cyccnt == 0 ) {
5248  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");
5249  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");
5250  }
5251 
5252  fprintf(phasfile, "%d %.4f %.4f ", cyccnt, alpha_cur, time_cur);
5253  fprintf(disprobfile, "%d %.4f %.4f ", cyccnt, alpha_cur, time_cur);
5254 
5255 
5257 
5258 
5259  for ( i = 0; i <= HDCSH; i++ ) {
5260  if ( ( i < DIFFCSH ) || ( i >= EMPTYP ) ) {
5261  if ( i == CSH ) {
5262  fprintf(phasfile, "%ld ", count [ CSH ] - count [ HDCSH ]);
5263  } else {
5264  fprintf(phasfile, "%ld ", count [ i ]);
5265  }
5266 
5267  fprintf(disprobfile, "%f ", disprob [ i ]);
5268  }
5269 
5270  // printf("%ld ",count[i]);
5271  }
5272 
5273  fprintf(disprobfile, "\n");
5274  fprintf(phasfile, "%ld\n", water_left);
5275  fflush(phasfile);
5276  fflush(disprobfile);
5277 #endif
5278 
5279 #ifdef PRINTF
5280  printf("\n");
5281 #endif
5282 
5283  if ( cycle == 0 ) {
5284  return;
5285  }
5286 
5287 #ifdef PRINTF
5288  #ifdef __TM_MODULE
5289  printf("Cycle cyccnt %d, DoH %f, time %f, GP %p\n", cyccnt, alpha_cur, time_cur, this->gp);
5290  #else
5291  printf("Cycle cyccnt %d, DoH %f, time %f\n", cyccnt, alpha_cur, time_cur);
5292  #endif
5293 #endif
5294 
5295  cyccnt += 1;
5296  fflush(stdout);
5297  /* Update current volume count for CH */
5298  chold = chnew;
5299  chnew = count [ CH ];
5300 
5301  /* See if ettringite is soluble yet */
5302  /* Gypsum 80% consumed, changed 06.09.00 from 90% to 80% */
5303  /* Gypsum 75% consumed, changed 09.09.01 from 80% to 75% */
5304  /* or system temperature exceeds 70 C */
5305  if ( ( ( ncsbar + anhinit + heminit ) != 0.0 ) || ( temp_cur >= 70.0 ) ) {
5306  /* Account for all sulfate sources and forms */
5307  if ( ( soluble [ ETTR ] == 0 ) && ( ( temp_cur >= 70.0 ) || ( count [ AFM ] != 0 ) ||
5308  ( ( ( ( float ) count [ GYPSUM ] + 1.42 * ( float ) count [ ANHYDRITE ] + 1.4 *
5309  ( float ) count [ HEMIHYD ] + ( float ) count [ GYPSUMS ] ) / ( ( float ) ncsbar +
5310  1.42 * ( float ) anhinit + 1.4 * ( float ) heminit + ( ( float ) netbar / 3.30 ) ) ) < 0.25 ) ) ) {
5311  soluble [ ETTR ] = 1;
5312 #ifdef PRINTF
5313  printf("Ettringite is soluble beginning at cycle %d \n", cycle);
5314 #endif
5315  /* identify all new soluble ettringite */
5316  passone(ETTR, ETTR, 2, 0);
5317  }
5318  }
5319 
5320  /* end of soluble ettringite test */
5321 
5322  /* Adjust ettringite solubility */
5323  /* if too many ettringites already in solution */
5324  if ( count [ DIFFETTR ] > DETTRMAX ) {
5325  disprob [ ETTR ] = 0.0;
5326  } else {
5327  disprob [ ETTR ] = disbase [ ETTR ];
5328  }
5329 
5330  /* Adjust CaCl2 solubility */
5331  /* if too many CaCl2 already in solution */
5332  if ( count [ DIFFCACL2 ] > DCACL2MAX ) {
5333  disprob [ CACL2 ] = 0.0;
5334  } else {
5335  disprob [ CACL2 ] = disbase [ CACL2 ];
5336  }
5337 
5338  /* Adjust CaCO3 solubility */
5339  /* if too many CaCO3 already in solution */
5340  if ( ( count [ DIFFCACO3 ] > DCACO3MAX ) && ( soluble [ ETTR ] == 0 ) ) {
5341  disprob [ CACO3 ] = 0.0;
5342  } else if ( count [ DIFFCACO3 ] > ( 4 * DCACO3MAX ) ) {
5343  disprob [ CACO3 ] = 0.0;
5344  } else {
5345  disprob [ CACO3 ] = disbase [ CACO3 ];
5346  }
5347 
5348  /* Adjust solubility of CH */
5349  /* based on amount of CH currently diffusing */
5350  /* Note that CH is always soluble to allow some */
5351  /* Ostwald ripening of the CH crystals */
5352  if ( ( float ) count [ DIFFCH ] >= CHCRIT ) {
5353  disprob [ CH ] = disbase [ CH ] * CHCRIT / ( float ) count [ DIFFCH ];
5354  } else {
5355  disprob [ CH ] = disbase [ CH ];
5356  }
5357 
5358  /* Adjust solubility of CH for temperature */
5359  /* Fit to data provided in Taylor, Cement Chemistry */
5360  /* Scale to a reference temperature of 25 C */
5361  /* and adjust based on availability of pozzolan */
5362 
5363 #ifdef PRINTF
5364  printf("CH dissolution probability goes from %f ", disprob [ CH ]);
5365 #endif
5366  disprob [ CH ] *= ( ( A0_CHSOL - A1_CHSOL * temp_cur ) / ( A0_CHSOL - A1_CHSOL * 25.0 ) );
5367  if ( ( ppozz > 0.0 ) && ( nfill > 0 ) ) {
5368  disprob [ CH ] *= ppozz / PPOZZ;
5369  }
5370 
5371 #ifdef PRINTF
5372  printf("to %f \n", disprob [ CH ]);
5373 #endif
5374 
5375  /* Adjust solubility of ASG and CAS2 phases */
5376  /* based on pH rise during hydration */
5377  /* To be added at a later date */
5378  disprob [ ASG ] = disbase [ ASG ];
5379  disprob [ CAS2 ] = disbase [ CAS2 ];
5380  /* Address solubility of C3AH6 */
5381  /* If lots of gypsum or reactive ettringite, allow C3AH6 to dissolve */
5382  /* to generate diffusing C3A species */
5383  if ( ( ( count [ GYPSUM ] + count [ GYPSUMS ] ) > ( int ) ( ( ( float ) ncsbar +
5384  1.42 * ( float ) anhinit + 1.4 * ( float ) heminit ) * 0.05 ) ) ||
5385  ( count [ ETTR ] > 500 * SYSIZE_POW3 / 1000000. ) ) {
5386  soluble [ C3AH6 ] = 1;
5387  passone(C3AH6, C3AH6, 2, 0);
5388  /* Base C3AH6 solubility on maximum sulfate in solution */
5389  /* from gypsum or ettringite available for dissolution */
5390  /* The more the sulfate, the higher this solubility should be */
5391  maxsulfate = count [ DIFFGYP ];
5392  if ( ( maxsulfate < count [ DIFFETTR ] ) && ( soluble [ ETTR ] == 1 ) ) {
5393  maxsulfate = count [ DIFFETTR ];
5394  }
5395 
5396  /* Adjust C3AH6 solubility based on potential gypsum which will dissolve */
5397  /*gypready and maxsulfate is size dependent */
5398  if ( maxsulfate < ( int ) ( ( float ) gypready * disprob [ GYPSUM ] * ( float ) count [ POROSITY ] / SYSIZE_POW3 ) ) { //fixed
5399  maxsulfate = ( int ) ( ( float ) gypready * disprob [ GYPSUM ] * ( float ) count [ POROSITY ] / SYSIZE_POW3 ); //fixed
5400  }
5401 
5402  if ( maxsulfate > 0 ) {
5403  disprob [ C3AH6 ] = disbase [ C3AH6 ] * ( float ) ( maxsulfate / C3AH6CRIT );
5404  if ( disprob [ C3AH6 ] > 0.5 ) {
5405  disprob [ C3AH6 ] = 0.5;
5406  }
5407  } else {
5408  disprob [ C3AH6 ] = disbase [ C3AH6 ];
5409  }
5410  } else {
5411  soluble [ C3AH6 ] = 0;
5412  }
5413 
5414  /* See if silicates are soluble yet */
5415  if ( ( soluble [ C3S ] == 0 ) && ( ( cycle > 1 ) || ( count [ ETTR ] > 0 ) || ( count [ AFM ] > 0 ) || ( count [ ETTRC4AF ] > 0 ) ) ) {
5416  soluble [ C2S ] = 1;
5417  soluble [ C3S ] = 1;
5418  /* identify all new soluble silicates */
5419  passone(C3S, C2S, 2, 0);
5420  }
5421 
5422  /* end of soluble silicate test */
5423  /* Adjust solubility of C3S and C2S with CSH concentration */
5424  /* for simulation of induction period */
5425 
5426  tdisfact = A0_CHSOL - temp_cur * A1_CHSOL;
5427  /* printf("tdisfact is %f\n",tdisfact);
5428  * fflush(stdout); */
5429 
5430  /* Calculation of cs_acc; acceleration of C3S and C2S reaction by CaSO4 */
5431  /* Calculation of ca_acc; acceleration of C3A and C4AF reaction by CaSO4 */
5432  /* November 2004 --- modified to be on a sulfate per unit initial cement */
5433  /* per unit porosity basis */
5434  /* Try using current porosity count to see if this helps in initial */
5435  /* hydration rates of sealed vs. saturated */
5436  pfract = ( float ) count [ POROSITY ] / ( float ) ( SYSIZE * SYSIZE * SYSIZE );
5437  if ( ( ncsbar + anhinit + heminit ) == 0.0 ) {
5438  cs_acc = 1.0;
5439  ca_acc = 1.0;
5440  dismin_c3a = 5.0 * DISMIN_C3A_0;
5441  dismin_c4af = 5.0 * DISMIN_C4AF_0;
5442  } else {
5444  sulf_conc *= ( 1000000. / SYSIZE_POW3 ); //fixed
5445  if ( sulf_conc < 10.0 ) {
5446  cs_acc = 1.0;
5447  ca_acc = 1.0;
5450  } else if ( sulf_conc < 20.0 ) {
5451  cs_acc = 1.0 + ( ( sulf_conc ) - 10.0 ) / 10.0;
5452  ca_acc = 1.0;
5455  } else {
5456  cs_acc = 1.0 + ( double ) log10(sulf_conc - 10.0);
5457  ca_acc = 1.0;
5458  dismin_c3a = ( 6.0 - ( double ) log10(sulf_conc) ) * DISMIN_C3A_0;
5459  dismin_c4af = ( 6.0 - ( double ) log10(sulf_conc) ) * DISMIN_C4AF_0;
5460  if ( dismin_c3a < DISMIN_C3A_0 ) {
5462  }
5463 
5464  if ( dismin_c4af < DISMIN_C4AF_0 ) {
5466  }
5467  }
5468  }
5469 
5470  /* Suggest change WCSCALE/w_to_c to (0.3125+WCSCALE)/(0.3125+w_to_c) */
5471  /* to have the induction period scaling depend on volume of CSH */
5472  /* produced per volume (not mass) of cement */
5473  /* 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;*/
5474  /* October 2004 --- changed to truly scale with volume of cement in */
5475  /* system for both plain portland cements and filled systems */
5476 
5477  dfact = tdisfact * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * cs_acc;
5478 
5479  disprob [ C3S ] = DISMIN + dfact * disbase [ C3S ];
5480  disprob [ C2S ] = DISMIN2 + dfact * disbase [ C2S ];
5481  if ( disprob [ C3S ] > ( 1. * disbase [ C3S ] ) ) {
5482  disprob [ C3S ] = ( 1. * disbase [ C3S ] );
5483  }
5484 
5485  if ( disprob [ C2S ] > ( 1. * disbase [ C2S ] ) ) {
5486  disprob [ C2S ] = ( 1. * disbase [ C2S ] );
5487  }
5488 
5489  /* Also adjust slag and fly ash dissolution rates here */
5490  /* Really slow down initial slag and fly ash dissolutions */
5491  /* Ultimately should be linked to pH of pore solution, most likely */
5492  disprob [ SLAG ] = slagreact * ( DISMINSLAG + dfact * disbase [ SLAG ] ) / 10.0;
5493  if ( disprob [ SLAG ] > ( slagreact * disbase [ SLAG ] ) ) {
5494  disprob [ SLAG ] = ( slagreact * disbase [ SLAG ] );
5495  }
5496 
5497  if ( disprob [ C3S ] == disbase [ C3S ] ) {
5498  disprob [ SLAG ] = slagreact * disbase [ SLAG ];
5499  }
5500 
5501  disprob [ ASG ] = DISMINASG + dfact * disbase [ ASG ] / 5.0;
5502  if ( disprob [ ASG ] > ( 1. * disbase [ ASG ] ) ) {
5503  disprob [ ASG ] = ( 1. * disbase [ ASG ] );
5504  }
5505 
5506  if ( disprob [ C3S ] == disbase [ C3S ] ) {
5507  disprob [ ASG ] = disbase [ ASG ];
5508  }
5509 
5510  disprob [ CAS2 ] = DISMINCAS2 + dfact * disbase [ CAS2 ] / 5.0;
5511  if ( disprob [ CAS2 ] > ( 1. * disbase [ CAS2 ] ) ) {
5512  disprob [ CAS2 ] = ( 1. * disbase [ CAS2 ] );
5513  }
5514 
5515  if ( disprob [ C3S ] == disbase [ C3S ] ) {
5516  disprob [ CAS2 ] = disbase [ CAS2 ];
5517  }
5518 
5519  /* Adjust CAS2 solubility */
5520  /* if too many CAS2 already in solution */
5521  if ( count [ DIFFCAS2 ] > DCAS2MAX ) {
5522  disprob [ CAS2 ] = 0.0;
5523  }
5524 
5525 #ifdef PRINTF
5526  printf("Silicate probabilities: %f %f\n", disprob [ C3S ], disprob [ C2S ]);
5527 #endif
5528  fflush(stdout);
5529  /* Assume that aluminate dissolution controlled by formation */
5530  /* of impermeable layer proportional to CSH concentration */
5531  /* if sulfates are present in the system */
5532 
5533  /* dfact1=tdisfact*((float)count[CSH]/CSHSCALE)*((float)count[CSH]/CSHSCALE)*ca_acc; */
5534  if ( ( ncsbar + heminit + anhinit ) > 1000 * SYSIZE_POW3 / 1000000. ) { //fixed
5535  /* 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; */
5536  /* October 2004 --- changed to truly scale with volume of cement in */
5537  /* system for both plain portland cements and filled systems */
5538  dfact1 = tdisfact * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * ( ( float ) count [ CSH ] / ( ( float ) CSHSCALE * surffract * totfract / tfractw04 ) ) * ca_acc;
5539  disprob [ C3A ] = dismin_c3a + dfact1 * disbase [ C3A ];
5540  disprob [ C4AF ] = dismin_c4af + dfact1 * disbase [ C4AF ];
5541  if ( disprob [ C3A ] > ( 1. * disbase [ C3A ] ) ) {
5542  disprob [ C3A ] = ( 1. * disbase [ C3A ] );
5543  }
5544 
5545  if ( disprob [ C4AF ] > ( 1. * disbase [ C4AF ] ) ) {
5546  disprob [ C4AF ] = ( 1. * disbase [ C4AF ] );
5547  }
5548 
5549  /* Location to add in dissolution reduction in calcium sulfate phases */
5550  /* if needed */
5551  disprob [ GYPSUM ] = ( disbase [ GYPSUM ] / 15. ) + dfact1 * disbase [ GYPSUM ];
5552  if ( disprob [ GYPSUM ] > ( disbase [ GYPSUM ] ) ) {
5553  disprob [ GYPSUM ] = ( disbase [ GYPSUM ] );
5554  }
5555 
5556  disprob [ GYPSUMS ] = ( disbase [ GYPSUMS ] / 15. ) + dfact1 * disbase [ GYPSUMS ];
5557  if ( disprob [ GYPSUMS ] > ( disbase [ GYPSUMS ] ) ) {
5558  disprob [ GYPSUMS ] = ( disbase [ GYPSUMS ] );
5559  }
5560 
5561  /* Adjust gypsum solubility */
5562  /* if too many diffusing gypsums already in solution */
5563  if ( count [ DIFFGYP ] > DGYPMAX ) {
5564  disprob [ GYPSUM ] = disprob [ GYPSUMS ] = 0.0;
5565  }
5566 
5567  disprob [ HEMIHYD ] = ( disbase [ HEMIHYD ] / 15. ) + dfact1 * disbase [ HEMIHYD ];
5568  if ( disprob [ HEMIHYD ] > ( disbase [ HEMIHYD ] ) ) {
5569  disprob [ HEMIHYD ] = ( disbase [ HEMIHYD ] );
5570  }
5571 
5572  disprob [ ANHYDRITE ] = ( disbase [ ANHYDRITE ] / 15. ) + dfact1 * disbase [ ANHYDRITE ];
5573  if ( disprob [ ANHYDRITE ] > ( disbase [ ANHYDRITE ] ) ) {
5574  disprob [ ANHYDRITE ] = ( disbase [ ANHYDRITE ] );
5575  }
5576  } else {
5577  /* Cause flash set by increasing dissolution rates of C3A and C4AF */
5578  /* each by a factor of four */
5579  disprob [ C3A ] = 4. * disbase [ C3A ];
5580  disprob [ C4AF ] = 4. * disbase [ C4AF ];
5581  disprob [ GYPSUM ] = disbase [ GYPSUM ];
5582  disprob [ HEMIHYD ] = disbase [ HEMIHYD ];
5583  disprob [ ANHYDRITE ] = disbase [ ANHYDRITE ];
5584  }
5585 
5586  /* Reduce dissolution probabilities based on saturation of system */
5587  if ( ( count [ EMPTYP ] > 0 ) && ( ( count [ POROSITY ] + count [ EMPTYP ] ) < 220000. * ( double ) ( SYSIZE_POW3 / 1000000. ) ) ) { //fixed
5588  if ( countpore == 0 ) {
5589  countpore = count [ EMPTYP ];
5590  }
5591 
5592  saturation = ( float ) ( count [ POROSITY ] ) / ( float ) ( count [ POROSITY ] + ( count [ EMPTYP ] - countpore ) );
5593  /* Roughly according to results of Jensen, powers for RH
5594  * sensitivity are:
5595  * C3S-19
5596  * C2S-29
5597  * C3A, C4AF-6 */
5598  /* Adjust fly ash silicates (ASG and CAS2) and pozzolanic reactivity */
5599  /* by same factor as C3S (also CH) */
5600  disprob [ C3S ] *= ( saturation * saturation );
5601  disprob [ C3S ] *= ( saturation * saturation );
5602  disprob [ C3S ] *= ( saturation * saturation );
5603  disprob [ C3S ] *= ( saturation * saturation );
5604  disprob [ C3S ] *= ( saturation * saturation );
5605  disprob [ C3S ] *= ( saturation * saturation );
5606  disprob [ C3S ] *= ( saturation * saturation );
5607  disprob [ C3S ] *= ( saturation * saturation );
5608  disprob [ C3S ] *= ( saturation * saturation );
5609  disprob [ C3S ] *= ( 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 * saturation );
5615  disprob [ SLAG ] *= ( saturation * saturation );
5616  disprob [ SLAG ] *= ( saturation * saturation );
5617  disprob [ SLAG ] *= ( saturation * saturation );
5618  disprob [ SLAG ] *= ( saturation * saturation );
5619  disprob [ SLAG ] *= ( 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 * saturation );
5625  disprob [ CH ] *= ( saturation * saturation );
5626  disprob [ CH ] *= ( saturation * saturation );
5627  disprob [ CH ] *= ( saturation * saturation );
5628  disprob [ CH ] *= ( saturation * saturation );
5629  disprob [ CH ] *= ( 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 * saturation );
5635  disprob [ ASG ] *= ( saturation * saturation );
5636  disprob [ ASG ] *= ( saturation * saturation );
5637  disprob [ ASG ] *= ( saturation * saturation );
5638  disprob [ ASG ] *= ( saturation * saturation );
5639  disprob [ ASG ] *= ( 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 * saturation );
5645  disprob [ CAS2 ] *= ( saturation * saturation );
5646  disprob [ CAS2 ] *= ( saturation * saturation );
5647  disprob [ CAS2 ] *= ( saturation * saturation );
5648  disprob [ CAS2 ] *= ( saturation * saturation );
5649  disprob [ CAS2 ] *= ( saturation );
5650  ppozz *= ( saturation * saturation );
5651  ppozz *= ( saturation * saturation );
5652  ppozz *= ( saturation * saturation );
5653  ppozz *= ( saturation * saturation );
5654  ppozz *= ( saturation * saturation );
5655  ppozz *= ( saturation * saturation );
5656  ppozz *= ( saturation * saturation );
5657  ppozz *= ( saturation * saturation );
5658  ppozz *= ( saturation * saturation );
5659  ppozz *= ( 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  disprob [ C2S ] *= ( saturation * saturation );
5667  disprob [ C2S ] *= ( saturation * saturation );
5668  disprob [ C2S ] *= ( saturation * saturation );
5669  disprob [ C2S ] *= ( saturation * saturation );
5670  disprob [ C2S ] *= ( saturation * saturation );
5671 
5672  disprob [ C2S ] *= ( saturation * saturation );
5673  disprob [ C2S ] *= ( saturation * saturation );
5674  disprob [ C2S ] *= ( saturation * saturation );
5675  disprob [ C2S ] *= ( saturation );
5676  disprob [ C3A ] *= ( saturation * saturation );
5677  disprob [ C3A ] *= ( saturation * saturation );
5678  disprob [ C3A ] *= ( saturation * saturation );
5679  disprob [ C4AF ] *= ( saturation * saturation );
5680  disprob [ C4AF ] *= ( saturation * saturation );
5681  disprob [ C4AF ] *= ( saturation * saturation );
5682  }
5683 
5684 #ifdef PRINTF
5685  printf("Silicate and aluminate probabilities: %f %f %f %f\n", disprob [ C3S ], disprob [ C2S ], disprob [ C3A ], disprob [ C4AF ]);
5686  printf("cs_acc is %f and ca_acc is %f sulf_cur is %ld\n", cs_acc, ca_acc, sulf_cur);
5687 #endif
5688  fflush(stdout);
5689  /* Pass two- perform the dissolution of species */
5690  /* Determine the pH factor to use */
5691  pHfactor = 0.0;
5692  if ( ( pHactive == 1 ) && ( count [ CSH ] > ( ( CSHSCALE * surffract * surffract * totfract * totfract / tfractw04 / tfractw04 ) / 8.0 ) ) ) {
5693  pHfactor = 1.5;
5694  if ( pH_cur > 12.5 ) {
5695  pHfactor = 1.0;
5696  }
5697 
5698  /* 2/02*/
5699  /* pHfactor=0.30*(((14.1-pH_cur)/0.3)-1.0); */
5700  /* 3/02*/
5701  /* pHfactor=0.60*(((14.1-pH_cur)/0.5)-1.0); */
5702  if ( pH_cur > 12.75 ) {
5703  pHfactor = 0.667;
5704  }
5705 
5706  if ( pH_cur > 13.00 ) {
5707  pHfactor = 0.333;
5708  }
5709 
5710  if ( pH_cur > 13.25 ) {
5711  pHfactor = ( 0.0 );
5712  }
5713 
5714  if ( pH_cur > 13.75 ) {
5715  pHfactor = ( -0.25 );
5716  }
5717 
5718  pHfactor += concsulfate; /* influence of sulfate on reactivity */
5719  }
5720 
5721  nhgd = 0;
5722  /* Update molar volume ratios for CSH formation */
5723  pc3scsh = molarvcsh [ cyccnt ] / molarv [ C3S ] - 1.0;
5724  pc2scsh = molarvcsh [ cyccnt ] / molarv [ C2S ] - 1.0;
5725  /* Once again, scan all pixels in microstructure */
5726  slagemptyp = 0;
5727  for ( xloop = 0; xloop < SYSIZE; xloop++ ) {
5728  for ( yloop = 0; yloop < SYSIZE; yloop++ ) {
5729  for ( zloop = 0; zloop < SYSIZE; zloop++ ) {
5730  if ( mic [ xloop ] [ yloop ] [ zloop ] > OFFSET ) {
5731  phid = mic [ xloop ] [ yloop ] [ zloop ] - OFFSET;
5732  /* attempt a one-step random walk to dissolve */
5733  plnew = ( int ) ( ( float ) NEIGHBORS * ran1(seed) );
5734  if ( ( plnew < 0 ) || ( plnew >= NEIGHBORS ) ) {
5735  plnew = NEIGHBORS - 1;
5736  }
5737 
5738  xc = xloop + xoff [ plnew ];
5739  yc = yloop + yoff [ plnew ];
5740  zc = zloop + zoff [ plnew ];
5741  if ( xc < 0 ) {
5742  xc = ( SYSIZEM1 );
5743  }
5744 
5745  if ( yc < 0 ) {
5746  yc = ( SYSIZEM1 );
5747  }
5748 
5749  if ( xc >= SYSIZE ) {
5750  xc = 0;
5751  }
5752 
5753  if ( yc >= SYSIZE ) {
5754  yc = 0;
5755  }
5756 
5757  if ( zc < 0 ) {
5758  zc = ( SYSIZEM1 );
5759  }
5760 
5761  if ( zc >= SYSIZE ) {
5762  zc = 0;
5763  }
5764 
5765  /* Generate probability for dissolution */
5766  pdis = ran1(seed);
5767  /* Bias dissolution for one pixel particles as */
5768  /* indicated by a pixel value of zero in the */
5769  /* particle microstructure image */
5770  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
5771  discount [ phid ] += 1;
5772  cread = creates [ phid ];
5773  count [ phid ] -= 1;
5774  mic [ xloop ] [ yloop ] [ zloop ] = POROSITY;
5775  if ( phid == C3AH6 ) {
5776  nhgd += 1;
5777  }
5778 
5779  /* Special dissolution for C4AF */
5780  if ( phid == C4AF ) {
5781  plfh3 = ran1(seed);
5782  if ( ( plfh3 < 0.0 ) || ( plfh3 > 1.0 ) ) {
5783  plfh3 = 1.0;
5784  }
5785 
5786  /* For every C4AF that dissolves, 0.5453 */
5787  /* diffusing FH3 species should be created */
5788  if ( plfh3 <= 0.5453 ) {
5789  cread = DIFFFH3;
5790  }
5791  }
5792 
5793  if ( cread == POROSITY ) {
5794  count [ POROSITY ] += 1;
5795  }
5796 
5797  if ( cread != POROSITY ) {
5798  nmade += 1;
5799  ngoing += 1;
5800  phnew = cread;
5801  count [ phnew ] += 1;
5802  mic [ xc ] [ yc ] [ zc ] = phnew;
5803  antadd = ( struct ants * ) malloc( sizeof( struct ants ) );
5804  antadd->x = xc;
5805  antadd->y = yc;
5806  antadd->z = zc;
5807  antadd->id = phnew;
5808  antadd->cycbirth = cyccnt;
5809  /* Now connect this ant structure to end of linked list */
5810  antadd->prevant = tailant;
5811  tailant->nextant = antadd;
5812  antadd->nextant = NULL;
5813  tailant = antadd;
5814  }
5815 
5816  /* Extra CSH diffusing species based on current temperature */
5817  if ( ( phid == C3S ) || ( phid == C2S ) ) {
5818  plfh3 = ran1(seed);
5819  if ( ( ( phid == C2S ) && ( plfh3 <= pc2scsh ) ) || ( plfh3 <= pc3scsh ) ) {
5820  cshboxsize = ( int ) ( 3. + 5. * ( 40. - temp_cur ) / 20. );
5821  if ( cshboxsize < 1 ) {
5822  cshboxsize = 1;
5823  }
5824 
5825  if ( cshboxsize >= SYSIZE ) {
5826  cshboxsize = SYSIZE;
5827  }
5828 
5829  //11.12.2006 smilauer
5830  placed = loccsh(xc, yc, zc, cshboxsize);
5831  if ( placed != 0 ) {
5832  count [ DIFFCSH ] += 1;
5833  count [ POROSITY ] -= 1;
5834  } else {
5835  cshrand += 1;
5836  }
5837  }
5838  }
5839 
5840  if ( ( phid == C2S ) && ( pc2scsh > 1.0 ) ) {
5841  plfh3 = ran1(seed);
5842  if ( plfh3 <= ( pc2scsh - 1.0 ) ) {
5843  cshboxsize = ( int ) ( 3. + 5. * ( 40. - temp_cur ) / 20. );
5844  if ( cshboxsize < 1 ) {
5845  cshboxsize = 1;
5846  }
5847 
5848  if ( cshboxsize >= SYSIZE ) {
5849  cshboxsize = SYSIZE;
5850  }
5851 
5852  //11.12.2006 smilauer
5853  placed = loccsh(xc, yc, zc, cshboxsize);
5854  if ( placed != 0 ) {
5855  count [ DIFFCSH ] += 1;
5856  count [ POROSITY ] -= 1;
5857  } else {
5858  cshrand += 1;
5859  }
5860  }
5861  }
5862  } else {
5863  mic [ xloop ] [ yloop ] [ zloop ] -= OFFSET;
5864  }
5865  }
5866 
5867  /* end of if edge loop */
5868  /* Now check if CSH to pozzolanic CSH conversion is possible */
5869  /* Only if CH is less than 15% in volume */
5870  /* Only if CSH is in contact with at least one porosity */
5871  /* and user wishes to use this option */
5872  if ( ( count [ POZZ ] >= 13000 ) && ( chnew < ( 0.15 * SYSIZE * SYSIZE * SYSIZE ) ) && ( csh2flag == 1 ) ) {
5873  if ( mic [ xloop ] [ yloop ] [ zloop ] == CSH ) {
5874  if ( ( countbox(3, xloop, yloop, zloop) ) >= 1 ) {
5875  pconvert = ran1(seed);
5876  if ( pconvert < PCSH2CSH ) {
5877  count [ CSH ] -= 1;
5878  plfh3 = ran1(seed);
5879  /* molarvcsh units of C1.7SHx goes to */
5880  /* 101.81 units of C1.1SH3.9 */
5881  /* with 19.86 units of CH */
5882  /* so p=calcy */
5883  calcz = 0.0;
5884  cycnew = cshage [ xloop ] [ yloop ] [ zloop ];
5885  calcy = molarv [ POZZCSH ] / molarvcsh [ cycnew ];
5886  if ( calcy > 1.0 ) {
5887  calcz = calcy - 1.0;
5888  calcy = 1.0;
5889  printf("Problem of not creating enough pozzolanic CSH during CSH conversion \n");
5890  printf("Current temperature is %f C\n", temp_cur);
5891  }
5892 
5893  if ( plfh3 <= calcy ) {
5894  mic [ xloop ] [ yloop ] [ zloop ] = POZZCSH;
5895  count [ POZZCSH ] += 1;
5896  } else {
5897  mic [ xloop ] [ yloop ] [ zloop ] = DIFFCH;
5898  nmade += 1;
5899  ncshgo += 1;
5900  ngoing += 1;
5901  count [ DIFFCH ] += 1;
5902  antadd = ( struct ants * ) malloc( sizeof( struct ants ) );
5903  antadd->x = xloop;
5904  antadd->y = yloop;
5905  antadd->z = zloop;
5906  antadd->id = DIFFCH;
5907  antadd->cycbirth = cyccnt;
5908  /* Now connect this ant structure to end of linked list */
5909  antadd->prevant = tailant;
5910  tailant->nextant = antadd;
5911  antadd->nextant = NULL;
5912  tailant = antadd;
5913  }
5914 
5915  /* Possibly need even more pozzolanic CSH */
5916  /* Would need a diffusing pozzolanic
5917  * CSH species??? */
5918  /* if(calcz>0.0){
5919  * plfh3=ran1(seed);
5920  * if(plfh3<=calcz){
5921  * cshrand+=1;
5922  * }
5923  * } */
5924 
5925 
5926  plfh3 = ran1(seed);
5927  calcx = ( 19.86 / molarvcsh [ cycnew ] ) - ( 1. - calcy );
5928  /* Ex. 0.12658=(19.86/108.)-(1.-0.94269) */
5929  if ( plfh3 < calcx ) {
5930  npchext += 1;
5931  }
5932  }
5933  }
5934  }
5935  }
5936 
5937  /* See if slag can react --- in contact with at least one porosity */
5938  if ( mic [ xloop ] [ yloop ] [ zloop ] == SLAG ) {
5939  if ( ( countbox(3, xloop, yloop, zloop) ) >= 1 ) {
5940  pconvert = ran1(seed);
5941  if ( pconvert < ( disprob [ SLAG ] / ( 1. + pHfactor * pHeffect [ SLAG ] ) ) ) {
5942  nslagr += 1;
5943  count [ SLAG ] -= 1;
5944  discount [ SLAG ] += 1;
5945  /* Check on extra C3A generation */
5946  plfh3 = ran1(seed);
5947  if ( plfh3 < p5slag ) {
5948  nslagc3a += 1;
5949  }
5950 
5951  /* Convert slag to reaction products */
5952  plfh3 = ran1(seed);
5953  if ( plfh3 < p1slag ) {
5954  mic [ xloop ] [ yloop ] [ zloop ] = SLAGCSH;
5955  /* Assign a plate axes identifier to this slag C-S-H voxel */
5956  msface = ( int ) ( 3. * ran1(seed) + 1. );
5957  if ( msface > 3 ) {
5958  msface = 1;
5959  }
5960 
5961  faces [ xloop ] [ yloop ] [ zloop ] = msface;
5962  count [ SLAGCSH ] += 1;
5963  } else {
5964  if ( sealed == 1 ) {
5965  /* Create empty porosity at slag site */
5966  slagemptyp += 1;
5967  mic [ xloop ] [ yloop ] [ zloop ] = EMPTYP;
5968  count [ EMPTYP ] += 1;
5969  } else {
5970  mic [ xloop ] [ yloop ] [ zloop ] = POROSITY;
5971  count [ POROSITY ] += 1;
5972  }
5973  }
5974 
5975  /* Add in extra SLAGCSH as needed */
5976  p3init = p3slag;
5977  while ( p3init > 1.0 ) {
5978  extslagcsh(xloop, yloop, zloop);
5979  p3init -= 1.0;
5980  }
5981 
5982  plfh3 = ran1(seed);
5983  if ( plfh3 < p3init ) {
5984  extslagcsh(xloop, yloop, zloop);
5985  }
5986  }
5987  }
5988  }
5989  }
5990 
5991  /* end of zloop */
5992  }
5993 
5994  /* end of yloop */
5995  }
5996 
5997  /* end of xloop */
5998 
5999  if ( ncshgo != 0 ) {
6000  printf("CSH dissolved is %ld \n", ncshgo);
6001  }
6002 
6003  if ( npchext > 0 ) {
6004  printf("npchext is %ld at cycle %d \n", npchext, cycle);
6005  }
6006 
6007  /* Now add in the extra diffusing species for dissolution */
6008  /* Expansion factors from Young and Hansen and */
6009  /* Mindess and Young (Concrete) */
6010  ncshext = cshrand;
6011  if ( cshrand != 0 ) {
6012  printf("cshrand is %d \n", cshrand);
6013  }
6014 
6015  /* CH, Gypsum, and diffusing C3A are added at totally random
6016  * locations as opposed to at the dissolution site
6017  * molar_weight[CH]=74 g/mol
6018  * molar_weight[C3S]=228 g/mol
6019  * only for C3S hydration - reason is the Pignat's thesis
6020  * C3S+5.3 H2O -> C1.7SH4 + 1.3 CH
6021  */
6022 
6023  fchext = 1.3 * 74 * specgrav [ C3S ] / ( specgrav [ CH ] * 228 ) * ( float ) discount [ C3S ] + 0.191 * ( float ) discount [ C2S ] +
6024  0.2584 * ( float ) discount [ C4AF ]; //originally 0.61
6025 
6026  nchext = ( int ) fchext;
6027  if ( fchext > ( float ) nchext ) {
6028  pdis = ran1(seed);
6029  if ( ( fchext - ( float ) nchext ) > pdis ) {
6030  nchext += 1;
6031  }
6032  }
6033 
6034  nchext += npchext;
6035  /* Adjust CH addition for slag consumption and maintain deficit as needed */
6036  slagcum += discount [ SLAG ];
6037  chgone = ( int ) ( p4slag * ( float ) slagcum );
6038  nchext -= chgone;
6039  slagcum -= ( int ) ( ( float ) chgone / p4slag );
6040  nchext -= DIFFCHdeficit;
6041  DIFFCHdeficit = 0;
6042  if ( nchext < 0 ) {
6043  DIFFCHdeficit -= nchext;
6044  nchext = 0;
6045  }
6046 
6047  fc3aext = discount [ C3A ] + 0.5917 * ( float ) discount [ C3AH6 ];
6048  nc3aext = ( int ) ( fc3aext + nslagc3a );
6049  if ( fc3aext > ( float ) nc3aext ) {
6050  pdis = ran1(seed);
6051  if ( ( fc3aext - ( float ) nc3aext ) > pdis ) {
6052  nc3aext += 1;
6053  }
6054  }
6055 
6056  fc4aext = 0.696 * ( float ) discount [ C4AF ];
6057  nc4aext = ( int ) fc4aext;
6058  if ( fc4aext > ( float ) nc4aext ) {
6059  pdis = ran1(seed);
6060  if ( ( fc4aext - ( float ) nc4aext ) > pdis ) {
6061  nc4aext += 1;
6062  }
6063  }
6064 
6065  /* both forms of GYPSUM form same DIFFGYP species */
6066  ngypext = discount [ GYPSUM ] + discount [ GYPSUMS ];
6067  /* Convert to diffusing anhydrite at volume necessary for final */
6068  /* gypsum formation (1 anhydrite --> 1.423 gypsum) */
6069  /* Since hemihydrate can now react with C3A, etc., can't */
6070  /* do expansion here any longer 7/99 */
6071  /* fanhext=1.423*(float)discount[ANHYDRITE]; */
6072  fanhext = ( float ) discount [ ANHYDRITE ];
6073  nanhext = ( int ) fanhext;
6074  if ( fanhext > ( float ) nanhext ) {
6075  pdis = ran1(seed);
6076  if ( ( fanhext - ( float ) nanhext ) > pdis ) {
6077  nanhext += 1;
6078  }
6079  }
6080 
6081  /* Convert to diffusing hemiydrate at volume necessary for final */
6082  /* gypsum formation (1 hemihydrate --> 1.4 gypsum) */
6083  /* Since hemihydrate can now react with C3A, etc., can't */
6084  /* do expansion here any longer 7/99 */
6085  fhemext = ( float ) discount [ HEMIHYD ];
6086  /* fhemext=1.3955*(float)discount[HEMIHYD]; */
6087 
6088  nhemext = ( int ) fhemext;
6089  if ( fhemext > ( float ) nhemext ) {
6090  pdis = ran1(seed);
6091  if ( ( fhemext - ( float ) nhemext ) > pdis ) {
6092  nhemext += 1;
6093  }
6094  }
6095 
6096  count [ DIFFGYP ] += ngypext;
6097  count [ DIFFANH ] += nanhext;
6098  count [ DIFFHEM ] += nhemext;
6099  count [ DIFFCH ] += nchext;
6100  count [ DIFFCSH ] += ncshext;
6101  count [ DIFFC3A ] += nc3aext;
6102  count [ DIFFC4A ] += nc4aext;
6103 
6104  nsum2 = nchext + ncshext;
6105  nsum3 = nsum2 + nc3aext;
6106  nsum4 = nsum3 + nc4aext;
6107  nsum5 = nsum4 + ngypext;
6108  nsum6 = nsum5 + nhemext;
6109  fflush(stdout);
6110 
6111  //add extra diffusing species - check for infinite looping if porosity is not available - smilauer 01/16/2008
6112  for ( xext = 1; xext <= ( nsum6 + nanhext ); xext++ ) {
6113  plok = 0;
6114  tries = 0;
6115  do {
6116  xc = ( int ) ( ( float ) SYSIZE * ran1(seed) ); //locate random place in the microstructure
6117  yc = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6118  zc = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6119  if ( xc >= SYSIZE ) {
6120  xc = 0;
6121  }
6122 
6123  if ( yc >= SYSIZE ) {
6124  yc = 0;
6125  }
6126 
6127  if ( zc >= SYSIZE ) {
6128  zc = 0;
6129  }
6130 
6131  tries++;
6132 
6133  if ( mic [ xc ] [ yc ] [ zc ] == POROSITY ) {
6134  plok = 1;
6135  phid = DIFFCH;
6136  count [ POROSITY ] -= 1;
6137  if ( xext > nsum6 ) {
6138  phid = DIFFANH;
6139  } else if ( xext > nsum5 ) {
6140  phid = DIFFHEM;
6141  } else if ( xext > nsum4 ) {
6142  phid = DIFFGYP;
6143  } else if ( xext > nsum3 ) {
6144  phid = DIFFC4A;
6145  } else if ( xext > nsum2 ) {
6146  phid = DIFFC3A;
6147  } else if ( xext > nchext ) {
6148  phid = DIFFCSH;
6149  }
6150 
6151  mic [ xc ] [ yc ] [ zc ] = phid;
6152  nmade += 1;
6153  ngoing += 1;
6154  antadd = ( struct ants * ) malloc( sizeof( struct ants ) );
6155  //printf("MEM addr %p\n", (const void *)antadd);
6156  antadd->x = xc;
6157  antadd->y = yc;
6158  antadd->z = zc;
6159  antadd->id = phid;
6160  antadd->cycbirth = cyccnt;
6161  /* Now connect this ant structure to end of linked list */
6162  antadd->prevant = tailant;
6163  tailant->nextant = antadd;
6164  antadd->nextant = NULL;
6165  tailant = antadd;
6166  }
6167 
6168  if ( tries > 10 * SYSIZE_POW3 ) {
6169 #ifdef PRINTF
6170  printf("Could not place extra diffusing species (too few POROSITY voxels), continuing (line %d),\n", __LINE__);
6171 #endif
6172  continue;
6173  }
6174  } while ( plok == 0 );
6175  }
6176 
6177  /* end of xext for extra species generation */
6178 
6179 #ifdef PRINTF
6180  printf("Dissolved- %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", count [ DIFFCSH ],
6181  count [ DIFFCH ], count [ DIFFGYP ], count [ DIFFC3A ], count [ DIFFFH3 ],
6182  count [ DIFFETTR ], count [ DIFFAS ], count [ DIFFANH ], count [ DIFFHEM ],
6183  count [ DIFFCAS2 ], count [ DIFFCACL2 ], count [ DIFFCACO3 ]);
6184 #endif
6185 
6186  sulf_cur = count [ DIFFGYP ] + count [ DIFFANH ] + count [ DIFFHEM ];
6187  /* difffile=fopen("diffuse.out","a");
6188  * 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);
6189  *
6190  * fclose(difffile); */
6191 
6192  /* if too many diffusing gypsums already in solution */
6193  if ( sulf_cur > DGYPMAX ) {
6194  disprob [ GYPSUM ] = disprob [ GYPSUMS ] = 0.0;
6195  } else {
6196  disprob [ GYPSUM ] = disbase [ GYPSUM ];
6197  disprob [ ANHYDRITE ] = disbase [ ANHYDRITE ];
6198  disprob [ HEMIHYD ] = disbase [ HEMIHYD ];
6199  disprob [ GYPSUMS ] = disbase [ GYPSUMS ];
6200  }
6201 
6202 #ifdef PRINTF
6203  printf("C3AH6 dissolved- %ld with prob. of %f \n", nhgd, disprob [ C3AH6 ]);
6204 #endif
6205 
6206  fflush(stdout);
6207  ( void ) nsurf;
6208  ( void ) calcz;
6209 }
6210 /* routine to add nneed one pixel elements of phase randid at random */
6211 /* locations in microstructure */
6212 /* Special features for addition of 1-pixel CACO3 and INERT particles */
6213 /* added 5/26/2004 */
6214 /* Called by main program */
6215 /* Calls no other routines */
6216 void CemhydMatStatus :: addrand(int randid, long int nneed)
6217 {
6218  int ix, iy, iz;
6219  long int ic;
6220  int success, cpores;
6221 
6222  /* Add number of requested phase pixels at random pore locations */
6223  for ( ic = 1; ic <= nneed; ic++ ) {
6224  success = 0;
6225  while ( success == 0 ) {
6226  ix = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6227  iy = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6228  iz = ( int ) ( ( float ) SYSIZE * ran1(seed) );
6229  if ( ix == SYSIZE ) {
6230  ix = 0;
6231  }
6232 
6233  if ( iy == SYSIZE ) {
6234  iy = 0;
6235  }
6236 
6237  if ( iz == SYSIZE ) {
6238  iz = 0;
6239  }
6240 
6241  if ( mic [ ix ] [ iy ] [ iz ] == POROSITY ) {
6242  if ( ( randid != CACO3 ) && ( randid != INERT ) ) {
6243  mic [ ix ] [ iy ] [ iz ] = randid;
6244  micorig [ ix ] [ iy ] [ iz ] = randid;
6245  success = 1;
6246  } else {
6247  cpores = countboxc(3, ix, iy, iz);
6248  if ( cpores >= 26 ) {
6249  mic [ ix ] [ iy ] [ iz ] = randid;
6250  micorig [ ix ] [ iy ] [ iz ] = randid;
6251  success = 1;
6252  }
6253  }
6254  }
6255  }
6256  }
6257 }
6258 /* Routine measuresurf to measure initial surface counts for cement */
6259 /* and for all phases (cement= C3S, C2S, C3A, C4AF, and calcium sulfates */
6261 {
6262  int sx, sy, sz, jx = 0, jy = 0, jz = 0, faceid;
6263 
6264  for ( sx = 0; sx < SYSIZE; sx++ ) {
6265  for ( sy = 0; sy < SYSIZE; sy++ ) {
6266  for ( sz = 0; sz < SYSIZE; sz++ ) {
6267  if ( mic [ sx ] [ sy ] [ sz ] == POROSITY ) {
6268  for ( faceid = 0; faceid < 6; faceid++ ) {
6269  if ( faceid == 1 ) {
6270  jx = sx - 1;
6271  if ( jx < 0 ) {
6272  jx = SYSIZE - 1;
6273  }
6274 
6275  jy = sy;
6276  jz = sz;
6277  } else if ( faceid == 0 ) {
6278  jx = sx + 1;
6279  if ( jx > ( SYSIZE - 1 ) ) {
6280  jx = 0;
6281  }
6282 
6283  jy = sy;
6284  jz = sz;
6285  } else if ( faceid == 2 ) {
6286  jy = sy + 1;
6287  if ( jy > ( SYSIZE - 1 ) ) {
6288  jy = 0;
6289  }
6290 
6291  jx = sx;
6292  jz = sz;
6293  } else if ( faceid == 3 ) {
6294  jy = sy - 1;
6295  if ( jy < 0 ) {
6296  jy = SYSIZE - 1;
6297  }
6298 
6299  jx = sx;
6300  jz = sz;
6301  } else if ( faceid == 4 ) {
6302  jz = sz + 1;
6303  if ( jz > ( SYSIZE - 1 ) ) {
6304  jz = 0;
6305  }
6306 
6307  jx = sx;
6308  jy = sy;
6309  } else if ( faceid == 5 ) {
6310  jz = sz - 1;
6311  if ( jz < 0 ) {
6312  jz = SYSIZE - 1;
6313  }
6314 
6315  jx = sx;
6316  jy = sy;
6317  }
6318 
6319  /* If the neighboring pixel is solid, update surface counts */
6320  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 ) ) {
6321  scnttotal += 1;
6322  if ( ( mic [ jx ] [ jy ] [ jz ] == C3S ) || ( mic [ jx ] [ jy ] [ jz ] == C2S ) || ( mic [ jx ] [ jy ] [ jz ] == C3A ) || ( mic [ jx ] [ jy ] [ jz ] == C4AF ) ) {
6323  scntcement += 1;
6324  }
6325  }
6326  }
6327  }
6328  }
6329  }
6330  }
6331 
6332 #ifdef PRINTF
6333  printf("Cement surface count is %ld \n", scntcement);
6334  printf("Total surface count is %ld \n", scnttotal);
6335 #endif
6336 
6337  surffract = ( float ) scntcement / ( float ) scnttotal;
6338 
6339 #ifdef PRINTF
6340  printf("Surface fraction is %f \n", surffract);
6341 #endif
6342 
6343  fflush(stdout);
6344 }
6345 
6346 /* Routine to resaturate all empty porosity */
6347 /* and continue with hydration under saturated conditions */
6349 {
6350  int sx, sy, sz;
6351  long int nresat = 0;
6352 
6353  for ( sx = 0; sx < SYSIZE; sx++ ) {
6354  for ( sy = 0; sy < SYSIZE; sy++ ) {
6355  for ( sz = 0; sz < SYSIZE; sz++ ) {
6356  if ( mic [ sx ] [ sy ] [ sz ] == EMPTYP ) {
6357  mic [ sx ] [ sy ] [ sz ] = POROSITY;
6358  nresat++;
6359  }
6360  }
6361  }
6362  }
6363 
6364  if ( nresat > 0 ) {
6365  porefl1 = porefl2 = porefl3 = 1;
6366  }
6367 
6368  printf("Number resaturated is %ld \n", nresat);
6369  fflush(stdout);
6370 }
6371 
6372 
6373 /*called from main loop*/
6375 {
6376  FILE *imgout;
6377  char extension [ 10 ];
6378  //char outputname[80];
6379  char *prefix;
6380  prefix = ( char * ) malloc(80);
6381 
6382  //mkdir("unperc", 0777);//make directory (every time)
6383  //system("mk unperc");
6384  //system("mkdir unperc 2> /dev/null");
6385  fprintf(infoUnperc, "%d %.4f %.3f\n", icyc, alpha_cur, time_cur);
6386  fflush(infoUnperc);
6387 
6388  sprintf(extension, "%04d", icyc);
6389  strcpy(prefix, "unperc/out5."); //see line with mkdir in order to be the same
6390  strcat(prefix, extension);
6391  strcat(prefix, ".img");
6392 #ifdef PRINTF
6393  printf("Name of output file is %s\n", prefix);
6394 #endif
6395 
6396  if ( ( imgout = fopen(prefix, "w") ) == NULL ) {
6397  printf("File %s can not be opened\n", prefix);
6398  free(prefix);
6399  return;
6400  }
6401 
6402  for ( int dz = 0; dz < SYSIZE; dz++ ) {
6403  for ( int dy = 0; dy < SYSIZE; dy++ ) {
6404  for ( int dx = 0; dx < SYSIZE; dx++ ) {
6405  fprintf(imgout, "%d\n", m [ dx ] [ dy ] [ dz ]);
6406  }
6407  }
6408  }
6409 
6410  fclose(imgout);
6411 #ifdef PRINTF
6412  printf("Unpercolated file %s wrote\n", prefix);
6413 #endif
6414  free(prefix);
6415 }
6416 
6417 
6419 {
6420  int fidc3s, fidc2s, fidc3a, fidc4af, fidgyp, fidagg, ffac3a;
6421  int fidhem, fidanh, fidcaco3;
6422  int read_micr;
6423  long int valin;
6424  int ix, iy, iz, phtodo;
6425  long int nadd;
6426  char filei [ 80 ];
6427  FILE *infile;
6428 
6429  /* Get random number seed */
6430  //printf("Enter random number seed \n");
6431  //fscanf(in, "%d",&nseed);
6432  nseed = iseed;
6433  seed = ( & nseed );
6434 
6435 #ifdef PRINTF
6436  printf("Seed %d\n", * seed);
6437 #endif
6438 
6439  //check whether microstructure from file should be used
6440 #ifdef CMLFILE
6441  F->get_value(13, ( long & )read_micr);
6442 #endif
6443 #ifdef TINYXML
6444  QueryNumAttributeExt(xmlFile, "Given_microstructure", 0, read_micr);
6445 #endif
6446 
6447  /* Open file and read in original cement particle microstructure if required*/
6448  if ( read_micr ) {
6449 #ifdef PRINTF
6450  printf("Enter name of file to read initial microstructure from \n");
6451 #endif
6452 #ifdef CMLFILE
6453  F->get_value(1, filei);
6454 #endif
6455 #ifdef TINYXML
6456  QueryStringAttributeExt(xmlFile, "Input_img_file", 0, filei);
6457 #endif
6458  //fscanf(in, "%s",filei);
6459 
6460 #ifdef PRINTF
6461  printf("%s\n", filei);
6462  fflush(stdout);
6463 #endif
6464  }
6465 
6466  /* Get phase assignments for original microstructure */
6467  /* to transform to needed ID values */
6468 
6469 #ifdef PRINTF
6470  printf("Enter IDs in file for C3S, C2S, C3A, C4AF, Gypsum, Hemihydrate, Anhydrite, Aggregate, CaCO3\n");
6471 #endif
6472 
6473  fidc3s = C3S;
6474  fidc2s = C2S;
6475  fidc3a = C3A;
6476  fidc4af = C4AF;
6477  fidgyp = GYPSUM;
6478  fidhem = HEMIHYD;
6479  fidanh = ANHYDRITE;
6480  fidagg = INERTAGG;
6481  fidcaco3 = CACO3;
6482 
6483  //scanf("%d %d %d %d %d %d %d %d %d",&fidc3s,&fidc2s,&fidc3a,&fidc4af,&fidgyp,&fidhem,&fidanh,&fidagg,&fidcaco3);
6484 #ifdef PRINTF
6485  printf("%d %d %d %d %d %d %d %d %d\n", fidc3s, fidc2s, fidc3a, fidc4af, fidgyp, fidhem, fidanh, fidagg, fidcaco3);
6486  printf("Enter ID in file for C3A in fly ash (default=35)\n");
6487 #endif
6488  //fscanf(in, "%d",&ffac3a);
6489  ffac3a = 35;
6490 #ifdef PRINTF
6491  printf("%d\n", ffac3a);
6492 #endif
6493  fflush(stdout);
6494 
6495  if ( read_micr ) {
6496  if ( ( infile = fopen(filei, "r") ) == NULL ) {
6497  printf("CEMHYD3D microstructure file %s not found\n", filei);
6498  exit(0);
6499  }
6500 
6501  for ( iz = 0; iz < SYSIZE; iz++ ) { //fixed cycle order
6502  for ( iy = 0; iy < SYSIZE; iy++ ) {
6503  for ( ix = 0; ix < SYSIZE; ix++ ) {
6504  cshage [ ix ] [ iy ] [ iz ] = 0;
6505  faces [ ix ] [ iy ] [ iz ] = 0;
6506 
6507  if ( fscanf(infile, "%ld", & valin) == EOF ) {
6508  printf("End of file %s reached, terminating\n", filei);
6509  exit(1);
6510  }
6511 
6512  if ( valin < 0 ) {
6513  printf("Error in the reading at x=%d y=%d z=%d, value %ld\n", ix, iy, iz, valin);
6514  exit(1);
6515  }
6516 
6517  mic [ ix ] [ iy ] [ iz ] = valin;
6518  if ( valin == fidc3s ) {
6519  mic [ ix ] [ iy ] [ iz ] = C3S;
6520  } else if ( valin == fidc2s ) {
6521  mic [ ix ] [ iy ] [ iz ] = C2S;
6522  } else if ( ( valin == fidc3a ) || ( valin == ffac3a ) ) {
6523  mic [ ix ] [ iy ] [ iz ] = C3A;
6524  } else if ( valin == fidc4af ) {
6525  mic [ ix ] [ iy ] [ iz ] = C4AF;
6526  } else if ( valin == fidgyp ) {
6527  mic [ ix ] [ iy ] [ iz ] = GYPSUM;
6528  } else if ( valin == fidanh ) {
6529  mic [ ix ] [ iy ] [ iz ] = ANHYDRITE;
6530  } else if ( valin == fidhem ) {
6531  mic [ ix ] [ iy ] [ iz ] = HEMIHYD;
6532  } else if ( valin == fidcaco3 ) {
6533  mic [ ix ] [ iy ] [ iz ] = CACO3;
6534  } else if ( valin == fidagg ) {
6535  mic [ ix ] [ iy ] [ iz ] = INERTAGG;
6536  }
6537 
6538  micorig [ ix ] [ iy ] [ iz ] = mic [ ix ] [ iy ] [ iz ];
6539  }
6540  }
6541  }
6542 
6543  fclose(infile);
6544  } else {
6545 #ifdef PRINTF
6546  printf("Generated microstructure from memory will be used\n");
6547 #endif
6548  }
6549 
6550  fflush(stdout);
6551 
6552  /* Now read in particle IDs from file if required*/
6553  if ( read_micr ) {
6554 #ifdef PRINTF
6555  printf("Enter name of file to read particle IDs from \n");
6556 #endif
6557 #ifdef CMLFILE
6558  F->get_value(2, filei);
6559 #endif
6560 #ifdef TINYXML
6561  QueryStringAttributeExt(xmlFile, "Input_id_file", 0, filei);
6562 #endif
6563  //fscanf(in, "%s",filei);
6564 
6565 #ifdef PRINTF
6566  printf("%s\n", filei);
6567 #endif
6568 
6569  if ( ( infile = fopen(filei, "r") ) == NULL ) {
6570  printf("CEMHYD3D microstructure ID file %s not found\n", filei);
6571  exit(0);
6572  }
6573 
6574  for ( iz = 0; iz < SYSIZE; iz++ ) { //fixed cycle order
6575  for ( iy = 0; iy < SYSIZE; iy++ ) {
6576  for ( ix = 0; ix < SYSIZE; ix++ ) {
6577  if ( fscanf(infile, "%ld", & valin) == EOF ) {
6578  printf("End of file %s reached, terminating\n", filei);
6579  exit(1);
6580  }
6581 
6582  micpart [ ix ] [ iy ] [ iz ] = valin;
6583  }
6584  }
6585  }
6586 
6587  fclose(infile);
6588  } else {
6589 #ifdef PRINTF
6590  printf("Generated microstructure ID from memory will be used\n");
6591 #endif
6592  }
6593 
6594 
6595  fflush(stdout);
6596 
6597 
6598  /* Allow user to iteratively add one pixel particles of various phases */
6599  /* Typical application would be for addition of silica fume */
6600 #ifdef PRINTF
6601  printf("Enter number of one pixel particles to add (0 to quit) \n");
6602 #endif
6603  //fscanf(in, "%ld",&nadd);
6604  nadd = 0;
6605 
6606 #ifdef PRINTF
6607  printf("%ld\n", nadd);
6608 #endif
6609 
6610  while ( nadd > 0 ) {
6611 #ifdef PRINTF
6612  printf("Enter phase to add \n");
6613  printf(" C3S 1 \n");
6614  printf(" C2S 2 \n");
6615  printf(" C3A 3 \n");
6616  printf(" C4AF 4 \n");
6617  printf(" GYPSUM 5 \n");
6618  printf(" HEMIHYD 6 \n");
6619  printf(" ANHYDRITE 7 \n");
6620  printf(" POZZ 8 \n");
6621  printf(" INERT 9 \n");
6622  printf(" SLAG 10 \n");
6623  printf(" ASG 11 \n");
6624  printf(" CAS2 12 \n");
6625  printf(" CH 13 \n");
6626  printf(" CSH 14 \n");
6627  printf(" C3AH6 15 \n");
6628  printf(" Ettringite 16 \n");
6629  printf(" Stable Ettringite from C4AF 17 \n");
6630  printf(" AFM 18 \n");
6631  printf(" FH3 19 \n");
6632  printf(" POZZCSH 20 \n");
6633  printf(" SLAGCSH 21 \n");
6634  printf(" CACL2 22 \n");
6635  printf(" Friedels salt 23 \n");
6636  printf(" Stratlingite 24 \n");
6637  printf(" Calcium carbonate 26 \n");
6638 #endif
6639  //fscanf(in, "%d",&phtodo);
6640  phtodo = 0;
6641 #ifdef PRINTF
6642  printf("%d \n", phtodo);
6643 #endif
6644  if ( ( phtodo < 0 ) || ( phtodo > CACO3 ) ) {
6645  printf("Error in phase input for one pixel particles \n");
6646  exit(1);
6647  }
6648 
6649  addrand(phtodo, nadd);
6650 
6651 #ifdef PRINTF
6652  printf("Enter number of one pixel particles to add (0 to quit) \n");
6653 #endif
6654 
6655  //fscanf(in, "%ld",&nadd);
6656  nadd = 0;
6657 #ifdef PRINTF
6658  printf("%ld\n", nadd);
6659 #endif
6660  }
6661 
6662  fflush(stdout);
6663 
6664  //printf("Do you wish hydration under 0) saturated or 1) sealed conditions \n");
6665 #ifdef CMLFILE
6666  F->get_value(3, ( long & )sealed);
6667 #endif
6668 #ifdef TINYXML
6669  QueryNumAttributeExt(xmlFile, "Saturated_sealed", 0, sealed);
6670 #endif
6671  //fscanf(in, "%d",&sealed);
6672  //printf("%d \n",sealed);
6673  //printf("Enter max. # of diffusion steps per cycle (500) \n");
6674  //fscanf(in, "%d",&ntimes);
6675 #ifdef CMLFILE
6676  F->get_value(23, ( long & )ntimes);
6677 #endif
6678 #ifdef TINYXML
6679  QueryNumAttributeExt(xmlFile, "Diffusion_steps_per_cycle", 0, ntimes);
6680 #endif
6681  //ntimes=500;
6682  //printf("%d \n",ntimes);
6683  //printf("Enter nuc. prob. and scale factor for CH nucleation \n");
6684  //fscanf(in, "%f %f",&pnucch,&pscalech);
6685 #ifdef CMLFILE
6686  F->get_value(24, pnucch);
6687  F->get_value(25, pscalech);
6688 #endif
6689 #ifdef TINYXML
6690  QueryNumAttributeExt(xmlFile, "CH_nucleation_probability", 0, pnucch);
6691  QueryNumAttributeExt(xmlFile, "CH_scale_factor", 0, pscalech);
6692 #endif
6693  //pnucch=0.0001;
6694  //pscalech=9000.;
6695  //printf("%f %f \n",pnucch,pscalech);
6696  //printf("Enter nuc. prob. and scale factor for gypsum nucleation \n");
6697  //fscanf(in, "%f %f",&pnucgyp,&pscalegyp);
6698 #ifdef CMLFILE
6699  F->get_value(26, pnucgyp);
6700  F->get_value(27, pscalegyp);
6701 #endif
6702 #ifdef TINYXML
6703  QueryNumAttributeExt(xmlFile, "Gypsum_nucleation_probability", 0, pnucgyp);
6704  QueryNumAttributeExt(xmlFile, "Gypsum_scale_factor", 0, pscalegyp);
6705 #endif
6706  //pnucgyp=0.01;
6707  //pscalegyp=9000.;
6708  //printf("%f %f \n",pnucgyp,pscalegyp);
6709  //printf("Enter nuc. prob. and scale factor for C3AH6 nucleation \n");
6710  //fscanf(in, "%f %f",&pnuchg,&pscalehg);
6711 #ifdef CMLFILE
6712  F->get_value(28, pnuchg);
6713  F->get_value(29, pscalehg);
6714 #endif
6715 #ifdef TINYXML
6716  QueryNumAttributeExt(xmlFile, "C3AH6_nucleation_probability", 0, pnuchg);
6717  QueryNumAttributeExt(xmlFile, "C3AH6_scale_factor", 0, pscalehg);
6718 #endif
6719  //pnuchg=0.00002;
6720  //pscalehg=10000.;
6721  //printf("%f %f \n",pnuchg,pscalehg);
6722  //printf("Enter nuc. prob. and scale factor for FH3 nucleation \n");
6723  //fscanf(in, "%f %f",&pnucfh3,&pscalefh3);
6724 #ifdef CMLFILE
6725  F->get_value(30, pnucfh3);
6726  F->get_value(31, pscalefh3);
6727 #endif
6728 #ifdef TINYXML
6729  QueryNumAttributeExt(xmlFile, "FH3_nucleation_probability", 0, pnucfh3);
6730  QueryNumAttributeExt(xmlFile, "FH3_scale_factor", 0, pscalefh3);
6731 #endif
6732  //pnucfh3=0.002;
6733  //pscalefh3=2500.;
6734  //printf("%f %f \n",pnucfh3,pscalefh3);
6735  //printf("Enter cycle frequency for checking pore space percolation \n");
6736  //fscanf(in, "%d",&burnfreq);
6737 #ifdef CMLFILE
6738  F->get_value(17, ( long & )burnfreq);
6739  F->get_value(33, adiabatic_curing);
6740 #endif
6741 #ifdef TINYXML
6742  QueryNumAttributeExt(xmlFile, "Cycle_freq_perc_pore", 0, burnfreq);
6743  QueryNumAttributeExt(xmlFile, "Adiabatic_conditions", 0, adiabatic_curing);
6744 #endif
6745 
6746 #ifdef __TM_MODULE //OOFEM transport module
6747  adiabatic_curing = 0;
6748 #endif
6749 
6750 #ifdef PRINTF
6751  printf("Enter cycle frequency for checking percolation of solids (set) \n");
6752  printf("%d\n", burnfreq);
6753  printf("Adiabatic curing conditions %d\n", adiabatic_curing);
6754 #endif
6755  //fscanf(in, "%d",&setfreq);
6756 #ifdef CMLFILE
6757  F->get_value(18, ( long & )setfreq);
6758 #endif
6759 #ifdef TINYXML
6760  QueryNumAttributeExt(xmlFile, "Cycle_freq_perc_sol", 0, setfreq);
6761 #endif
6762  //setfreq=50000;
6763 #ifdef PRINTF
6764  printf("Enter cycle frequency for checking hydration of particles \n");
6765  printf("%d\n", setfreq);
6766 #endif
6767  //fscanf(in, "%d",&phydfreq);
6768  phydfreq = 50000; //disabled
6769  //printf("%d\n",phydfreq);
6770  //printf("Enter cycle frequency for outputting hydrating microstructure \n");
6771  //fscanf(in, "%d",&outfreq);
6772  outfreq = 50000;
6773  //printf("%d\n",outfreq);
6774  //printf("Enter the induction time in hours \n");
6775 #ifdef CMLFILE
6776  F->get_value(4, ind_time);
6777 #endif
6778 #ifdef TINYXML
6779  QueryNumAttributeExt(xmlFile, "Induction_time", 0, ind_time);
6780 #endif
6781  //fscanf(in, "%lf",&ind_time);
6782  //printf("%f \n",ind_time);
6783  time_cur += ind_time;
6784  /* heat transfer coefficient in J/g/C/s - not used*/
6785  //fscanf(in, "%f",&U_coeff);
6786  U_coeff = 0;
6787 #ifdef PRINTF
6788  printf("Enter apparent activation energy for hydration in kJ/mole \n");
6789 #endif
6790 #ifdef CMLFILE
6791  F->get_value(5, E_act);
6792 #endif
6793 #ifdef TINYXML
6794  QueryNumAttributeExt(xmlFile, "Ea_cement", 0, E_act);
6795 #endif
6796  //fscanf(in, "%lf",&E_act);
6797 #ifdef PRINTF
6798  printf("%f \n", E_act);
6799  printf("Enter apparent activation energy for pozzolanic reactions in kJ/mole \n");
6800 #endif
6801 #ifdef CMLFILE
6802  F->get_value(6, E_act_pozz);
6803 #endif
6804 #ifdef TINYXML
6805  QueryNumAttributeExt(xmlFile, "Ea_pozz", 0, E_act_pozz);
6806 #endif
6807  //fscanf(in, "%f",&E_act_pozz);
6808 #ifdef PRINTF
6809  printf("%f \n", E_act_pozz);
6810  printf("Enter apparent activation energy for slag reactions in kJ/mole \n");
6811 #endif
6812 #ifdef CMLFILE
6813  F->get_value(7, E_act_slag);
6814 #endif
6815 #ifdef TINYXML
6816  QueryNumAttributeExt(xmlFile, "Ea_slag", 0, E_act_slag);
6817 #endif
6818  //fscanf(in, "%f",&E_act_slag);
6819 #ifdef PRINTF
6820  printf("%f \n", E_act_slag);
6821  printf("Enter kinetic factor to convert cycles to time for 25 C \n");
6822 #endif
6823 #ifdef CMLFILE
6824  F->get_value(8, beta);
6825 #endif
6826 #ifdef TINYXML
6827  QueryNumAttributeExt(xmlFile, "Beta", 0, beta);
6828 #endif
6829  //fscanf(in, "%lf",&beta);
6830 #ifdef PRINTF
6831  printf("%f \n", beta);
6832  printf("Enter mass fraction of aggregate in concrete \n");
6833 #endif
6834 #ifdef CMLFILE
6835  F->get_value(9, mass_agg);
6836 #endif
6837 #ifdef TINYXML
6838  QueryNumAttributeExt(xmlFile, "Mass_SCM_FA_CA_inert_frac", 0, mass_agg);
6839 #endif
6840  //fscanf(in, "%f",&mass_agg);
6841 #ifdef PRINTF
6842  printf("%f \n", mass_agg);
6843  printf("Enter kg of cement (+admixtures) in 1 m3\n");
6844 #endif
6845 #ifdef CMLFILE
6846  F->get_value(10, Mass_cement_concrete);
6847 #endif
6848 #ifdef TINYXML
6849  QueryNumAttributeExt(xmlFile, "Mass_cement_concrete", 0, Mass_cement_concrete);
6850 #endif
6851  //fscanf(in, "%f",&Mass_cement_concrete);
6852 #ifdef PRINTF
6853  printf("%f \n", Mass_cement_concrete);
6854  printf("Enter heat capacity of aggregate in concrete J/g/C\n");
6855 #endif
6856 #ifdef CMLFILE
6857  F->get_value(11, Cp_agg);
6858  Cp_agg /= 1000.; //scale to J/g/K
6859 #endif
6860 #ifdef TINYXML
6861  QueryNumAttributeExt(xmlFile, "Cp_SCM_FA_CA_inert", 0, Cp_agg);
6862  Cp_agg /= 1000.; //scale to J/g/K
6863 #endif
6864  //fscanf(in, "%f",&Cp_agg);
6865 #ifdef PRINTF
6866  printf("%f \n", Cp_agg);
6867  printf("Enter heat capacity of cement J/g/C\n");
6868 #endif
6869 #ifdef CMLFILE
6870  F->get_value(12, Cp_cement);
6871  Cp_cement /= 1000.; //scale to J/g/K
6872 #endif
6873 #ifdef TINYXML
6874  QueryNumAttributeExt(xmlFile, "Cp_cem", 0, Cp_cement);
6875  Cp_cement /= 1000.; //scale to J/g/K
6876 #endif
6877  //fscanf(in, "%f",&Cp_cement);
6878 #ifdef PRINTF
6879  printf("%f \n", Cp_cement);
6880  printf("CSH to pozzolanic CSH 0) prohibited or 1) allowed \n");
6881 #endif
6882  //fscanf(in, "%d",&csh2flag);
6883  csh2flag = 0;
6884 #ifdef PRINTF
6885  printf("%d \n", csh2flag);
6886  printf("CH precipitation on aggregate surfaces 0) prohibited or 1) allowed \n");
6887 #endif
6888  //fscanf(in, "%d",&chflag);
6889  chflag = 0;
6890 #ifdef PRINTF
6891  printf("%d \n", chflag);
6892  printf("Enter number of cycles before executing total resaturation \n");
6893 #endif
6894  //fscanf(in, "%d\n",&resatcyc);
6895  resatcyc = 0;
6896 #ifdef PRINTF
6897  printf("%d\n", resatcyc);
6898  printf("Enter choice for C-S-H geometry 0) random or 1) plates \n");
6899 #endif
6900  //fscanf(in, "%d\n",&cshgeom);
6901  cshgeom = 0;
6902 #ifdef PRINTF
6903  printf("%d \n", cshgeom);
6904  printf("Does pH influence hydration kinetics 0) no or 1) yes \n");
6905 #endif
6906  //fscanf(in, "%d\n",&pHactive);
6907  pHactive = 0;
6908 #ifdef PRINTF
6909  printf("%d\n", pHactive);
6910 #endif
6911 #ifdef CMLFILE
6912  F->get_value(34, Vol_cement_clinker_gypsum);
6913  F->get_value(35, Vol_cement_SCM);
6914  F->get_value(36, Vol_water);
6915  F->get_value(37, Vol_FA);
6916  F->get_value(38, Vol_CA);
6917  F->get_value(39, Vol_inert_filler);
6918  F->get_value(40, Vol_entrained_entrapped_air);
6919  F->get_value(41, Grain_average_FA);
6920  F->get_value(42, Grain_average_CA);
6921  F->get_value(43, ITZ_thickness);
6922  F->get_value(44, ITZ_Young_red);
6923  F->get_value(45, Young_SCM);
6924  F->get_value(46, Poisson_SCM);
6925  F->get_value(47, Young_FA);
6926  F->get_value(48, Poisson_FA);
6927  F->get_value(49, Young_CA);
6928  F->get_value(50, Poisson_CA);
6929  F->get_value(51, Young_inert);
6930  F->get_value(52, Poisson_inert);
6931  F->get_value(53, Calculate_elastic_homogenization);
6932 #endif
6933 #ifdef TINYXML
6934  QueryNumAttributeExt(xmlFile, "Vol_cement_clinker_gypsum", 0, Vol_cement_clinker_gypsum);
6935  QueryNumAttributeExt(xmlFile, "Vol_cement_SCM", 0, Vol_cement_SCM);
6936  QueryNumAttributeExt(xmlFile, "Vol_water", 0, Vol_water);
6937  QueryNumAttributeExt(xmlFile, "Vol_FA", 0, Vol_FA);
6938  QueryNumAttributeExt(xmlFile, "Vol_CA", 0, Vol_CA);
6939  QueryNumAttributeExt(xmlFile, "Vol_inert_filler", 0, Vol_inert_filler);
6940  QueryNumAttributeExt(xmlFile, "Vol_entrained_entrapped_air", 0, Vol_entrained_entrapped_air);
6941  QueryNumAttributeExt(xmlFile, "Grain_average_FA", 0, Grain_average_FA);
6942  QueryNumAttributeExt(xmlFile, "Grain_average_CA", 0, Grain_average_CA);
6943  QueryNumAttributeExt(xmlFile, "ITZ_thickness", 0, ITZ_thickness);
6944  QueryNumAttributeExt(xmlFile, "ITZ_Young_red", 0, ITZ_Young_red);
6945  QueryNumAttributeExt(xmlFile, "Young_SCM", 0, Young_SCM);
6946  QueryNumAttributeExt(xmlFile, "Poisson_SCM", 0, Poisson_SCM);
6947  QueryNumAttributeExt(xmlFile, "Young_FA", 0, Young_FA);
6948  QueryNumAttributeExt(xmlFile, "Poisson_FA", 0, Poisson_FA);
6949  QueryNumAttributeExt(xmlFile, "Young_CA", 0, Young_CA);
6950  QueryNumAttributeExt(xmlFile, "Poisson_CA", 0, Poisson_CA);
6951  QueryNumAttributeExt(xmlFile, "Young_inert", 0, Young_inert);
6952  QueryNumAttributeExt(xmlFile, "Poisson_inert", 0, Poisson_inert);
6953  QueryNumAttributeExt(xmlFile, "Calculate_elastic_homogenization", 0, Calculate_elastic_homogenization);
6954  //needed in OOFEM for conductivity and capacity calculations
6955  QueryNumAttributeExt(xmlFile, "Mass_tot_concrete", 0, Mass_tot_concrete);
6956  QueryNumAttributeExt(xmlFile, "Cp_SCM", 0, Cp_SCM);
6957  QueryNumAttributeExt(xmlFile, "Cp_FA", 0, Cp_FA);
6958  QueryNumAttributeExt(xmlFile, "Cp_CA", 0, Cp_CA);
6959  QueryNumAttributeExt(xmlFile, "Cp_inert", 0, Cp_inert);
6960  QueryNumAttributeExt(xmlFile, "Mass_SCM_frac", 0, Mass_SCM_frac);
6961  QueryNumAttributeExt(xmlFile, "Mass_FA_frac", 0, Mass_FA_frac);
6962  QueryNumAttributeExt(xmlFile, "Mass_CA_frac", 0, Mass_CA_frac);
6963  QueryNumAttributeExt(xmlFile, "Mass_inert_frac", 0, Mass_inert_frac);
6964  QueryNumAttributeExt(xmlFile, "Concrete_thermal_conductivity", 0, Concrete_thermal_conductivity); //[W/m/K]
6965  QueryNumAttributeExt(xmlFile, "Concrete_bulk_density", 0, Concrete_bulk_density); //[kg/m3]
6966 #endif
6967 }
6968 
6969 
6970 /* Calls init, dissolve and addrand */
6972 {
6973 #ifdef OUTFILES
6974  char fileo [ 80 ];
6975 #endif
6976 
6977  nseed = iseed; //set random number generator the same number
6978  seed = & nseed;
6979 
6980  ncshplategrow = 0;
6981  ncshplateinit = 0;
6982  slagemptyp = 0;
6983  countpore = 0;
6984  time_step = 0.0;
6985  w_to_c = 0.0;
6986  totfract = 1.0;
6987  tfractw04 = 0.438596;
6988  fractwithfill = 1.0;
6989  tfractw05 = 0.384615;
6990  surffract = 0.0;
6991  pfractw05 = 0.615385;
6992  scntcement = 0;
6993  scnttotal = 0;
6994  saturation = 1.0;
6995  cs_acc = 1.0;
6996  ca_acc = 1.0;
6999  gsratio2 = 0.0;
7000  onepixelbias = 1.0;
7001  DIFFCHdeficit = 0;
7002  slaginit = 0;
7003  slagcum = 0;
7004  chgone = 0;
7005  nch_slag = 0;
7006  sulf_cur = 0;
7007  pHfactor = 0.0;
7008  conccaplus = 0.0;
7009  moles_syn_precip = 0.0;
7010  concsulfate = 0.0;
7011 
7012  primevalues [ 0 ] = 2;
7013  primevalues [ 1 ] = 3;
7014  primevalues [ 2 ] = 5;
7015  primevalues [ 3 ] = 7;
7016  primevalues [ 4 ] = 11;
7017  primevalues [ 5 ] = 13;
7018 
7019  ngoing = 0;
7020  porefl1 = porefl2 = porefl3 = 1;
7021  pore_off = water_off = 0;
7022  cycflag = 0;
7023  heat_old = heat_new = 0.0;
7024  chold = chnew = 0; /* Current and previous cycle CH counts */
7025  cubesize = CUBEMAX;
7026  ppozz = PPOZZ;
7027  poregone = poretodo = 0;
7028 
7029  /* Initialize counters, etc. */
7030  npr = nasr = nslagr = 0;
7031  nfill = 0;
7032  ncsbar = 0;
7033  netbar = 0;
7034  porinit = 0;
7035  cyccnt = 0;
7036  setflag = 0;
7038 
7039  /* Initialize structure for ants */
7040  headant = ( struct ants * ) malloc( sizeof( struct ants ) );
7041  headant->prevant = NULL;
7042  headant->nextant = NULL;
7043  headant->x = 0;
7044  headant->y = 0;
7045  headant->z = 0;
7046  headant->id = 100; /* special ID indicating first ant in list */
7047  headant->cycbirth = 0;
7048  tailant = headant;
7049 
7050  LastHydrTime = 0.;
7051  LastCycHeat = 0.;
7052  LastTotHeat = 0.;
7053  LastCycCnt = 0;
7054  PrevHydrTime = 0.;
7055  PrevCycHeat = 0.;
7056 
7057 
7058  init();
7059 #ifdef PRINTF
7060  printf("After init routine \n");
7061 #endif
7062  fflush(stdout);
7063 
7064 
7065 
7066 #ifdef OUTFILES
7067  fileperc = fopen("percpore.out", "w"); //in burn3d.cpp
7068  //fprintf(fileperc,"Cycle time(h) alpha_mass conn_por total_por frac_conn\n");
7069  fprintf(fileperc, "#cycle alpha #through #tot_phase\n");
7070  disprobfile = fopen("disprob.out", "w");
7071  //percfile = fopen("percset.out", "w"); //in burnset.cpp
7072  //fprintf(percfile, "#cycle time alpha #through #C3S+C2S+C3A+C4AF+CAS2+SLAG+ASG+POZZ+ETTR+ETTRC4AF+CSH conn_frac\n");
7073  strcpy(heatname, "heat.out");
7074  heatfile = fopen(heatname, "w");
7075  strcpy(chshrname, "chemshr.out");
7076  //chsfile=fopen(chshrname,"w");
7077  strcpy(adianame, "adiabatic.out");
7078  strcpy(pHname, "pHfile.out");
7079  pHfile = fopen(pHname, "w");
7080  fprintf(pHfile, "Cycle time(h) alpha_mass pH sigma [Na+] [K+] [Ca++] [SO4--] activityCa activityOH activitySO4 activityK molesSyngenite\n");
7081  strcpy(fileo, "out5.img");
7082  strcpy(phasname, "phases.out");
7083  phasfile = fopen(phasname, "w");
7084  strcpy(ppsname, "percpore.out");
7085  strcpy(phrname, "parthydr.out");
7086  perc_phases = fopen("perc_phases.out", "w");
7087  adiafile = fopen(adianame, "w");
7088  fprintf(adiafile, "Cyc Time(h) Temperature Alpha Krate Cp_now Mass_cem kpozz/khyd kslag/khyd DoR_Blend\n");
7089  elasfile = fopen("elas.out", "w");
7090  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");
7091  CSHfile = fopen("CSH.out", "w");
7092  fprintf(CSHfile, "cyc alpha [h] HD CSH-total HD/CSH\n");
7093  system("mkdir perc 2> /dev/null");
7094  system("mkdir unperc 2> /dev/null");
7095 #endif
7096 
7097 #ifdef IMAGEFILES
7098  infoperc = fopen("perc/info.dat", "w");
7099  fprintf(infoperc, "#Cyc DoH Time[h]\n");
7100  infoUnperc = fopen("unperc/info.dat", "w");
7101  fprintf(infoUnperc, "#Cyc DoH Time[h]\n");
7102 #endif
7103  /* Set initial properties of CSH */
7104  molarvcsh [ 0 ] = molarv [ CSH ];
7105  watercsh [ 0 ] = waterc [ CSH ];
7106 
7107  krate = exp( -( 1000. * E_act / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7108  /* Determine pozzolanic and slag reaction rate constants */
7109  kpozz = exp( -( 1000. * E_act_pozz / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7110  kslag = exp( -( 1000. * E_act_slag / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7111  ppozz = PPOZZ * kpozz / krate;
7112  /* Assume same holds for dissolution of fly ash phases */
7113  disprob [ ASG ] = disbase [ ASG ] * kpozz / krate;
7114  disprob [ CAS2 ] = disbase [ CAS2 ] * kpozz / krate;
7115  /* Update probability of slag dissolution */
7116  disprob [ SLAG ] = slagreact * disbase [ SLAG ] * kslag / krate;
7117 
7118 
7119  /* Determine surface counts */
7120  measuresurf();
7121 }
7122 
7123 
7124 /*perform as many hydration cycles as necessary
7125  * flag = 0 - controlled with hydrationTime
7126  * flag != 0 - perform exactly flag cycles
7127  * GiveTemp is effective in the first cycle of adiabatic regime only
7128  */
7129 void CemhydMatStatus :: disrealnew(double GiveTemp, double hydrationTime, int flag)
7130 {
7131  int counter = 0;
7132 
7133  if ( adiabatic_curing != 1 ) {
7134  temp_cur = GiveTemp;
7135  temp_0 = GiveTemp;
7136  }
7137 
7138  InitTime = time_cur;
7139 
7140  if ( icyc == 1 ) { //first cycle
7141  temp_cur = GiveTemp;
7142  temp_0 = GiveTemp;
7143  disrealnew_init();
7144  }
7145 
7146  /****************************************************************/
7147  /**************************MAIN LOOP*****************************/
7148  /****************************************************************/
7149 
7150  /*determine the minimum number of cycles*/
7151  while ( flag == 0 ? ( time_cur < hydrationTime ) : counter < flag ) {
7153 
7154  //printf("CNT seed=%d\n", *seed);
7155  //update counters of "previous", i.e. before any last cycle
7156  PrevHydrTime = time_cur * 3600.;
7157  PrevCycHeat = ( double ) ( heat_new ) * heat_cf;
7158 
7159  if ( ( sealed == 1 ) && ( icyc == ( resatcyc + 1 ) ) && ( resatcyc != 0 ) ) {
7160  resaturate();
7161  sealed = 0;
7162  }
7163 
7164  if ( temp_cur <= 80.0 ) {
7165  molarvcsh [ icyc ] = molarv [ CSH ] - 8.0 * ( ( temp_cur - 20. ) / ( 80. - 20. ) );
7166  watercsh [ icyc ] = waterc [ CSH ] - 1.3 * ( ( temp_cur - 20. ) / ( 80. - 20. ) );
7167  } else {
7168  molarvcsh [ icyc ] = molarv [ CSH ] - 8.0;
7169  watercsh [ icyc ] = waterc [ CSH ] - 1.3;
7170  }
7171 
7172  dissolve(icyc); //cyccnt is increased
7173 #ifdef OUTFILES
7174  //printf("Number dissolved this pass- %ld total diffusing- %ld \n",nmade,ngoing);
7175 
7176  fflush(stdout);
7177  if ( icyc == 1 ) {
7178  // printf("ncsbar is %ld netbar is %ld \n",ncsbar,netbar);
7179  }
7180 
7181 #endif
7182 
7184  temp_0 = temp_cur;
7185 
7186  /* Handle adiabatic case first */
7187  /* Cement + aggregate +water + filler=1; that's all there is */
7190 
7191  /* determine heat capacity of current mixture, */
7192  /* accounting for imbided water if necessary */
7193  if ( sealed == 1 ) {
7194  Cp_now = mass_agg * Cp_agg;
7195  Cp_now += Cp_pozz * mass_fill;
7197  Cp_now += Cp_CH * mass_CH;
7198  Cp_now += ( Cp_h2o * mass_water - alpha_cur * WN * mass_cement * ( Cp_h2o - Cp_bh2o ) );
7200  }
7201  /* Else need to account for extra capillary water drawn in */
7202  /* Basis is WCHSH(0.06) g H2O per gram cement for chemical shrinkage */
7203  /* Need to adjust mass basis to account for extra imbibed H2O */
7204  else {
7205  mass_cur = 1. + WCHSH * mass_cement * alpha_cur;
7209  Cp_now += Cp_CH * mass_CH / mass_cur;
7210  Cp_now += ( Cp_h2o * mass_water - alpha_cur * WN * mass_cement * ( Cp_h2o - Cp_bh2o ) );
7211  Cp_now += ( WCHSH * Cp_h2o * alpha_cur * mass_cement );
7213  }
7214 
7215 
7216  /* Recall that temp_cur is in degrees Celsius */
7217  krate = exp( -( 1000. * E_act / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7218  /* Determine pozzolanic and slag reaction rate constant */
7219  kpozz = exp( -( 1000. * E_act_pozz / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7220  kslag = exp( -( 1000. * E_act_slag / 8.314 ) * ( ( 1. / ( temp_cur + 273.15 ) ) - ( 1. / 298.15 ) ) );
7221  /* Update probability of pozzolanic and slag reactions */
7222  /* based on ratio of pozzolanic (slag) reaction rate to hydration rate */
7223  ppozz = PPOZZ * kpozz / krate;
7224  disprob [ ASG ] = disbase [ ASG ] * kpozz / krate;
7225  disprob [ CAS2 ] = disbase [ CAS2 ] * kpozz / krate;
7226  disprob [ SLAG ] = slagreact * disbase [ SLAG ] * kslag / krate;
7227 
7228  /* Update temperature based on heat generated and current Cp only in adiabatic case*/
7229  if ( adiabatic_curing == 1 ) {
7230  if ( mass_cem_now > 0.01 ) {
7232  } else {
7234  }
7235  }
7236 
7237  /* Update system temperature due to heat loss/gain to/from */
7238  /* surroundings (semi-adiabatic case) */
7239  //temp_cur-=(temp_cur-T_ambient)*time_step*U_coeff/Cp_now;
7240 
7241  /* Update time based on simple numerical integration */
7242  /* simulating maturity approach */
7243  /* with parabolic kinetics (Knudsen model) */
7244  if ( cyccnt > 1 ) {
7245  time_cur += ( 2. * ( double ) ( cyccnt - 1 ) - 1.0 ) * beta / krate;
7246  time_step = ( 2. * ( double ) ( cyccnt - 1 ) - 1.0 ) * beta / krate;
7247  }
7248 
7249  gsratio2 = 0.0;
7250  gsratio2 += ( float ) ( count [ CH ] + count [ CSH ] + count [ C3AH6 ] + count [ ETTR ] );
7251  gsratio2 += ( float ) ( count [ POZZCSH ] + count [ SLAGCSH ] + count [ FH3 ] + count [ AFM ] + count [ ETTRC4AF ] );
7252  gsratio2 += ( float ) ( count [ FREIDEL ] + count [ STRAT ] + count [ ABSGYP ] + count [ AFMC ] );
7253  gsratio2 = ( gsratio2 ) / ( gsratio2 + ( float ) ( count [ POROSITY ] + count [ EMPTYP ] ) );
7254 
7255 
7256 #ifdef OUTFILES
7257  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);
7258  fprintf( heatfile, "%d %f %f %f %f %f %f \n",
7259  cyccnt - 1, time_cur, alpha, alpha_cur, heat_new * heat_cf, gsratio2, ( ( 0.68 * alpha_cur ) / ( 0.32 * alpha_cur + w_to_c ) ) );
7260  fflush(adiafile);
7261  fflush(heatfile);
7262 #endif
7263 
7264  /*chemical shrinkage*/
7265  //fprintf(chsfile,"%d %f %f %f\n", cyccnt-1,time_cur,alpha_cur,chs_new);
7266  //fflush(chsfile);
7267  //pHpred();-dangerous function - can lead to zero division etc.
7268 
7269  /* Check percolation of pore space */
7270  /* Note that first variable passed corresponds to phase to check */
7271  /* Could easily add calls to check for percolation of CH, CSH, etc. */
7272 
7273  if ( ( ( icyc % burnfreq ) == 0 ) && ( ( porefl1 + porefl2 + porefl3 ) != 0 ) ) {
7274  porefl1 = burn3d(0, 1, 0, 0);
7275  porefl2 = burn3d(0, 0, 1, 0);
7276  porefl3 = burn3d(0, 0, 0, 1);
7277  /* Switch to self-desiccating conditions when porosity */
7278  /* disconnects */
7279  if ( ( ( porefl1 + porefl2 + porefl3 ) == 0 ) && ( sealed == 0 ) ) {
7281  pore_off = countkeep;
7282  sealed = 1;
7283 #ifdef PRINTF
7284  printf("Switching to self-desiccating at cycle %d \n", cyccnt);
7285 #endif
7286  fflush(stdout);
7287  }
7288  }
7289 
7290 
7291  /*update microstructure in mic_CSH[][][] to HDCSH and use it in*/
7292  /*burn_phases function and outputImageFile function*/
7293  //CSHbox(CSH_vicinity); - called independently, does not influence percolation
7294 
7295 
7296  /* Check percolation of solids (set point) */
7297  if ( ( ( icyc % setfreq ) == 0 ) && ( setflag == 0 ) ) {
7298  // sf1 = burnset(1, 0, 0);
7299  // sf2 = burnset(0, 1, 0);
7300  // sf3 = burnset(0, 0, 1);
7301  // setflag = sf1 * sf2 * sf3;
7302  }
7303 
7304 #ifdef IMAGEFILES
7305  //outputImageFilePerc();//is executed from CemhydMatStatus :: burn_phases
7307 #endif
7308  /* Check hydration of particles */
7309  if ( ( icyc % phydfreq ) == 0 ) {
7310  // parthyd();
7311  }
7312 
7313  /* Calculate homogenized elastic values if turned on */
7315  //increase DoH by 0.02 till 0.2 and then by 0.05 step
7316  if ( TargDoHelas < 0.1 ) {
7317  TargDoHelas += 0.01; //0.02
7318  } else if ( TargDoHelas < 0.2 ) {
7319  TargDoHelas += 0.01; //0.05
7320  } else {
7321  TargDoHelas += 0.01; //0.05
7322  }
7323 
7324  double E_paste_SCM_filler_air, nu_paste_SCM_filler_air, E_mortar, nu_mortar;
7325 
7326  CreateHDCSH(); //alters microstructure so it contains HDCSH - need for all homogenizations
7328  AnalyticHomogenizationPaste(last_values [ 2 ], last_values [ 3 ], 0); //0-perc, 1-unperc
7329  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 ]);
7330 #ifdef OUTFILES
7331  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 ]);
7332  fflush(elasfile);
7333 #endif
7334  }
7335 
7336 #ifdef OUTFILES
7337  fprintf(CSHfile, "%d %.4f %.4f %ld %ld %f\n", icyc, alpha_cur, time_cur, count [ HDCSH ], count [ CSH ], ( double ) count [ HDCSH ] / count [ CSH ]);
7338  fflush(CSHfile);
7339 #endif
7340 
7341  icyc++;
7342  counter++;
7343  }
7344 
7345  //end of main while loop
7346 }
7347 
7348 
7349 /*Function returning the concrete released heat during the difference in given times
7350  * of hydration. Units are in kJ/kg_all_cement_solids.
7351  * All solids include cement clinker minerals, gypsum forms, [INERT],
7352  * [SLAG],[POZZ],[CACL2],[ASG],[CAS2], NOT aggregates!!!
7353  * The heat is independent on the hydrating cube size but may slightly
7354  * decrease as some reversible reactions exist!!! (checked)
7355  * ^
7356  ***|Released heat (stops now)
7357  | CYC_m
7358  | (last stop) t_n+1 |
7359  | CYC ..CYC.. CYC_m-1 | |
7360  | t_n ! | | |
7361  | !LastTotHeat !LastHydrTime |PrevHydrTime |TargTime |time_cur
7362  | !LastCallTime !LastCycHeat |PrevCycHeat |LastTargTime |heat_new
7363  | ! !LastCycCnt | | |
7364  ||||------------------------------------------------------------------->time
7365  *
7366  * let all time counters in seconds! (numerical precision)
7367  * TargTime, LastCallTime, LastTargTime are in absolute time taken from OOFEM
7368  * time_cur, PrevHydrTime, LastHydrTime is hydration time, ofset with the castingTime
7369  */
7370 
7371 // GiveTemp in [C], TargTime in [s]
7372 double CemhydMatStatus :: GivePower(double GiveTemp, double TargTime)
7373 {
7374 #ifdef __TM_MODULE //OOFEM transport module
7375  double castingTime = this->gp->giveMaterial()->giveCastingTime();
7376 #else
7377  double castingTime = 0.;
7378 #endif
7379 
7380  //do not calculate anything before casting time
7381  if ( TargTime - castingTime <= 0 ) {
7382  PartHeat = 0.;
7383  LastCallTime = castingTime;
7384  return 0.;
7385  }
7386 
7387  LastTargTime = TargTime;
7388 
7389  if ( TargTime < LastCallTime ) {
7390  printf("Cannot go backwards in hydration, TargTime = %f s < LastCallTime = %f s\n", TargTime, LastCallTime);
7391  exit(0);
7392  }
7393 
7394 #ifdef __TM_MODULE //OOFEM transport module
7395  CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
7396  if ( !cemhydmat->nowarnings.at(4) && ( GiveTemp > 200. ) ) {
7397  printf("Temperature exceeds 200 C (file %s, line %d),\n", __FILE__, __LINE__);
7398  }
7399 
7400 #else
7401  if ( GiveTemp > 200. ) {
7402  printf("Temperature exceeds 200 C (file %s, line %d),\n", __FILE__, __LINE__);
7403  }
7404 
7405 #endif
7406 
7407 
7408  /*perform as many cycles as necessary, always more than required
7409  * first, calculate everything on the cement paste*/
7410 
7411  disrealnew(GiveTemp, ( TargTime - castingTime ) / 3600., 0); //perform hydration cycles controled with TargTime [h]
7412 
7413 #ifdef PRINTF
7414  printf("Hydration heat %f [J/g of cement]\n", heat_new * heat_cf);
7415  printf("time_cur %f [h]\n", time_cur);
7416  printf("PrevHydrTime %f [h]\n", PrevHydrTime / 3600.);
7417 #endif
7418 
7419  PartHeat = 0.;
7420 
7421  if ( TargTime != LastCallTime && icyc > 1 ) {
7422  if ( LastCycCnt - icyc ) { //if at least one hydration cycle has elapsed
7423  //interpolate between CYC_m-1 and CYC_m
7424  PartHeat = ( heat_new * heat_cf - PrevCycHeat ) * ( TargTime - PrevHydrTime - castingTime ) / ( 3600. * time_cur - PrevHydrTime );
7425  //add between CYC and CYC_m-1
7427  //add between t_n and CYC
7428  PartHeat += LastCycHeat - LastTotHeat;
7429  } else { //not even one cycle elapsed
7430  PartHeat = ( LastCycHeat - LastTotHeat ) * ( TargTime - LastCallTime ) / ( LastHydrTime - LastCallTime + castingTime );
7431  }
7432 
7433  LastTotHeat += PartHeat;
7434 
7435  if ( TargTime != LastCallTime ) {
7436  //Mass_cement_concrete tells the amount of cement [kg] in a m3 of concrete
7437  //add aggregates and rescale to kJ/m3 of concrete
7439  //rescale from kJ/m3/time_interval to J/m3/s or W/m3
7440  PartHeat /= ( TargTime - LastCallTime );
7441  PartHeat *= 1000;
7442  }
7443  }
7444 
7445  LastCallTime = TargTime;
7446  LastHydrTime = time_cur * 3600.;
7447  LastCycHeat = ( double ) ( heat_new ) * heat_cf;
7448  LastCycCnt = icyc;
7449 
7450 #ifdef PRINTF
7451  printf("PartHeat %f [W/m3 of concrete]\n", PartHeat);
7452 #endif
7453 
7454  //PartHeat = 1500;
7455  return PartHeat;
7456 }
7457 
7458 
7459 //move hydration model by several steps and update all internal variables
7460 double CemhydMatStatus :: MoveCycles(double GiveTemp, int cycles)
7461 {
7462  double PartHeat;
7463  double castingTime = 0.;
7464 #ifdef __TM_MODULE
7465  castingTime = this->gp->giveMaterial()->giveCastingTime();
7466 #endif
7467 
7468  disrealnew(GiveTemp, -1., cycles); //perform amount of hydration cycles controlled
7469 
7470  //at least one cycle elapsed
7471  //difference in heat before and now at CYC_m
7472  PartHeat = heat_new * heat_cf - PrevCycHeat;
7473  //add between CYC and CYC_m-1
7474  PartHeat += PrevCycHeat - LastCycHeat;
7475  //add between t_n and CYC
7476  PartHeat += LastCycHeat - LastTotHeat;
7477 
7478  LastTotHeat += PartHeat;
7479 
7480  //Mass_cement_concrete tells the amount of cement [kg] in a m3 of concrete
7481  //add aggregates and rescale to kJ/m3 of concrete
7482  PartHeat *= Mass_cement_concrete;
7483  //rescale from kJ/m3/time_interval to J/m3/s
7484  PartHeat /= ( 3600. * time_cur - LastCallTime + castingTime );
7485  PartHeat *= 1000;
7486 
7487  LastCallTime = 3600. * time_cur + castingTime;
7488  LastHydrTime = 3600. * time_cur;
7489  LastCycHeat = ( double ) ( heat_new ) * heat_cf;
7490  LastCycCnt = icyc;
7491 
7492  LastTargTime = time_cur * 3600.;
7493  return time_cur; //return in hours
7494 }
7495 
7496 //move to desired DoH (the next DoH in CEMHYD3D cycle) limited by maxcyc
7497 //return 1 if the number of cycles was exceeded
7498 int CemhydMatStatus :: MoveToDoH(double GiveTemp, double DesiredDoH, int maxcyc)
7499 {
7500  int cycle = 1;
7501 
7502  while ( alpha_cur < DesiredDoH ) {
7503  if ( cycle > maxcyc ) {
7504 #ifdef PRINTF
7505  printf("Target DoH %f (now is %f) was not reached after %d cycles (%s, line %d)\n", DesiredDoH, alpha_cur, maxcyc, __FILE__, __LINE__);
7506 #endif
7507  return 1;
7508  }
7509 
7510  MoveCycles(GiveTemp, 1); //move one cycle
7511  cycle++;
7512  }
7513 
7514  return 0;
7515 }
7516 
7517 //TargTime in [h]
7518 //move to desired Time[h] (the next time in CEMHYD3D cycle, no interpolation)
7519 //no cycle limit is specified (any time can be reached)
7520 int CemhydMatStatus :: MoveToTime(double GiveTemp, double TargTime)
7521 {
7522  GivePower(GiveTemp, 3600. * TargTime);
7523  return 0;
7524 }
7525 
7526 
7527 //return total released heat from cement in kJ/kg_cement_solids at TargTime
7529 {
7530  return LastTotHeat;
7531 }
7532 
7533 //return total heat in J/m3_of_concrete at TargTime
7535 {
7536  return 1000 * LastTotHeat * Mass_cement_concrete;
7537 }
7538 
7539 //return heat capacity in kJ/K/kg_of_everything in the last CEMHYD cycle
7541 {
7542  return Cp_now;
7543 }
7544 
7545 
7546 //see D. P. Bentz: Transient Plane Source Measurements of the Thermal Properties of Hydrating Cement Pastes, Materials and Structures, 1073-1080, 2007
7548 {
7549  double capacityPaste, capacityConcrete;
7550  capacityPaste = ( 4180. * Vol_water * 1.0 + Cp_cement * 1000. * Mass_cement_concrete ) / Mass_tot_concrete; //capacity of cement paste [J/kg/K]
7551  capacityPaste *= ( 1. - 0.26 * ( 1 - pow(2.71828, -2.9 * alpha_cur) ) );
7552  capacityConcrete = capacityPaste + Cp_SCM * Mass_SCM_frac + Cp_FA * Mass_FA_frac + Cp_CA * Mass_CA_frac + Cp_inert * Mass_inert_frac;
7553 
7554  return capacityConcrete;
7555 }
7556 
7558 {
7559  return Concrete_bulk_density;
7560 }
7561 
7562 //return degree of hydration in the last CEMHYD cycle, corresponding to time_cur
7564 {
7565  return alpha_cur;
7566 }
7567 
7568 //return actual degree of hydration (interpolated)
7570 {
7571  double castingTime = 0;
7572 
7573  if ( icyc <= 1 ) { //not even one cycle has elapsed
7574  return 0;
7575  }
7576 
7577 #ifdef __TM_MODULE
7578  castingTime = this->gp->giveMaterial()->giveCastingTime();
7579 #endif
7580 
7581  return alpha_last + ( alpha_cur - alpha_last ) * ( LastTargTime - castingTime - PrevHydrTime ) / ( 3600. * time_cur - PrevHydrTime ); //interpolate
7582 }
7583 
7584 
7585 //return cycle in the last CEMHYD cycle (higher or the same as actual time)
7587 {
7588  return icyc;
7589 }
7590 
7591 //return actual time of the last cycle (higher or the same as actual time)
7593 {
7594  return time_cur;
7595 }
7596 
7597 
7598 
7599 /* routine to assess the connectivity (percolation) of a single phase */
7600 /* Two matrices are used here: one to store the recently burnt locations */
7601 /* burn3d.cpp:97: implicit declaration of function `int printf(...)'
7602  * the other to store the newly found burnt locations */
7603 
7604 int CemhydMatStatus :: burn3d(int npix, int d1, int d2, int d3)
7605 /* npix is ID of phase to perform burning on */
7606 /* directional flags */
7607 {
7608  long int ntop, nthrough, ncur, nnew, ntot, nphc;
7609  int i, inew, j, k;
7610  int xl, xh, j1, k1, px, py, pz, qx, qy, qz, xcn, ycn, zcn;
7611  int x1, y1, z1, igood;
7612  int *nmatx, *nmaty, *nmatz, *nnewx, *nnewy, *nnewz;
7613  int jnew, icur;
7614  int bflag;
7615  float mass_burn = 0.0, alpha_burn = 0.0;
7616 
7617  nmatx = new int [ SIZE2D ];
7618  nmaty = new int [ SIZE2D ];
7619  nmatz = new int [ SIZE2D ];
7620  nnewx = new int [ SIZE2D ];
7621  nnewy = new int [ SIZE2D ];
7622  nnewz = new int [ SIZE2D ];
7623 
7624 
7625  /* counters for number of pixels of phase accessible from surface #1 */
7626  /* and number which are part of a percolated pathway to surface #2 */
7627  ntop = 0;
7628  bflag = 0;
7629  nthrough = 0;
7630  nphc = 0;
7631 
7632  /* percolation is assessed from top to bottom only */
7633  /* and burning algorithm is periodic in other two directions */
7634  /* use of directional flags allow transformation of coordinates */
7635  /* to burn in direction of choosing (x, y, or z) */
7636  i = 0;
7637 
7638  for ( k = 0; k < SYSIZE; k++ ) {
7639  for ( j = 0; j < SYSIZE; j++ ) {
7640  igood = 0;
7641  ncur = 0;
7642  ntot = 0;
7643  /* Transform coordinates */
7644  px = cx(i, j, k, d1, d2, d3);
7645  py = cy(i, j, k, d1, d2, d3);
7646  pz = cz(i, j, k, d1, d2, d3);
7647  if ( mic [ px ] [ py ] [ pz ] == npix ) {
7648  /* Start a burn front */
7649  mic [ px ] [ py ] [ pz ] = BURNT;
7650  ntot += 1;
7651  ncur += 1;
7652  /* burn front is stored in matrices nmat* */
7653  /* and nnew* */
7654  nmatx [ ncur ] = i;
7655  nmaty [ ncur ] = j;
7656  nmatz [ ncur ] = k;
7657  /* Burn as long as new (fuel) pixels are found */
7658  do {
7659  nnew = 0;
7660  for ( inew = 1; inew <= ncur; inew++ ) {
7661  xcn = nmatx [ inew ];
7662  ycn = nmaty [ inew ];
7663  zcn = nmatz [ inew ];
7664 
7665  /* Check all six neighbors */
7666  for ( jnew = 1; jnew <= 6; jnew++ ) {
7667  x1 = xcn;
7668  y1 = ycn;
7669  z1 = zcn;
7670  if ( jnew == 1 ) {
7671  x1 -= 1;
7672  }
7673 
7674  if ( jnew == 2 ) {
7675  x1 += 1;
7676  }
7677 
7678  if ( jnew == 3 ) {
7679  y1 -= 1;
7680  }
7681 
7682  if ( jnew == 4 ) {
7683  y1 += 1;
7684  }
7685 
7686  if ( jnew == 5 ) {
7687  z1 -= 1;
7688  }
7689 
7690  if ( jnew == 6 ) {
7691  z1 += 1;
7692  }
7693 
7694  /* Periodic in y and */
7695  if ( y1 >= SYSIZE ) {
7696  y1 -= SYSIZE;
7697  } else if ( y1 < 0 ) {
7698  y1 += SYSIZE;
7699  }
7700 
7701  /* Periodic in z direction */
7702  if ( z1 >= SYSIZE ) {
7703  z1 -= SYSIZE;
7704  } else if ( z1 < 0 ) {
7705  z1 += SYSIZE;
7706  }
7707 
7708  /* Nonperiodic so be sure to remain in the 3-D box */
7709  if ( ( x1 >= 0 ) && ( x1 < SYSIZE ) ) {
7710  /* Transform coordinates */
7711  px = cx(x1, y1, z1, d1, d2, d3);
7712  py = cy(x1, y1, z1, d1, d2, d3);
7713  pz = cz(x1, y1, z1, d1, d2, d3);
7714  if ( mic [ px ] [ py ] [ pz ] == npix ) {
7715  ntot += 1;
7716  mic [ px ] [ py ] [ pz ] = BURNT;
7717  nnew += 1;
7718  if ( nnew >= SIZE2D ) {
7719  printf("error in size of nnew \n");
7720  }
7721 
7722  nnewx [ nnew ] = x1;
7723  nnewy [ nnew ] = y1;
7724  nnewz [ nnew ] = z1;
7725  }
7726  }
7727  }
7728  }
7729 
7730  if ( nnew > 0 ) {
7731  ncur = nnew;
7732  /* update the burn front matrices */
7733  for ( icur = 1; icur <= ncur; icur++ ) {
7734  nmatx [ icur ] = nnewx [ icur ];
7735  nmaty [ icur ] = nnewy [ icur ];
7736  nmatz [ icur ] = nnewz [ icur ];
7737  }
7738  }
7739  } while ( nnew > 0 );
7740 
7741  ntop += ntot;
7742  xl = 0;
7743  xh = SYSIZE - 1;
7744  /* See if current path extends through the microstructure */
7745  for ( j1 = 0; j1 < SYSIZE; j1++ ) {
7746  for ( k1 = 0; k1 < SYSIZE; k1++ ) {
7747  px = cx(xl, j1, k1, d1, d2, d3);
7748  py = cy(xl, j1, k1, d1, d2, d3);
7749  pz = cz(xl, j1, k1, d1, d2, d3);
7750  qx = cx(xh, j1, k1, d1, d2, d3);
7751  qy = cy(xh, j1, k1, d1, d2, d3);
7752  qz = cz(xh, j1, k1, d1, d2, d3);
7753  if ( ( mic [ px ] [ py ] [ pz ] == BURNT ) && ( mic [ qx ] [ qy ] [ qz ] == BURNT ) ) {
7754  igood = 2;
7755  }
7756 
7757  if ( mic [ px ] [ py ] [ pz ] == BURNT ) {
7758  mic [ px ] [ py ] [ pz ] = BURNT + 1;
7759  }
7760 
7761  if ( mic [ qx ] [ qy ] [ qz ] == BURNT ) {
7762  mic [ qx ] [ qy ] [ qz ] = BURNT + 1;
7763  }
7764  }
7765  }
7766 
7767  if ( igood == 2 ) {
7768  nthrough += ntot;
7769  }
7770  }
7771  }
7772  }
7773 
7774  /* return the burnt sites to their original phase values */
7775  for ( i = 0; i < SYSIZE; i++ ) {
7776  for ( j = 0; j < SYSIZE; j++ ) {
7777  for ( k = 0; k < SYSIZE; k++ ) {
7778  if ( mic [ i ] [ j ] [ k ] >= BURNT ) {
7779  nphc += 1;
7780  mic [ i ] [ j ] [ k ] = npix;
7781  } else if ( mic [ i ] [ j ] [ k ] == npix ) {
7782  nphc += 1;
7783  }
7784  }
7785  }
7786  }
7787 
7788 #ifdef PRINTF
7789  printf("Phase ID= %d \n", npix);
7790  printf("Number accessible from first surface = %ld \n", ntop);
7791  printf("Number contained in through pathways= %ld \n", nthrough);
7792 #endif
7793 
7794 
7795  mass_burn += specgrav [ C3S ] * count [ C3S ];
7796  mass_burn += specgrav [ C2S ] * count [ C2S ];
7797  mass_burn += specgrav [ C3A ] * count [ C3A ];
7798  mass_burn += specgrav [ C4AF ] * count [ C4AF ];
7799  alpha_burn = 1. - ( mass_burn / cemmass );
7800 
7801 #ifdef OUTFILES
7802  fprintf(fileperc, "%d %f %ld %ld \n", cyccnt, alpha_cur, nthrough, nphc);
7803  fflush(fileperc);
7804 #endif
7805 
7806  if ( nthrough > 0 ) {
7807  bflag = 1;
7808  }
7809 
7810  delete [] nmatx;
7811  delete [] nmaty;
7812  delete [] nmatz;
7813  delete [] nnewx;
7814  delete [] nnewy;
7815  delete [] nnewz;
7816  return ( bflag );
7817 
7818  ( void ) alpha_burn;
7819 }
7820 
7821 
7822 /* routine to assess connectivity (percolation) of solids for set estimation*/
7823 /* Definition of set is a through pathway of cement particles connected */
7824 /* together by CSH or ettringite */
7825 /* Two matrices are used here: one to store the recently burnt locations */
7826 /* the other to store the newly found burnt locations */
7827 //use perc_phases instead. It contains all solid phases, :: burnset function is outdated
7828 
7829 int CemhydMatStatus :: burnset(int d1, int d2, int d3)
7830 {
7831  long int ntop, nthrough, icur, inew, ncur, nnew, ntot, count_solid;
7832  int i, j, k, setyet;
7833  //static int nmatx[SIZESET],nmaty[SIZESET],nmatz[SIZESET];
7834  int *nmatx, *nmaty, *nmatz;
7835  int xl, xh, j1, k1, px, py, pz, qx, qy, qz;
7836  int xcn, ycn, zcn, x1, y1, z1, igood;
7837  //static int nnewx[SIZESET],nnewy[SIZESET],nnewz[SIZESET];
7838  int *nnewx, *nnewy, *nnewz;
7839  int jnew;
7840  float mass_burn = 0.0, alpha_burn = 0.0, con_frac;
7841  //static char newmat [SYSIZE] [SYSIZE] [SYSIZE];
7842  char ***newmat;
7843 
7844  alloc_char_3D(newmat, SYSIZE);
7845  nmatx = new int [ SIZESET ];
7846  nmaty = new int [ SIZESET ];
7847  nmatz = new int [ SIZESET ];
7848  nnewx = new int [ SIZESET ];
7849  nnewy = new int [ SIZESET ];
7850  nnewz = new int [ SIZESET ];
7851 
7852  /* counters for number of pixels of phase accessible from surface #1 */
7853  /* and number which are part of a percolated pathway to surface #2 */
7854  ntop = 0;
7855  nthrough = 0;
7856  setyet = 0;
7857  for ( k = 0; k < SYSIZE; k++ ) {
7858  for ( j = 0; j < SYSIZE; j++ ) {
7859  for ( i = 0; i < SYSIZE; i++ ) {
7860  newmat [ i ] [ j ] [ k ] = mic [ i ] [ j ] [ k ];
7861  }
7862  }
7863  }
7864 
7865  /* percolation is assessed from top to bottom only */
7866  /* in transformed coordinates */
7867  /* and burning algorithm is periodic in other two directions */
7868  i = 0;
7869 
7870  for ( k = 0; k < SYSIZE; k++ ) {
7871  for ( j = 0; j < SYSIZE; j++ ) {
7872  igood = 0;
7873  ncur = 0;
7874  ntot = 0;
7875  /* Transform coordinates */
7876  px = cx(i, j, k, d1, d2, d3);
7877  py = cy(i, j, k, d1, d2, d3);
7878  pz = cz(i, j, k, d1, d2, d3);
7879  /* start from a cement clinker, slag, fly ash ettringite, C3AH6, or
7880  * CSH pixel */
7881  if ( ( mic [ px ] [ py ] [ pz ] == C3S ) ||
7882  ( mic [ px ] [ py ] [ pz ] == C2S ) ||
7883  ( mic [ px ] [ py ] [ pz ] == SLAG ) ||
7884  ( mic [ px ] [ py ] [ pz ] == ASG ) ||
7885  ( mic [ px ] [ py ] [ pz ] == CAS2 ) ||
7886  ( mic [ px ] [ py ] [ pz ] == POZZ ) ||
7887  ( mic [ px ] [ py ] [ pz ] == CSH ) ||
7888  ( mic [ px ] [ py ] [ pz ] == C3AH6 ) ||
7889  ( mic [ px ] [ py ] [ pz ] == ETTR ) ||
7890  ( mic [ px ] [ py ] [ pz ] == ETTRC4AF ) ||
7891  ( mic [ px ] [ py ] [ pz ] == C3A ) ||
7892  ( mic [ px ] [ py ] [ pz ] == C4AF ) ) {
7893  /* Start a burn front */
7894  mic [ px ] [ py ] [ pz ] = BURNT;
7895  ntot += 1;
7896  ncur += 1;
7897  /* burn front is stored in matrices nmat* */
7898  /* and nnew* */
7899  nmatx [ ncur ] = i;
7900  nmaty [ ncur ] = j;
7901  nmatz [ ncur ] = k;
7902  /* Burn as long as new (fuel) pixels are found */
7903  do {
7904  nnew = 0;
7905  for ( inew = 1; inew <= ncur; inew++ ) {
7906  xcn = nmatx [ inew ];
7907  ycn = nmaty [ inew ];
7908  zcn = nmatz [ inew ];
7909  /* Convert to directional coordinates */
7910  qx = cx(xcn, ycn, zcn, d1, d2, d3);
7911  qy = cy(xcn, ycn, zcn, d1, d2, d3);
7912  qz = cz(xcn, ycn, zcn, d1, d2, d3);
7913 
7914  /* Check all six neighbors */
7915  for ( jnew = 1; jnew <= 6; jnew++ ) {
7916  x1 = xcn;
7917  y1 = ycn;
7918  z1 = zcn;
7919  if ( jnew == 1 ) {
7920  x1 -= 1;
7921  }
7922 
7923  if ( jnew == 2 ) {
7924  x1 += 1;
7925  }
7926 
7927  if ( jnew == 3 ) {
7928  y1 -= 1;
7929  }
7930 
7931  if ( jnew == 4 ) {
7932  y1 += 1;
7933  }
7934 
7935  if ( jnew == 5 ) {
7936  z1 -= 1;
7937  }
7938 
7939  if ( jnew == 6 ) {
7940  z1 += 1;
7941  }
7942 
7943  /* Periodic in y and */
7944  if ( y1 >= SYSIZE ) {
7945  y1 -= SYSIZE;
7946  } else if ( y1 < 0 ) {
7947  y1 += SYSIZE;
7948  }
7949 
7950  /* Periodic in z direction */
7951  if ( z1 >= SYSIZE ) {
7952  z1 -= SYSIZE;
7953  } else if ( z1 < 0 ) {
7954  z1 += SYSIZE;
7955  }
7956 
7957  /* Nonperiodic so be sure to remain in the 3-D box */
7958  if ( ( x1 >= 0 ) && ( x1 < SYSIZE ) ) {
7959  px = cx(x1, y1, z1, d1, d2, d3);
7960  py = cy(x1, y1, z1, d1, d2, d3);
7961  pz = cz(x1, y1, z1, d1, d2, d3);
7962  /* Conditions for propagation of burning */
7963  /* 1) new pixel is CH, CSH or ETTR or C3AH6*/
7964  if ( ( mic [ px ] [ py ] [ pz ] == CSH ) || ( mic [ px ] [ py ] [ pz ] == ETTRC4AF ) || ( mic [ px ] [ py ] [ pz ] == C3AH6 ) || ( mic [ px ] [ py ] [ pz ] == ETTR ) ) {
7965  ntot += 1;
7966  mic [ px ] [ py ] [ pz ] = BURNT;
7967  nnew += 1;
7968  if ( nnew >= SIZESET ) {
7969  printf("error in size of nnew %ld\n", nnew);
7970  }
7971 
7972  nnewx [ nnew ] = x1;
7973  nnewy [ nnew ] = y1;
7974  nnewz [ nnew ] = z1;
7975  }
7976  /* 2) old pixel is CSH or ETTR or C3AH6 and new pixel is one of cement clinker, slag, or fly ash phases */
7977  else if ( ( ( newmat [ qx ] [ qy ] [ qz ] == CSH ) || ( newmat [ qx ] [ qy ] [ qz ] == ETTRC4AF ) || ( newmat [ qx ] [ qy ] [ qz ] == C3AH6 ) || ( newmat [ qx ] [ qy ] [ qz ] == ETTR ) ) &&
7978  ( ( mic [ px ] [ py ] [ pz ] == C3S ) ||
7979  ( mic [ px ] [ py ] [ pz ] == C2S ) ||
7980  ( mic [ px ] [ py ] [ pz ] == CAS2 ) ||
7981  ( mic [ px ] [ py ] [ pz ] == SLAG ) ||
7982  ( mic [ px ] [ py ] [ pz ] == POZZ ) ||
7983  ( mic [ px ] [ py ] [ pz ] == ASG ) ||
7984  ( mic [ px ] [ py ] [ pz ] == C3A ) ||
7985  ( mic [ px ] [ py ] [ pz ] == C4AF ) ) ) {
7986  ntot += 1;
7987  mic [ px ] [ py ] [ pz ] = BURNT;
7988  nnew += 1;
7989  if ( nnew >= SIZESET ) {
7990  printf("error in size of nnew %ld\n", nnew);
7991  }
7992 
7993  nnewx [ nnew ] = x1;
7994  nnewy [ nnew ] = y1;
7995  nnewz [ nnew ] = z1;
7996  }
7997  /* 3) old and new pixels belong to one of cement clinker, slag, or fly ash phases and */
7998  /* are contained in the same initial cement particle */
7999  /* and it is not a one-pixel particle */
8000  else if ( ( micpart [ qx ] [ qy ] [ qz ] == micpart [ px ] [ py ] [ pz ] ) &&
8001  ( ( mic [ px ] [ py ] [ pz ] == C3S ) ||
8002  ( mic [ px ] [ py ] [ pz ] == C2S ) ||
8003  ( mic [ px ] [ py ] [ pz ] == POZZ ) ||
8004  ( mic [ px ] [ py ] [ pz ] == SLAG ) ||
8005  ( mic [ px ] [ py ] [ pz ] == ASG ) ||
8006  ( mic [ px ] [ py ] [ pz ] == CAS2 ) ||
8007  ( mic [ px ] [ py ] [ pz ] == C3A ) ||
8008  ( mic [ px ] [ py ] [ pz ] == C4AF ) ) && ( ( newmat [ qx ] [ qy ] [ qz ] == C3S ) ||
8009  ( newmat [ qx ] [ qy ] [ qz ] == C2S ) ||
8010  ( newmat [ qx ] [ qy ] [ qz ] == SLAG ) ||
8011  ( newmat [ qx ] [ qy ] [ qz ] == ASG ) ||
8012  ( newmat [ qx ] [ qy ] [ qz ] == POZZ ) ||
8013  ( newmat [ qx ] [ qy ] [ qz ] == CAS2 ) ||
8014  ( newmat [ qx ] [ qy ] [ qz ] == C3A ) ||
8015  ( newmat [ qx ] [ qy ] [ qz ] == C4AF ) ) ) {
8016  ntot += 1;
8017  mic [ px ] [ py ] [ pz ] = BURNT;
8018  nnew += 1;
8019  if ( nnew >= SIZESET ) {
8020  printf("error in size of nnew %ld\n", nnew);
8021  }
8022 
8023  nnewx [ nnew ] = x1;
8024  nnewy [ nnew ] = y1;
8025  nnewz [ nnew ] = z1;
8026  }
8027  }
8028 
8029  /* nonperiodic if delimiter */
8030  }
8031 
8032  /* neighbors loop */
8033  }
8034 
8035  /* propagators loop */
8036  if ( nnew > 0 ) {
8037  ncur = nnew;
8038  /* update the burn front matrices */
8039  for ( icur = 1; icur <= ncur; icur++ ) {
8040  nmatx [ icur ] = nnewx [ icur ];
8041  nmaty [ icur ] = nnewy [ icur ];
8042  nmatz [ icur ] = nnewz [ icur ];
8043  }
8044  }
8045  } while ( nnew > 0 );
8046 
8047  ntop += ntot;
8048  xl = 0;
8049  xh = SYSIZE - 1;
8050  /* Check for percolated path through system */
8051  for ( j1 = 0; j1 < SYSIZE; j1++ ) {
8052  for ( k1 = 0; k1 < SYSIZE; k1++ ) {
8053  px = cx(xl, j1, k1, d1, d2, d3);
8054  py = cy(xl, j1, k1, d1, d2, d3);
8055  pz = cz(xl, j1, k1, d1, d2, d3);
8056  qx = cx(xh, j1, k1, d1, d2, d3);
8057  qy = cy(xh, j1, k1, d1, d2, d3);
8058  qz = cz(xh, j1, k1, d1, d2, d3);
8059  if ( ( mic [ px ] [ py ] [ pz ] == BURNT ) && ( mic [ qx ] [ qy ] [ qz ] == BURNT ) ) {
8060  igood = 2;
8061  }
8062 
8063  if ( mic [ px ] [ py ] [ pz ] == BURNT ) {
8064  mic [ px ] [ py ] [ pz ] = BURNT + 1;
8065  }
8066 
8067  if ( mic [ qx ] [ qy ] [ qz ] == BURNT ) {
8068  mic [ qx ] [ qy ] [ qz ] = BURNT + 1;
8069  }
8070  }
8071  }
8072 
8073  if ( igood == 2 ) {
8074  nthrough += ntot;
8075  }
8076  }
8077  }
8078  }
8079 
8080 #ifdef PRINTF
8081  printf("Phase ID= Solid Phases \n");
8082  printf("Number accessible from first surface = %ld \n", ntop);
8083  printf("Number contained in through pathways= %ld \n", nthrough);
8084 #endif
8085 
8086  mass_burn += specgrav [ C3S ] * count [ C3S ];
8087  mass_burn += specgrav [ C2S ] * count [ C2S ];
8088  mass_burn += specgrav [ C3A ] * count [ C3A ];
8089  mass_burn += specgrav [ C4AF ] * count [ C4AF ];
8090  alpha_burn = 1. - ( mass_burn / cemmass );
8091 
8092  con_frac = 0.0;
8093  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 ];
8094 
8095  if ( count_solid > 0 ) {
8096  con_frac = ( float ) nthrough / ( float ) count_solid;
8097  }
8098 
8099 #ifdef OUTFILES
8100  //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);
8101  //fflush(percfile);
8102 #endif
8103 
8104  if ( con_frac > 0.985 ) {
8105  setyet = 1;
8106  }
8107 
8109 
8110  /* return the burnt sites to their original phase values */
8111  for ( i = 0; i < SYSIZE; i++ ) {
8112  for ( j = 0; j < SYSIZE; j++ ) {
8113  for ( k = 0; k < SYSIZE; k++ ) {
8114  if ( mic [ i ] [ j ] [ k ] >= BURNT ) {
8115  mic [ i ] [ j ] [ k ] = newmat [ i ] [ j ] [ k ];
8116  }
8117  }
8118  }
8119  }
8120 
8121 
8122  dealloc_char_3D(newmat, SYSIZE);
8123  delete [] nmatx;
8124  delete [] nmaty;
8125  delete [] nmatz;
8126  delete [] nnewx;
8127  delete [] nnewy;
8128  delete [] nnewz;
8129 
8130  /* Return flag indicating if set has indeed occurred */
8131  return ( setyet );
8132 
8133  ( void ) alpha_burn;
8134 }
8135 
8136 
8137 
8138 /* Routine to assess relative particle hydration */
8140 {
8141  int norig [ 100000 ], nleft [ 100000 ];
8142  int ix, iy, iz;
8143  char valmic, valmicorig;
8144  int valpart, partmax;
8145  float alpart;
8146  FILE *phydfile;
8147 
8148  /* Initialize the particle count arrays */
8149  for ( ix = 0; ix < 100000; ix++ ) {
8150  nleft [ ix ] = norig [ ix ] = 0;
8151  }
8152 
8153  phydfile = fopen(phrname, "a");
8154  fprintf(phydfile, "%d %f\n", cyccnt, alpha_cur);
8155 
8156  partmax = 0;
8157  /* Scan the microstructure pixel by pixel and update counts */
8158  for ( ix = 0; ix < SYSIZE; ix++ ) {
8159  for ( iy = 0; iy < SYSIZE; iy++ ) {
8160  for ( iz = 0; iz < SYSIZE; iz++ ) {
8161  if ( micpart [ ix ] [ iy ] [ iz ] != 0 ) {
8162  valpart = micpart [ ix ] [ iy ] [ iz ];
8163  if ( valpart > partmax ) {
8164  partmax = valpart;
8165  }
8166 
8167  valmic = mic [ ix ] [ iy ] [ iz ];
8168  if ( ( valmic == C3S ) || ( valmic == C2S ) || ( valmic == C3A ) || ( valmic == C4AF ) ) {
8169  nleft [ valpart ] += 1;
8170  }
8171 
8172  valmicorig = micorig [ ix ] [ iy ] [ iz ];
8173  if ( ( valmicorig == C3S ) || ( valmicorig == C2S ) || ( valmicorig == C3A ) || ( valmicorig == C4AF ) ) {
8174  norig [ valpart ] += 1;
8175  }
8176  }
8177  }
8178  }
8179  }
8180 
8181  /* Output results to end of particle hydration file */
8182  for ( ix = 100; ix <= partmax; ix++ ) {
8183  alpart = 0.0;
8184  if ( norig [ ix ] != 0 ) {
8185  alpart = 1. - ( float ) nleft [ ix ] / ( float ) norig [ ix ];
8186  }
8187 
8188  fprintf(phydfile, "%d %d %d %.3f\n", ix, norig [ ix ], nleft [ ix ], alpart);
8189  }
8190 
8191  fclose(phydfile);
8192 }
8193 
8194 
8195 /* extpozz, movefh3, movech, extc3ah6, movec3a */
8196 /* extfreidel, movecacl2, extstrat, moveas */
8197 int CemhydMatStatus :: moveone(int *xloc, int *yloc, int *zloc, int *act, int sumold)
8198 {
8199  int plok, sumnew, xl1, yl1, zl1, act1;
8200 
8201  sumnew = 1;
8202  /* store the input values for location */
8203  xl1 = ( * xloc );
8204  yl1 = ( * yloc );
8205  zl1 = ( * zloc );
8206  act1 = ( * act );
8207 
8208  /* Choose one of six directions (at random) for the new */
8209  /* location */
8210  plok = ( int ) ( 6. * ran1(seed) );
8211  if ( ( plok > 5 ) || ( plok < 0 ) ) {
8212  plok = 5;
8213  }
8214 
8215  switch ( plok ) {
8216  case 0:
8217  xl1 -= 1;
8218  act1 = 1;
8219  if ( xl1 < 0 ) {
8220  xl1 = ( SYSIZEM1 );
8221  }
8222 
8223  if ( sumold % 2 != 0 ) {
8224  sumnew = 2;
8225  }
8226 
8227  break;
8228  case 1:
8229  xl1 += 1;
8230  act1 = 2;
8231  if ( xl1 >= SYSIZE ) {
8232  xl1 = 0;
8233  }
8234 
8235  if ( sumold % 3 != 0 ) {
8236  sumnew = 3;
8237  }
8238 
8239  break;
8240  case 2:
8241  yl1 -= 1;
8242  act1 = 3;
8243  if ( yl1 < 0 ) {
8244  yl1 = ( SYSIZEM1 );
8245  }
8246 
8247  if ( sumold % 5 != 0 ) {
8248  sumnew = 5;
8249  }
8250 
8251  break;
8252  case 3:
8253  yl1 += 1;
8254  act1 = 4;
8255  if ( yl1 >= SYSIZE ) {
8256  yl1 = 0;
8257  }
8258 
8259  if ( sumold % 7 != 0 ) {
8260  sumnew = 7;
8261  }
8262 
8263  break;
8264  case 4:
8265  zl1 -= 1;
8266  act1 = 5;
8267  if ( zl1 < 0 ) {
8268  zl1 = ( SYSIZEM1 );
8269  }
8270 
8271  if ( sumold % 11 != 0 ) {
8272  sumnew = 11;
8273  }
8274 
8275  break;
8276  case 5:
8277  zl1 += 1;
8278  act1 = 6;
8279  if ( zl1 >= SYSIZE ) {
8280  zl1 = 0;
8281  }
8282 
8283  if ( sumold % 13 != 0 ) {
8284  sumnew = 13;
8285  }
8286 
8287  break;
8288  default:
8289  break;
8290  }
8291 
8292  /* Return the new location */
8293  * xloc = xl1;
8294  * yloc = yl1;
8295  * zloc = zl1;
8296  * act = act1;
8297  /* sumnew returns a prime number indicating that a specific direction */
8298  /* has been chosen */
8299  return ( sumnew );
8300 }
8301 
8302 /* routine to return count of number of neighboring pixels for pixel */
8303 /* (xck,yck,zck) which are not phase ph1, ph2, or ph3 which are input as */
8304 /* parameters */
8305 /* Calls no other routines */
8306 /* Called by extettr, extfh3, extch, extafm, extpozz, extc3ah6 */
8307 /* extfreidel, extcsh, and extstrat */
8308 int CemhydMatStatus :: edgecnt(int xck, int yck, int zck, int ph1, int ph2, int ph3)
8309 {
8310  int ixe, iye, ize, edgeback, x2, y2, z2, check;
8311 
8312  /* counter for number of neighboring pixels which are not ph1, ph2, or ph3 */
8313  edgeback = 0;
8314 
8315  /* Examine all pixels in a 3*3*3 box centered at (xck,yck,zck) */
8316  /* except for the central pixel */
8317  for ( ixe = ( -1 ); ixe <= 1; ixe++ ) {
8318  x2 = xck + ixe;
8319  for ( iye = ( -1 ); iye <= 1; iye++ ) {
8320  y2 = yck + iye;
8321  for ( ize = ( -1 ); ize <= 1; ize++ ) {
8322  if ( ( ixe != 0 ) || ( iye != 0 ) || ( ize != 0 ) ) {
8323  z2 = zck + ize;
8324  /* adjust to maintain periodic boundaries */
8325  if ( x2 < 0 ) {
8326  x2 = ( SYSIZEM1 );
8327  } else if ( x2 >= SYSIZE ) {
8328  x2 = 0;
8329  }
8330 
8331  if ( y2 < 0 ) {
8332  y2 = ( SYSIZEM1 );
8333  } else if ( y2 >= SYSIZE ) {
8334  y2 = 0;
8335  }
8336 
8337  if ( z2 < 0 ) {
8338  z2 = ( SYSIZEM1 );
8339  } else if ( z2 >= SYSIZE ) {
8340  z2 = 0;
8341  }
8342 
8343  check = mic [ x2 ] [ y2 ] [ z2 ];
8344  if ( ( check != ph1 ) && ( check != ph2 ) && ( check != ph3 ) ) {
8345  edgeback += 1;
8346  }
8347  }
8348  }
8349  }
8350  }
8351 
8352  /* return number of neighboring pixels which are not ph1, ph2, or ph3 */
8353  return ( edgeback );
8354 }
8355 
8356 /* routine to add extra CSH when diffusing CSH reacts */
8357 /* Called by movecsh */
8358 /* Calls edgecnt */
8360 {
8361  int numnear, xchr, ychr, zchr, fchr, check, msface;
8362  long int tries;
8363 
8364  fchr = 0;
8365  tries = 0;
8366  /* locate CSH at random location */
8367  /* in pore space in contact with at least another CSH or C3S or C2S */
8368  while ( fchr == 0 ) {
8369  tries += 1;
8370  /* generate a random location in the 3-D system */
8371  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8372  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8373  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8374  if ( xchr >= SYSIZE ) {
8375  xchr = 0;
8376  }
8377 
8378  if ( ychr >= SYSIZE ) {
8379  ychr = 0;
8380  }
8381 
8382  if ( zchr >= SYSIZE ) {
8383  zchr = 0;
8384  }
8385 
8386  check = mic [ xchr ] [ ychr ] [ zchr ];
8387 
8388  /* if location is porosity, locate the CSH there */
8389  if ( check == POROSITY ) {
8390  numnear = edgecnt(xchr, ychr, zchr, CSH, C3S, C2S);
8391  /* be sure that at least one neighboring pixel */
8392  /* is C2S, C3S, or diffusing CSH */
8393  if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8394  mic [ xchr ] [ ychr ] [ zchr ] = CSH;
8395  count [ CSH ] += 1;
8396  count [ POROSITY ] -= 1;
8397  cshage [ xchr ] [ ychr ] [ zchr ] = cyccnt;
8398  if ( cshgeom == 1 ) {
8399  msface = ( int ) ( 3. * ran1(seed) + 1. );
8400  if ( msface > 3 ) {
8401  msface = 1;
8402  }
8403 
8404  faces [ xchr ] [ ychr ] [ zchr ] = msface;
8405  ncshplateinit += 1;
8406  }
8407 
8408  fchr = 1;
8409  }
8410  }
8411  }
8412 }
8413 
8414 /* routine to move a diffusing CSH species */
8415 /* Inputs: current location (xcur,ycur,zcur) and flag indicating if final */
8416 /* step in diffusion process */
8417 /* Returns flag indicating action taken (reaction or diffusion/no movement) */
8418 /* Calls moveone,extcsh */
8419 /* Called by hydrate */
8420 int CemhydMatStatus :: movecsh(int xcur, int ycur, int zcur, int finalstep, int cycorig)
8421 {
8422  int xnew, ynew, znew, action, sumback, sumin, check;
8423  int msface, mstest = 0, mstest2 = 0;
8424  float prcsh, prcsh1, prcsh2, prtest;
8425 
8426  action = 0;
8427  /* Store current location of species */
8428  xnew = xcur;
8429  ynew = ycur;
8430  znew = zcur;
8431  sumin = 1;
8432  sumback = moveone(& xnew, & ynew, & znew, & action, sumin);
8433  if ( cshgeom == 1 ) {
8434  /* Determine eligible faces based on direction of move */
8435  if ( xnew != xcur ) {
8436  mstest = 1;
8437  mstest2 = 2;
8438  }
8439 
8440  if ( ynew != ycur ) {
8441  mstest = 2;
8442  mstest2 = 3;
8443  }
8444 
8445  if ( znew != zcur ) {
8446  mstest = 3;
8447  mstest2 = 1;
8448  }
8449  }
8450 
8451  if ( action == 0 ) {
8452  printf("Error in value of action \n");
8453  }
8454 
8455  check = mic [ xnew ] [ ynew ] [ znew ];
8456 
8457 
8458  /* if new location is solid CSH and plate growth is favorable, */
8459  /* then convert diffusing CSH species to solid CSH */
8460  prcsh = ran1(seed);
8461  if ( ( check == CSH ) && ( ( cshgeom == 0 ) || ( faces [ xnew ] [ ynew ] [ znew ] == 0 ) || ( faces [ xnew ] [ ynew ] [ znew ] == mstest ) || ( faces [ xnew ] [ ynew ] [ znew ] == mstest2 ) ) ) {
8462  /* decrement count of diffusing CSH species */
8463  count [ DIFFCSH ] -= 1;
8464  /* and increment count of solid CSH if needed */
8465  prtest = molarvcsh [ cyccnt ] / molarvcsh [ cycorig ];
8466  prcsh1 = ran1(seed);
8467  if ( prcsh1 <= prtest ) {
8468  mic [ xcur ] [ ycur ] [ zcur ] = CSH;
8469  if ( cshgeom == 1 ) {
8470  faces [ xcur ] [ ycur ] [ zcur ] = faces [ xnew ] [ ynew ] [ znew ];
8471  ncshplategrow += 1;
8472  }
8473 
8474  cshage [ xcur ] [ ycur ] [ zcur ] = cyccnt;
8475  count [ CSH ] += 1;
8476  } else {
8477  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
8478  count [ POROSITY ] += 1;
8479  }
8480 
8481  /* May need extra solid CSH if temperature goes down with time */
8482  if ( prtest > 1.0 ) {
8483  prcsh2 = ran1(seed);
8484  if ( prcsh2 < ( prtest - 1.0 ) ) {
8485  extcsh();
8486  }
8487  }
8488 
8489  action = 0;
8490  }
8491  /* Changed prcsh limit from 0.1 to 0.01 for CH test 1/27/05 */
8492  else if ( ( check == SLAGCSH ) || ( check == POZZCSH ) || ( finalstep == 1 ) ||
8493  ( ( ( check == C3S ) || ( check == C2S ) ) && ( prcsh < 0.001 ) ) ||
8494  ( ( ( check == C3A ) || ( check == C4AF ) ) && ( prcsh < 0.2 ) ) ||
8495  ( ( check == CH ) && ( prcsh < 0.01 ) ) ||
8496  ( check == CACO3 ) || ( check == INERT ) ) {
8497  /* decrement count of diffusing CSH species */
8498  count [ DIFFCSH ] -= 1;
8499  /* and increment count of solid CSH if needed */
8500  prtest = molarvcsh [ cyccnt ] / molarvcsh [ cycorig ];
8501  prcsh1 = ran1(seed);
8502  if ( prcsh1 <= prtest ) {
8503  mic [ xcur ] [ ycur ] [ zcur ] = CSH;
8504  cshage [ xcur ] [ ycur ] [ zcur ] = cyccnt;
8505  if ( cshgeom == 1 ) {
8506  msface = ( int ) ( 2. * ran1(seed) + 1. );
8507  if ( msface > 2 ) {
8508  msface = 1;
8509  }
8510 
8511  if ( msface == 1 ) {
8512  faces [ xcur ] [ ycur ] [ zcur ] = mstest;
8513  } else {
8514  faces [ xcur ] [ ycur ] [ zcur ] = mstest2;
8515  }
8516 
8517  ncshplateinit += 1;
8518  }
8519 
8520  count [ CSH ] += 1;
8521  } else {
8522  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
8523  count [ POROSITY ] += 1;
8524  }
8525 
8526  /* May need extra solid CSH if temperature goes down with time */
8527  if ( prtest > 1.0 ) {
8528  prcsh2 = ran1(seed);
8529  if ( prcsh2 < ( prtest - 1.0 ) ) {
8530  extcsh();
8531  }
8532  }
8533 
8534  action = 0;
8535  }
8536 
8537  if ( action != 0 ) {
8538  /* if diffusion step is possible, perform it */
8539  if ( check == POROSITY ) {
8540  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
8541  mic [ xnew ] [ ynew ] [ znew ] = DIFFCSH;
8542  } else {
8543  /* indicate that diffusing CSH species remained */
8544  /* at original location */
8545  action = 7;
8546  }
8547  }
8548 
8549  return ( action );
8550 
8551  ( void ) sumback;
8552 }
8553 
8554 /* routine to add extra FH3 when gypsum, hemihydrate, anhydrite, CAS2, or */
8555 /* CaCl2 reacts with C4AF at location (xpres,ypres,zpres) */
8556 /* Called by movegyp, moveettr, movecas2, movehem, moveanh, and movecacl2 */
8557 /* Calls moveone and edgecnt */
8558 void CemhydMatStatus :: extfh3(int xpres, int ypres, int zpres)
8559 {
8560  int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
8561  long int tries;
8562 
8563  /* first try 6 neighboring locations until */
8564  /* a) successful */
8565  /* b) all 6 sites are tried and full or */
8566  /* c) 500 tries are made */
8567  fchr = 0;
8568  sump = 1;
8569  for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
8570  /* choose a neighbor at random */
8571  xchr = xpres;
8572  ychr = ypres;
8573  zchr = zpres;
8574  newact = 0;
8575  multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
8576  if ( newact == 0 ) {
8577  printf("Error in value of newact in extfh3 \n");
8578  }
8579 
8580  check = mic [ xchr ] [ ychr ] [ zchr ];
8581 
8582  /* if neighbor is porosity */
8583  /* then locate the FH3 there */
8584  if ( check == POROSITY ) {
8585  mic [ xchr ] [ ychr ] [ zchr ] = FH3;
8586  count [ FH3 ] += 1;
8587  count [ POROSITY ] -= 1;
8588  fchr = 1;
8589  } else {
8590  sump *= multf;
8591  }
8592  }
8593 
8594  /* if no neighbor available, locate FH3 at random location */
8595  /* in pore space in contact with at least one FH3 */
8596  tries = 0;
8597  while ( fchr == 0 ) {
8598  tries += 1;
8599  /* generate a random location in the 3-D system */
8600  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8601  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8602  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8603  if ( xchr >= SYSIZE ) {
8604  xchr = 0;
8605  }
8606 
8607  if ( ychr >= SYSIZE ) {
8608  ychr = 0;
8609  }
8610 
8611  if ( zchr >= SYSIZE ) {
8612  zchr = 0;
8613  }
8614 
8615  check = mic [ xchr ] [ ychr ] [ zchr ];
8616  /* if location is porosity, locate the FH3 there */
8617  if ( check == POROSITY ) {
8618  numnear = edgecnt(xchr, ychr, zchr, FH3, FH3, DIFFFH3);
8619  /* be sure that at least one neighboring pixel */
8620  /* is FH3 or diffusing FH3 */
8621  if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8622  mic [ xchr ] [ ychr ] [ zchr ] = FH3;
8623  count [ FH3 ] += 1;
8624  count [ POROSITY ] -= 1;
8625  fchr = 1;
8626  }
8627  }
8628  }
8629 }
8630 
8631 /* routine to add extra ettringite when gypsum, anhydrite, or hemihydrate */
8632 /* reacts with aluminates addition adjacent to location (xpres,ypres,zpres) */
8633 /* in a fashion to preserve needle growth */
8634 /* etype=0 indicates primary ettringite */
8635 /* etype=1 indicates iron-rich stable ettringite */
8636 /* Returns flag indicating action taken */
8637 /* Calls moveone and edgecnt */
8638 /* Called by movegyp, movehem, moveanh, and movec3a */
8639 int CemhydMatStatus :: extettr(int xpres, int ypres, int zpres, int etype)
8640 {
8641  int check, newact, multf, numnear, sump, xchr, ychr, zchr, fchr, i1;
8642  int numalum, numsil;
8643  float pneigh, ptest;
8644  long int tries;
8645 
8646  /* first try neighboring locations until */
8647  /* a) successful */
8648  /* c) 1000 tries are made */
8649  fchr = 0;
8650  sump = 1;
8651  /* Note that 30030 = 2*3*5*7*11*13 */
8652  /* indicating that all six sites have been tried */
8653  for ( i1 = 1; ( ( i1 <= 1000 ) && ( fchr == 0 ) ); i1++ ) {
8654  /* determine location of neighbor (using periodic boundaries) */
8655  xchr = xpres;
8656  ychr = ypres;
8657  zchr = zpres;
8658  newact = 0;
8659  multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
8660  if ( newact == 0 ) {
8661  printf("Error in value of action \n");
8662  }
8663 
8664  check = mic [ xchr ] [ ychr ] [ zchr ];
8665 
8666  /* if neighbor is porosity, and conditions are favorable */
8667  /* based on number of neighboring ettringite, C3A, or C4AF */
8668  /* pixels then locate the ettringite there */
8669  if ( check == POROSITY ) {
8670  /* be sure ettringite doesn't touch C3S */
8671  numsil = edgecnt(xchr, ychr, zchr, C3S, C2S, C3S);
8672  numsil = 26 - numsil;
8673  if ( etype == 0 ) {
8674  numnear = edgecnt(xchr, ychr, zchr, ETTR, ETTR, ETTR);
8675  numalum = edgecnt(xchr, ychr, zchr, C3A, C3A, C3A);
8676  numalum = 26 - numalum;
8677  } else {
8678  numnear = edgecnt(xchr, ychr, zchr, ETTRC4AF, ETTRC4AF, ETTRC4AF);
8679  numalum = edgecnt(xchr, ychr, zchr, C4AF, C4AF, C4AF);
8680  numalum = 26 - numalum;
8681  }
8682 
8683  pneigh = ( float ) ( numnear + 1 ) / 26.0;
8684  pneigh *= pneigh;
8685  if ( numalum <= 1 ) {
8686  pneigh = 0.0;
8687  }
8688 
8689  if ( numalum >= 2 ) {
8690  pneigh += 0.5;
8691  }
8692 
8693  if ( numalum >= 3 ) {
8694  pneigh += 0.25;
8695  }
8696 
8697  if ( numalum >= 5 ) {
8698  pneigh += 0.25;
8699  }
8700 
8701  ptest = ran1(seed);
8702  if ( numsil < 1 ) {
8703  if ( pneigh >= ptest ) {
8704  if ( etype == 0 ) {
8705  mic [ xchr ] [ ychr ] [ zchr ] = ETTR;
8706  count [ ETTR ] += 1;
8707  } else {
8708  mic [ xchr ] [ ychr ] [ zchr ] = ETTRC4AF;
8709  count [ ETTRC4AF ] += 1;
8710  }
8711 
8712  fchr = 1;
8713  count [ POROSITY ] -= 1;
8714  }
8715  }
8716  }
8717  }
8718 
8719  /* if no neighbor available, locate ettringite at random location */
8720  /* in pore space in contact with at least another ettringite */
8721  /* or aluminate surface */
8722  tries = 0;
8723  while ( fchr == 0 ) {
8724  tries += 1;
8725  newact = 7;
8726  /* generate a random location in the 3-D system */
8727  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8728  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8729  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8730  if ( xchr >= SYSIZE ) {
8731  xchr = 0;
8732  }
8733 
8734  if ( ychr >= SYSIZE ) {
8735  ychr = 0;
8736  }
8737 
8738  if ( zchr >= SYSIZE ) {
8739  zchr = 0;
8740  }
8741 
8742  check = mic [ xchr ] [ ychr ] [ zchr ];
8743  /* if location is porosity, locate the ettringite there */
8744  if ( check == POROSITY ) {
8745  numsil = edgecnt(xchr, ychr, zchr, C3S, C2S, C3S);
8746  numsil = 26 - numsil;
8747  if ( etype == 0 ) {
8748  numnear = edgecnt(xchr, ychr, zchr, ETTR, C3A, C4AF);
8749  } else {
8750  numnear = edgecnt(xchr, ychr, zchr, ETTRC4AF, C3A, C4AF);
8751  }
8752 
8753  /* be sure that at least one neighboring pixel */
8754  /* is ettringite, or aluminate clinker */
8755  if ( ( tries > 5000 ) || ( ( numnear < 26 ) && ( numsil < 1 ) ) ) {
8756  if ( etype == 0 ) {
8757  mic [ xchr ] [ ychr ] [ zchr ] = ETTR;
8758  count [ ETTR ] += 1;
8759  } else {
8760  mic [ xchr ] [ ychr ] [ zchr ] = ETTRC4AF;
8761  count [ ETTRC4AF ] += 1;
8762  }
8763 
8764  count [ POROSITY ] -= 1;
8765  fchr = 1;
8766  }
8767  }
8768  }
8769 
8770  return ( newact );
8771 
8772  ( void ) multf;
8773 }
8774 
8775 /* routine to add extra CH when gypsum, hemihydrate, anhydrite, CaCl2, or */
8776 /* diffusing CAS2 reacts with C4AF */
8777 /* Called by movegyp, movehem, moveanh, moveettr, movecas2, and movecacl2 */
8778 /* Calls edgecnt */
8780 {
8781  int numnear, xchr, ychr, zchr, fchr, check;
8782  long int tries;
8783 
8784  fchr = 0;
8785  tries = 0;
8786  /* locate CH at random location */
8787  /* in pore space in contact with at least another CH */
8788  while ( fchr == 0 ) {
8789  tries += 1;
8790  /* generate a random location in the 3-D system */
8791  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8792  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8793  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8794  if ( xchr >= SYSIZE ) {
8795  xchr = 0;
8796  }
8797 
8798  if ( ychr >= SYSIZE ) {
8799  ychr = 0;
8800  }
8801 
8802  if ( zchr >= SYSIZE ) {
8803  zchr = 0;
8804  }
8805 
8806  check = mic [ xchr ] [ ychr ] [ zchr ];
8807 
8808  /* if location is porosity, locate the CH there */
8809  if ( check == POROSITY ) {
8810  numnear = edgecnt(xchr, ychr, zchr, CH, DIFFCH, CH);
8811  /* be sure that at least one neighboring pixel */
8812  /* is CH or diffusing CH */
8813  if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8814  mic [ xchr ] [ ychr ] [ zchr ] = CH;
8815  count [ CH ] += 1;
8816  count [ POROSITY ] -= 1;
8817  fchr = 1;
8818  }
8819  }
8820  }
8821 }
8822 
8823 /* routine to add extra gypsum when hemihydrate or anhydrite hydrates */
8824 /* Called by movehem and moveanh */
8825 /* Calls moveone and edgecnt */
8826 void CemhydMatStatus :: extgyps(int xpres, int ypres, int zpres)
8827 {
8828  int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
8829  long int tries;
8830 
8831  /* first try 6 neighboring locations until */
8832  /* a) successful */
8833  /* b) all 6 sites are tried and full or */
8834  /* c) 500 tries are made */
8835  fchr = 0;
8836  sump = 1;
8837  for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
8838  /* choose a neighbor at random */
8839  xchr = xpres;
8840  ychr = ypres;
8841  zchr = zpres;
8842  newact = 0;
8843  multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
8844  if ( newact == 0 ) {
8845  printf("Error in value of newact in extfh3 \n");
8846  }
8847 
8848  check = mic [ xchr ] [ ychr ] [ zchr ];
8849 
8850  /* if neighbor is porosity */
8851  /* then locate the GYPSUMS there */
8852  if ( check == POROSITY ) {
8853  mic [ xchr ] [ ychr ] [ zchr ] = GYPSUMS;
8854  count [ GYPSUMS ] += 1;
8855  count [ POROSITY ] -= 1;
8856  fchr = 1;
8857  } else {
8858  sump *= multf;
8859  }
8860  }
8861 
8862  /* if no neighbor available, locate GYPSUMS at random location */
8863  /* in pore space in contact with at least one GYPSUMS */
8864  tries = 0;
8865  while ( fchr == 0 ) {
8866  tries += 1;
8867  /* generate a random location in the 3-D system */
8868  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8869  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8870  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
8871  if ( xchr >= SYSIZE ) {
8872  xchr = 0;
8873  }
8874 
8875  if ( ychr >= SYSIZE ) {
8876  ychr = 0;
8877  }
8878 
8879  if ( zchr >= SYSIZE ) {
8880  zchr = 0;
8881  }
8882 
8883  check = mic [ xchr ] [ ychr ] [ zchr ];
8884  /* if location is porosity, locate the GYPSUMS there */
8885  if ( check == POROSITY ) {
8886  numnear = edgecnt(xchr, ychr, zchr, HEMIHYD, GYPSUMS, ANHYDRITE);
8887  /* be sure that at least one neighboring pixel */
8888  /* is Gypsum in some form */
8889  if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
8890  mic [ xchr ] [ ychr ] [ zchr ] = GYPSUMS;
8891  count [ GYPSUMS ] += 1;
8892  count [ POROSITY ] -= 1;
8893  fchr = 1;
8894  }
8895  }
8896  }
8897 }
8898 
8899 /* routine to move a diffusing ANHYDRITE species */
8900 /* Inputs: current location (xcur,ycur,zcur) and flag indicating if final */
8901 /* step in diffusion process */
8902 /* Returns flag indicating action taken (reaction or diffusion/no movement) */
8903 /* Calls moveone */
8904 /* Called by hydrate */
8905 int CemhydMatStatus :: moveanh(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
8906 {
8907  int xnew, ynew, znew, action, sumback, sumin, check = -1;
8908  int nexp, iexp, xexp, yexp, zexp, newact, ettrtype;
8909  float pgen, pexp, pext, p2diff;
8910 
8911  action = 0;
8912  /* first check for nucleation */
8913  pgen = ran1(seed);
8914  p2diff = ran1(seed);
8915  if ( ( nucprgyp >= pgen ) || ( finalstep == 1 ) ) {
8916  action = 0;
8917  mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
8918  count [ DIFFANH ] -= 1;
8919  count [ GYPSUMS ] += 1;
8920  pexp = ran1(seed);
8921  if ( pexp < 0.4 ) {
8922  extgyps(xcur, ycur, zcur);
8923  }
8924  } else {
8925  /* Store current location of species */
8926  xnew = xcur;
8927  ynew = ycur;
8928  znew = zcur;
8929  sumin = 1;
8930  sumback = moveone(& xnew, & ynew, & znew, & action, sumin);
8931 
8932  if ( action == 0 ) {
8933  printf("Error in value of action \n");
8934  }
8935 
8936  check = mic [ xnew ] [ ynew ] [ znew ];
8937 
8938  /* if new location is solid GYPSUM(S) or diffusing GYPSUM, then convert */
8939  /* diffusing ANHYDRITE species to solid GYPSUM */
8940  if ( ( check == GYPSUM ) || ( check == GYPSUMS ) || ( check == DIFFGYP ) ) {
8941  mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
8942  /* decrement count of diffusing ANHYDRITE species */
8943  /* and increment count of solid GYPSUMS */
8944  count [ DIFFANH ] -= 1;
8945  count [ GYPSUMS ] += 1;
8946  action = 0;
8947  /* Add extra gypsum as necessary */
8948  pexp = ran1(seed);
8949  if ( pexp < 0.4 ) {
8950  extgyps(xnew, ynew, znew);
8951  }
8952  }
8953  /* if new location is C3A or diffusing C3A, execute conversion */
8954  /* to ettringite (including necessary volumetric expansion) */
8955  else if ( ( ( check == C3A ) && ( p2diff < SOLIDC3AGYP ) ) || ( ( check == DIFFC3A ) && ( p2diff < C3AGYP ) ) || ( ( check == DIFFC4A ) && ( p2diff < C3AGYP ) ) ) {
8956  /* Convert diffusing gypsum to an ettringite pixel */
8957  ettrtype = 0;
8958  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
8959  if ( check == DIFFC4A ) {
8960  ettrtype = 1;
8961  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
8962  }
8963 
8964  action = 0;
8965  count [ DIFFANH ] -= 1;
8966  count [ check ] -= 1;
8967 
8968  /* determine if C3A should be converted to ettringite */
8969  /* 1 unit of hemihydrate requires 0.569 units of C3A */
8970  /* and should form 4.6935 units of ettringite */
8971  pexp = ran1(seed);
8972  nexp = 3;
8973  if ( pexp <= 0.569 ) {
8974  if ( ettrtype == 0 ) {
8975  mic [ xnew ] [ ynew ] [ znew ] = ETTR;
8976  count [ ETTR ] += 1;
8977  } else {
8978  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
8979  count [ ETTRC4AF ] += 1;
8980  }
8981 
8982  nexp = 2;
8983  } else {
8984  /* maybe someday, use a new FIXEDC3A here */
8985  /* so it won't dissolve later */
8986  if ( check == C3A ) {
8987  mic [ xnew ] [ ynew ] [ znew ] = C3A;
8988  count [ C3A ] += 1;
8989  } else {
8990  if ( ettrtype == 0 ) {
8991  count [ DIFFC3A ] += 1;
8992  mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
8993  } else {
8994  count [ DIFFC4A ] += 1;
8995  mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
8996  }
8997  }
8998 
8999  nexp = 3;
9000  }
9001 
9002  /* create extra ettringite pixels to maintain volume stoichiometry */
9003  /* xexp, yexp, and zexp hold coordinates of most recently added ettringite */
9004  /* species as we attempt to grow a needle like structure */
9005  xexp = xcur;
9006  yexp = ycur;
9007  zexp = zcur;
9008  for ( iexp = 1; iexp <= nexp; iexp++ ) {
9009  newact = extettr(xexp, yexp, zexp, ettrtype);
9010  /* update xexp, yexp and zexp as needed */
9011  switch ( newact ) {
9012  case 1:
9013  xexp -= 1;
9014  if ( xexp < 0 ) {
9015  xexp = ( SYSIZEM1 );
9016  }
9017 
9018  break;
9019  case 2:
9020  xexp += 1;
9021  if ( xexp >= SYSIZE ) {
9022  xexp = 0;
9023  }
9024 
9025  break;
9026  case 3:
9027  yexp -= 1;
9028  if ( yexp < 0 ) {
9029  yexp = ( SYSIZEM1 );
9030  }
9031 
9032  break;
9033  case 4:
9034  yexp += 1;
9035  if ( yexp >= SYSIZE ) {
9036  yexp = 0;
9037  }
9038 
9039  break;
9040  case 5:
9041  zexp -= 1;
9042  if ( zexp < 0 ) {
9043  zexp = ( SYSIZEM1 );
9044  }
9045 
9046  break;
9047  case 6:
9048  zexp += 1;
9049  if ( zexp >= SYSIZE ) {
9050  zexp = 0;
9051  }
9052 
9053  break;
9054  default:
9055  break;
9056  }
9057  }
9058 
9059  /* probabilistic-based expansion for last ettringite pixel */
9060  pexp = ran1(seed);
9061  if ( pexp <= 0.6935 ) {
9062  newact = extettr(xexp, yexp, zexp, ettrtype);
9063  }
9064  }
9065 
9066  /* if new location is C4AF execute conversion */
9067  /* to ettringite (including necessary volumetric expansion) */
9068  if ( ( check == C4AF ) && ( p2diff < SOLIDC4AFGYP ) ) {
9069  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9070  count [ ETTRC4AF ] += 1;
9071  count [ DIFFANH ] -= 1;
9072 
9073  /* determine if C4AF should be converted to ettringite */
9074  /* 1 unit of gypsum requires 0.8174 units of C4AF */
9075  /* and should form 4.6935 units of ettringite */
9076  pexp = ran1(seed);
9077  nexp = 3;
9078  if ( pexp <= 0.8174 ) {
9079  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9080  count [ ETTRC4AF ] += 1;
9081  count [ C4AF ] -= 1;
9082  nexp = 2;
9083  pext = ran1(seed);
9084  /* Addition of extra CH */
9085  if ( pext < 0.2584 ) {
9086  extch();
9087  }
9088 
9089  pext = ran1(seed);
9090  /* Addition of extra FH3 */
9091  if ( pext < 0.5453 ) {
9092  extfh3(xnew, ynew, znew);
9093  }
9094  } else {
9095  /* maybe someday, use a new FIXEDC4AF here */
9096  /* so it won't dissolve later */
9097  mic [ xnew ] [ ynew ] [ znew ] = C4AF;
9098  nexp = 3;
9099  }
9100 
9101  /* create extra ettringite pixels to maintain volume stoichiometry */
9102  /* xexp, yexp and zexp hold coordinates of most recently added ettringite */
9103  /* species as we attempt to grow a needle like structure */
9104  xexp = xcur;
9105  yexp = ycur;
9106  zexp = zcur;
9107  for ( iexp = 1; iexp <= nexp; iexp++ ) {
9108  newact = extettr(xexp, yexp, zexp, 1);
9109  /* update xexp, yexp and zexp as needed */
9110  switch ( newact ) {
9111  case 1:
9112  xexp -= 1;
9113  if ( xexp < 0 ) {
9114  xexp = ( SYSIZEM1 );
9115  }
9116 
9117  break;
9118  case 2:
9119  xexp += 1;
9120  if ( xexp >= SYSIZE ) {
9121  xexp = 0;
9122  }
9123 
9124  break;
9125  case 3:
9126  yexp -= 1;
9127  if ( yexp < 0 ) {
9128  yexp = ( SYSIZEM1 );
9129  }
9130 
9131  break;
9132  case 4:
9133  yexp += 1;
9134  if ( yexp >= SYSIZE ) {
9135  yexp = 0;
9136  }
9137 
9138  break;
9139  case 5:
9140  zexp -= 1;
9141  if ( zexp < 0 ) {
9142  zexp = ( SYSIZEM1 );
9143  }
9144 
9145  break;
9146  case 6:
9147  zexp += 1;
9148  if ( zexp >= SYSIZE ) {
9149  zexp = 0;
9150  }
9151 
9152  break;
9153  default:
9154  break;
9155  }
9156  }
9157 
9158  /* probabilistic-based expansion for last ettringite pixel */
9159  pexp = ran1(seed);
9160  if ( pexp <= 0.6935 ) {
9161  newact = extettr(xexp, yexp, zexp, 1);
9162  }
9163 
9164  action = 0;
9165  }
9166  }
9167 
9168  if ( action != 0 ) {
9169  /* if diffusion step is possible, perform it */
9170  if ( check == POROSITY ) {
9171  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
9172  mic [ xnew ] [ ynew ] [ znew ] = DIFFANH;
9173  } else {
9174  /* indicate that diffusing ANHYDRITE species remained */
9175  /* at original location */
9176  action = 7;
9177  }
9178  }
9179 
9180  return ( action );
9181 
9182  ( void ) sumback;
9183 }
9184 
9185 /* routine to move a diffusing HEMIHYDRATE species */
9186 /* Inputs: current location (xcur,ycur,zcur) and flag indicating if final */
9187 /* step in diffusion process */
9188 /* Returns flag indicating action taken (reaction or diffusion/no movement) */
9189 /* Calls moveone, extettr, extch, and extfh3 */
9190 /* Called by hydrate */
9191 int CemhydMatStatus :: movehem(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
9192 {
9193  int xnew, ynew, znew, action, sumback, sumin, check = -1;
9194  int nexp, iexp, xexp, yexp, zexp, newact, ettrtype;
9195  float pgen, pexp, pext, p2diff;
9196 
9197  action = 0;
9198  /* first check for nucleation */
9199  pgen = ran1(seed);
9200  p2diff = ran1(seed);
9201  if ( ( nucprgyp >= pgen ) || ( finalstep == 1 ) ) {
9202  action = 0;
9203  mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
9204  count [ DIFFHEM ] -= 1;
9205  count [ GYPSUMS ] += 1;
9206  /* Add extra gypsum as necessary */
9207  pexp = ran1(seed);
9208  if ( pexp < 0.4 ) {
9209  extgyps(xcur, ycur, zcur);
9210  }
9211  } else {
9212  /* Store current location of species */
9213  xnew = xcur;
9214  ynew = ycur;
9215  znew = zcur;
9216  sumin = 1;
9217  sumback = moveone(& xnew, & ynew, & znew, & action, sumin);
9218 
9219  if ( action == 0 ) {
9220  printf("Error in value of action \n");
9221  }
9222 
9223  check = mic [ xnew ] [ ynew ] [ znew ];
9224 
9225  /* if new location is solid GYPSUM(S) or diffusing GYPSUM, then convert */
9226  /* diffusing HEMIHYDRATE species to solid GYPSUM */
9227  if ( ( check == GYPSUM ) || ( check == GYPSUMS ) || ( check == DIFFGYP ) ) {
9228  mic [ xcur ] [ ycur ] [ zcur ] = GYPSUMS;
9229  /* decrement count of diffusing HEMIHYDRATE species */
9230  /* and increment count of solid GYPSUMS */
9231  count [ DIFFHEM ] -= 1;
9232  count [ GYPSUMS ] += 1;
9233  action = 0;
9234  /* Add extra gypsum as necessary */
9235  pexp = ran1(seed);
9236  if ( pexp < 0.4 ) {
9237  extgyps(xnew, ynew, znew);
9238  }
9239  }
9240  /* if new location is C3A or diffusing C3A, execute conversion */
9241  /* to ettringite (including necessary volumetric expansion) */
9242  else if ( ( ( check == C3A ) && ( p2diff < SOLIDC3AGYP ) ) || ( ( check == DIFFC3A ) && ( p2diff < C3AGYP ) ) || ( ( check == DIFFC4A ) && ( p2diff < C3AGYP ) ) ) {
9243  /* Convert diffusing gypsum to an ettringite pixel */
9244  ettrtype = 0;
9245  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
9246  if ( check == DIFFC4A ) {
9247  ettrtype = 1;
9248  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9249  }
9250 
9251  action = 0;
9252  count [ DIFFHEM ] -= 1;
9253  count [ check ] -= 1;
9254 
9255  /* determine if C3A should be converted to ettringite */
9256  /* 1 unit of hemihydrate requires 0.5583 units of C3A */
9257  /* and should form 4.6053 units of ettringite */
9258  pexp = ran1(seed);
9259  nexp = 3;
9260  if ( pexp <= 0.5583 ) {
9261  if ( ettrtype == 0 ) {
9262  mic [ xnew ] [ ynew ] [ znew ] = ETTR;
9263  count [ ETTR ] += 1;
9264  } else {
9265  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9266  count [ ETTRC4AF ] += 1;
9267  }
9268 
9269  nexp = 2;
9270  } else {
9271  /* maybe someday, use a new FIXEDC3A here */
9272  /* so it won't dissolve later */
9273  if ( check == C3A ) {
9274  mic [ xnew ] [ ynew ] [ znew ] = C3A;
9275  count [ C3A ] += 1;
9276  } else {
9277  if ( ettrtype == 0 ) {
9278  count [ DIFFC3A ] += 1;
9279  mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
9280  } else {
9281  count [ DIFFC4A ] += 1;
9282  mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
9283  }
9284  }
9285 
9286  nexp = 3;
9287  }
9288 
9289  /* create extra ettringite pixels to maintain volume stoichiometry */
9290  /* xexp, yexp, and zexp hold coordinates of most recently added ettringite */
9291  /* species as we attempt to grow a needle like structure */
9292  xexp = xcur;
9293  yexp = ycur;
9294  zexp = zcur;
9295  for ( iexp = 1; iexp <= nexp; iexp++ ) {
9296  newact = extettr(xexp, yexp, zexp, ettrtype);
9297  /* update xexp, yexp and zexp as needed */
9298  switch ( newact ) {
9299  case 1:
9300  xexp -= 1;
9301  if ( xexp < 0 ) {
9302  xexp = ( SYSIZEM1 );
9303  }
9304 
9305  break;
9306  case 2:
9307  xexp += 1;
9308  if ( xexp >= SYSIZE ) {
9309  xexp = 0;
9310  }
9311 
9312  break;
9313  case 3:
9314  yexp -= 1;
9315  if ( yexp < 0 ) {
9316  yexp = ( SYSIZEM1 );
9317  }
9318 
9319  break;
9320  case 4:
9321  yexp += 1;
9322  if ( yexp >= SYSIZE ) {
9323  yexp = 0;
9324  }
9325 
9326  break;
9327  case 5:
9328  zexp -= 1;
9329  if ( zexp < 0 ) {
9330  zexp = ( SYSIZEM1 );
9331  }
9332 
9333  break;
9334  case 6:
9335  zexp += 1;
9336  if ( zexp >= SYSIZE ) {
9337  zexp = 0;
9338  }
9339 
9340  break;
9341  default:
9342  break;
9343  }
9344  }
9345 
9346  /* probabilistic-based expansion for last ettringite pixel */
9347  pexp = ran1(seed);
9348  if ( pexp <= 0.6053 ) {
9349  newact = extettr(xexp, yexp, zexp, ettrtype);
9350  }
9351  }
9352 
9353  /* if new location is C4AF execute conversion */
9354  /* to ettringite (including necessary volumetric expansion) */
9355  if ( ( check == C4AF ) && ( p2diff < SOLIDC4AFGYP ) ) {
9356  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9357  count [ ETTRC4AF ] += 1;
9358  count [ DIFFHEM ] -= 1;
9359 
9360  /* determine if C4AF should be converted to ettringite */
9361  /* 1 unit of gypsum requires 0.802 units of C4AF */
9362  /* and should form 4.6053 units of ettringite */
9363  pexp = ran1(seed);
9364  nexp = 3;
9365  if ( pexp <= 0.802 ) {
9366  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9367  count [ ETTRC4AF ] += 1;
9368  count [ C4AF ] -= 1;
9369  nexp = 2;
9370  pext = ran1(seed);
9371  /* Addition of extra CH */
9372  if ( pext < 0.2584 ) {
9373  extch();
9374  }
9375 
9376  pext = ran1(seed);
9377  /* Addition of extra FH3 */
9378  if ( pext < 0.5453 ) {
9379  extfh3(xnew, ynew, znew);
9380  }
9381  } else {
9382  /* maybe someday, use a new FIXEDC4AF here */
9383  /* so it won't dissolve later */
9384  mic [ xnew ] [ ynew ] [ znew ] = C4AF;
9385  nexp = 3;
9386  }
9387 
9388  /* create extra ettringite pixels to maintain volume stoichiometry */
9389  /* xexp, yexp and zexp hold coordinates of most recently added ettringite */
9390  /* species as we attempt to grow a needle like structure */
9391  xexp = xcur;
9392  yexp = ycur;
9393  zexp = zcur;
9394  for ( iexp = 1; iexp <= nexp; iexp++ ) {
9395  newact = extettr(xexp, yexp, zexp, 1);
9396  /* update xexp, yexp and zexp as needed */
9397  switch ( newact ) {
9398  case 1:
9399  xexp -= 1;
9400  if ( xexp < 0 ) {
9401  xexp = ( SYSIZEM1 );
9402  }
9403 
9404  break;
9405  case 2:
9406  xexp += 1;
9407  if ( xexp >= SYSIZE ) {
9408  xexp = 0;
9409  }
9410 
9411  break;
9412  case 3:
9413  yexp -= 1;
9414  if ( yexp < 0 ) {
9415  yexp = ( SYSIZEM1 );
9416  }
9417 
9418  break;
9419  case 4:
9420  yexp += 1;
9421  if ( yexp >= SYSIZE ) {
9422  yexp = 0;
9423  }
9424 
9425  break;
9426  case 5:
9427  zexp -= 1;
9428  if ( zexp < 0 ) {
9429  zexp = ( SYSIZEM1 );
9430  }
9431 
9432  break;
9433  case 6:
9434  zexp += 1;
9435  if ( zexp >= SYSIZE ) {
9436  zexp = 0;
9437  }
9438 
9439  break;
9440  default:
9441  break;
9442  }
9443  }
9444 
9445  /* probabilistic-based expansion for last ettringite pixel */
9446  pexp = ran1(seed);
9447  if ( pexp <= 0.6053 ) {
9448  newact = extettr(xexp, yexp, zexp, 1);
9449  }
9450 
9451  action = 0;
9452  }
9453  }
9454 
9455  if ( action != 0 ) {
9456  /* if diffusion step is possible, perform it */
9457  if ( check == POROSITY ) {
9458  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
9459  mic [ xnew ] [ ynew ] [ znew ] = DIFFHEM;
9460  } else {
9461  /* indicate that diffusing HEMIHYDRATE species */
9462  /* remained at original location */
9463  action = 7;
9464  }
9465  }
9466 
9467  return ( action );
9468 
9469  ( void ) sumback;
9470 }
9471 
9472 /* routine to add extra Freidel's salt when CaCl2 reacts with */
9473 /* C3A or C4AF at location (xpres,ypres,zpres) */
9474 /* Called by movecacl2 and movec3a */
9475 /* Calls moveone and edgecnt */
9476 int CemhydMatStatus :: extfreidel(int xpres, int ypres, int zpres)
9477 {
9478  int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
9479  long int tries;
9480 
9481  /* first try 6 neighboring locations until */
9482  /* a) successful */
9483  /* b) all 6 sites are tried and full or */
9484  /* c) 500 tries are made */
9485  fchr = 0;
9486  sump = 1;
9487  for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
9488  /* choose a neighbor at random */
9489  xchr = xpres;
9490  ychr = ypres;
9491  zchr = zpres;
9492  newact = 0;
9493  multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
9494  if ( newact == 0 ) {
9495  printf("Error in value of newact in extfreidel \n");
9496  }
9497 
9498  check = mic [ xchr ] [ ychr ] [ zchr ];
9499 
9500  /* if neighbor is porosity */
9501  /* then locate the freidel's salt there */
9502  if ( check == POROSITY ) {
9503  mic [ xchr ] [ ychr ] [ zchr ] = FREIDEL;
9504  count [ FREIDEL ] += 1;
9505  count [ POROSITY ] -= 1;
9506  fchr = 1;
9507  } else {
9508  sump *= multf;
9509  }
9510  }
9511 
9512  /* if no neighbor available, locate FREIDEL at random location */
9513  /* in pore space in contact with at least one FREIDEL */
9514  tries = 0;
9515  while ( fchr == 0 ) {
9516  tries += 1;
9517  newact = 7;
9518  /* generate a random location in the 3-D system */
9519  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9520  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9521  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9522  if ( xchr >= SYSIZE ) {
9523  xchr = 0;
9524  }
9525 
9526  if ( ychr >= SYSIZE ) {
9527  ychr = 0;
9528  }
9529 
9530  if ( zchr >= SYSIZE ) {
9531  zchr = 0;
9532  }
9533 
9534  check = mic [ xchr ] [ ychr ] [ zchr ];
9535  /* if location is porosity, locate the FREIDEL there */
9536  if ( check == POROSITY ) {
9537  numnear = edgecnt(xchr, ychr, zchr, FREIDEL, FREIDEL, DIFFCACL2);
9538  /* be sure that at least one neighboring pixel */
9539  /* is FREIDEL or diffusing CACL2 */
9540  if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
9541  mic [ xchr ] [ ychr ] [ zchr ] = FREIDEL;
9542  count [ FREIDEL ] += 1;
9543  count [ POROSITY ] -= 1;
9544  fchr = 1;
9545  }
9546  }
9547  }
9548 
9549  return ( newact );
9550 }
9551 
9552 /* routine to add extra stratlingite when AS reacts with */
9553 /* CH at location (xpres,ypres,zpres) */
9554 /* or when diffusing CAS2 reacts with aluminates */
9555 /* Called by moveas, movech, and movecas2 */
9556 /* Calls moveone and edgecnt */
9557 int CemhydMatStatus :: extstrat(int xpres, int ypres, int zpres)
9558 {
9559  int multf, numnear, sump, xchr, ychr, zchr, check, fchr, i1, newact;
9560  long int tries;
9561 
9562  /* first try 6 neighboring locations until */
9563  /* a) successful */
9564  /* b) all 6 sites are tried and full or */
9565  /* c) 500 tries are made */
9566  fchr = 0;
9567  sump = 1;
9568  for ( i1 = 1; ( ( i1 <= 500 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
9569  /* choose a neighbor at random */
9570  xchr = xpres;
9571  ychr = ypres;
9572  zchr = zpres;
9573  newact = 0;
9574  multf = moveone(& xchr, & ychr, & zchr, & newact, sump);
9575  if ( newact == 0 ) {
9576  printf("Error in value of newact in extstrat \n");
9577  }
9578 
9579  check = mic [ xchr ] [ ychr ] [ zchr ];
9580 
9581  /* if neighbor is porosity */
9582  /* then locate the stratlingite there */
9583  if ( check == POROSITY ) {
9584  mic [ xchr ] [ ychr ] [ zchr ] = STRAT;
9585  count [ STRAT ] += 1;
9586  count [ POROSITY ] -= 1;
9587  fchr = 1;
9588  } else {
9589  sump *= multf;
9590  }
9591  }
9592 
9593  /* if no neighbor available, locate STRAT at random location */
9594  /* in pore space in contact with at least one STRAT */
9595  tries = 0;
9596  while ( fchr == 0 ) {
9597  tries += 1;
9598  newact = 7;
9599  /* generate a random location in the 3-D system */
9600  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9601  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9602  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
9603  if ( xchr >= SYSIZE ) {
9604  xchr = 0;
9605  }
9606 
9607  if ( ychr >= SYSIZE ) {
9608  ychr = 0;
9609  }
9610 
9611  if ( zchr >= SYSIZE ) {
9612  zchr = 0;
9613  }
9614 
9615  check = mic [ xchr ] [ ychr ] [ zchr ];
9616  /* if location is porosity, locate the STRAT there */
9617  if ( check == POROSITY ) {
9618  numnear = edgecnt(xchr, ychr, zchr, STRAT, DIFFCAS2, DIFFAS);
9619  /* be sure that at least one neighboring pixel */
9620  /* is STRAT, diffusing CAS2, or diffusing AS */
9621  if ( ( numnear < 26 ) || ( tries > 5000 ) ) {
9622  mic [ xchr ] [ ychr ] [ zchr ] = STRAT;
9623  count [ STRAT ] += 1;
9624  count [ POROSITY ] -= 1;
9625  fchr = 1;
9626  }
9627  }
9628  }
9629 
9630  return ( newact );
9631 }
9632 
9633 /* routine to move a diffusing gypsum species */
9634 /* from current location (xcur,ycur,zcur) */
9635 /* Returns action flag indicating response taken */
9636 /* Called by hydrate */
9637 /* Calls moveone, extettr, extch, and extfh3 */
9638 int CemhydMatStatus :: movegyp(int xcur, int ycur, int zcur, int finalstep)
9639 {
9640  int check, xnew, ynew, znew, action, nexp, iexp;
9641  int xexp, yexp, zexp, newact, sumold, sumgarb, ettrtype;
9642  float pexp, pext, p2diff;
9643 
9644  sumold = 1;
9645 
9646  /* First be sure that a diffusing gypsum species is located at xcur,ycur,zcur */
9647  /* if not, return to calling routine */
9648  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFGYP ) {
9649  action = 0;
9650  return ( action );
9651  }
9652 
9653  /* Determine new coordinates (periodic boundaries are used) */
9654  xnew = xcur;
9655  ynew = ycur;
9656  znew = zcur;
9657  action = 0;
9658  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
9659  if ( action == 0 ) {
9660  printf("Error in value of action in movegyp \n");
9661  }
9662 
9663  check = mic [ xnew ] [ ynew ] [ znew ];
9664  p2diff = ran1(seed);
9665  /* if new location is CSH, check for absorption of gypsum */
9666  if ( ( check == CSH ) && ( ( float ) count [ ABSGYP ] < ( gypabsprob * ( float ) count [ CSH ] ) ) ) {
9667  pexp = ran1(seed);
9668  if ( pexp < AGRATE ) {
9669  /* update counts for absorbed and diffusing gypsum */
9670  count [ ABSGYP ] += 1;
9671  count [ DIFFGYP ] -= 1;
9672  mic [ xcur ] [ ycur ] [ zcur ] = ABSGYP;
9673  action = 0;
9674  }
9675  }
9676  /* if new location is C3A or diffusing C3A, execute conversion */
9677  /* to ettringite (including necessary volumetric expansion) */
9678  /* Use p2diff to try to favor formation of ettringite on */
9679  /* aluminate surfaces as opposed to in solution */
9680  else if ( ( ( check == C3A ) && ( p2diff < SOLIDC3AGYP ) ) || ( ( check == DIFFC3A ) && ( p2diff < C3AGYP ) ) || ( ( check == DIFFC4A ) && ( p2diff < C3AGYP ) ) ) {
9681  /* Convert diffusing gypsum to an ettringite pixel */
9682  ettrtype = 0;
9683  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
9684  if ( check == DIFFC4A ) {
9685  ettrtype = 1;
9686  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9687  }
9688 
9689  action = 0;
9690  count [ DIFFGYP ] -= 1;
9691  count [ check ] -= 1;
9692 
9693  /* determine if C3A should be converted to ettringite */
9694  /* 1 unit of gypsum requires 0.40 units of C3A */
9695  /* and should form 3.30 units of ettringite */
9696  pexp = ran1(seed);
9697  nexp = 2;
9698  if ( pexp <= 0.40 ) {
9699  if ( ettrtype == 0 ) {
9700  mic [ xnew ] [ ynew ] [ znew ] = ETTR;
9701  count [ ETTR ] += 1;
9702  } else {
9703  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9704  count [ ETTRC4AF ] += 1;
9705  }
9706 
9707  nexp = 1;
9708  } else {
9709  /* maybe someday, use a new FIXEDC3A here */
9710  /* so it won't dissolve later */
9711  if ( check == C3A ) {
9712  mic [ xnew ] [ ynew ] [ znew ] = C3A;
9713  count [ C3A ] += 1;
9714  } else {
9715  if ( ettrtype == 0 ) {
9716  count [ DIFFC3A ] += 1;
9717  mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
9718  } else {
9719  count [ DIFFC4A ] += 1;
9720  mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
9721  }
9722  }
9723 
9724  nexp = 2;
9725  }
9726 
9727  /* create extra ettringite pixels to maintain volume stoichiometry */
9728  /* xexp, yexp, and zexp hold coordinates of most recently added ettringite */
9729  /* species as we attempt to grow a needle like structure */
9730  xexp = xcur;
9731  yexp = ycur;
9732  zexp = zcur;
9733  for ( iexp = 1; iexp <= nexp; iexp++ ) {
9734  newact = extettr(xexp, yexp, zexp, ettrtype);
9735  /* update xexp, yexp and zexp as needed */
9736  switch ( newact ) {
9737  case 1:
9738  xexp -= 1;
9739  if ( xexp < 0 ) {
9740  xexp = ( SYSIZEM1 );
9741  }
9742 
9743  break;
9744  case 2:
9745  xexp += 1;
9746  if ( xexp >= SYSIZE ) {
9747  xexp = 0;
9748  }
9749 
9750  break;
9751  case 3:
9752  yexp -= 1;
9753  if ( yexp < 0 ) {
9754  yexp = ( SYSIZEM1 );
9755  }
9756 
9757  break;
9758  case 4:
9759  yexp += 1;
9760  if ( yexp >= SYSIZE ) {
9761  yexp = 0;
9762  }
9763 
9764  break;
9765  case 5:
9766  zexp -= 1;
9767  if ( zexp < 0 ) {
9768  zexp = ( SYSIZEM1 );
9769  }
9770 
9771  break;
9772  case 6:
9773  zexp += 1;
9774  if ( zexp >= SYSIZE ) {
9775  zexp = 0;
9776  }
9777 
9778  break;
9779  default:
9780  break;
9781  }
9782  }
9783 
9784  /* probabilistic-based expansion for last ettringite pixel */
9785  pexp = ran1(seed);
9786  if ( pexp <= 0.30 ) {
9787  newact = extettr(xexp, yexp, zexp, ettrtype);
9788  }
9789  }
9790 
9791  /* if new location is C4AF execute conversion */
9792  /* to ettringite (including necessary volumetric expansion) */
9793  if ( ( check == C4AF ) && ( p2diff < SOLIDC4AFGYP ) ) {
9794  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
9795  count [ ETTRC4AF ] += 1;
9796  count [ DIFFGYP ] -= 1;
9797 
9798  /* determine if C4AF should be converted to ettringite */
9799  /* 1 unit of gypsum requires 0.575 units of C4AF */
9800  /* and should form 3.30 units of ettringite */
9801  pexp = ran1(seed);
9802  nexp = 2;
9803  if ( pexp <= 0.575 ) {
9804  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
9805  count [ ETTRC4AF ] += 1;
9806  count [ C4AF ] -= 1;
9807  nexp = 1;
9808  pext = ran1(seed);
9809  /* Addition of extra CH */
9810  if ( pext < 0.2584 ) {
9811  extch();
9812  }
9813 
9814  pext = ran1(seed);
9815  /* Addition of extra FH3 */
9816  if ( pext < 0.5453 ) {
9817  extfh3(xnew, ynew, znew);
9818  }
9819  } else {
9820  /* maybe someday, use a new FIXEDC4AF here */
9821  /* so it won't dissolve later */
9822  mic [ xnew ] [ ynew ] [ znew ] = C4AF;
9823  nexp = 2;
9824  }
9825 
9826  /* create extra ettringite pixels to maintain volume stoichiometry */
9827  /* xexp, yexp and zexp hold coordinates of most recently added ettringite */
9828  /* species as we attempt to grow a needle like structure */
9829  xexp = xcur;
9830  yexp = ycur;
9831  zexp = zcur;
9832  for ( iexp = 1; iexp <= nexp; iexp++ ) {
9833  newact = extettr(xexp, yexp, zexp, 1);
9834  /* update xexp, yexp and zexp as needed */
9835  switch ( newact ) {
9836  case 1:
9837  xexp -= 1;
9838  if ( xexp < 0 ) {
9839  xexp = ( SYSIZEM1 );
9840  }
9841 
9842  break;
9843  case 2:
9844  xexp += 1;
9845  if ( xexp >= SYSIZE ) {
9846  xexp = 0;
9847  }
9848 
9849  break;
9850  case 3:
9851  yexp -= 1;
9852  if ( yexp < 0 ) {
9853  yexp = ( SYSIZEM1 );
9854  }
9855 
9856  break;
9857  case 4:
9858  yexp += 1;
9859  if ( yexp >= SYSIZE ) {
9860  yexp = 0;
9861  }
9862 
9863  break;
9864  case 5:
9865  zexp -= 1;
9866  if ( zexp < 0 ) {
9867  zexp = ( SYSIZEM1 );
9868  }
9869 
9870  break;
9871  case 6:
9872  zexp += 1;
9873  if ( zexp >= SYSIZE ) {
9874  zexp = 0;
9875  }
9876 
9877  break;
9878  default:
9879  break;
9880  }
9881  }
9882 
9883  /* probabilistic-based expansion for last ettringite pixel */
9884  pexp = ran1(seed);
9885  if ( pexp <= 0.30 ) {
9886  newact = extettr(xexp, yexp, zexp, 1);
9887  }
9888 
9889  action = 0;
9890  }
9891 
9892  /* if last diffusion step and no reaction, convert back to */
9893  /* primary solid gypsum */
9894  if ( ( action != 0 ) && ( finalstep == 1 ) ) {
9895  action = 0;
9896  count [ DIFFGYP ] -= 1;
9897  count [ GYPSUM ] += 1;
9898  mic [ xcur ] [ ycur ] [ zcur ] = GYPSUM;
9899  }
9900 
9901  if ( action != 0 ) {
9902  /* if diffusion is possible, execute it */
9903  if ( check == POROSITY ) {
9904  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
9905  mic [ xnew ] [ ynew ] [ znew ] = DIFFGYP;
9906  } else {
9907  /* indicate that diffusing gypsum remained at */
9908  /* original location */
9909  action = 7;
9910  }
9911  }
9912 
9913  return ( action );
9914 
9915  ( void ) sumgarb;
9916 }
9917 
9918 /* routine to move a diffusing CaCl2 species */
9919 /* from current location (xcur,ycur,zcur) */
9920 /* Returns action flag indicating response taken */
9921 /* Called by hydrate */
9922 /* Calls moveone, extfreidel, extch, and extfh3 */
9923 int CemhydMatStatus :: movecacl2(int xcur, int ycur, int zcur, int finalstep)
9924 {
9925  int check, xnew, ynew, znew, action, nexp, iexp;
9926  int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
9927  float pexp, pext;
9928 
9929  sumold = 1;
9930  keep = 0;
9931 
9932  /* First be sure that a diffusing CaCl2 species is located at xcur,ycur,zcur */
9933  /* if not, return to calling routine */
9934  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFCACL2 ) {
9935  action = 0;
9936  return ( action );
9937  }
9938 
9939  /* Determine new coordinates (periodic boundaries are used) */
9940  xnew = xcur;
9941  ynew = ycur;
9942  znew = zcur;
9943  action = 0;
9944  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
9945  if ( action == 0 ) {
9946  printf("Error in value of action in movecacl2 \n");
9947  }
9948 
9949  check = mic [ xnew ] [ ynew ] [ znew ];
9950 
9951  /* if new location is C3A or diffusing C3A, execute conversion */
9952  /* to freidel's salt (including necessary volumetric expansion) */
9953  if ( ( check == C3A ) || ( check == DIFFC3A ) || ( check == DIFFC4A ) ) {
9954  /* Convert diffusing C3A or C3A to a freidel's salt pixel */
9955  action = 0;
9956  mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
9957  count [ FREIDEL ] += 1;
9958  count [ check ] -= 1;
9959 
9960  /* determine if diffusing CaCl2 should be converted to FREIDEL */
9961  /* 0.5793 unit of CaCl2 requires 1 unit of C3A */
9962  /* and should form 3.3295 units of FREIDEL */
9963  pexp = ran1(seed);
9964  nexp = 2;
9965  if ( pexp <= 0.5793 ) {
9966  mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
9967  count [ FREIDEL ] += 1;
9968  count [ DIFFCACL2 ] -= 1;
9969  nexp = 1;
9970  } else {
9971  keep = 1;
9972  nexp = 2;
9973  }
9974 
9975  /* create extra Freidel's salt pixels to maintain volume stoichiometry */
9976  /* xexp, yexp, and zexp hold coordinates of most recently added FREIDEL */
9977  xexp = xcur;
9978  yexp = ycur;
9979  zexp = zcur;
9980  for ( iexp = 1; iexp <= nexp; iexp++ ) {
9981  newact = extfreidel(xexp, yexp, zexp);
9982  /* update xexp, yexp and zexp as needed */
9983  switch ( newact ) {
9984  case 1:
9985  xexp -= 1;
9986  if ( xexp < 0 ) {
9987  xexp = ( SYSIZEM1 );
9988  }
9989 
9990  break;
9991  case 2:
9992  xexp += 1;
9993  if ( xexp >= SYSIZE ) {
9994  xexp = 0;
9995  }
9996 
9997  break;
9998  case 3:
9999  yexp -= 1;
10000  if ( yexp < 0 ) {
10001  yexp = ( SYSIZEM1 );
10002  }
10003 
10004  break;
10005  case 4:
10006  yexp += 1;
10007  if ( yexp >= SYSIZE ) {
10008  yexp = 0;
10009  }
10010 
10011  break;
10012  case 5:
10013  zexp -= 1;
10014  if ( zexp < 0 ) {
10015  zexp = ( SYSIZEM1 );
10016  }
10017 
10018  break;
10019  case 6:
10020  zexp += 1;
10021  if ( zexp >= SYSIZE ) {
10022  zexp = 0;
10023  }
10024 
10025  break;
10026  default:
10027  break;
10028  }
10029  }
10030 
10031  /* probabilistic-based expansion for last FREIDEL pixel */
10032  pexp = ran1(seed);
10033  if ( pexp <= 0.3295 ) {
10034  newact = extfreidel(xexp, yexp, zexp);
10035  }
10036  }
10037  /* if new location is C4AF execute conversion */
10038  /* to freidel's salt (including necessary volumetric expansion) */
10039  else if ( check == C4AF ) {
10040  mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
10041  count [ FREIDEL ] += 1;
10042  count [ C4AF ] -= 1;
10043 
10044  /* determine if CACL2 should be converted to FREIDEL */
10045  /* 0.4033 unit of CaCl2 requires 1 unit of C4AF */
10046  /* and should form 2.3176 units of FREIDEL */
10047  /* Also 0.6412 units of CH and 1.3522 units of FH3 */
10048  /* per unit of CACL2 */
10049  pexp = ran1(seed);
10050  nexp = 1;
10051  if ( pexp <= 0.4033 ) {
10052  mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
10053  count [ FREIDEL ] += 1;
10054  count [ DIFFCACL2 ] -= 1;
10055  nexp = 0;
10056  pext = ran1(seed);
10057  /* Addition of extra CH */
10058  if ( pext < 0.6412 ) {
10059  extch();
10060  }
10061 
10062  pext = ran1(seed);
10063  /* Addition of extra FH3 */
10064  if ( pext < 0.3522 ) {
10065  extfh3(xnew, ynew, znew);
10066  }
10067 
10068  extfh3(xnew, ynew, znew);
10069  } else {
10070  nexp = 1;
10071  keep = 1;
10072  }
10073 
10074  /* create extra freidel's salt pixels to maintain volume stoichiometry */
10075  /* xexp, yexp and zexp hold coordinates of most recently added FREIDEL */
10076  xexp = xcur;
10077  yexp = ycur;
10078  zexp = zcur;
10079  for ( iexp = 1; iexp <= nexp; iexp++ ) {
10080  newact = extfreidel(xexp, yexp, zexp);
10081  /* update xexp, yexp and zexp as needed */
10082  switch ( newact ) {
10083  case 1:
10084  xexp -= 1;
10085  if ( xexp < 0 ) {
10086  xexp = ( SYSIZEM1 );
10087  }
10088 
10089  break;
10090  case 2:
10091  xexp += 1;
10092  if ( xexp >= SYSIZE ) {
10093  xexp = 0;
10094  }
10095 
10096  break;
10097  case 3:
10098  yexp -= 1;
10099  if ( yexp < 0 ) {
10100  yexp = ( SYSIZEM1 );
10101  }
10102 
10103  break;
10104  case 4:
10105  yexp += 1;
10106  if ( yexp >= SYSIZE ) {
10107  yexp = 0;
10108  }
10109 
10110  break;
10111  case 5:
10112  zexp -= 1;
10113  if ( zexp < 0 ) {
10114  zexp = ( SYSIZEM1 );
10115  }
10116 
10117  break;
10118  case 6:
10119  zexp += 1;
10120  if ( zexp >= SYSIZE ) {
10121  zexp = 0;
10122  }
10123 
10124  break;
10125  default:
10126  break;
10127  }
10128  }
10129 
10130  /* probabilistic-based expansion for last FREIDEL pixel */
10131  pexp = ran1(seed);
10132  if ( pexp <= 0.3176 ) {
10133  newact = extfreidel(xexp, yexp, zexp);
10134  }
10135 
10136  action = 0;
10137  }
10138 
10139  /* if last diffusion step and no reaction, convert back to */
10140  /* solid CaCl2 */
10141  if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10142  action = 0;
10143  count [ DIFFCACL2 ] -= 1;
10144  count [ CACL2 ] += 1;
10145  mic [ xcur ] [ ycur ] [ zcur ] = CACL2;
10146  }
10147 
10148  if ( action != 0 ) {
10149  /* if diffusion is possible, execute it */
10150  if ( check == POROSITY ) {
10151  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10152  mic [ xnew ] [ ynew ] [ znew ] = DIFFCACL2;
10153  } else {
10154  /* indicate that diffusing CACL2 remained at */
10155  /* original location */
10156  action = 7;
10157  }
10158  }
10159 
10160  if ( keep == 1 ) {
10161  action = 7;
10162  }
10163 
10164  return ( action );
10165 
10166  ( void ) sumgarb;
10167 }
10168 
10169 /* routine to move a diffusing CAS2 species */
10170 /* from current location (xcur,ycur,zcur) */
10171 /* Returns action flag indicating response taken */
10172 /* Called by hydrate */
10173 /* Calls moveone, extstrat, extch, and extfh3 */
10174 int CemhydMatStatus :: movecas2(int xcur, int ycur, int zcur, int finalstep)
10175 {
10176  int check, xnew, ynew, znew, action, nexp, iexp;
10177  int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
10178  float pexp, pext;
10179 
10180  sumold = 1;
10181  keep = 0;
10182 
10183  /* First be sure that a diffusing CAS2 species is located at xcur,ycur,zcur */
10184  /* if not, return to calling routine */
10185  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFCAS2 ) {
10186  action = 0;
10187  return ( action );
10188  }
10189 
10190  /* Determine new coordinates (periodic boundaries are used) */
10191  xnew = xcur;
10192  ynew = ycur;
10193  znew = zcur;
10194  action = 0;
10195  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10196  if ( action == 0 ) {
10197  printf("Error in value of action in movecas2 \n");
10198  }
10199 
10200  check = mic [ xnew ] [ ynew ] [ znew ];
10201 
10202  /* if new location is C3A or diffusing C3A, execute conversion */
10203  /* to stratlingite (including necessary volumetric expansion) */
10204  if ( ( check == C3A ) || ( check == DIFFC3A ) || ( check == DIFFC4A ) ) {
10205  /* Convert diffusing CAS2 to a stratlingite pixel */
10206  action = 0;
10207  mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
10208  count [ STRAT ] += 1;
10209  count [ DIFFCAS2 ] -= 1;
10210 
10211  /* determine if diffusing or solid C3A should be converted to STRAT*/
10212  /* 1 unit of CAS2 requires 0.886 units of C3A */
10213  /* and should form 4.286 units of STRAT */
10214  pexp = ran1(seed);
10215  nexp = 3;
10216  if ( pexp <= 0.886 ) {
10217  mic [ xnew ] [ ynew ] [ znew ] = STRAT;
10218  count [ STRAT ] += 1;
10219  count [ check ] -= 1;
10220  nexp = 2;
10221  }
10222 
10223  /* create extra stratlingite pixels to maintain volume stoichiometry */
10224  /* xexp, yexp, and zexp hold coordinates of most recently added STRAT */
10225  xexp = xcur;
10226  yexp = ycur;
10227  zexp = zcur;
10228  for ( iexp = 1; iexp <= nexp; iexp++ ) {
10229  newact = extstrat(xexp, yexp, zexp);
10230  /* update xexp, yexp and zexp as needed */
10231  switch ( newact ) {
10232  case 1:
10233  xexp -= 1;
10234  if ( xexp < 0 ) {
10235  xexp = ( SYSIZEM1 );
10236  }
10237 
10238  break;
10239  case 2:
10240  xexp += 1;
10241  if ( xexp >= SYSIZE ) {
10242  xexp = 0;
10243  }
10244 
10245  break;
10246  case 3:
10247  yexp -= 1;
10248  if ( yexp < 0 ) {
10249  yexp = ( SYSIZEM1 );
10250  }
10251 
10252  break;
10253  case 4:
10254  yexp += 1;
10255  if ( yexp >= SYSIZE ) {
10256  yexp = 0;
10257  }
10258 
10259  break;
10260  case 5:
10261  zexp -= 1;
10262  if ( zexp < 0 ) {
10263  zexp = ( SYSIZEM1 );
10264  }
10265 
10266  break;
10267  case 6:
10268  zexp += 1;
10269  if ( zexp >= SYSIZE ) {
10270  zexp = 0;
10271  }
10272 
10273  break;
10274  default:
10275  break;
10276  }
10277  }
10278 
10279  /* probabilistic-based expansion for last STRAT pixel */
10280  pexp = ran1(seed);
10281  if ( pexp <= 0.286 ) {
10282  newact = extstrat(xexp, yexp, zexp);
10283  }
10284  }
10285  /* if new location is C4AF execute conversion */
10286  /* to stratlingite (including necessary volumetric expansion) */
10287  else if ( check == C4AF ) {
10288  mic [ xnew ] [ ynew ] [ znew ] = STRAT;
10289  count [ STRAT ] += 1;
10290  count [ C4AF ] -= 1;
10291 
10292  /* determine if CAS2 should be converted to STRAT */
10293  /* 0.786 units of CAS2 requires 1 unit of C4AF */
10294  /* and should form 3.37 units of STRAT */
10295  /* Also 0.2586 units of CH and 0.5453 units of FH3 */
10296  /* per unit of C4AF */
10297  pexp = ran1(seed);
10298  nexp = 2;
10299  if ( pexp <= 0.786 ) {
10300  mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
10301  count [ STRAT ] += 1;
10302  count [ DIFFCAS2 ] -= 1;
10303  nexp = 1;
10304  pext = ran1(seed);
10305  /* Addition of extra CH */
10306  /* 0.329= 0.2586/0.786 */
10307  if ( pext < 0.329 ) {
10308  extch();
10309  }
10310 
10311  pext = ran1(seed);
10312  /* Addition of extra FH3 */
10313  /* 0.6938= 0.5453/0.786 */
10314  if ( pext < 0.6938 ) {
10315  extfh3(xnew, ynew, znew);
10316  }
10317  } else {
10318  nexp = 2;
10319  keep = 1;
10320  }
10321 
10322  /* create extra stratlingite pixels to maintain volume stoichiometry */
10323  /* xexp, yexp and zexp hold coordinates of most recently added STRAT */
10324  xexp = xcur;
10325  yexp = ycur;
10326  zexp = zcur;
10327  for ( iexp = 1; iexp <= nexp; iexp++ ) {
10328  newact = extstrat(xexp, yexp, zexp);
10329  /* update xexp, yexp and zexp as needed */
10330  switch ( newact ) {
10331  case 1:
10332  xexp -= 1;
10333  if ( xexp < 0 ) {
10334  xexp = ( SYSIZEM1 );
10335  }
10336 
10337  break;
10338  case 2:
10339  xexp += 1;
10340  if ( xexp >= SYSIZE ) {
10341  xexp = 0;
10342  }
10343 
10344  break;
10345  case 3:
10346  yexp -= 1;
10347  if ( yexp < 0 ) {
10348  yexp = ( SYSIZEM1 );
10349  }
10350 
10351  break;
10352  case 4:
10353  yexp += 1;
10354  if ( yexp >= SYSIZE ) {
10355  yexp = 0;
10356  }
10357 
10358  break;
10359  case 5:
10360  zexp -= 1;
10361  if ( zexp < 0 ) {
10362  zexp = ( SYSIZEM1 );
10363  }
10364 
10365  break;
10366  case 6:
10367  zexp += 1;
10368  if ( zexp >= SYSIZE ) {
10369  zexp = 0;
10370  }
10371 
10372  break;
10373  default:
10374  break;
10375  }
10376  }
10377 
10378  /* probabilistic-based expansion for last STRAT pixel */
10379  pexp = ran1(seed);
10380  if ( pexp <= 0.37 ) {
10381  newact = extstrat(xexp, yexp, zexp);
10382  }
10383 
10384  action = 0;
10385  }
10386 
10387  /* if last diffusion step and no reaction, convert back to */
10388  /* solid CAS2 */
10389  if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10390  action = 0;
10391  count [ DIFFCAS2 ] -= 1;
10392  count [ CAS2 ] += 1;
10393  mic [ xcur ] [ ycur ] [ zcur ] = CAS2;
10394  }
10395 
10396  if ( action != 0 ) {
10397  /* if diffusion is possible, execute it */
10398  if ( check == POROSITY ) {
10399  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10400  mic [ xnew ] [ ynew ] [ znew ] = DIFFCAS2;
10401  } else {
10402  /* indicate that diffusing CAS2 remained at */
10403  /* original location */
10404  action = 7;
10405  }
10406  }
10407 
10408  if ( keep == 1 ) {
10409  action = 7;
10410  }
10411 
10412  return ( action );
10413 
10414  ( void ) sumgarb;
10415 }
10416 
10417 /* routine to move a diffusing AS species */
10418 /* from current location (xcur,ycur,zcur) */
10419 /* Returns action flag indicating response taken */
10420 /* Called by hydrate */
10421 /* Calls moveone, extstrat */
10422 int CemhydMatStatus :: moveas(int xcur, int ycur, int zcur, int finalstep)
10423 {
10424  int check, xnew, ynew, znew, action, nexp, iexp;
10425  int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
10426  float pexp;
10427 
10428  sumold = 1;
10429  keep = 0;
10430 
10431  /* First be sure that a diffusing AS species is located at xcur,ycur,zcur */
10432  /* if not, return to calling routine */
10433  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFAS ) {
10434  action = 0;
10435  return ( action );
10436  }
10437 
10438  /* Determine new coordinates (periodic boundaries are used) */
10439  xnew = xcur;
10440  ynew = ycur;
10441  znew = zcur;
10442  action = 0;
10443  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10444  if ( action == 0 ) {
10445  printf("Error in value of action in moveas \n");
10446  }
10447 
10448  check = mic [ xnew ] [ ynew ] [ znew ];
10449 
10450  /* if new location is CH or diffusing CH, execute conversion */
10451  /* to stratlingite (including necessary volumetric expansion) */
10452  if ( ( check == CH ) || ( check == DIFFCH ) ) {
10453  /* Convert diffusing CH or CH to a stratlingite pixel */
10454  action = 0;
10455  mic [ xnew ] [ ynew ] [ znew ] = STRAT;
10456  count [ STRAT ] += 1;
10457  count [ check ] -= 1;
10458 
10459  /* determine if diffusing AS should be converted to STRAT */
10460  /* 0.7538 unit of AS requires 1 unit of CH */
10461  /* and should form 3.26 units of STRAT */
10462  pexp = ran1(seed);
10463  nexp = 2;
10464  if ( pexp <= 0.7538 ) {
10465  mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
10466  count [ STRAT ] += 1;
10467  count [ DIFFAS ] -= 1;
10468  nexp = 1;
10469  } else {
10470  keep = 1;
10471  nexp = 2;
10472  }
10473 
10474  /* create extra stratlingite pixels to maintain volume stoichiometry */
10475  /* xexp, yexp, and zexp hold coordinates of most recently added STRAT */
10476  xexp = xcur;
10477  yexp = ycur;
10478  zexp = zcur;
10479  for ( iexp = 1; iexp <= nexp; iexp++ ) {
10480  newact = extstrat(xexp, yexp, zexp);
10481  /* update xexp, yexp and zexp as needed */
10482  switch ( newact ) {
10483  case 1:
10484  xexp -= 1;
10485  if ( xexp < 0 ) {
10486  xexp = ( SYSIZEM1 );
10487  }
10488 
10489  break;
10490  case 2:
10491  xexp += 1;
10492  if ( xexp >= SYSIZE ) {
10493  xexp = 0;
10494  }
10495 
10496  break;
10497  case 3:
10498  yexp -= 1;
10499  if ( yexp < 0 ) {
10500  yexp = ( SYSIZEM1 );
10501  }
10502 
10503  break;
10504  case 4:
10505  yexp += 1;
10506  if ( yexp >= SYSIZE ) {
10507  yexp = 0;
10508  }
10509 
10510  break;
10511  case 5:
10512  zexp -= 1;
10513  if ( zexp < 0 ) {
10514  zexp = ( SYSIZEM1 );
10515  }
10516 
10517  break;
10518  case 6:
10519  zexp += 1;
10520  if ( zexp >= SYSIZE ) {
10521  zexp = 0;
10522  }
10523 
10524  break;
10525  default:
10526  break;
10527  }
10528  }
10529 
10530  /* probabilistic-based expansion for last stratlingite pixel */
10531  pexp = ran1(seed);
10532  if ( pexp <= 0.326 ) {
10533  newact = extstrat(xexp, yexp, zexp);
10534  }
10535  }
10536 
10537  /* if last diffusion step and no reaction, convert back to */
10538  /* solid ASG */
10539  if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10540  action = 0;
10541  count [ DIFFAS ] -= 1;
10542  count [ ASG ] += 1;
10543  mic [ xcur ] [ ycur ] [ zcur ] = ASG;
10544  }
10545 
10546  if ( action != 0 ) {
10547  /* if diffusion is possible, execute it */
10548  if ( check == POROSITY ) {
10549  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10550  mic [ xnew ] [ ynew ] [ znew ] = DIFFAS;
10551  } else {
10552  /* indicate that diffusing AS remained at */
10553  /* original location */
10554  action = 7;
10555  }
10556  }
10557 
10558  if ( keep == 1 ) {
10559  action = 7;
10560  }
10561 
10562  return ( action );
10563 
10564  ( void ) sumgarb;
10565 }
10566 
10567 /* routine to move a diffusing CACO3 species */
10568 /* from current location (xcur,ycur,zcur) */
10569 /* Returns action flag indicating response taken */
10570 /* Called by hydrate */
10571 /* Calls moveone, extettr */
10572 int CemhydMatStatus :: movecaco3(int xcur, int ycur, int zcur, int finalstep)
10573 {
10574  int check, xnew, ynew, znew, action;
10575  int xexp, yexp, zexp, newact, sumold, sumgarb, keep;
10576  float pexp;
10577 
10578  sumold = 1;
10579  keep = 0;
10580 
10581  /* First be sure that a diffusing CACO3 species is located at xcur,ycur,zcur */
10582  /* if not, return to calling routine */
10583  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFCACO3 ) {
10584  action = 0;
10585  return ( action );
10586  }
10587 
10588  /* Determine new coordinates (periodic boundaries are used) */
10589  xnew = xcur;
10590  ynew = ycur;
10591  znew = zcur;
10592  action = 0;
10593  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10594  if ( action == 0 ) {
10595  printf("Error in value of action in moveas \n");
10596  }
10597 
10598  check = mic [ xnew ] [ ynew ] [ znew ];
10599 
10600  /* if new location is AFM execute conversion */
10601  /* to carboaluminate and ettringite (including necessary */
10602  /* volumetric expansion) */
10603  if ( check == AFM ) {
10604  /* Convert AFM to a carboaluminate or ettringite pixel */
10605  action = 0;
10606  pexp = ran1(seed);
10607  if ( pexp <= 0.479192 ) {
10608  mic [ xnew ] [ ynew ] [ znew ] = AFMC;
10609  count [ AFMC ] += 1;
10610  } else {
10611  mic [ xnew ] [ ynew ] [ znew ] = ETTR;
10612  count [ ETTR ] += 1;
10613  }
10614 
10615  count [ check ] -= 1;
10616 
10617  /* determine if diffusing CACO3 should be converted to AFMC */
10618  /* 0.078658 unit of AS requires 1 unit of AFM */
10619  /* and should form 0.55785 units of AFMC */
10620  pexp = ran1(seed);
10621  if ( pexp <= 0.078658 ) {
10622  mic [ xcur ] [ ycur ] [ zcur ] = AFMC;
10623  count [ AFMC ] += 1;
10624  count [ DIFFCACO3 ] -= 1;
10625  } else {
10626  keep = 1;
10627  }
10628 
10629  /* create extra ettringite pixels to maintain volume stoichiometry */
10630  /* xexp, yexp, and zexp hold coordinates of most recently added ETTR */
10631  xexp = xnew;
10632  yexp = ynew;
10633  zexp = znew;
10634 
10635  /* probabilistic-based expansion for new ettringite pixel */
10636  pexp = ran1(seed);
10637  if ( pexp <= 0.26194 ) {
10638  newact = extettr(xexp, yexp, zexp, 0);
10639  }
10640  }
10641 
10642  /* if last diffusion step and no reaction, convert back to */
10643  /* solid CACO3 */
10644  if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10645  action = 0;
10646  count [ DIFFCACO3 ] -= 1;
10647  count [ CACO3 ] += 1;
10648  mic [ xcur ] [ ycur ] [ zcur ] = CACO3;
10649  }
10650 
10651  if ( action != 0 ) {
10652  /* if diffusion is possible, execute it */
10653  if ( check == POROSITY ) {
10654  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10655  mic [ xnew ] [ ynew ] [ znew ] = DIFFCACO3;
10656  } else {
10657  /* indicate that diffusing CACO3 remained at */
10658  /* original location */
10659  action = 7;
10660  }
10661  }
10662 
10663  if ( keep == 1 ) {
10664  action = 7;
10665  }
10666 
10667  return ( action );
10668 
10669  ( void ) newact;
10670  ( void ) sumgarb;
10671 }
10672 
10673 /* routine to add extra AFm phase when diffusing ettringite reacts */
10674 /* with C3A (diffusing or solid) at location (xpres,ypres,zpres) */
10675 /* Called by moveettr and movec3a */
10676 /* Calls moveone and edgecnt */
10677 void CemhydMatStatus :: extafm(int xpres, int ypres, int zpres)
10678 {
10679  int check, sump, xchr, ychr, zchr, fchr, i1, newact, numnear;
10680  long int tries;
10681 
10682  /* first try 6 neighboring locations until */
10683  /* a) successful */
10684  /* b) all 6 sites are tried or */
10685  /* c) 100 tries are made */
10686  fchr = 0;
10687  sump = 1;
10688  for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
10689  /* determine location of neighbor (using periodic boundaries) */
10690  xchr = xpres;
10691  ychr = ypres;
10692  zchr = zpres;
10693  newact = 0;
10694  sump *= moveone(& xchr, & ychr, & zchr, & newact, sump);
10695  if ( newact == 0 ) {
10696  printf("Error in value of newact in extafm \n");
10697  }
10698 
10699  check = mic [ xchr ] [ ychr ] [ zchr ];
10700 
10701  /* if neighbor is porosity, locate the AFm phase there */
10702  if ( check == POROSITY ) {
10703  mic [ xchr ] [ ychr ] [ zchr ] = AFM;
10704  count [ AFM ] += 1;
10705  count [ POROSITY ] -= 1;
10706  fchr = 1;
10707  }
10708  }
10709 
10710  /* if no neighbor available, locate AFm phase at random location */
10711  /* in pore space */
10712  tries = 0;
10713  while ( fchr == 0 ) {
10714  tries += 1;
10715  /* generate a random location in the 3-D system */
10716  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10717  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10718  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10719  if ( xchr >= SYSIZE ) {
10720  xchr = 0;
10721  }
10722 
10723  if ( ychr >= SYSIZE ) {
10724  ychr = 0;
10725  }
10726 
10727  if ( zchr >= SYSIZE ) {
10728  zchr = 0;
10729  }
10730 
10731  check = mic [ xchr ] [ ychr ] [ zchr ];
10732 
10733  /* if location is porosity, locate the extra AFm there */
10734  if ( check == POROSITY ) {
10735  numnear = edgecnt(xchr, ychr, zchr, AFM, C3A, C4AF);
10736  /* Be sure that at least one neighboring pixel is */
10737  /* Afm phase, C3A, or C4AF */
10738  if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
10739  mic [ xchr ] [ ychr ] [ zchr ] = AFM;
10740  count [ AFM ] += 1;
10741  count [ POROSITY ] -= 1;
10742  fchr = 1;
10743  }
10744  }
10745  }
10746 }
10747 
10748 /* routine to move a diffusing ettringite species */
10749 /* currently located at (xcur,ycur,zcur) */
10750 /* Called by hydrate */
10751 /* Calls moveone, extch, extfh3, and extafm */
10752 int CemhydMatStatus :: moveettr(int xcur, int ycur, int zcur, int finalstep)
10753 {
10754  int check, xnew, ynew, znew, action;
10755  int sumold, sumgarb;
10756  float pexp, pafm, pgrow;
10757 
10758  /* First be sure a diffusing ettringite species is located at xcur,ycur,zcur */
10759  /* if not, return to calling routine */
10760  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFETTR ) {
10761  action = 0;
10762  return ( action );
10763  }
10764 
10765  /* Determine new coordinates (periodic boundaries are used) */
10766  xnew = xcur;
10767  ynew = ycur;
10768  znew = zcur;
10769  action = 0;
10770  sumold = 1;
10771  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10772  if ( action == 0 ) {
10773  printf("Error in value of action in moveettr \n");
10774  }
10775 
10776  check = mic [ xnew ] [ ynew ] [ znew ];
10777 
10778  /* if new location is C4AF, execute conversion */
10779  /* to AFM phase (including necessary volumetric expansion) */
10780  if ( check == C4AF ) {
10781  /* Convert diffusing ettringite to AFM phase */
10782  mic [ xcur ] [ ycur ] [ zcur ] = AFM;
10783  count [ AFM ] += 1;
10784  count [ DIFFETTR ] -= 1;
10785 
10786  /* determine if C4AF should be converted to Afm */
10787  /* or FH3- 1 unit of ettringite requires 0.348 units */
10788  /* of C4AF to form 1.278 units of Afm, */
10789  /* 0.0901 units of CH and 0.1899 units of FH3 */
10790  pexp = ran1(seed);
10791 
10792  if ( pexp <= 0.278 ) {
10793  mic [ xnew ] [ ynew ] [ znew ] = AFM;
10794  count [ AFM ] += 1;
10795  count [ C4AF ] -= 1;
10796  pafm = ran1(seed);
10797  /* 0.3241= 0.0901/0.278 */
10798  if ( pafm <= 0.3241 ) {
10799  extch();
10800  }
10801 
10802  pafm = ran1(seed);
10803  /* 0.4313= ((.1899-(.348-.278))/.278) */
10804  if ( pafm <= 0.4313 ) {
10805  extfh3(xnew, ynew, znew);
10806  }
10807  } else if ( pexp <= 0.348 ) {
10808  mic [ xnew ] [ ynew ] [ znew ] = FH3;
10809  count [ FH3 ] += 1;
10810  count [ C4AF ] -= 1;
10811  }
10812 
10813  action = 0;
10814  }
10815  /* if new location is C3A or diffusing C3A, execute conversion */
10816  /* to AFM phase (including necessary volumetric expansion) */
10817  else if ( ( check == C3A ) || ( check == DIFFC3A ) ) {
10818  /* Convert diffusing ettringite to AFM phase */
10819  action = 0;
10820  mic [ xcur ] [ ycur ] [ zcur ] = AFM;
10821  count [ DIFFETTR ] -= 1;
10822  count [ AFM ] += 1;
10823  count [ check ] -= 1;
10824 
10825  /* determine if C3A should be converted to AFm */
10826  /* 1 unit of ettringite requires 0.2424 units of C3A */
10827  /* and should form 1.278 units of AFm phase */
10828  pexp = ran1(seed);
10829  if ( pexp <= 0.2424 ) {
10830  mic [ xnew ] [ ynew ] [ znew ] = AFM;
10831  count [ AFM ] += 1;
10832  pafm = ( -0.1 );
10833  } else {
10834  /* maybe someday, use a new FIXEDC3A here */
10835  /* so it won't dissolve later */
10836  if ( check == C3A ) {
10837  mic [ xnew ] [ ynew ] [ znew ] = C3A;
10838  count [ C3A ] += 1;
10839  } else {
10840  count [ DIFFC3A ] += 1;
10841  mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
10842  }
10843 
10844  /* pafm=(0.278-0.2424)/(1.0-0.2424); */
10845  pafm = 0.04699;
10846  }
10847 
10848  /* probabilistic-based expansion for new AFm phase pixel */
10849  pexp = ran1(seed);
10850  if ( pexp <= pafm ) {
10851  extafm(xcur, ycur, zcur);
10852  }
10853  }
10854  /* Check for conversion back to solid ettringite */
10855  else if ( check == ETTR ) {
10856  pgrow = ran1(seed);
10857  if ( pgrow <= ETTRGROW ) {
10858  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
10859  count [ ETTR ] += 1;
10860  action = 0;
10861  count [ DIFFETTR ] -= 1;
10862  }
10863  }
10864 
10865  /* if last diffusion step and no reaction, convert back to */
10866  /* solid ettringite */
10867  if ( ( action != 0 ) && ( finalstep == 1 ) ) {
10868  action = 0;
10869  count [ DIFFETTR ] -= 1;
10870  count [ ETTR ] += 1;
10871  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
10872  }
10873 
10874  if ( action != 0 ) {
10875  /* if diffusion is possible, execute it */
10876  if ( check == POROSITY ) {
10877  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
10878  mic [ xnew ] [ ynew ] [ znew ] = DIFFETTR;
10879  } else {
10880  /* indicate that diffusing ettringite remained at */
10881  /* original location */
10882  action = 7;
10883  }
10884  }
10885 
10886  return ( action );
10887 
10888  ( void ) sumgarb;
10889 }
10890 
10891 /* routine to add extra pozzolanic CSH when CH reacts at */
10892 /* pozzolanic surface (e.g. silica fume) located at (xpres,ypres,zpres) */
10893 /* Called by movech */
10894 /* Calls moveone and edgecnt */
10895 void CemhydMatStatus :: extpozz(int xpres, int ypres, int zpres)
10896 {
10897  int check, sump, xchr, ychr, zchr, fchr, i1, action, numnear;
10898  long int tries;
10899 
10900  /* first try 6 neighboring locations until */
10901  /* a) successful */
10902  /* b) all 6 sites are tried or */
10903  /* c) 100 tries are made */
10904  fchr = 0;
10905  sump = 1;
10906  for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
10907  /* determine location of neighbor (using periodic boundaries) */
10908  xchr = xpres;
10909  ychr = ypres;
10910  zchr = zpres;
10911  action = 0;
10912  sump *= moveone(& xchr, & ychr, & zchr, & action, sump);
10913  if ( action == 0 ) {
10914  printf("Error in value of action in extpozz \n");
10915  }
10916 
10917  check = mic [ xchr ] [ ychr ] [ zchr ];
10918 
10919  /* if neighbor is porosity, locate the pozzolanic CSH there */
10920  if ( check == POROSITY ) {
10921  mic [ xchr ] [ ychr ] [ zchr ] = POZZCSH;
10922  count [ POZZCSH ] += 1;
10923  count [ POROSITY ] -= 1;
10924  fchr = 1;
10925  }
10926  }
10927 
10928  /* if no neighbor available, locate pozzolanic CSH at random location */
10929  /* in pore space */
10930  tries = 0;
10931  while ( fchr == 0 ) {
10932  tries += 1;
10933  /* generate a random location in the 3-D system */
10934  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10935  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10936  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
10937  if ( xchr >= SYSIZE ) {
10938  xchr = 0;
10939  }
10940 
10941  if ( ychr >= SYSIZE ) {
10942  ychr = 0;
10943  }
10944 
10945  if ( zchr >= SYSIZE ) {
10946  zchr = 0;
10947  }
10948 
10949  check = mic [ xchr ] [ ychr ] [ zchr ];
10950  /* if location is porosity, locate the extra pozzolanic CSH there */
10951  if ( check == POROSITY ) {
10952  numnear = edgecnt(xchr, ychr, zchr, POZZ, CSH, POZZCSH);
10953  /* Be sure that one neighboring species is CSH or */
10954  /* pozzolanic material */
10955  if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
10956  mic [ xchr ] [ ychr ] [ zchr ] = POZZCSH;
10957  count [ POZZCSH ] += 1;
10958  count [ POROSITY ] -= 1;
10959  fchr = 1;
10960  }
10961  }
10962  }
10963 }
10964 
10965 /* routine to move a diffusing FH3 species */
10966 /* from location (xcur,ycur,zcur) with nucleation probability nucprob */
10967 /* Called by hydrate */
10968 /* Calls moveone */
10969 int CemhydMatStatus :: movefh3(int xcur, int ycur, int zcur, int finalstep, float nucprob)
10970 {
10971  int check, xnew, ynew, znew, action, sumold, sumgarb;
10972  float pgen;
10973 
10974  /* first check for nucleation */
10975  pgen = ran1(seed);
10976 
10977  if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
10978  action = 0;
10979  mic [ xcur ] [ ycur ] [ zcur ] = FH3;
10980  count [ FH3 ] += 1;
10981  count [ DIFFFH3 ] -= 1;
10982  } else {
10983  /* determine new location (using periodic boundaries) */
10984  xnew = xcur;
10985  ynew = ycur;
10986  znew = zcur;
10987  action = 0;
10988  sumold = 1;
10989  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
10990  if ( action == 0 ) {
10991  printf("Error in value of action in movefh3 \n");
10992  }
10993 
10994  check = mic [ xnew ] [ ynew ] [ znew ];
10995 
10996  /* check for growth of FH3 crystal */
10997  if ( check == FH3 ) {
10998  mic [ xcur ] [ ycur ] [ zcur ] = FH3;
10999  count [ FH3 ] += 1;
11000  count [ DIFFFH3 ] -= 1;
11001  action = 0;
11002  }
11003 
11004  if ( action != 0 ) {
11005  /* if diffusion is possible, execute it */
11006  if ( check == POROSITY ) {
11007  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
11008  mic [ xnew ] [ ynew ] [ znew ] = DIFFFH3;
11009  } else {
11010  /* indicate that diffusing FH3 species */
11011  /* remained at original location */
11012  action = 7;
11013  }
11014  }
11015  }
11016 
11017  return ( action );
11018 
11019  ( void ) sumgarb;
11020 }
11021 
11022 /* routine to move a diffusing CH species */
11023 /* from location (xcur,ycur,zcur) with nucleation probability nucprob */
11024 /* Called by hydrate */
11025 /* Calls moveone and extpozz */
11026 int CemhydMatStatus :: movech(int xcur, int ycur, int zcur, int finalstep, float nucprob)
11027 {
11028  int check, xnew, ynew, znew, action, sumgarb, sumold;
11029  float pexp, pgen, pfix;
11030 
11031  /* first check for nucleation */
11032  pgen = ran1(seed);
11033  if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
11034  action = 0;
11035  mic [ xcur ] [ ycur ] [ zcur ] = CH;
11036  count [ DIFFCH ] -= 1;
11037  count [ CH ] += 1;
11038  } else {
11039  /* determine new location (using periodic boundaries) */
11040  xnew = xcur;
11041  ynew = ycur;
11042  znew = zcur;
11043  action = 0;
11044  sumold = 1;
11045  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
11046  if ( action == 0 ) {
11047  printf("Error in value of action in movech \n");
11048  }
11049 
11050  check = mic [ xnew ] [ ynew ] [ znew ];
11051 
11052  /* check for growth of CH crystal */
11053  if ( ( check == CH ) && ( pgen <= CHGROW ) ) {
11054  mic [ xcur ] [ ycur ] [ zcur ] = CH;
11055  count [ DIFFCH ] -= 1;
11056  count [ CH ] += 1;
11057  action = 0;
11058  }
11059  /* check for growth of CH crystal on aggregate or CaCO3 surface */
11060  /* re suggestion of Sidney Diamond */
11061  else if ( ( ( check == INERTAGG ) || ( check == CACO3 ) || ( check == INERT ) ) && ( pgen <= CHGROWAGG ) && ( chflag == 1 ) ) {
11062  mic [ xcur ] [ ycur ] [ zcur ] = CH;
11063  count [ DIFFCH ] -= 1;
11064  count [ CH ] += 1;
11065  action = 0;
11066  }
11067  /* check for pozzolanic reaction */
11068  /* 36.41 units CH can react with 27 units of S */
11069  else if ( ( pgen <= ppozz ) && ( check == POZZ ) && ( npr <= ( int ) ( ( float ) nfill * 1.35 ) ) ) {
11070  action = 0;
11071  mic [ xcur ] [ ycur ] [ zcur ] = POZZCSH;
11072  count [ POZZCSH ] += 1;
11073  /* update counter of number of diffusing CH */
11074  /* which have reacted pozzolanically */
11075  npr += 1;
11076  count [ DIFFCH ] -= 1;
11077  /* Convert pozzolan to pozzolanic CSH as needed */
11078  pfix = ran1(seed);
11079  if ( pfix <= ( 1. / 1.35 ) ) {
11080  mic [ xnew ] [ ynew ] [ znew ] = POZZCSH;
11081  count [ POZZ ] -= 1;
11082  count [ POZZCSH ] += 1;
11083  }
11084 
11085  /* allow for extra pozzolanic CSH as needed */
11086  pexp = ran1(seed);
11087  /* should form 101.81 units of pozzolanic CSH for */
11088  /* each 36.41 units of CH and 27 units of S */
11089  /* 1.05466=(101.81-36.41-27)/36.41 */
11090  extpozz(xcur, ycur, zcur);
11091  if ( pexp <= 0.05466 ) {
11092  extpozz(xcur, ycur, zcur);
11093  }
11094  } else if ( check == DIFFAS ) {
11095  action = 0;
11096  mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
11097  count [ STRAT ] += 1;
11098  /* update counter of number of diffusing CH */
11099  /* which have reacted to form stratlingite */
11100  nasr += 1;
11101  count [ DIFFCH ] -= 1;
11102  /* Convert DIFFAS to STRAT as needed */
11103  pfix = ran1(seed);
11104  if ( pfix <= 0.7538 ) {
11105  mic [ xnew ] [ ynew ] [ znew ] = STRAT;
11106  count [ STRAT ] += 1;
11107  count [ DIFFAS ] -= 1;
11108  }
11109 
11110  /* allow for extra stratlingite as needed */
11111  /* 1.5035=(215.63-66.2-49.9)/66.2 */
11112  extstrat(xcur, ycur, zcur);
11113  pexp = ran1(seed);
11114  if ( pexp <= 0.5035 ) {
11115  extstrat(xcur, ycur, zcur);
11116  }
11117  }
11118 
11119  if ( action != 0 ) {
11120  /* if diffusion is possible, execute it */
11121  if ( check == POROSITY ) {
11122  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
11123  mic [ xnew ] [ ynew ] [ znew ] = DIFFCH;
11124  } else {
11125  /* indicate that diffusing CH species */
11126  /* remained at original location */
11127  action = 7;
11128  }
11129  }
11130  }
11131 
11132  return ( action );
11133 
11134  ( void ) sumgarb;
11135 }
11136 
11137 /* routine to add extra C3AH6 when diffusing C3A nucleates or reacts at */
11138 /* C3AH6 surface at location (xpres,ypres,zpres) */
11139 /* Called by movec3a */
11140 /* Calls moveone and edgecnt */
11141 void CemhydMatStatus :: extc3ah6(int xpres, int ypres, int zpres)
11142 {
11143  int check, sump, xchr, ychr, zchr, fchr, i1, action, numnear;
11144  long int tries;
11145 
11146  /* First try 6 neighboring locations until */
11147  /* a) successful */
11148  /* b) all 6 sites are tried or */
11149  /* c) 100 random attempts are made */
11150  fchr = 0;
11151  sump = 1;
11152  for ( i1 = 1; ( ( i1 <= 100 ) && ( fchr == 0 ) && ( sump != 30030 ) ); i1++ ) {
11153  /* determine new coordinates (using periodic boundaries) */
11154  xchr = xpres;
11155  ychr = ypres;
11156  zchr = zpres;
11157  action = 0;
11158  sump *= moveone(& xchr, & ychr, & zchr, & action, sump);
11159  if ( action == 0 ) {
11160  printf("Error in action value in extc3ah6 \n");
11161  }
11162 
11163  check = mic [ xchr ] [ ychr ] [ zchr ];
11164 
11165  /* if neighbor is pore space, convert it to C3AH6 */
11166  if ( check == POROSITY ) {
11167  mic [ xchr ] [ ychr ] [ zchr ] = C3AH6;
11168  count [ C3AH6 ] += 1;
11169  count [ POROSITY ] -= 1;
11170  fchr = 1;
11171  }
11172  }
11173 
11174  /* if unsuccessful, add C3AH6 at random location in pore space */
11175  tries = 0;
11176  while ( fchr == 0 ) {
11177  tries += 1;
11178  xchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
11179  ychr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
11180  zchr = ( int ) ( ( float ) SYSIZE * ran1(seed) );
11181  if ( xchr >= SYSIZE ) {
11182  xchr = 0;
11183  }
11184 
11185  if ( ychr >= SYSIZE ) {
11186  ychr = 0;
11187  }
11188 
11189  if ( zchr >= SYSIZE ) {
11190  zchr = 0;
11191  }
11192 
11193  check = mic [ xchr ] [ ychr ] [ zchr ];
11194 
11195  if ( check == POROSITY ) {
11196  numnear = edgecnt(xchr, ychr, zchr, C3AH6, C3A, C3AH6);
11197  /* Be sure that new C3AH6 is in contact with */
11198  /* at least one C3AH6 or C3A */
11199  if ( ( tries > 5000 ) || ( numnear < 26 ) ) {
11200  mic [ xchr ] [ ychr ] [ zchr ] = C3AH6;
11201  count [ C3AH6 ] += 1;
11202  count [ POROSITY ] -= 1;
11203  fchr = 1;
11204  }
11205  }
11206  }
11207 }
11208 
11209 /* routine to move a diffusing C3A species */
11210 /* from location (xcur,ycur,zcur) with nucleation probability of nucprob */
11211 /* Called by hydrate */
11212 /* Calls extc3ah6, moveone, extettr, and extafm */
11213 int CemhydMatStatus :: movec3a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
11214 {
11215  int check, xnew, ynew, znew, action, sumgarb, sumold;
11216  int xexp, yexp, zexp, nexp, iexp, newact;
11217  float pgen, pexp, pafm, pgrow, p2diff;
11218 
11219  /* First be sure that a diffusing C3A species is at (xcur,ycur,zcur) */
11220  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFC3A ) {
11221  action = 0;
11222  return ( action );
11223  }
11224 
11225  /* Check for nucleation into solid C3AH6 */
11226  pgen = ran1(seed);
11227  p2diff = ran1(seed);
11228 
11229  if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
11230  action = 0;
11231  mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11232  count [ C3AH6 ] += 1;
11233  /* decrement count of diffusing C3A species */
11234  count [ DIFFC3A ] -= 1;
11235  /* allow for probabilistic-based expansion of C3AH6 */
11236  /* crystal to account for volume stoichiometry */
11237  pexp = ran1(seed);
11238  if ( pexp <= 0.69 ) {
11239  extc3ah6(xcur, ycur, zcur);
11240  }
11241  } else {
11242  /* determine new coordinates (using periodic boundaries) */
11243  xnew = xcur;
11244  ynew = ycur;
11245  znew = zcur;
11246  action = 0;
11247  sumold = 1;
11248  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
11249  if ( action == 0 ) {
11250  printf("Error in value of action in movec3a \n");
11251  }
11252 
11253  check = mic [ xnew ] [ ynew ] [ znew ];
11254 
11255  /* check for growth of C3AH6 crystal */
11256  if ( check == C3AH6 ) {
11257  pgrow = ran1(seed);
11258  /* Try to slow down growth of C3AH6 crystals to */
11259  /* promote ettringite and Afm formation */
11260  if ( pgrow <= C3AH6GROW ) {
11261  mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11262  count [ C3AH6 ] += 1;
11263  count [ DIFFC3A ] -= 1;
11264  action = 0;
11265  /* allow for probabilistic-based expansion of C3AH6 */
11266  /* crystal to account for volume stoichiometry */
11267  pexp = ran1(seed);
11268  if ( pexp <= 0.69 ) {
11269  extc3ah6(xcur, ycur, zcur);
11270  }
11271  }
11272  }
11273  /* examine reaction with diffusing gypsum to form ettringite */
11274  /* Only allow reaction with diffusing gypsum */
11275  else if ( ( check == DIFFGYP ) && ( p2diff < C3AGYP ) ) {
11276  /* convert diffusing gypsum to ettringite */
11277  mic [ xnew ] [ ynew ] [ znew ] = ETTR;
11278  count [ ETTR ] += 1;
11279  /* decrement counts of diffusing gypsum */
11280  count [ DIFFGYP ] -= 1;
11281  action = 0;
11282 
11283  /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11284  pexp = ran1(seed);
11285  nexp = 2;
11286  if ( pexp <= 0.40 ) {
11287  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
11288  count [ ETTR ] += 1;
11289  count [ DIFFC3A ] -= 1;
11290  nexp = 1;
11291  } else {
11292  /* indicate that diffusing species remains in current location */
11293  action = 7;
11294  nexp = 2;
11295  }
11296 
11297  /* Perform expansion that occurs when ettringite is formed */
11298  /* xexp, yexp and zexp are the coordinates of the last ettringite */
11299  /* pixel to be added */
11300  xexp = xnew;
11301  yexp = ynew;
11302  zexp = znew;
11303  for ( iexp = 1; iexp <= nexp; iexp++ ) {
11304  newact = extettr(xexp, yexp, zexp, 0);
11305  /* update xexp, yexp and zexp */
11306  switch ( newact ) {
11307  case 1:
11308  xexp -= 1;
11309  if ( xexp < 0 ) {
11310  xexp = ( SYSIZEM1 );
11311  }
11312 
11313  break;
11314  case 2:
11315  xexp += 1;
11316  if ( xexp >= SYSIZE ) {
11317  xexp = 0;
11318  }
11319 
11320  break;
11321  case 3:
11322  yexp -= 1;
11323  if ( yexp < 0 ) {
11324  yexp = ( SYSIZEM1 );
11325  }
11326 
11327  break;
11328  case 4:
11329  yexp += 1;
11330  if ( yexp >= SYSIZE ) {
11331  yexp = 0;
11332  }
11333 
11334  break;
11335  case 5:
11336  zexp -= 1;
11337  if ( zexp < 0 ) {
11338  zexp = ( SYSIZEM1 );
11339  }
11340 
11341  break;
11342  case 6:
11343  zexp += 1;
11344  if ( zexp >= SYSIZE ) {
11345  zexp = 0;
11346  }
11347 
11348  break;
11349  default:
11350  break;
11351  }
11352  }
11353 
11354  /* probabilistic-based expansion for last ettringite pixel */
11355  pexp = ran1(seed);
11356  if ( pexp <= 0.30 ) {
11357  newact = extettr(xexp, yexp, zexp, 0);
11358  }
11359  }
11360  /* examine reaction with diffusing hemihydrate to form ettringite */
11361  /* Only allow reaction with diffusing hemihydrate */
11362  else if ( ( check == DIFFHEM ) && ( p2diff < C3AGYP ) ) {
11363  /* convert diffusing hemihydrate to ettringite */
11364  mic [ xnew ] [ ynew ] [ znew ] = ETTR;
11365  count [ ETTR ] += 1;
11366  /* decrement counts of diffusing hemihydrate */
11367  count [ DIFFHEM ] -= 1;
11368  action = 0;
11369 
11370  /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11371  pexp = ran1(seed);
11372  nexp = 3;
11373  if ( pexp <= 0.5583 ) {
11374  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
11375  count [ ETTR ] += 1;
11376  count [ DIFFC3A ] -= 1;
11377  nexp = 2;
11378  } else {
11379  /* indicate that diffusing species remains in current location */
11380  action = 7;
11381  nexp = 3;
11382  }
11383 
11384  /* Perform expansion that occurs when ettringite is formed */
11385  /* xexp, yexp and zexp are the coordinates of the last ettringite */
11386  /* pixel to be added */
11387  xexp = xnew;
11388  yexp = ynew;
11389  zexp = znew;
11390  for ( iexp = 1; iexp <= nexp; iexp++ ) {
11391  newact = extettr(xexp, yexp, zexp, 0);
11392  /* update xexp, yexp and zexp */
11393  switch ( newact ) {
11394  case 1:
11395  xexp -= 1;
11396  if ( xexp < 0 ) {
11397  xexp = ( SYSIZEM1 );
11398  }
11399 
11400  break;
11401  case 2:
11402  xexp += 1;
11403  if ( xexp >= SYSIZE ) {
11404  xexp = 0;
11405  }
11406 
11407  break;
11408  case 3:
11409  yexp -= 1;
11410  if ( yexp < 0 ) {
11411  yexp = ( SYSIZEM1 );
11412  }
11413 
11414  break;
11415  case 4:
11416  yexp += 1;
11417  if ( yexp >= SYSIZE ) {
11418  yexp = 0;
11419  }
11420 
11421  break;
11422  case 5:
11423  zexp -= 1;
11424  if ( zexp < 0 ) {
11425  zexp = ( SYSIZEM1 );
11426  }
11427 
11428  break;
11429  case 6:
11430  zexp += 1;
11431  if ( zexp >= SYSIZE ) {
11432  zexp = 0;
11433  }
11434 
11435  break;
11436  default:
11437  break;
11438  }
11439  }
11440 
11441  /* probabilistic-based expansion for last ettringite pixel */
11442  pexp = ran1(seed);
11443  if ( pexp <= 0.6053 ) {
11444  newact = extettr(xexp, yexp, zexp, 0);
11445  }
11446  }
11447  /* examine reaction with diffusing anhydrite to form ettringite */
11448  /* Only allow reaction with diffusing anhydrite */
11449  else if ( ( check == DIFFANH ) && ( p2diff < C3AGYP ) ) {
11450  /* convert diffusing anhydrite to ettringite */
11451  mic [ xnew ] [ ynew ] [ znew ] = ETTR;
11452  count [ ETTR ] += 1;
11453  /* decrement counts of diffusing anhydrite */
11454  count [ DIFFANH ] -= 1;
11455  action = 0;
11456 
11457  /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11458  pexp = ran1(seed);
11459  nexp = 3;
11460  if ( pexp <= 0.569 ) {
11461  mic [ xcur ] [ ycur ] [ zcur ] = ETTR;
11462  count [ ETTR ] += 1;
11463  count [ DIFFC3A ] -= 1;
11464  nexp = 2;
11465  } else {
11466  /* indicate that diffusing species remains in current location */
11467  action = 7;
11468  nexp = 3;
11469  }
11470 
11471  /* Perform expansion that occurs when ettringite is formed */
11472  /* xexp, yexp and zexp are the coordinates of the last ettringite */
11473  /* pixel to be added */
11474  xexp = xnew;
11475  yexp = ynew;
11476  zexp = znew;
11477  for ( iexp = 1; iexp <= nexp; iexp++ ) {
11478  newact = extettr(xexp, yexp, zexp, 0);
11479  /* update xexp, yexp and zexp */
11480  switch ( newact ) {
11481  case 1:
11482  xexp -= 1;
11483  if ( xexp < 0 ) {
11484  xexp = ( SYSIZEM1 );
11485  }
11486 
11487  break;
11488  case 2:
11489  xexp += 1;
11490  if ( xexp >= SYSIZE ) {
11491  xexp = 0;
11492  }
11493 
11494  break;
11495  case 3:
11496  yexp -= 1;
11497  if ( yexp < 0 ) {
11498  yexp = ( SYSIZEM1 );
11499  }
11500 
11501  break;
11502  case 4:
11503  yexp += 1;
11504  if ( yexp >= SYSIZE ) {
11505  yexp = 0;
11506  }
11507 
11508  break;
11509  case 5:
11510  zexp -= 1;
11511  if ( zexp < 0 ) {
11512  zexp = ( SYSIZEM1 );
11513  }
11514 
11515  break;
11516  case 6:
11517  zexp += 1;
11518  if ( zexp >= SYSIZE ) {
11519  zexp = 0;
11520  }
11521 
11522  break;
11523  default:
11524  break;
11525  }
11526  }
11527 
11528  /* probabilistic-based expansion for last ettringite pixel */
11529  pexp = ran1(seed);
11530  if ( pexp <= 0.6935 ) {
11531  newact = extettr(xexp, yexp, zexp, 0);
11532  }
11533  }
11534  /* examine reaction with diffusing CaCl2 to form FREIDEL */
11535  /* Only allow reaction with diffusing CaCl2 */
11536  else if ( check == DIFFCACL2 ) {
11537  /* convert diffusing C3A to Freidel's salt */
11538  mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
11539  count [ FREIDEL ] += 1;
11540  /* decrement counts of diffusing C3A and CaCl2 */
11541  count [ DIFFC3A ] -= 1;
11542  action = 0;
11543 
11544  /* convert diffusing CACL2 to solid FREIDEL or else leave as a diffusing CACL2 */
11545  pexp = ran1(seed);
11546  nexp = 2;
11547  if ( pexp <= 0.5793 ) {
11548  mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
11549  count [ FREIDEL ] += 1;
11550  count [ DIFFCACL2 ] -= 1;
11551  nexp = 1;
11552  } else {
11553  nexp = 2;
11554  }
11555 
11556  /* Perform expansion that occurs when Freidel's salt is formed */
11557  /* xexp, yexp and zexp are the coordinates of the last FREIDEL */
11558  /* pixel to be added */
11559  xexp = xnew;
11560  yexp = ynew;
11561  zexp = znew;
11562  for ( iexp = 1; iexp <= nexp; iexp++ ) {
11563  newact = extfreidel(xexp, yexp, zexp);
11564  /* update xexp, yexp and zexp */
11565  switch ( newact ) {
11566  case 1:
11567  xexp -= 1;
11568  if ( xexp < 0 ) {
11569  xexp = ( SYSIZEM1 );
11570  }
11571 
11572  break;
11573  case 2:
11574  xexp += 1;
11575  if ( xexp >= SYSIZE ) {
11576  xexp = 0;
11577  }
11578 
11579  break;
11580  case 3:
11581  yexp -= 1;
11582  if ( yexp < 0 ) {
11583  yexp = ( SYSIZEM1 );
11584  }
11585 
11586  break;
11587  case 4:
11588  yexp += 1;
11589  if ( yexp >= SYSIZE ) {
11590  yexp = 0;
11591  }
11592 
11593  break;
11594  case 5:
11595  zexp -= 1;
11596  if ( zexp < 0 ) {
11597  zexp = ( SYSIZEM1 );
11598  }
11599 
11600  break;
11601  case 6:
11602  zexp += 1;
11603  if ( zexp >= SYSIZE ) {
11604  zexp = 0;
11605  }
11606 
11607  break;
11608  default:
11609  break;
11610  }
11611  }
11612 
11613  /* probabilistic-based expansion for last FREIDEL pixel */
11614  pexp = ran1(seed);
11615  if ( pexp <= 0.3295 ) {
11616  newact = extfreidel(xexp, yexp, zexp);
11617  }
11618  }
11619  /* examine reaction with diffusing CAS2 to form STRAT */
11620  /* Only allow reaction with diffusing (not solid) CAS2 */
11621  else if ( check == DIFFCAS2 ) {
11622  /* convert diffusing CAS2 to stratlingite */
11623  mic [ xnew ] [ ynew ] [ znew ] = STRAT;
11624  count [ STRAT ] += 1;
11625  /* decrement counts of diffusing C3A and CAS2 */
11626  count [ DIFFCAS2 ] -= 1;
11627  action = 0;
11628 
11629  /* convert diffusing C3A to solid STRAT or else leave as a diffusing C3A */
11630  pexp = ran1(seed);
11631  nexp = 3;
11632  if ( pexp <= 0.886 ) {
11633  mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
11634  count [ STRAT ] += 1;
11635  count [ DIFFC3A ] -= 1;
11636  nexp = 2;
11637  } else {
11638  action = 7;
11639  nexp = 3;
11640  }
11641 
11642  /* Perform expansion that occurs when stratlingite is formed */
11643  /* xexp, yexp and zexp are the coordinates of the last STRAT */
11644  /* pixel to be added */
11645  xexp = xnew;
11646  yexp = ynew;
11647  zexp = znew;
11648  for ( iexp = 1; iexp <= nexp; iexp++ ) {
11649  newact = extstrat(xexp, yexp, zexp);
11650  /* update xexp, yexp and zexp */
11651  switch ( newact ) {
11652  case 1:
11653  xexp -= 1;
11654  if ( xexp < 0 ) {
11655  xexp = ( SYSIZEM1 );
11656  }
11657 
11658  break;
11659  case 2:
11660  xexp += 1;
11661  if ( xexp >= SYSIZE ) {
11662  xexp = 0;
11663  }
11664 
11665  break;
11666  case 3:
11667  yexp -= 1;
11668  if ( yexp < 0 ) {
11669  yexp = ( SYSIZEM1 );
11670  }
11671 
11672  break;
11673  case 4:
11674  yexp += 1;
11675  if ( yexp >= SYSIZE ) {
11676  yexp = 0;
11677  }
11678 
11679  break;
11680  case 5:
11681  zexp -= 1;
11682  if ( zexp < 0 ) {
11683  zexp = ( SYSIZEM1 );
11684  }
11685 
11686  break;
11687  case 6:
11688  zexp += 1;
11689  if ( zexp >= SYSIZE ) {
11690  zexp = 0;
11691  }
11692 
11693  break;
11694  default:
11695  break;
11696  }
11697  }
11698 
11699  /* probabilistic-based expansion for last STRAT pixel */
11700  pexp = ran1(seed);
11701  if ( pexp <= 0.286 ) {
11702  newact = extstrat(xexp, yexp, zexp);
11703  }
11704  }
11705 
11706  /* check for reaction with diffusing or solid ettringite to form AFm */
11707  /* reaction at solid ettringite only possible if ettringite is soluble */
11708  /* and even then on a limited bases to avoid a great formation of AFm */
11709  /* when ettringite first becomes soluble */
11710  pgrow = ran1(seed);
11711  if ( ( check == DIFFETTR ) || ( ( check == ETTR ) && ( soluble [ ETTR ] == 1 ) && ( pgrow <= C3AETTR ) ) ) {
11712  /* convert diffusing or solid ettringite to AFm */
11713  mic [ xnew ] [ ynew ] [ znew ] = AFM;
11714  count [ AFM ] += 1;
11715  /* decrement count of ettringite */
11716  count [ check ] -= 1;
11717  action = 0;
11718 
11719  /* convert diffusing C3A to AFm or leave as diffusing C3A */
11720  pexp = ran1(seed);
11721  if ( pexp <= 0.2424 ) {
11722  mic [ xcur ] [ ycur ] [ zcur ] = AFM;
11723  count [ AFM ] += 1;
11724  count [ DIFFC3A ] -= 1;
11725  pafm = ( -0.1 );
11726  } else {
11727  action = 7;
11728  pafm = 0.04699;
11729  }
11730 
11731  /* probabilistic-based expansion for new AFm pixel */
11732  pexp = ran1(seed);
11733  if ( pexp <= pafm ) {
11734  extafm(xnew, ynew, znew);
11735  }
11736  }
11737 
11738  if ( ( action != 0 ) && ( action != 7 ) ) {
11739  /* if diffusion is possible, execute it */
11740  if ( check == POROSITY ) {
11741  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
11742  mic [ xnew ] [ ynew ] [ znew ] = DIFFC3A;
11743  } else {
11744  /* indicate that diffusing C3A remained */
11745  /* at original location */
11746  action = 7;
11747  }
11748  }
11749  }
11750 
11751  return ( action );
11752 
11753  ( void ) sumgarb;
11754 }
11755 
11756 /* routine to move a diffusing C4A species */
11757 /* from location (xcur,ycur,zcur) with nucleation probability of nucprob */
11758 /* Called by hydrate */
11759 /* Calls extc3ah6, moveone, extettr, and extafm */
11760 int CemhydMatStatus :: movec4a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
11761 {
11762  int check, xnew, ynew, znew, action, sumgarb, sumold;
11763  int xexp, yexp, zexp, nexp, iexp, newact;
11764  float pgen, pexp, pafm, pgrow, p2diff;
11765 
11766  /* First be sure that a diffusing C4A species is at (xcur,ycur,zcur) */
11767  if ( mic [ xcur ] [ ycur ] [ zcur ] != DIFFC4A ) {
11768  action = 0;
11769  return ( action );
11770  }
11771 
11772  /* Check for nucleation into solid C3AH6 */
11773  pgen = ran1(seed);
11774  p2diff = ran1(seed);
11775 
11776  if ( ( nucprob >= pgen ) || ( finalstep == 1 ) ) {
11777  action = 0;
11778  mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11779  count [ C3AH6 ] += 1;
11780  /* decrement count of diffusing C3A species */
11781  count [ DIFFC4A ] -= 1;
11782  /* allow for probabilistic-based expansion of C3AH6 */
11783  /* crystal to account for volume stoichiometry */
11784  pexp = ran1(seed);
11785  if ( pexp <= 0.69 ) {
11786  extc3ah6(xcur, ycur, zcur);
11787  }
11788  } else {
11789  /* determine new coordinates (using periodic boundaries) */
11790  xnew = xcur;
11791  ynew = ycur;
11792  znew = zcur;
11793  action = 0;
11794  sumold = 1;
11795  sumgarb = moveone(& xnew, & ynew, & znew, & action, sumold);
11796  if ( action == 0 ) {
11797  printf("Error in value of action in movec4a \n");
11798  }
11799 
11800  check = mic [ xnew ] [ ynew ] [ znew ];
11801 
11802  /* check for growth of C3AH6 crystal */
11803  if ( check == C3AH6 ) {
11804  pgrow = ran1(seed);
11805  /* Try to slow down growth of C3AH6 crystals to */
11806  /* promote ettringite and Afm formation */
11807  if ( pgrow <= C3AH6GROW ) {
11808  mic [ xcur ] [ ycur ] [ zcur ] = C3AH6;
11809  count [ C3AH6 ] += 1;
11810  count [ DIFFC4A ] -= 1;
11811  action = 0;
11812  /* allow for probabilistic-based expansion of C3AH6 */
11813  /* crystal to account for volume stoichiometry */
11814  pexp = ran1(seed);
11815  if ( pexp <= 0.69 ) {
11816  extc3ah6(xcur, ycur, zcur);
11817  }
11818  }
11819  }
11820  /* examine reaction with diffusing gypsum to form ettringite */
11821  /* Only allow reaction with diffusing gypsum */
11822  else if ( ( check == DIFFGYP ) && ( p2diff < C3AGYP ) ) {
11823  /* convert diffusing gypsum to ettringite */
11824  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
11825  count [ ETTRC4AF ] += 1;
11826  /* decrement counts of diffusing gypsum */
11827  count [ DIFFGYP ] -= 1;
11828  action = 0;
11829 
11830  /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11831  pexp = ran1(seed);
11832  nexp = 2;
11833  if ( pexp <= 0.40 ) {
11834  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
11835  count [ ETTRC4AF ] += 1;
11836  count [ DIFFC4A ] -= 1;
11837  nexp = 1;
11838  } else {
11839  /* indicate that diffusing species remains in current location */
11840  action = 7;
11841  nexp = 2;
11842  }
11843 
11844  /* Perform expansion that occurs when ettringite is formed */
11845  /* xexp, yexp and zexp are the coordinates of the last ettringite */
11846  /* pixel to be added */
11847  xexp = xnew;
11848  yexp = ynew;
11849  zexp = znew;
11850  for ( iexp = 1; iexp <= nexp; iexp++ ) {
11851  newact = extettr(xexp, yexp, zexp, 1);
11852  /* update xexp, yexp and zexp */
11853  switch ( newact ) {
11854  case 1:
11855  xexp -= 1;
11856  if ( xexp < 0 ) {
11857  xexp = ( SYSIZEM1 );
11858  }
11859 
11860  break;
11861  case 2:
11862  xexp += 1;
11863  if ( xexp >= SYSIZE ) {
11864  xexp = 0;
11865  }
11866 
11867  break;
11868  case 3:
11869  yexp -= 1;
11870  if ( yexp < 0 ) {
11871  yexp = ( SYSIZEM1 );
11872  }
11873 
11874  break;
11875  case 4:
11876  yexp += 1;
11877  if ( yexp >= SYSIZE ) {
11878  yexp = 0;
11879  }
11880 
11881  break;
11882  case 5:
11883  zexp -= 1;
11884  if ( zexp < 0 ) {
11885  zexp = ( SYSIZEM1 );
11886  }
11887 
11888  break;
11889  case 6:
11890  zexp += 1;
11891  if ( zexp >= SYSIZE ) {
11892  zexp = 0;
11893  }
11894 
11895  break;
11896  default:
11897  break;
11898  }
11899  }
11900 
11901  /* probabilistic-based expansion for last ettringite pixel */
11902  pexp = ran1(seed);
11903  if ( pexp <= 0.30 ) {
11904  newact = extettr(xexp, yexp, zexp, 1);
11905  }
11906  }
11907  /* examine reaction with diffusing hemi to form ettringite */
11908  /* Only allow reaction with diffusing hemihydrate */
11909  else if ( ( check == DIFFHEM ) && ( p2diff < C3AGYP ) ) {
11910  /* convert diffusing hemihydrate to ettringite */
11911  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
11912  count [ ETTRC4AF ] += 1;
11913  /* decrement counts of diffusing hemihydrate */
11914  count [ DIFFHEM ] -= 1;
11915  action = 0;
11916 
11917  /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
11918  pexp = ran1(seed);
11919  nexp = 3;
11920  if ( pexp <= 0.5583 ) {
11921  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
11922  count [ ETTRC4AF ] += 1;
11923  count [ DIFFC4A ] -= 1;
11924  nexp = 2;
11925  } else {
11926  /* indicate that diffusing species remains in current location */
11927  action = 7;
11928  nexp = 3;
11929  }
11930 
11931  /* Perform expansion that occurs when ettringite is formed */
11932  /* xexp, yexp and zexp are the coordinates of the last ettringite */
11933  /* pixel to be added */
11934  xexp = xnew;
11935  yexp = ynew;
11936  zexp = znew;
11937  for ( iexp = 1; iexp <= nexp; iexp++ ) {
11938  newact = extettr(xexp, yexp, zexp, 1);
11939  /* update xexp, yexp and zexp */
11940  switch ( newact ) {
11941  case 1:
11942  xexp -= 1;
11943  if ( xexp < 0 ) {
11944  xexp = ( SYSIZEM1 );
11945  }
11946 
11947  break;
11948  case 2:
11949  xexp += 1;
11950  if ( xexp >= SYSIZE ) {
11951  xexp = 0;
11952  }
11953 
11954  break;
11955  case 3:
11956  yexp -= 1;
11957  if ( yexp < 0 ) {
11958  yexp = ( SYSIZEM1 );
11959  }
11960 
11961  break;
11962  case 4:
11963  yexp += 1;
11964  if ( yexp >= SYSIZE ) {
11965  yexp = 0;
11966  }
11967 
11968  break;
11969  case 5:
11970  zexp -= 1;
11971  if ( zexp < 0 ) {
11972  zexp = ( SYSIZEM1 );
11973  }
11974 
11975  break;
11976  case 6:
11977  zexp += 1;
11978  if ( zexp >= SYSIZE ) {
11979  zexp = 0;
11980  }
11981 
11982  break;
11983  default:
11984  break;
11985  }
11986  }
11987 
11988  /* probabilistic-based expansion for last ettringite pixel */
11989  pexp = ran1(seed);
11990  if ( pexp <= 0.6053 ) {
11991  newact = extettr(xexp, yexp, zexp, 1);
11992  }
11993  }
11994  /* examine reaction with diffusing anhydrite to form ettringite */
11995  /* Only allow reaction with diffusing anhydrite */
11996  else if ( ( check == DIFFANH ) && ( p2diff < C3AGYP ) ) {
11997  /* convert diffusing anhydrite to ettringite */
11998  mic [ xnew ] [ ynew ] [ znew ] = ETTRC4AF;
11999  count [ ETTRC4AF ] += 1;
12000  /* decrement counts of diffusing anhydrite */
12001  count [ DIFFANH ] -= 1;
12002  action = 0;
12003 
12004  /* convert diffusing C3A to solid ettringite or else leave as a diffusing C3A */
12005  pexp = ran1(seed);
12006  nexp = 3;
12007  if ( pexp <= 0.569 ) {
12008  mic [ xcur ] [ ycur ] [ zcur ] = ETTRC4AF;
12009  count [ ETTRC4AF ] += 1;
12010  count [ DIFFC4A ] -= 1;
12011  nexp = 2;
12012  } else {
12013  /* indicate that diffusing species remains in current location */
12014  action = 7;
12015  nexp = 3;
12016  }
12017 
12018  /* Perform expansion that occurs when ettringite is formed */
12019  /* xexp, yexp and zexp are the coordinates of the last ettringite */
12020  /* pixel to be added */
12021  xexp = xnew;
12022  yexp = ynew;
12023  zexp = znew;
12024  for ( iexp = 1; iexp <= nexp; iexp++ ) {
12025  newact = extettr(xexp, yexp, zexp, 1);
12026  /* update xexp, yexp and zexp */
12027  switch ( newact ) {
12028  case 1:
12029  xexp -= 1;
12030  if ( xexp < 0 ) {
12031  xexp = ( SYSIZEM1 );
12032  }
12033 
12034  break;
12035  case 2:
12036  xexp += 1;
12037  if ( xexp >= SYSIZE ) {
12038  xexp = 0;
12039  }
12040 
12041  break;
12042  case 3:
12043  yexp -= 1;
12044  if ( yexp < 0 ) {
12045  yexp = ( SYSIZEM1 );
12046  }
12047 
12048  break;
12049  case 4:
12050  yexp += 1;
12051  if ( yexp >= SYSIZE ) {
12052  yexp = 0;
12053  }
12054 
12055  break;
12056  case 5:
12057  zexp -= 1;
12058  if ( zexp < 0 ) {
12059  zexp = ( SYSIZEM1 );
12060  }
12061 
12062  break;
12063  case 6:
12064  zexp += 1;
12065  if ( zexp >= SYSIZE ) {
12066  zexp = 0;
12067  }
12068 
12069  break;
12070  default:
12071  break;
12072  }
12073  }
12074 
12075  /* probabilistic-based expansion for last ettringite pixel */
12076  pexp = ran1(seed);
12077  if ( pexp <= 0.6935 ) {
12078  newact = extettr(xexp, yexp, zexp, 1);
12079  }
12080  }
12081  /* examine reaction with diffusing CaCl2 to form FREIDEL */
12082  /* Only allow reaction with diffusing CaCl2 */
12083  else if ( check == DIFFCACL2 ) {
12084  /* convert diffusing C3A to Freidel's salt */
12085  mic [ xcur ] [ ycur ] [ zcur ] = FREIDEL;
12086  count [ FREIDEL ] += 1;
12087  /* decrement counts of diffusing C3A and CaCl2 */
12088  count [ DIFFC4A ] -= 1;
12089  action = 0;
12090 
12091  /* convert diffusing CACL2 to solid FREIDEL or else leave as a diffusing CACL2 */
12092  pexp = ran1(seed);
12093  nexp = 2;
12094  if ( pexp <= 0.5793 ) {
12095  mic [ xnew ] [ ynew ] [ znew ] = FREIDEL;
12096  count [ FREIDEL ] += 1;
12097  count [ DIFFCACL2 ] -= 1;
12098  nexp = 1;
12099  } else {
12100  nexp = 2;
12101  }
12102 
12103  /* Perform expansion that occurs when Freidel's salt is formed */
12104  /* xexp, yexp and zexp are the coordinates of the last FREIDEL */
12105  /* pixel to be added */
12106  xexp = xnew;
12107  yexp = ynew;
12108  zexp = znew;
12109  for ( iexp = 1; iexp <= nexp; iexp++ ) {
12110  newact = extfreidel(xexp, yexp, zexp);
12111  /* update xexp, yexp and zexp */
12112  switch ( newact ) {
12113  case 1:
12114  xexp -= 1;
12115  if ( xexp < 0 ) {
12116  xexp = ( SYSIZEM1 );
12117  }
12118 
12119  break;
12120  case 2:
12121  xexp += 1;
12122  if ( xexp >= SYSIZE ) {
12123  xexp = 0;
12124  }
12125 
12126  break;
12127  case 3:
12128  yexp -= 1;
12129  if ( yexp < 0 ) {
12130  yexp = ( SYSIZEM1 );
12131  }
12132 
12133  break;
12134  case 4:
12135  yexp += 1;
12136  if ( yexp >= SYSIZE ) {
12137  yexp = 0;
12138  }
12139 
12140  break;
12141  case 5:
12142  zexp -= 1;
12143  if ( zexp < 0 ) {
12144  zexp = ( SYSIZEM1 );
12145  }
12146 
12147  break;
12148  case 6:
12149  zexp += 1;
12150  if ( zexp >= SYSIZE ) {
12151  zexp = 0;
12152  }
12153 
12154  break;
12155  default:
12156  break;
12157  }
12158  }
12159 
12160  /* probabilistic-based expansion for last FREIDEL pixel */
12161  pexp = ran1(seed);
12162  if ( pexp <= 0.3295 ) {
12163  newact = extfreidel(xexp, yexp, zexp);
12164  }
12165  }
12166  /* examine reaction with diffusing CAS2 to form STRAT */
12167  /* Only allow reaction with diffusing (not solid) CAS2 */
12168  else if ( check == DIFFCAS2 ) {
12169  /* convert diffusing CAS2 to stratlingite */
12170  mic [ xnew ] [ ynew ] [ znew ] = STRAT;
12171  count [ STRAT ] += 1;
12172  /* decrement counts of diffusing CAS2 */
12173  count [ DIFFCAS2 ] -= 1;
12174  action = 0;
12175 
12176  /* convert diffusing C3A to solid STRAT or else leave as a diffusing C3A */
12177  pexp = ran1(seed);
12178  nexp = 3;
12179  if ( pexp <= 0.886 ) {
12180  mic [ xcur ] [ ycur ] [ zcur ] = STRAT;
12181  count [ STRAT ] += 1;
12182  count [ DIFFC4A ] -= 1;
12183  nexp = 2;
12184  } else {
12185  action = 7;
12186  nexp = 3;
12187  }
12188 
12189  /* Perform expansion that occurs when stratlingite is formed */
12190  /* xexp, yexp and zexp are the coordinates of the last STRAT */
12191  /* pixel to be added */
12192  xexp = xnew;
12193  yexp = ynew;
12194  zexp = znew;
12195  for ( iexp = 1; iexp <= nexp; iexp++ ) {
12196  newact = extstrat(xexp, yexp, zexp);
12197  /* update xexp, yexp and zexp */
12198  switch ( newact ) {
12199  case 1:
12200  xexp -= 1;
12201  if ( xexp < 0 ) {
12202  xexp = ( SYSIZEM1 );
12203  }
12204 
12205  break;
12206  case 2:
12207  xexp += 1;
12208  if ( xexp >= SYSIZE ) {
12209  xexp = 0;
12210  }
12211 
12212  break;
12213  case 3:
12214  yexp -= 1;
12215  if ( yexp < 0 ) {
12216  yexp = ( SYSIZEM1 );
12217  }
12218 
12219  break;
12220  case 4:
12221  yexp += 1;
12222  if ( yexp >= SYSIZE ) {
12223  yexp = 0;
12224  }
12225 
12226  break;
12227  case 5:
12228  zexp -= 1;
12229  if ( zexp < 0 ) {
12230  zexp = ( SYSIZEM1 );
12231  }
12232 
12233  break;
12234  case 6:
12235  zexp += 1;
12236  if ( zexp >= SYSIZE ) {
12237  zexp = 0;
12238  }
12239 
12240  break;
12241  default:
12242  break;
12243  }
12244  }
12245 
12246  /* probabilistic-based expansion for last STRAT pixel */
12247  pexp = ran1(seed);
12248  if ( pexp <= 0.286 ) {
12249  newact = extstrat(xexp, yexp, zexp);
12250  }
12251  }
12252 
12253  /* check for reaction with diffusing or solid ettringite to form AFm */
12254  /* reaction at solid ettringite only possible if ettringite is soluble */
12255  /* and even then on a limited bases to avoid a great formation of AFm */
12256  /* when ettringite first becomes soluble */
12257  pgrow = ran1(seed);
12258  if ( ( check == DIFFETTR ) || ( ( check == ETTR ) && ( soluble [ ETTR ] == 1 ) && ( pgrow <= C3AETTR ) ) ) {
12259  /* convert diffusing or solid ettringite to AFm */
12260  mic [ xnew ] [ ynew ] [ znew ] = AFM;
12261  count [ AFM ] += 1;
12262  /* decrement count of ettringite */
12263  count [ check ] -= 1;
12264  action = 0;
12265 
12266  /* convert diffusing C4A to AFm or leave as diffusing C4A */
12267  pexp = ran1(seed);
12268  if ( pexp <= 0.2424 ) {
12269  mic [ xcur ] [ ycur ] [ zcur ] = AFM;
12270  count [ AFM ] += 1;
12271  count [ DIFFC4A ] -= 1;
12272  pafm = ( -0.1 );
12273  } else {
12274  action = 7;
12275  pafm = 0.04699;
12276  }
12277 
12278  /* probabilistic-based expansion for new AFm pixel */
12279  pexp = ran1(seed);
12280  if ( pexp <= pafm ) {
12281  extafm(xnew, ynew, znew);
12282  }
12283  }
12284 
12285  if ( ( action != 0 ) && ( action != 7 ) ) {
12286  /* if diffusion is possible, execute it */
12287  if ( check == POROSITY ) {
12288  mic [ xcur ] [ ycur ] [ zcur ] = POROSITY;
12289  mic [ xnew ] [ ynew ] [ znew ] = DIFFC4A;
12290  } else {
12291  /* indicate that diffusing C4A remained */
12292  /* at original location */
12293  action = 7;
12294  }
12295  }
12296  }
12297 
12298  return ( action );
12299 
12300  ( void ) sumgarb;
12301 }
12302 
12303 /* routine to oversee hydration by updating position of all */
12304 /* remaining diffusing species */
12305 /* Calls movech, movec3a, movefh3, moveettr, movecsh, and movegyp */
12306 
12307 void CemhydMatStatus :: hydrate(int fincyc, int stepmax, float chpar1, float chpar2, float hgpar1, float hgpar2, float fhpar1, float fhpar2, float gypar1, float gypar2)
12308 {
12309  int xpl, ypl, zpl, phpl, agepl, xpnew, ypnew, zpnew;
12310  float chprob, c3ah6prob, fh3prob, gypprob;
12311  long int nleft, ntodo, ndale;
12312  int istep, termflag, reactf = -1;
12313  float beterm;
12314  struct ants *curant, *antgone;
12315 
12316  ntodo = nmade;
12317  nleft = nmade;
12318  termflag = 0;
12319 
12320  /* Perform diffusion until all reacted or max. # of diffusion steps reached */
12321  for ( istep = 1; ( ( istep <= stepmax ) && ( nleft > 0 ) ); istep++ ) {
12322  if ( ( fincyc == 1 ) && ( istep == stepmax ) ) {
12323  termflag = 1;
12324  }
12325 
12326  nleft = 0;
12327  ndale = 0;
12328 
12329  /* determine probabilities for CH and C3AH6 nucleation */
12330  beterm = exp(-( double ) ( count [ DIFFCH ] ) * 1000000. / SYSIZE_POW3 / chpar2); //fixed
12331  chprob = chpar1 * ( 1. - beterm );
12332  beterm = exp(-( double ) ( count [ DIFFC3A ] ) * 1000000. / SYSIZE_POW3 / hgpar2); //fixed
12333  c3ah6prob = hgpar1 * ( 1. - beterm );
12334  beterm = exp(-( double ) ( count [ DIFFFH3 ] ) * 1000000. / SYSIZE_POW3 / fhpar2); //fixed
12335  fh3prob = fhpar1 * ( 1. - beterm );
12336  beterm = exp(-( double ) ( count [ DIFFANH ] + count [ DIFFHEM ] ) * 1000000. / SYSIZE_POW3 / gypar2); //fixed
12337  gypprob = gypar1 * ( 1. - beterm );
12338 
12339  /* Process each diffusing species in turn */
12340  curant = headant->nextant;
12341  while ( curant != NULL ) {
12342  ndale += 1;
12343  xpl = curant->x;
12344  ypl = curant->y;
12345  zpl = curant->z;
12346  phpl = curant->id;
12347  agepl = curant->cycbirth;
12348 
12349  /* based on ID, call appropriate routine to process diffusing species */
12350  if ( phpl == DIFFCSH ) {
12351  /* printf("Calling movecsh \n");
12352  * fflush(stdout); */
12353  reactf = movecsh(xpl, ypl, zpl, termflag, agepl);
12354  } else if ( phpl == DIFFANH ) {
12355  /* printf("Calling moveanh \n");
12356  * fflush(stdout); */
12357  reactf = moveanh(xpl, ypl, zpl, termflag, gypprob);
12358  } else if ( phpl == DIFFHEM ) {
12359  /* printf("Calling movehem \n");
12360  * fflush(stdout); */
12361  reactf = movehem(xpl, ypl, zpl, termflag, gypprob);
12362  } else if ( phpl == DIFFCH ) {
12363  /* printf("Calling movech \n");
12364  * fflush(stdout); */
12365  reactf = movech(xpl, ypl, zpl, termflag, chprob);
12366  } else if ( phpl == DIFFFH3 ) {
12367  /* printf("Calling movefh3 \n");
12368  * fflush(stdout); */
12369  reactf = movefh3(xpl, ypl, zpl, termflag, fh3prob);
12370  } else if ( phpl == DIFFGYP ) {
12371  /* printf("Calling movegyp \n");
12372  * fflush(stdout); */
12373  reactf = movegyp(xpl, ypl, zpl, termflag);
12374  } else if ( phpl == DIFFC3A ) {
12375  /* printf("Calling movec3a \n");
12376  * fflush(stdout); */
12377  reactf = movec3a(xpl, ypl, zpl, termflag, c3ah6prob);
12378  } else if ( phpl == DIFFC4A ) {
12379  /* printf("Calling movec4a \n");
12380  * fflush(stdout); */
12381  reactf = movec4a(xpl, ypl, zpl, termflag, c3ah6prob);
12382  } else if ( phpl == DIFFETTR ) {
12383  /* printf("Calling moveettr \n");
12384  * fflush(stdout); */
12385  reactf = moveettr(xpl, ypl, zpl, termflag);
12386  } else if ( phpl == DIFFCACL2 ) {
12387  /* printf("Calling movecacl2 \n");
12388  * fflush(stdout); */
12389  reactf = movecacl2(xpl, ypl, zpl, termflag);
12390  } else if ( phpl == DIFFCAS2 ) {
12391  /* printf("Calling movecas2 \n");
12392  * fflush(stdout); */
12393  reactf = movecas2(xpl, ypl, zpl, termflag);
12394  } else if ( phpl == DIFFAS ) {
12395  /* printf("Calling moveas \n");
12396  * fflush(stdout); */
12397  reactf = moveas(xpl, ypl, zpl, termflag);
12398  } else if ( phpl == DIFFCACO3 ) {
12399  /* printf("Calling movecaco3 \n");
12400  * fflush(stdout); */
12401  reactf = movecaco3(xpl, ypl, zpl, termflag);
12402  } else {
12403  printf("Error in ID of phase \n");
12404  }
12405 
12406  /* if no reaction */
12407  if ( reactf != 0 ) {
12408  nleft += 1;
12409  xpnew = xpl;
12410  ypnew = ypl;
12411  zpnew = zpl;
12412 
12413  /* update location of diffusing species */
12414  switch ( reactf ) {
12415  case 1:
12416  xpnew -= 1;
12417  if ( xpnew < 0 ) {
12418  xpnew = ( SYSIZEM1 );
12419  }
12420 
12421  break;
12422  case 2:
12423  xpnew += 1;
12424  if ( xpnew >= SYSIZE ) {
12425  xpnew = 0;
12426  }
12427 
12428  break;
12429  case 3:
12430  ypnew -= 1;
12431  if ( ypnew < 0 ) {
12432  ypnew = ( SYSIZEM1 );
12433  }
12434 
12435  break;
12436  case 4:
12437  ypnew += 1;
12438  if ( ypnew >= SYSIZE ) {
12439  ypnew = 0;
12440  }
12441 
12442  break;
12443  case 5:
12444  zpnew -= 1;
12445  if ( zpnew < 0 ) {
12446  zpnew = ( SYSIZEM1 );
12447  }
12448 
12449  break;
12450  case 6:
12451  zpnew += 1;
12452  if ( zpnew >= SYSIZE ) {
12453  zpnew = 0;
12454  }
12455 
12456  break;
12457  default:
12458  break;
12459  }
12460 
12461  /* store new location of diffusing species */
12462  curant->x = xpnew;
12463  curant->y = ypnew;
12464  curant->z = zpnew;
12465  curant->id = phpl;
12466  curant = curant->nextant;
12467  } /* end of reactf!=0 loop */
12468  /* else remove ant from list */
12469  else {
12470  if ( ndale == 1 ) {
12471  headant->nextant = curant->nextant;
12472  } else {
12473  ( curant->prevant )->nextant = curant->nextant;
12474  }
12475 
12476  if ( curant->nextant != NULL ) {
12477  ( curant->nextant )->prevant = curant->prevant;
12478  } else {
12479  tailant = curant->prevant;
12480  }
12481 
12482  antgone = curant;
12483  curant = curant->nextant;
12484  //printf("DEMEM antgone addr %p\n", (const void *)antgone);
12485  free(antgone);
12486  ngoing -= 1;
12487  }
12488  }
12489 
12490  /* end of curant loop */
12491  ntodo = nleft;
12492  }
12493 
12494  /* end of istep loop */
12495  ( void ) ntodo;
12496 }
12497 
12498 
12499 void CemhydMatStatus :: laguer(fcomplex_cem a[], int m, fcomplex_cem *x, float eps, int polish)
12500 {
12501  int j, iter;
12502  float err, dxold, cdx, abx;
12503  fcomplex_cem sq, h, gp, gm, g2, g, b, d, dx, f, x1;
12504 
12505  dxold = Cabs(* x);
12506  for ( iter = 1; iter <= MAXIT; iter++ ) {
12507  b = a [ m ];
12508  err = Cabs(b);
12509  d = f = ComplexCemhyd(0.0, 0.0);
12510  abx = Cabs(* x);
12511  for ( j = m - 1; j >= 0; j-- ) {
12512  f = Cadd(Cmul(* x, f), d);
12513  d = Cadd(Cmul(* x, d), b);
12514  b = Cadd(Cmul(* x, b), a [ j ]);
12515  err = Cabs(b) + abx * err;
12516  }
12517 
12518  err *= EPSS;
12519  if ( Cabs(b) <= err ) {
12520  return;
12521  }
12522 
12523  g = Cdiv(d, b);
12524  g2 = Cmul(g, g);
12525  h = Csub( g2, RCmul( 2.0, Cdiv(f, b) ) );
12526  sq = Csqrt( RCmul( ( float ) ( m - 1 ), Csub(RCmul( ( float ) m, h ), g2) ) );
12527  gp = Cadd(g, sq);
12528  gm = Csub(g, sq);
12529  if ( Cabs(gp) < Cabs(gm) ) {
12530  gp = gm;
12531  }
12532 
12533  dx = Cdiv(ComplexCemhyd( ( float ) m, 0.0 ), gp);
12534  x1 = Csub(* x, dx);
12535  if ( x->r == x1.r && x->i == x1.i ) {
12536  return;
12537  }
12538 
12539  * x = x1;
12540  cdx = Cabs(dx);
12541  if ( iter > 6 && cdx >= dxold ) {
12542  return;
12543  }
12544 
12545  dxold = cdx;
12546  if ( !polish ) {
12547  if ( cdx <= eps * Cabs(* x) ) {
12548  return;
12549  }
12550  }
12551  }
12552 
12553  nrerror("Too many iterations in routine CemhydMat - LAGUER\n");
12554 }
12555 
12556 
12557 
12558 void CemhydMatStatus :: zroots(fcomplex_cem a[], int m, fcomplex_cem roots[], int polish)
12559 {
12560  int jj, j, i;
12561  fcomplex_cem x, b, c;
12562  fcomplex_cem *ad;
12563  //void laguer();fixed-no influence
12564  ad = new fcomplex_cem [ MAXM ];
12565 
12566  for ( j = 0; j <= m; j++ ) {
12567  ad [ j ] = a [ j ];
12568  }
12569 
12570  for ( j = m; j >= 1; j-- ) {
12571  x = ComplexCemhyd(0.0, 0.0);
12572  laguer(ad, j, & x, EPSP, 0);
12573  if ( fabs(x.i) <= ( 2.0 * EPSP * fabs(x.r) ) ) {
12574  x.i = 0.0;
12575  }
12576 
12577  roots [ j ] = x;
12578  b = ad [ j ];
12579  for ( jj = j - 1; jj >= 0; jj-- ) {
12580  c = ad [ jj ];
12581  ad [ jj ] = b;
12582  b = Cadd(Cmul(x, b), c);
12583  }
12584  }
12585 
12586  if ( polish ) {
12587  for ( j = 1; j <= m; j++ ) {
12588  laguer(a, m, & roots [ j ], EPSP, 1);
12589  }
12590  }
12591 
12592  for ( j = 2; j <= m; j++ ) {
12593  x = roots [ j ];
12594  for ( i = j - 1; i >= 1; i-- ) {
12595  if ( roots [ i ].r <= x.r ) {
12596  break;
12597  }
12598 
12599  roots [ i + 1 ] = roots [ i ];
12600  }
12601 
12602  roots [ i + 1 ] = x;
12603  }
12604 
12605  delete [] ad;
12606 }
12607 
12608 
12609 
12611 { //dangerous function - can lead to zero division etc.
12612  int j, syngen_change = 0, syn_old = 0, counter = 0;
12613  double concnaplus, conckplus;
12614  double concohminus = 0., A, B, C, conctest, concsulfate1;
12615  double volpore, grams_cement;
12616  double releasedna, releasedk, activitySO4, activityK, test_precip;
12617  double activityCa, activityOH, Istrength, Anow, Bnow, Inew;
12618  double conductivity = 0.0;
12619  fcomplex_cem coef [ 5 ], roots [ 5 ];
12620  float sumbest, sumtest, pozzreact, KspCH;
12621 
12622  /* Update CH activity product based on current system temperature */
12623  /* Factors derived from fitting CH solubility vs. temperature */
12624  /* data in Taylor book (p. 117) */
12625  KspCH = KspCH25C * ( 1.534385 - 0.02057 * temp_cur );
12626 
12627  if ( conccaplus > 1.0 ) {
12628  conccaplus = 0.0;
12629  }
12630 
12631  /* Calculate volume of pore solution in the concrete in Liters */
12632  volpore = ( double ) count [ POROSITY ] + 0.38 * ( double ) count [ CSH ] + 0.20 * ( double ) count [ POZZCSH ] + 0.20 * count [ SLAGCSH ]; //relative amount, no need to rescale
12633  /* Convert from pixels (cubic micrometers) to liters (cubic decimeters) */
12634  volpore *= VOLFACTOR;
12635  volpore *= VOLFACTOR;
12636  volpore *= VOLFACTOR;
12637  /* Compute pore volume per gram of cement */
12638  grams_cement = cemmasswgyp * MASSFACTOR * MASSFACTOR * MASSFACTOR;
12639  /* Compute pore volume per gram of cement */
12640  volpore /= grams_cement;
12641  /* Compute grams of pozzolan which have reacted */
12642  pozzreact = ( ( float ) npr / 1.35 ) * MASSFACTOR * MASSFACTOR * MASSFACTOR * specgrav [ POZZ ];
12643 
12644  /* Compute moles of released potassium and sodium per gram of cement*/
12645  if ( time_cur > 1.0 ) {
12646  releasedk = ( 2. * ( rspotassium + ( totpotassium - rspotassium ) * alpha_cur ) );
12647  releasedk /= MMK2O;
12648  releasedna = ( 2. * ( rssodium + ( totsodium - rssodium ) * alpha_cur ) );
12649  releasedna /= MMNa2O;
12650  } else {
12651  /* Proportion the early time release over the first hour */
12652  /* 90% immediately and the remaining 10% over the first hour */
12653  /* based on limited data from Davide Zampini (MBT) */
12654  releasedk = ( 2. * ( ( 0.9 + 0.1 * time_cur ) * ( rspotassium ) + ( totpotassium - rspotassium ) * alpha_cur ) );
12655  releasedk /= MMK2O;
12656  releasedna = ( 2. * ( ( 0.9 + 0.1 * time_cur ) * ( rssodium ) + ( totsodium - rssodium ) * alpha_cur ) );
12657  releasedna /= MMNa2O;
12658  }
12659 
12660  /* Compute concentrations of K+ and Na+ in pore solution currently */
12661  /* Remember to decrease K+ by KperSyn*moles of syngenite precipitated */
12662  /* Units must be in moles/gram for both */
12663  conckplus = ( ( releasedk - moles_syn_precip * KperSyn ) / ( volpore + BK * alpha_cur + BprimeK * pozzreact ) );
12664  concnaplus = ( releasedna ) / ( volpore + BNa * alpha_cur + BprimeNa * pozzreact );
12665 
12666  do { /* while Syngenite precipitating loop */
12667  /* Now compute the activities (estimated) of Ca++ and OH- */
12668  activityCa = activityOH = activitySO4 = activityK = 1.0;
12669  Inew = 0.0;
12670  if ( ( ( concnaplus + conckplus ) > 0.0 ) && ( soluble [ ETTR ] == 0 ) ) {
12671  /* Factor of 1000 to convert from M to mmol/L */
12672  Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12673  if ( Istrength < 1.0 ) {
12674  Istrength = 1.0;
12675  }
12676 
12677  while ( ( fabs(Istrength - Inew) / Istrength ) > 0.10 ) {
12678  Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12679  if ( Istrength < 1.0 ) {
12680  Istrength = 1.0;
12681  }
12682 
12683  Anow = activeA0 * 295. * sqrt(295.) / ( ( temp_cur + 273.15 ) * sqrt(temp_cur + 273.15) );
12684  Bnow = activeB0 * sqrt(295.) / ( sqrt(temp_cur + 273.15) );
12685  /* Equations from papers of Marchand et al. */
12686  activityCa = ( -Anow * zCa * zCa * sqrt(Istrength) ) / ( 1. + aCa * Bnow * sqrt(Istrength) );
12687  activityCa += ( 0.2 - 0.0000417 * Istrength ) * Anow * zCa * zCa * Istrength / sqrt(1000.);
12688  activityCa = exp(activityCa);
12689  activityOH = ( -Anow * zOH * zOH * sqrt(Istrength) ) / ( 1. + aOH * Bnow * sqrt(Istrength) );
12690  activityOH += ( 0.2 - 0.0000417 * Istrength ) * Anow * zOH * zOH * Istrength / sqrt(1000.);
12691  activityOH = exp(activityOH);
12692  activityK = ( -Anow * zK * zK * sqrt(Istrength) ) / ( 1. + aK * Bnow * sqrt(Istrength) );
12693  activityK += ( 0.2 - 0.0000417 * Istrength ) * Anow * zK * zK * Istrength / sqrt(1000.);
12694  activityK = exp(activityK);
12695  activitySO4 = ( -Anow * zSO4 * zSO4 * sqrt(Istrength) ) / ( 1. + aSO4 * Bnow * sqrt(Istrength) );
12696  activitySO4 += ( 0.2 - 0.0000417 * Istrength ) * Anow * zSO4 * zSO4 * Istrength / sqrt(1000.);
12697  activitySO4 = exp(activitySO4);
12698  /* Now try to find roots of fourth degree polynomial */
12699  /* to determine sulfate, OH-, and calcium ion concentrations */
12700  /* A=(-KspCH); */
12701  /* Now with activities */
12702  A = ( -KspCH / ( activityCa * activityOH * activityOH ) );
12703  B = conckplus + concnaplus;
12704  C = ( -2. * KspGypsum / ( activityCa * activitySO4 ) );
12705  concohminus = conckplus + concnaplus;
12706  coef [ 0 ] = ComplexCemhyd(C, 0.0);
12707  coef [ 1 ] = ComplexCemhyd( ( A + 2. * B * C ) / C, 0.0 );
12708  coef [ 2 ] = ComplexCemhyd(B * B / C + 4., 0.0);
12709  coef [ 3 ] = ComplexCemhyd(4. * B / C, 0.0);
12710  coef [ 4 ] = ComplexCemhyd(4. / C, 0.0);
12711  /* printf("coef 0 is (%f,%f)\n",coef[0].r,coef[0].i);
12712  * printf("coef 1 is (%f,%f)\n",coef[1].r,coef[1].i);
12713  * printf("coef 2 is (%f,%f)\n",coef[2].r,coef[2].i);
12714  * printf("coef 3 is (%f,%f)\n",coef[3].r,coef[3].i);
12715  * printf("coef 4 is (%f,%f)\n",coef[4].r,coef[4].i); */
12716  roots [ 1 ] = ComplexCemhyd(0.0, 0.0);
12717  roots [ 2 ] = ComplexCemhyd(0.0, 0.0);
12718  roots [ 3 ] = ComplexCemhyd(0.0, 0.0);
12719  roots [ 4 ] = ComplexCemhyd(0.0, 0.0);
12720  zroots(coef, 4, roots, 1);
12721  sumbest = 100;
12722  /* Find the best real root for electoneutrality */
12723  for ( j = 1; j <= 4; j++ ) {
12724  //printf("pH root %d is (%f,%f)\n",j,roots[j].r,roots[j].i);
12725  fflush(stdout);
12726  if ( ( ( roots [ j ].i ) == 0.0 ) && ( ( roots [ j ].r ) > 0.0 ) ) {
12727  conctest = sqrt( KspCH / ( roots [ j ].r * activityCa * activityOH * activityOH ) );
12728  concsulfate1 = KspGypsum / ( roots [ j ].r * activityCa * activitySO4 );
12729  sumtest = concnaplus + conckplus + 2. * roots [ j ].r - conctest - 2. * concsulfate1;
12730  if ( fabs(sumtest) < sumbest ) {
12731  sumbest = fabs(sumtest);
12732  concohminus = conctest;
12733  conccaplus = roots [ j ].r;
12734  concsulfate = concsulfate1;
12735  }
12736  }
12737  }
12738 
12739  /* Update ionic strength */
12740  Inew = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12741  }
12742 
12743  /* end of while loop for Istrength-Inew */
12744  } else {
12745  /* Factor of 1000 to convert from M to mmol/L */
12746  Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12747  if ( Istrength < 1.0 ) {
12748  Istrength = 1.0;
12749  }
12750 
12751  while ( ( fabs(Istrength - Inew) / Istrength ) > 0.10 && counter < 4 ) {
12752  //add counter to limit to 3 iterations, normally it suffices but when high wcr it hangs - smilauer@cml.fsv.cvut.cz
12753  Istrength = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12754  Anow = activeA0 * 295. * sqrt(295.) / ( ( temp_cur + 273.15 ) * sqrt(temp_cur + 273.15) );
12755  Bnow = activeB0 * sqrt(295.) / ( sqrt(temp_cur + 273.15) );
12756  /* Equations from papers of Marchand et al. */
12757  activityCa = ( -Anow * zCa * zCa * sqrt(Istrength) ) / ( 1. + aCa * Bnow * sqrt(Istrength) );
12758  activityCa += ( 0.2 - 0.0000417 * Istrength ) * Anow * zCa * zCa * Istrength / sqrt(1000.);
12759  activityCa = exp(activityCa);
12760  activityOH = ( -Anow * zOH * zOH * sqrt(Istrength) ) / ( 1. + aOH * Bnow * sqrt(Istrength) );
12761  activityOH += ( 0.2 - 0.0000417 * Istrength ) * Anow * zOH * zOH * Istrength / sqrt(1000.);
12762  activityOH = exp(activityOH);
12763  activityK = ( -Anow * zK * zK * sqrt(Istrength) ) / ( 1. + aK * Bnow * sqrt(Istrength) );
12764  activityK += ( 0.2 - 0.0000417 * Istrength ) * Anow * zK * zK * Istrength / sqrt(1000.);
12765  activityK = exp(activityK);
12766  /* Calculate pH assuming simply that OH- balances sum of Na+ and K+ */
12767  concohminus = conckplus + concnaplus;
12768  if ( ( conccaplus ) > ( 0.1 * ( concohminus ) ) ) {
12769  concohminus += ( 2. * conccaplus );
12770  }
12771 
12772  conccaplus = ( KspCH / ( activityCa * activityOH * activityOH * concohminus * concohminus ) );
12773  concsulfate = 0.0;
12774  /* Update ionic strength */
12775  Inew = 1000. * ( zK * zK * conckplus + zNa * zNa * concnaplus + zCa * zCa * conccaplus );
12776  counter++;
12777  }
12778 
12779  /* end of while loop for Istrength-Inew */
12780  }
12781 
12782  /* Check for syngenite precipitation */
12783  syngen_change = 0;
12784  if ( syn_old != 2 ) {
12785  test_precip = conckplus * conckplus * activityK * activityK;
12786  test_precip *= conccaplus * activityCa;
12787  test_precip *= concsulfate * concsulfate * activitySO4 * activitySO4;
12788  if ( test_precip > KspSyngenite ) {
12789 #ifdef PRINTF
12790  printf("Syngenite precipitating at cycle %d\n", icyc);
12791 #endif
12792  syngen_change = syn_old = 1;
12793  /* Units of moles_syn_precip are moles per gram of cement */
12794  if ( conckplus > 0.002 ) {
12795  conckplus -= 0.001;
12796  moles_syn_precip += 0.001 * volpore / KperSyn;
12797  } else if ( conckplus > 0.0002 ) {
12798  conckplus -= 0.0001;
12799  moles_syn_precip += 0.0001 * volpore / KperSyn;
12800  } else {
12801  moles_syn_precip += conckplus * volpore / KperSyn;
12802  conckplus = 0.0;
12803  }
12804  }
12805 
12806  /* Check for syngenite dissolution */
12807  /* How to control dissolution rates??? */
12808  /* Have 0.001*KperSyn increase in conckplus each cycle */
12809  /* Only one dissolution per cycle --- purpose of syn_old */
12810  /* and no dissolution if some precipitation in that cycle */
12811  if ( ( syn_old == 0 ) && ( moles_syn_precip > 0.0 ) ) {
12812  syngen_change = syn_old = 2;
12813  /* conckplus+=(moles_syn_precip/10.0)/volpore; */
12814  if ( ( moles_syn_precip / volpore ) > 0.001 ) {
12815  conckplus += 0.001 * KperSyn;
12816  moles_syn_precip -= ( 0.001 * volpore );
12817  } else {
12818  conckplus += ( moles_syn_precip * KperSyn / volpore );
12819  moles_syn_precip = 0.0;
12820  }
12821  }
12822  }
12823  } while ( syngen_change != 0 );
12824 
12825  if ( concohminus < ( 0.0000001 ) ) {
12826  concohminus = 0.0000001;
12827  conccaplus = ( KspCH / ( activityCa * activityOH * activityOH * concohminus * concohminus ) );
12828  }
12829 
12830  pH_cur = 14.0 + log10(concohminus * activityOH);
12831  /* Calculation of solution conductivity (Snyder and Feng basis) */
12832  /* First convert ionic strength back to M units */
12833  Istrength /= 1000.;
12834  conductivity += zCa * conccaplus * ( lambdaCa_0 / ( 1. + GCa * sqrt(Istrength) ) );
12835  conductivity += zOH * concohminus * ( lambdaOH_0 / ( 1. + GOH * sqrt(Istrength) ) );
12836  conductivity += zNa * concnaplus * ( lambdaNa_0 / ( 1. + GNa * sqrt(Istrength) ) );
12837  conductivity += zK * conckplus * ( lambdaK_0 / ( 1. + GK * sqrt(Istrength) ) );
12838  conductivity += zSO4 * concsulfate * ( lambdaSO4_0 / ( 1. + GSO4 * sqrt(Istrength) ) );
12839  conductivity *= cm2perL2m;
12840 
12841  /* Output results to logging file */
12842 #ifdef OUTFILES
12843  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);
12844  fflush(pHfile);
12845 #endif
12846 }
12847 
12848 
12850 {
12851  if ( ( phase >= C3S && phase <= ABSGYP ) || ( phase == HDCSH ) ) {
12852  return 1;
12853  } else {
12854  return 0;
12855  }
12856 }
12857 
12858 void CemhydMatStatus :: burn_phases(int d1, int d2, int d3)
12859 {
12860  long int icur, inew, ncur, nnew;
12861  int i, j, k, cnt_perc, cnt_tot, kh;
12862  int *nmatx, *nmaty, *nmatz;
12863  int xl, xh, j1, k1, px, py, pz, qx, qy, qz;
12864  int xcn, ycn, zcn, x1, y1, z1, igood;
12865  int *nnewx, *nnewy, *nnewz;
12866  int jnew;
12867  int phase_temp [ 51 ];
12868  char ***newmat;
12869 
12870 
12871  alloc_char_3D(newmat, SYSIZE);
12872  nmatx = new int [ SIZESET ];
12873  nmaty = new int [ SIZESET ];
12874  nmatz = new int [ SIZESET ];
12875  nnewx = new int [ SIZESET ];
12876  nnewy = new int [ SIZESET ];
12877  nnewz = new int [ SIZESET ];
12878 
12879  last = NULL;
12880 
12881  /* counters for number of pixels of phase accessible from surface #1 */
12882  /* and number which are part of a percolated pathway to surface #2 */
12883  /* create copy of original microstructure to newmat[][][]*/
12884  /* array mic_CSH[][][] will not be changed through this routine */
12885  /* phase_temp[] and phase[] are for phases storage in percolated pathway */
12886  // ntop=0;
12887  // nthrough=0;
12888  for ( k = 0; k < SYSIZE; k++ ) {
12889  for ( j = 0; j < SYSIZE; j++ ) {
12890  for ( i = 0; i < SYSIZE; i++ ) {
12891  newmat [ i ] [ j ] [ k ] = mic_CSH [ i ] [ j ] [ k ];
12892  //assign 0 or EMPTYP to ArrPerc[][][]
12893  if ( mic_CSH [ i ] [ j ] [ k ] == EMPTYP ) {
12894  ArrPerc [ i ] [ j ] [ k ] = EMPTYP;
12895  } else {
12896  ArrPerc [ i ] [ j ] [ k ] = 0;
12897  }
12898  }
12899  }
12900  }
12901 
12902  for ( k = 0; k < 51; k++ ) {
12903  phase [ k ] = 0;
12904  }
12905 
12906  /* percolation is assessed from top to bottom only */
12907  /* in transformed coordinates */
12908  /* and burning algorithm is periodic in other two directions */
12909  i = 0;
12910 
12911  for ( k = 0; k < SYSIZE; k++ ) {
12912  for ( j = 0; j < SYSIZE; j++ ) {
12913  igood = 0;
12914  ncur = 0;
12915  for ( kh = 0; kh < 51; kh++ ) {
12916  phase_temp [ kh ] = 0;
12917  }
12918 
12919 
12920  //delete all array in case of next cycle
12921  while ( last != NULL ) { //go through all voxel coordinates
12922  current = last;
12923  last = last->prev;
12924  /*deallocate memory*/
12925  delete current;
12926  }
12927 
12928  /* Transform coordinates */
12929  px = cx(i, j, k, d1, d2, d3);
12930  py = cy(i, j, k, d1, d2, d3);
12931  pz = cz(i, j, k, d1, d2, d3);
12932  /* start from any solid phase */
12933  if ( IsSolidPhase(newmat [ px ] [ py ] [ pz ]) == 1 ) {
12934  /* Start a burn front */
12935  phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
12936 
12937  //store in unnamed list
12938  WriteUnsortedList(px, py, pz);
12939  newmat [ px ] [ py ] [ pz ] = BURNT;
12940  ncur += 1;
12941 
12942 
12943 
12944  /* burn front is stored in matrices nmat* */
12945  /* and nnew* */
12946  nmatx [ ncur ] = i;
12947  nmaty [ ncur ] = j;
12948  nmatz [ ncur ] = k;
12949  /* Burn as long as new (fuel) pixels are found */
12950  do {
12951  nnew = 0;
12952  for ( inew = 1; inew <= ncur; inew++ ) {
12953  xcn = nmatx [ inew ];
12954  ycn = nmaty [ inew ];
12955  zcn = nmatz [ inew ];
12956  /* Convert to directional coordinates */
12957  qx = cx(xcn, ycn, zcn, d1, d2, d3);
12958  qy = cy(xcn, ycn, zcn, d1, d2, d3);
12959  qz = cz(xcn, ycn, zcn, d1, d2, d3);
12960 
12961  /* Check all six neighbors */
12962  for ( jnew = 1; jnew <= 6; jnew++ ) {
12963  x1 = xcn;
12964  y1 = ycn;
12965  z1 = zcn;
12966  if ( jnew == 1 ) {
12967  x1 -= 1;
12968  }
12969 
12970  if ( jnew == 2 ) {
12971  x1 += 1;
12972  }
12973 
12974  if ( jnew == 3 ) {
12975  y1 -= 1;
12976  }
12977 
12978  if ( jnew == 4 ) {
12979  y1 += 1;
12980  }
12981 
12982  if ( jnew == 5 ) {
12983  z1 -= 1;
12984  }
12985 
12986  if ( jnew == 6 ) {
12987  z1 += 1;
12988  }
12989 
12990  /* Periodic in y and */
12991  if ( y1 >= SYSIZE ) {
12992  y1 -= SYSIZE;
12993  } else if ( y1 < 0 ) {
12994  y1 += SYSIZE;
12995  }
12996 
12997  /* Periodic in z direction */
12998  if ( z1 >= SYSIZE ) {
12999  z1 -= SYSIZE;
13000  } else if ( z1 < 0 ) {
13001  z1 += SYSIZE;
13002  }
13003 
13004  /* Nonperiodic so be sure to remain in the 3-D box */
13005  if ( ( x1 >= 0 ) && ( x1 < SYSIZE ) ) {
13006  px = cx(x1, y1, z1, d1, d2, d3);
13007  py = cy(x1, y1, z1, d1, d2, d3);
13008  pz = cz(x1, y1, z1, d1, d2, d3);
13009  /* Conditions for propagation of burning */
13010  /* 1) new pixel is any solid except clinker phases */
13011 
13012  if ( ( IsSolidPhase(newmat [ px ] [ py ] [ pz ]) == 1 ) &&
13013  ( newmat [ px ] [ py ] [ pz ] != C3S ) &&
13014  ( newmat [ px ] [ py ] [ pz ] != C2S ) &&
13015  ( newmat [ px ] [ py ] [ pz ] != C3A ) &&
13016  ( newmat [ px ] [ py ] [ pz ] != C4AF ) ) {
13017  /*
13018  * if((newmat[px][py][pz]==CSH)||(newmat[px][py][pz]==ETTRC4AF)||(newmat[px][py][pz]==ETTR)){
13019  */
13020  phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
13021  WriteUnsortedList(px, py, pz);
13022  newmat [ px ] [ py ] [ pz ] = BURNT;
13023  nnew += 1;
13024  if ( nnew >= SIZESET ) {
13025  printf("error in size of nnew %ld\n", nnew);
13026  }
13027 
13028  nnewx [ nnew ] = x1;
13029  nnewy [ nnew ] = y1;
13030  nnewz [ nnew ] = z1;
13031  }
13032  /* 2) old pixel is solid except clinker and new pixel is one of cement clinker phases */
13033  else if ( ( ( IsSolidPhase(mic_CSH [ qx ] [ qy ] [ qz ]) == 1 ) &&
13034  ( mic_CSH [ qx ] [ qy ] [ qz ] != C3S ) &&
13035  ( mic_CSH [ qx ] [ qy ] [ qz ] != C2S ) &&
13036  ( mic_CSH [ qx ] [ qy ] [ qz ] != C3A ) &&
13037  ( mic_CSH [ qx ] [ qy ] [ qz ] != C4AF ) ) &&
13038  ( ( newmat [ px ] [ py ] [ pz ] == C3S ) ||
13039  ( newmat [ px ] [ py ] [ pz ] == C2S ) ||
13040  ( newmat [ px ] [ py ] [ pz ] == C3A ) ||
13041  ( newmat [ px ] [ py ] [ pz ] == C4AF ) ) ) {
13042  phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
13043  WriteUnsortedList(px, py, pz);
13044  newmat [ px ] [ py ] [ pz ] = BURNT;
13045  nnew += 1;
13046  if ( nnew >= SIZESET ) {
13047  printf("error in size of nnew %ld\n", nnew);
13048  }
13049 
13050  nnewx [ nnew ] = x1;
13051  nnewy [ nnew ] = y1;
13052  nnewz [ nnew ] = z1;
13053  }
13054  /* 3) old and new pixels belong to one of cement clinker phases and */
13055  /* are contained in the same initial cement particle */
13056  else if ( ( micpart [ qx ] [ qy ] [ qz ] == micpart [ px ] [ py ] [ pz ] ) &&
13057  ( ( newmat [ px ] [ py ] [ pz ] == C3S ) ||
13058  ( newmat [ px ] [ py ] [ pz ] == C2S ) ||
13059  ( newmat [ px ] [ py ] [ pz ] == C3A ) ||
13060  ( newmat [ px ] [ py ] [ pz ] == C4AF ) ) &&
13061  ( ( mic_CSH [ qx ] [ qy ] [ qz ] == C3S ) ||
13062  ( mic_CSH [ qx ] [ qy ] [ qz ] == C2S ) ||
13063  ( mic_CSH [ qx ] [ qy ] [ qz ] == C3A ) ||
13064  ( mic_CSH [ qx ] [ qy ] [ qz ] == C4AF ) ) ) {
13065  // ntot+=1;
13066  phase_temp [ ( int ) newmat [ px ] [ py ] [ pz ] ]++;
13067  WriteUnsortedList(px, py, pz);
13068  newmat [ px ] [ py ] [ pz ] = BURNT;
13069  nnew += 1;
13070  if ( nnew >= SIZESET ) {
13071  printf("error in size of nnew %ld\n", nnew);
13072  }
13073 
13074  nnewx [ nnew ] = x1;
13075  nnewy [ nnew ] = y1;
13076  nnewz [ nnew ] = z1;
13077  }
13078  }
13079 
13080  /* nonperiodic if delimiter */
13081  }
13082 
13083  /* neighbors loop */
13084  }
13085 
13086  /* propagators loop */
13087  if ( nnew > 0 ) {
13088  ncur = nnew;
13089  /* update the burn front matrices */
13090  for ( icur = 1; icur <= ncur; icur++ ) {
13091  nmatx [ icur ] = nnewx [ icur ];
13092  nmaty [ icur ] = nnewy [ icur ];
13093  nmatz [ icur ] = nnewz [ icur ];
13094  }
13095  }
13096  } while ( nnew > 0 );
13097 
13098  // ntop+=ntot;
13099  xl = 0;
13100  xh = SYSIZE - 1;
13101  /* Check for percolated path through system */
13102  for ( j1 = 0; j1 < SYSIZE; j1++ ) {
13103  for ( k1 = 0; k1 < SYSIZE; k1++ ) {
13104  px = cx(xl, j1, k1, d1, d2, d3);
13105  py = cy(xl, j1, k1, d1, d2, d3);
13106  pz = cz(xl, j1, k1, d1, d2, d3);
13107  qx = cx(xh, j1, k1, d1, d2, d3);
13108  qy = cy(xh, j1, k1, d1, d2, d3);
13109  qz = cz(xh, j1, k1, d1, d2, d3);
13110  if ( ( newmat [ px ] [ py ] [ pz ] == BURNT ) && ( newmat [ qx ] [ qy ] [ qz ] == BURNT ) ) {
13111  igood = 2;
13112  }
13113 
13114  if ( newmat [ px ] [ py ] [ pz ] == BURNT ) {
13115  newmat [ px ] [ py ] [ pz ] = BURNT + 1;
13116  }
13117 
13118  if ( newmat [ qx ] [ qy ] [ qz ] == BURNT ) {
13119  newmat [ qx ] [ qy ] [ qz ] = BURNT + 1;
13120  }
13121  }
13122  }
13123 
13124  if ( igood == 2 ) {
13125  // nthrough+=ntot;
13126 
13127  while ( last != NULL ) { //go through all voxel coordinates
13128  ArrPerc [ last->x ] [ last->y ] [ last->z ] = mic_CSH [ last->x ] [ last->y ] [ last->z ];
13129  // printf("AAA%d %d %d\n", last->x, last->y, last->z);
13130  current = last;
13131  last = last->prev;
13132  /*deallocate memory*/
13133  delete current;
13134  }
13135 
13136 
13137  for ( kh = 0; kh < 51; kh++ ) {
13138  phase [ kh ] += phase_temp [ kh ];
13139  }
13140  }
13141  }
13142 
13143  //if(IsSolidPhase(newmat [px] [py] [pz])==1)
13144  }
13145 
13146  //loop j
13147  }
13148 
13149  //loop k
13150 
13151  //GenerateConnNumbers();//only for FEM analysis
13152 
13153  //output only solid phases in percolation path
13154 #ifdef IMAGEFILES
13156 #endif
13157 
13158  cnt_perc = 0;
13159  for ( kh = 0; kh < 51; kh++ ) {
13160  cnt_perc += phase [ kh ];
13161  }
13162 
13163 #ifdef OUTFILES
13164  fprintf(perc_phases, "%d %f %f %d ", cyccnt, time_cur, alpha_cur, cnt_perc);
13165 #endif
13166  cnt_tot = 0;
13167  phase [ EMPTYP ] = count [ EMPTYP ];
13168 
13169  /* calculate sum of all solid phases*/
13170  for ( kh = 1; kh <= HDCSH; kh++ ) {
13171  if ( ( kh >= DIFFCSH && kh <= EMPTYP ) || kh == HDCSH ) {
13172  continue;
13173  }
13174 
13175  cnt_tot += count [ kh ];
13176  }
13177 
13178 #ifdef OUTFILES
13179  fprintf(perc_phases, "%d %f | ", cnt_tot, ( double ) cnt_perc / cnt_tot);
13180  for ( kh = 0; kh <= HDCSH; kh++ ) {
13181  if ( kh > ABSGYP && kh < EMPTYP ) {
13182  continue;
13183  }
13184 
13185  //assign EMPTYP to percolated path (used in homogenization)
13186  phase [ EMPTYP ] = count [ EMPTYP ];
13187  fprintf(perc_phases, "%ld %ld ",
13188  phase [ kh ], kh == CSH ? ( count [ CSH ] - count [ HDCSH ] ) : count [ kh ]);
13189  }
13190 
13191  fprintf(perc_phases, "\n");
13192  fflush(perc_phases);
13193 #endif
13194 
13195  dealloc_char_3D(newmat, SYSIZE);
13196  delete [] nmatx;
13197  delete [] nmaty;
13198  delete [] nmatz;
13199  delete [] nnewx;
13200  delete [] nnewy;
13201  delete [] nnewz;
13202 }
13203 
13204 
13205 /*Check whether two adjacent voxels by side are/aren't connected
13206  * i.e. if they are in the percolated pathway.
13207  * Return function will always terminate loops.
13208  * Return 0 if one of phases is not solid.
13209  * Return 1 if phases are solid and are disconnected.
13210  * Return 2 if phases are solid and connected.
13211  */
13212 
13213 int CemhydMatStatus :: IsConnected(int cx, int cy, int cz, int dx, int dy, int dz)
13214 {
13215  int CentPhase, NeighPhase;
13216 
13217  CentPhase = ArrPerc [ AdjCoord(cx) ] [ AdjCoord(cy) ] [ AdjCoord(cz) ];
13218  if ( IsSolidPhase(CentPhase) ) { //is non-zero
13219  NeighPhase = ArrPerc [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ];
13220 
13221  //skip non-solid phases
13222  if ( IsSolidPhase(NeighPhase) ) { //is non-zero
13223  /* 1) old voxel is any solid, new voxel is any
13224  * solid except clinker phases */
13225  if ( ( NeighPhase != C3S ) &&
13226  NeighPhase != C2S &&
13227  NeighPhase != C3A &&
13228  NeighPhase != C4AF ) {
13229  return 2;
13230  }
13231  /*2) old voxel is solid except clinker and new voxel is one
13232  * of cement clinker phases */
13233  else if ( ( CentPhase != C3S &&
13234  CentPhase != C2S &&
13235  CentPhase != C3A &&
13236  CentPhase != C4AF ) &&
13237  ( NeighPhase == C3S ||
13238  NeighPhase == C2S ||
13239  NeighPhase == C3A ||
13240  NeighPhase == C4AF ) ) {
13241  return 2;
13242  }
13243  /* 3) old and new voxels belong to one of cement clinker phases and
13244  * are contained in the same initial cement particle
13245  * one-voxel particles have also non-zero ID number*/
13246  else if ( ( micpart [ AdjCoord(cx) ] [ AdjCoord(cy) ] [ AdjCoord(cz) ] ==
13247  micpart [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ] ) &&
13248  ( CentPhase == C3S ||
13249  CentPhase == C2S ||
13250  CentPhase == C3A ||
13251  CentPhase == C4AF ) &&
13252  ( NeighPhase == C3S ||
13253  NeighPhase == C2S ||
13254  NeighPhase == C3A ||
13255  NeighPhase == C4AF ) ) {
13256  return 2;
13257  } else {
13258  return 1;
13259  }
13260  }
13261 
13262  //IsSolidPhase(NeighPhase)
13263  return 0;
13264  }
13265 
13266  //IsSolidPhase(CentPhase)
13267  return 0;
13268 }
13269 
13270 
13271 
13272 /*Routine to perform check of connected and disconnected phases
13273  * on percolated microstructure stored in ArrPerc[dx][dy][dz].
13274  * Can not be executed during percolation algorithm since whole microstructure
13275  * is unknown.
13276  * Each vertex has possible 8x multiple node.
13277  * Voxel coordinates are the closest to the vertex coordinates
13278  * in the positive octant.
13279  * Disconnected node is added to the array as the sum of vertexes
13280  * by the following scheme (Big Voxel):
13281  *
13282  * ---------4096
13283  * /. /|
13284  * / . 32|
13285  * / . 4 / 256
13286  * / . / 2 |
13287  ***|--16---512 |
13288  | .....|...2048
13289  | . 8 /
13290  | . 1 | 128
13291  ||||. | /
13292  * ----64---1024
13293  *
13294  * e.g. if number 1 is present, that means that solid voxel below is disconnected
13295  * number 1024 means that voxel in front, right and down is solid and disconnected
13296  *
13297  * z^
13298  |
13299  |
13300  * ----->y
13301  * /
13302  * /x
13303  * coordinates transformation is irrelevant, used x,y,z loop
13304  */
13306 {
13307  int cx, cy, cz;
13308  int CentPhase;
13309 
13310 
13311  for ( cz = 0; cz < SYSIZE; cz++ ) {
13312  for ( cy = 0; cy < SYSIZE; cy++ ) {
13313  for ( cx = 0; cx < SYSIZE; cx++ ) {
13314  //set zero values
13315  ConnNumbers [ cx ] [ cy ] [ cz ] = 0;
13316 
13317  //if voxel is any solid phase
13318  CentPhase = ArrPerc [ cx ] [ cy ] [ cz ];
13319  if ( IsSolidPhase(CentPhase) ) { //is non-zero value
13320  /*Each vertex has 7 surrouning neighbors, go through them
13321  * Return 0 if one of phases is not solid.
13322  * Return 1 if phases are solid and are disconnected.
13323  * Return 2 if phases are solid and connected.*/
13324 
13325  //(1) x+1
13326  if ( IsConnected(cx, cy, cz, 1, 0, 0) == 1 ) {
13327  ConnNumbers [ cx ] [ cy ] [ cz ] += 1;
13328  }
13329 
13330  //(2) y+1
13331  if ( IsConnected(cx, cy, cz, 0, 1, 0) == 1 ) {
13332  ConnNumbers [ cx ] [ cy ] [ cz ] += 2;
13333  }
13334 
13335  //(4) z+1
13336  if ( IsConnected(cx, cy, cz, 0, 0, 1) == 1 ) {
13337  ConnNumbers [ cx ] [ cy ] [ cz ] += 4;
13338  }
13339 
13340  /*(8) x+1, y+1, 2 possible ways of connection
13341  * voxel may not be connected to master (CentPhase), i.e.
13342  * not connected in first way && not connected in second way
13343  */
13344  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz) ]) ) {
13345  if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13346  IsConnected(cx + 1, cy, cz, 0, 1, 0) != 2 ) &&
13347  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13348  IsConnected(cx, cy + 1, cz, 1, 0, 0) != 2 ) ) {
13349  ConnNumbers [ cx ] [ cy ] [ cz ] += 8;
13350  }
13351  }
13352 
13353  /*(16) x+1, z+1, 2 possible ways of connection
13354  * voxel may not be connected to master (CentPhase), i.e.
13355  * not connected in first way && not connected in second way
13356  */
13357  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy) ] [ AdjCoord(cz + 1) ]) ) {
13358  if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13359  IsConnected(cx + 1, cy, cz, 0, 0, 1) != 2 ) &&
13360  ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13361  IsConnected(cx, cy, cz + 1, 1, 0, 0) != 2 ) ) {
13362  ConnNumbers [ cx ] [ cy ] [ cz ] += 16;
13363  }
13364  }
13365 
13366  /*(32) y+1, z+1, 2 possible ways of connection
13367  * voxel may not be connected to master (CentPhase), i.e.
13368  * not connected in first way && not connected in second way
13369  */
13370  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz + 1) ]) ) {
13371  if ( ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13372  IsConnected(cx, cy + 1, cz, 0, 0, 1) != 2 ) &&
13373  ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13374  IsConnected(cx, cy, cz + 1, 0, 1, 0) != 2 ) ) {
13375  ConnNumbers [ cx ] [ cy ] [ cz ] += 32;
13376  }
13377  }
13378 
13379  /*(64) x+1, z-1, 2 possible ways of connection
13380  * AdjCoord MUST be present at z direction
13381  * voxel may not be connected to master (CentPhase), i.e.
13382  * not connected in first way && not connected in second way
13383  */
13384  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy) ] [ AdjCoord(cz - 1) ]) ) {
13385  if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13386  IsConnected(cx + 1, cy, cz, 0, 0, -1) != 2 ) &&
13387  ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13388  IsConnected(cx, cy, cz - 1, 1, 0, 0) != 2 ) ) {
13389  ConnNumbers [ cx ] [ cy ] [ cz ] += 64;
13390  }
13391  }
13392 
13393  /*(128) y+1, z-1, 2 possible ways of connection
13394  * AdjCoord MUST be present at z direction
13395  * voxel may not be connected to master (CentPhase), i.e.
13396  * not connected in first way && not connected in second way
13397  */
13398  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz - 1) ]) ) {
13399  if ( ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13400  IsConnected(cx, cy + 1, cz, 0, 0, -1) != 2 ) &&
13401  ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13402  IsConnected(cx, cy, cz - 1, 0, 1, 0) != 2 ) ) {
13403  ConnNumbers [ cx ] [ cy ] [ cz ] += 128;
13404  }
13405  }
13406 
13407 
13408  /*(256) x-1, y+1, 2 possible ways of connection
13409  * AdjCoord MUST be present at x direction
13410  * voxel may not be connected to master (CentPhase), i.e.
13411  * not connected in first way && not connected in second way
13412  */
13413  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx - 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz) ]) ) {
13414  if ( ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13415  IsConnected(cx, cy + 1, cz, -1, 0, 0) != 2 ) &&
13416  ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13417  IsConnected(cx - 1, cy, cz, 0, 1, 0) != 2 ) ) {
13418  ConnNumbers [ cx ] [ cy ] [ cz ] += 256;
13419  }
13420  }
13421 
13422  /*(512) x+1, y+1, z+1, 6 possible ways of connection
13423  * voxel may not be connected to master (CentPhase), i.e.
13424  * not connected in first way && not connected in second way && not in
13425  * third way
13426  */
13427  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz + 1) ]) ) {
13428  // 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));
13429 
13430  if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13431  IsConnected(cx + 1, cy, cz, 0, 0, 1) != 2 ||
13432  IsConnected(cx + 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13433  ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13434  IsConnected(cx + 1, cy, cz, 0, 1, 0) != 2 ||
13435  IsConnected(cx + 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13436 
13437  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13438  IsConnected(cx, cy + 1, cz, 1, 0, 0) != 2 ||
13439  IsConnected(cx + 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13440  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13441  IsConnected(cx, cy + 1, cz, 0, 0, 1) != 2 ||
13442  IsConnected(cx, cy + 1, cz + 1, 1, 0, 0) != 2 ) &&
13443 
13444  ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13445  IsConnected(cx, cy, cz + 1, 1, 0, 0) != 2 ||
13446  IsConnected(cx + 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13447  ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13448  IsConnected(cx, cy, cz + 1, 0, 1, 0) != 2 ||
13449  IsConnected(cx, cy + 1, cz + 1, 1, 0, 0) != 2 ) ) {
13450  ConnNumbers [ cx ] [ cy ] [ cz ] += 512;
13451  }
13452  }
13453 
13454 
13455  /*(1024) x+1, y+1, z-1, 6 possible ways of connection
13456  * voxel may not be connected to master (CentPhase), i.e.
13457  * not connected in first way && not connected in second way && not in
13458  * third way
13459  */
13460  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx + 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz - 1) ]) ) {
13461  if ( ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13462  IsConnected(cx + 1, cy, cz, 0, 0, -1) != 2 ||
13463  IsConnected(cx + 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13464  ( IsConnected(cx, cy, cz, 1, 0, 0) != 2 ||
13465  IsConnected(cx + 1, cy, cz, 0, 1, 0) != 2 ||
13466  IsConnected(cx + 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13467 
13468  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13469  IsConnected(cx, cy + 1, cz, 1, 0, 0) != 2 ||
13470  IsConnected(cx + 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13471  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13472  IsConnected(cx, cy + 1, cz, 0, 0, -1) != 2 ||
13473  IsConnected(cx, cy + 1, cz - 1, 1, 0, 0) != 2 ) &&
13474 
13475  ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13476  IsConnected(cx, cy, cz - 1, 1, 0, 0) != 2 ||
13477  IsConnected(cx + 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13478  ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13479  IsConnected(cx, cy, cz - 1, 0, 1, 0) != 2 ||
13480  IsConnected(cx, cy + 1, cz - 1, 1, 0, 0) != 2 ) ) {
13481  ConnNumbers [ cx ] [ cy ] [ cz ] += 1024;
13482  }
13483  }
13484 
13485 
13486  /*(2048) x-1, y+1, z-1, 6 possible ways of connection
13487  * voxel may not be connected to master (CentPhase), i.e.
13488  * not connected in first way && not connected in second way && not in
13489  * third way
13490  */
13491  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx - 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz - 1) ]) ) {
13492  if ( ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13493  IsConnected(cx - 1, cy, cz, 0, 0, -1) != 2 ||
13494  IsConnected(cx - 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13495  ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13496  IsConnected(cx - 1, cy, cz, 0, 1, 0) != 2 ||
13497  IsConnected(cx - 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13498 
13499  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13500  IsConnected(cx, cy + 1, cz, -1, 0, 0) != 2 ||
13501  IsConnected(cx - 1, cy + 1, cz, 0, 0, -1) != 2 ) &&
13502  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13503  IsConnected(cx, cy + 1, cz, 0, 0, -1) != 2 ||
13504  IsConnected(cx, cy + 1, cz - 1, -1, 0, 0) != 2 ) &&
13505 
13506  ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13507  IsConnected(cx, cy, cz - 1, -1, 0, 0) != 2 ||
13508  IsConnected(cx - 1, cy, cz - 1, 0, 1, 0) != 2 ) &&
13509  ( IsConnected(cx, cy, cz, 0, 0, -1) != 2 ||
13510  IsConnected(cx, cy, cz - 1, 0, 1, 0) != 2 ||
13511  IsConnected(cx, cy + 1, cz - 1, -1, 0, 0) != 2 ) ) {
13512  ConnNumbers [ cx ] [ cy ] [ cz ] += 2048;
13513  }
13514  }
13515 
13516  /*(4096) x-1, y+1, z+1, 6 possible ways of connection
13517  * voxel may not be connected to master (CentPhase), i.e.
13518  * not connected in first way && not connected in second way && not in
13519  * third way
13520  */
13521  if ( IsSolidPhase(ArrPerc [ AdjCoord(cx - 1) ] [ AdjCoord(cy + 1) ] [ AdjCoord(cz + 1) ]) ) {
13522  if ( ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13523  IsConnected(cx - 1, cy, cz, 0, 0, 1) != 2 ||
13524  IsConnected(cx - 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13525  ( IsConnected(cx, cy, cz, -1, 0, 0) != 2 ||
13526  IsConnected(cx - 1, cy, cz, 0, 1, 0) != 2 ||
13527  IsConnected(cx - 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13528 
13529  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13530  IsConnected(cx, cy + 1, cz, -1, 0, 0) != 2 ||
13531  IsConnected(cx - 1, cy + 1, cz, 0, 0, 1) != 2 ) &&
13532  ( IsConnected(cx, cy, cz, 0, 1, 0) != 2 ||
13533  IsConnected(cx, cy + 1, cz, 0, 0, 1) != 2 ||
13534  IsConnected(cx, cy + 1, cz + 1, -1, 0, 0) != 2 ) &&
13535 
13536  ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13537  IsConnected(cx, cy, cz + 1, -1, 0, 0) != 2 ||
13538  IsConnected(cx - 1, cy, cz + 1, 0, 1, 0) != 2 ) &&
13539  ( IsConnected(cx, cy, cz, 0, 0, 1) != 2 ||
13540  IsConnected(cx, cy, cz + 1, 0, 1, 0) != 2 ||
13541  IsConnected(cx, cy + 1, cz + 1, -1, 0, 0) != 2 ) ) {
13542  ConnNumbers [ cx ] [ cy ] [ cz ] += 4096;
13543  }
13544  }
13545  }
13546 
13547  //IsSolidPhase(CentPhase)
13548  }
13549 
13550  //loop cx
13551  }
13552 
13553  //loop cy
13554  }
13555 
13556  //loop cz
13557 }
13558 
13560 {
13561  FILE *perc_img;
13562  char extension [ 10 ];
13563  //char outputname[80];
13564  char *prefix;
13565  prefix = ( char * ) malloc(80);
13566 
13567  //mkdir("perc", 0777);//make directory (every time)
13568  //system("mk perc");
13569  //system("mkdir perc 2> /dev/null");
13570  fprintf(infoperc, "%d %.4f %.3f\n", icyc, alpha_cur, time_cur);
13571  fflush(infoperc);
13572  sprintf(extension, "%04d", icyc);
13573  strcpy(prefix, "perc/out5."); //see line with mkdir in order to be the same
13574  strcat(prefix, extension);
13575  strcat(prefix, ".p.img");
13576 #ifdef PRINTF
13577  printf("Name of percolated output file is %s\n", prefix);
13578 #endif
13579 
13580 
13581  if ( ( perc_img = fopen(prefix, "w") ) == NULL ) {
13582  printf("\nFile %s can not be opened\n", prefix);
13583  free(prefix);
13584  return;
13585  }
13586 
13587  for ( int dz = 0; dz < SYSIZE; dz++ ) {
13588  for ( int dy = 0; dy < SYSIZE; dy++ ) {
13589  for ( int dx = 0; dx < SYSIZE; dx++ ) {
13590  //fprintf(perc_img, "%d %d\n", ArrPerc[dx][dy][dz], ConnNumbers[dx][dy][dz]);
13591  fprintf(perc_img, "%d\n", ArrPerc [ dx ] [ dy ] [ dz ]);
13592  }
13593  }
13594  }
13595 
13596  fclose(perc_img);
13597 #ifdef PRINTF
13598  printf("Percolated file %s wrote\n", prefix);
13599 #endif
13600  free(prefix);
13601 }
13602 
13603 
13604 
13605 void CemhydMatStatus :: WriteUnsortedList(int px, int py, int pz)
13606 {
13607  current = new percolatedpath;
13608  if ( last != NULL ) {
13609  last->next = current;
13610  } else {
13611  current->prev = NULL;
13612  }
13613 
13614  current->x = px;
13615  current->y = py;
13616  current->z = pz;
13617  current->prev = last;
13618  last = current;
13619 }
13620 
13621 
13622 
13623 inline int CemhydMatStatus :: AdjCoord(int coord)
13624 {
13625  if ( coord < 0 ) {
13626  coord += SYSIZE;
13627  }
13628 
13629  if ( coord >= SYSIZE ) {
13630  coord -= SYSIZE;
13631  }
13632 
13633  return coord;
13634 }
13635 
13636 
13637 int CemhydMatStatus :: NumSol(int cx, int cy, int cz)
13638 {
13639  int cnt = 0;
13640  int *p_arr;
13641 
13642  /*check if box is eligible for CSH transformation*/
13643  for ( int dx = -BoxSize; dx <= BoxSize; dx++ ) {
13644  for ( int dy = -BoxSize; dy <= BoxSize; dy++ ) {
13645  for ( int dz = -BoxSize; dz <= BoxSize; dz++ ) {
13646  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 ) {
13647  cnt++;
13648  }
13649  }
13650  }
13651  }
13652 
13653  /*update count*/
13654  CSH_vicinity [ cnt ]++;
13655 
13656 
13657  /*if enough phases found, change all CSH in the box to HDCSH*/
13658  if ( cnt >= SolidLimit ) {
13659  cnt = 0;
13660 
13661  for ( int dx = -BoxSize; dx <= BoxSize; dx++ ) {
13662  for ( int dy = -BoxSize; dy <= BoxSize; dy++ ) {
13663  for ( int dz = -BoxSize; dz <= BoxSize; dz++ ) {
13664  p_arr = & mic_CSH [ AdjCoord(cx + dx) ] [ AdjCoord(cy + dy) ] [ AdjCoord(cz + dz) ];
13665  //printf("%d at %d %d %d \n", *p_arr, dx, dy, dz);
13666  if ( * p_arr == CSH ) {
13667  * p_arr = HDCSH;
13668  cnt++;
13669  // printf("ph %d\n", mic_CSH[AdjCoord(cx+dx)][AdjCoord(cy+dy)][AdjCoord(cz+dz)]);
13670  }
13671  }
13672  }
13673  }
13674  } else {
13675  cnt = 0;
13676  }
13677 
13678  return cnt;
13679 }
13680 
13681 /*use pointer to array as argument*/
13682 /*CSH_vicinity[(2*BoxSize+1)*(2*BoxSize+1)*(2*BoxSize+1)]*/
13683 
13685 {
13686  int TotPhase = 0;
13687  int cx, cy, cz;
13688 
13689  for ( int i = 0; i <= ( ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) * ( 2 * BoxSize + 1 ) ); i++ ) {
13690  CSH_vicinity [ i ] = 0;
13691  }
13692 
13693  /*make copy of microstructure*/
13694  for ( cx = 0; cx < SYSIZE; cx++ ) {
13695  for ( cy = 0; cy < SYSIZE; cy++ ) {
13696  for ( cz = 0; cz < SYSIZE; cz++ ) {
13697  mic_CSH [ cx ] [ cy ] [ cz ] = mic [ cx ] [ cy ] [ cz ];
13698  }
13699  }
13700  }
13701 
13702 
13703  /*routine to scan microstructure and find eligible voxels*/
13704  for ( cx = 0; cx < SYSIZE; cx++ ) {
13705  for ( cy = 0; cy < SYSIZE; cy++ ) {
13706  for ( cz = 0; cz < SYSIZE; cz++ ) {
13707  /*CSH may be already in the CSHbox*/
13708  if ( mic_CSH [ cx ] [ cy ] [ cz ] == CSH || mic_CSH [ cx ] [ cy ] [ cz ] == HDCSH ) {
13709  TotPhase += NumSol(cx, cy, cz);
13710  }
13711  }
13712  }
13713  }
13714 
13715  // printf("TotPhase:%d", TotPhase);
13716  count [ HDCSH ] = TotPhase;
13717 }
13718 
13719 
13720 
13721 void CemhydMatStatus :: nrerror(const char *error_text)
13722 {
13723  printf("\nNumerical Recipes run-time error...\n");
13724  printf("%s\n", error_text);
13725  printf("...now exiting to system...\n");
13726  exit(1);
13727 }
13728 
13729 
13730 float *CemhydMatStatus :: vector(int nl, int nh)
13731 {
13732  float *v;
13733 
13734  v = ( float * ) malloc( ( unsigned ) ( nh - nl + 1 ) * sizeof( float ) );
13735  if ( !v ) {
13736  nrerror("allocation failure in vector()");
13737  }
13738 
13739  return v - nl;
13740 }
13741 
13742 int *CemhydMatStatus :: ivector(int nl, int nh)
13743 {
13744  int *v;
13745 
13746  v = ( int * ) malloc( ( unsigned ) ( nh - nl + 1 ) * sizeof( int ) );
13747  if ( !v ) {
13748  nrerror("allocation failure in ivector()");
13749  }
13750 
13751  return v - nl;
13752 }
13753 
13754 double *CemhydMatStatus :: dvector(int nl, int nh)
13755 {
13756  double *v;
13757 
13758  v = ( double * ) malloc( ( unsigned ) ( nh - nl + 1 ) * sizeof( double ) );
13759  if ( !v ) {
13760  nrerror("allocation failure in dvector()");
13761  }
13762 
13763  return v - nl;
13764 }
13765 
13766 
13767 
13768 //float** CemhydMat::matrix(int nrl,int nrh,int ncl,int nch){
13769 float **CemhydMatStatus :: matrix_cem(int nrl, int nrh, int ncl, int nch)
13770 {
13771  int i;
13772  float **m;
13773 
13774  m = ( float ** ) malloc( ( unsigned ) ( nrh - nrl + 1 ) * sizeof( float * ) );
13775  if ( !m ) {
13776  nrerror("allocation failure 1 in matrix_cem()");
13777  }
13778 
13779  m -= nrl;
13780 
13781  for ( i = nrl; i <= nrh; i++ ) {
13782  m [ i ] = ( float * ) malloc( ( unsigned ) ( nch - ncl + 1 ) * sizeof( float ) );
13783  if ( !m [ i ] ) {
13784  nrerror("allocation failure 2 in matrix_cem()");
13785  }
13786 
13787  m [ i ] -= ncl;
13788  }
13789 
13790  return m;
13791 }
13792 
13793 double **CemhydMatStatus :: dmatrix(int nrl, int nrh, int ncl, int nch)
13794 {
13795  int i;
13796  double **m;
13797 
13798  m = ( double ** ) malloc( ( unsigned ) ( nrh - nrl + 1 ) * sizeof( double * ) );
13799  if ( !m ) {
13800  nrerror("allocation failure 1 in dmatrix()");
13801  }
13802 
13803  m -= nrl;
13804 
13805  for ( i = nrl; i <= nrh; i++ ) {
13806  m [ i ] = ( double * ) malloc( ( unsigned ) ( nch - ncl + 1 ) * sizeof( double ) );
13807  if ( !m [ i ] ) {
13808  nrerror("allocation failure 2 in dmatrix()");
13809  }
13810 
13811  m [ i ] -= ncl;
13812  }
13813 
13814  return m;
13815 }
13816 
13817 int **CemhydMatStatus :: imatrix(int nrl, int nrh, int ncl, int nch)
13818 {
13819  int i, **m;
13820 
13821  m = ( int ** ) malloc( ( unsigned ) ( nrh - nrl + 1 ) * sizeof( int * ) );
13822  if ( !m ) {
13823  nrerror("allocation failure 1 in imatrix()");
13824  }
13825 
13826  m -= nrl;
13827 
13828  for ( i = nrl; i <= nrh; i++ ) {
13829  m [ i ] = ( int * ) malloc( ( unsigned ) ( nch - ncl + 1 ) * sizeof( int ) );
13830  if ( !m [ i ] ) {
13831  nrerror("allocation failure 2 in imatrix()");
13832  }
13833 
13834  m [ i ] -= ncl;
13835  }
13836 
13837  return m;
13838 }
13839 
13840 
13841 
13842 float **CemhydMatStatus :: submatrix(float **a, int oldrl, int oldrh, int oldcl, int, int newrl, int newcl)
13843 {
13844  int i, j;
13845  float **m;
13846 
13847  m = ( float ** ) malloc( ( unsigned ) ( oldrh - oldrl + 1 ) * sizeof( float * ) );
13848  if ( !m ) {
13849  nrerror("allocation failure in submatrix()");
13850  }
13851 
13852  m -= newrl;
13853 
13854  for ( i = oldrl, j = newrl; i <= oldrh; i++, j++ ) {
13855  m [ j ] = a [ i ] + oldcl - newcl;
13856  }
13857 
13858  return m;
13859 }
13860 
13861 
13862 void free_vector(float *v, int nl) { free( ( char * ) ( v + nl ) ); }
13863 
13864 void free_ivector(int *v, int nl) { free( ( char * ) ( v + nl ) ); }
13865 
13866 void free_dvector(double *v, int nl) { free( ( char * ) ( v + nl ) ); }
13867 
13868 
13869 void free_matrix(float **m, int nrl, int nrh, int ncl)
13870 {
13871  int i;
13872 
13873  for ( i = nrh; i >= nrl; i-- ) {
13874  free( ( char * ) ( m [ i ] + ncl ) );
13875  }
13876 
13877  free( ( char * ) ( m + nrl ) );
13878 }
13879 
13880 void free_dmatrix(double **m, int nrl, int nrh, int ncl)
13881 {
13882  int i;
13883 
13884  for ( i = nrh; i >= nrl; i-- ) {
13885  free( ( char * ) ( m [ i ] + ncl ) );
13886  }
13887 
13888  free( ( char * ) ( m + nrl ) );
13889 }
13890 
13891 void free_imatrix(int **m, int nrl, int nrh, int ncl)
13892 {
13893  int i;
13894 
13895  for ( i = nrh; i >= nrl; i-- ) {
13896  free( ( char * ) ( m [ i ] + ncl ) );
13897  }
13898 
13899  free( ( char * ) ( m + nrl ) );
13900 }
13901 
13902 void free_submatrix(float *b, int nrl)
13903 {
13904  free( ( char * ) ( b + nrl ) );
13905 }
13906 
13907 float **CemhydMatStatus :: convert_matrix(float *a, int nrl, int nrh, int ncl, int nch)
13908 {
13909  int i, j, nrow, ncol;
13910  float **m;
13911 
13912  nrow = nrh - nrl + 1;
13913  ncol = nch - ncl + 1;
13914  m = ( float ** ) malloc( ( unsigned ) ( nrow ) * sizeof( float * ) );
13915  if ( !m ) {
13916  nrerror("allocation failure in convert_matrix()");
13917  }
13918 
13919  m -= nrl;
13920  for ( i = 0, j = nrl; i <= nrow - 1; i++, j++ ) {
13921  m [ j ] = a + ncol * i - ncl;
13922  }
13923 
13924  return m;
13925 }
13926 
13927 void free_convert_matrix(float **b, int nrl)
13928 {
13929  free( ( char * ) ( b + nrl ) );
13930 }
13931 
13933 {
13934  fcomplex_cem c;
13935  c.r = a.r + b.r;
13936  c.i = a.i + b.i;
13937  return c;
13938 }
13939 
13941 {
13942  fcomplex_cem c;
13943  c.r = a.r - b.r;
13944  c.i = a.i - b.i;
13945  return c;
13946 }
13947 
13949 {
13950  fcomplex_cem c;
13951  c.r = a.r * b.r - a.i * b.i;
13952  c.i = a.i * b.r + a.r * b.i;
13953  return c;
13954 }
13955 
13957 {
13958  fcomplex_cem c;
13959  c.r = re;
13960  c.i = im;
13961  return c;
13962 }
13963 
13965 {
13966  fcomplex_cem c;
13967  c.r = z.r;
13968  c.i = -z.i;
13969  return c;
13970 }
13971 
13973 {
13974  fcomplex_cem c;
13975  float r, den;
13976  if ( fabs(b.r) >= fabs(b.i) ) {
13977  r = b.i / b.r;
13978  den = b.r + r * b.i;
13979  c.r = ( a.r + r * a.i ) / den;
13980  c.i = ( a.i - r * a.r ) / den;
13981  } else {
13982  r = b.r / b.i;
13983  den = b.i + r * b.r;
13984  c.r = ( a.r * r + a.i ) / den;
13985  c.i = ( a.i * r - a.r ) / den;
13986  }
13987 
13988  return c;
13989 }
13990 
13992 {
13993  float x, y, ans, temp;
13994  x = fabs(z.r);
13995  y = fabs(z.i);
13996  if ( x == 0.0 ) {
13997  ans = y;
13998  } else if ( y == 0.0 ) {
13999  ans = x;
14000  } else if ( x > y ) {
14001  temp = y / x;
14002  ans = x * sqrt(1.0 + temp * temp);
14003  } else {
14004  temp = x / y;
14005  ans = y * sqrt(1.0 + temp * temp);
14006  }
14007 
14008  return ans;
14009 }
14010 
14012 {
14013  fcomplex_cem c;
14014  float x, y, w, r;
14015  if ( ( z.r == 0.0 ) && ( z.i == 0.0 ) ) {
14016  c.r = 0.0;
14017  c.i = 0.0;
14018  return c;
14019  } else {
14020  x = fabs(z.r);
14021  y = fabs(z.i);
14022  if ( x >= y ) {
14023  r = y / x;
14024  w = sqrt(x) * sqrt( 0.5 * ( 1.0 + sqrt(1.0 + r * r) ) );
14025  } else {
14026  r = x / y;
14027  w = sqrt(y) * sqrt( 0.5 * ( r + sqrt(1.0 + r * r) ) );
14028  }
14029 
14030  if ( z.r >= 0.0 ) {
14031  c.r = w;
14032  c.i = z.i / ( 2.0 * w );
14033  } else {
14034  c.i = ( z.i >= 0 ) ? w : -w;
14035  c.r = z.i / ( 2.0 * c.i );
14036  }
14037 
14038  return c;
14039  }
14040 }
14041 
14043 {
14044  fcomplex_cem c;
14045  c.r = x * a.r;
14046  c.i = x * a.i;
14047  return c;
14048 }
14049 
14050 
14051 //public function to call the routine for HDCSH creation
14053 {
14055 }
14056 
14057 //public function to call the routine for solid percolation
14059 {
14060  burn_phases(1, 0, 0);
14061 }
14062 
14063 //public function to access w/c ratio
14065 {
14066  return w_to_c;
14067 }
14068 
14069 /*function read into the string
14070  * 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
14071  */
14072 
14074 {
14075  sprintf(my_string, "%d", iseed);
14076 }
14077 
14078 long CemhydMatStatus :: cx(int x, int y, int z, int a, int b, int c)
14079 {
14080  return ( 1 - b - c ) * x + ( 1 - a - c ) * y + ( 1 - a - b ) * z;
14081 }
14082 
14083 
14084 long CemhydMatStatus :: cy(int x, int y, int z, int a, int b, int c)
14085 {
14086  return ( 1 - a - b ) * x + ( 1 - b - c ) * y + ( 1 - a - c ) * z;
14087 }
14088 
14089 long CemhydMatStatus :: cz(int x, int y, int z, int a, int b, int c)
14090 {
14091  return ( 1 - a - c ) * x + ( 1 - a - b ) * y + ( 1 - b - c ) * z;
14092 }
14093 
14094 //homogenization of plain cement paste without filler
14095 void CemhydMatStatus :: AnalyticHomogenizationPaste(double &E, double &nu, int perc_unperc_flag)
14096 {
14097  //flag 0 - percolated phases are is in phase[]
14098  //flag 1 - unpercolated phases are in count[]
14099  int index, x, i;
14100  double sum = 0.;
14101  FloatMatrix PhaseMatrix(32, 3), LevelI(2, 3);
14102  double E_CSH_hmg, nu_CSH_hmg;
14103  Homogenize CSH_level, Paste_level;
14104 
14105 
14106  //determine phase fractions
14107  //0-23, PhaseFrac[0] = none, [1]=POROSITY, [2]=C3S .. [31]=EMPTYP [32]=HDCSH
14108  for ( x = 0; x < 34; x++ ) {
14109  PhaseFrac [ x ] = 0.;
14110  }
14111 
14112  for ( x = 0; x < 51; x++ ) {
14113  index = x;
14114  if ( x == HDCSH ) {
14115  index = 31;
14116  } else if ( x == EMPTYP ) { //EMPTYP
14117  index = 30;
14118  } else if ( x >= DIFFCSH ) { //all dissolved phases
14119  continue;
14120  }
14121 
14122 
14123  if ( perc_unperc_flag == 0 ) { //percolated
14124  PhaseFrac [ index + 1 ] += phase [ x ];
14125  } else { //unpercolated
14126  if ( x == CSH ) {
14127  PhaseFrac [ index + 1 ] += ( count [ CSH ] - count [ HDCSH ] );
14128  } else {
14129  PhaseFrac [ index + 1 ] += count [ x ];
14130  }
14131  }
14132  }
14133 
14134  for ( x = 2; x < 34; x++ ) {
14135  PhaseFrac [ x ] /= SYSIZE_POW3;
14136  sum += PhaseFrac [ x ];
14137  }
14138 
14139 
14140  //water-filled porosity is what is missing
14141  PhaseFrac [ 1 ] = 1 - sum;
14142 
14143  for ( x = 0; x < 34; x++ ) { //34
14144  //printf("Phase %d PhaseFrac %f\n", x, PhaseFrac[x]);
14145  //printf("Phase %d perc / unper %ld %ld\n", x, phase[x], count[x]);
14146  }
14147 
14148  PhaseMatrix(0, 0) = PhaseFrac [ 1 ]; //POROSITY 0
14149  PhaseMatrix(0, 1) = 0.001;
14150  PhaseMatrix(0, 2) = 0.499924;
14151  PhaseMatrix(1, 0) = PhaseFrac [ 2 ]; //C3S 1
14152  PhaseMatrix(1, 1) = 135.0;
14153  PhaseMatrix(1, 2) = 0.300000;
14154  PhaseMatrix(2, 0) = PhaseFrac [ 3 ]; //C2S 2
14155  PhaseMatrix(2, 1) = 130.0;
14156  PhaseMatrix(2, 2) = 0.300000;
14157  PhaseMatrix(3, 0) = PhaseFrac [ 4 ]; //C3A 3
14158  PhaseMatrix(3, 1) = 145.0;
14159  PhaseMatrix(3, 2) = 0.300000;
14160  PhaseMatrix(4, 0) = PhaseFrac [ 5 ]; //C4AF 4
14161  PhaseMatrix(4, 1) = 125.0;
14162  PhaseMatrix(4, 2) = 0.300000;
14163  PhaseMatrix(5, 0) = PhaseFrac [ 6 ]; //GYPSUM 5
14164  PhaseMatrix(5, 1) = 30.00;
14165  PhaseMatrix(5, 2) = 0.300000;
14166  PhaseMatrix(6, 0) = PhaseFrac [ 7 ]; //HEMIHYD 6
14167  PhaseMatrix(6, 1) = 62.90;
14168  PhaseMatrix(6, 2) = 0.300000;
14169  PhaseMatrix(7, 0) = PhaseFrac [ 8 ]; //ANHYDRITE 7
14170  PhaseMatrix(7, 1) = 73.60;
14171  PhaseMatrix(7, 2) = 0.275000;
14172  PhaseMatrix(8, 0) = PhaseFrac [ 9 ]; //POZZ,SiO2 8
14173  PhaseMatrix(8, 1) = 72.80;
14174  PhaseMatrix(8, 2) = 0.167000;
14175  PhaseMatrix(9, 0) = PhaseFrac [ 10 ]; //INERT 9
14176  PhaseMatrix(9, 1) = 79.60;
14177  PhaseMatrix(9, 2) = 0.309900;
14178  PhaseMatrix(10, 0) = PhaseFrac [ 11 ]; //SLAG 10
14179  PhaseMatrix(10, 1) = 72.80;
14180  PhaseMatrix(10, 2) = 0.16700;
14181  PhaseMatrix(11, 0) = PhaseFrac [ 12 ]; //ASG 11
14182  PhaseMatrix(11, 1) = 72.80;
14183  PhaseMatrix(11, 2) = 0.16700;
14184  PhaseMatrix(12, 0) = PhaseFrac [ 13 ]; //CAS2 slag 12
14185  PhaseMatrix(12, 1) = 72.80;
14186  PhaseMatrix(12, 2) = 0.16700;
14187  PhaseMatrix(13, 0) = PhaseFrac [ 14 ]; //CH 13
14188  PhaseMatrix(13, 1) = 38.00;
14189  PhaseMatrix(13, 2) = 0.30500;
14190  PhaseMatrix(14, 0) = -10.; //CSH upsc. 14
14191  PhaseMatrix(14, 1) = -10.0;
14192  PhaseMatrix(14, 2) = -10.000;
14193  PhaseMatrix(15, 0) = PhaseFrac [ 16 ]; //C3AH6 15
14194  PhaseMatrix(15, 1) = 22.40;
14195  PhaseMatrix(15, 2) = 0.25000;
14196  PhaseMatrix(16, 0) = PhaseFrac [ 17 ]; //ETTR 16
14197  PhaseMatrix(16, 1) = 22.40;
14198  PhaseMatrix(16, 2) = 0.25000;
14199  PhaseMatrix(17, 0) = PhaseFrac [ 18 ]; //ETTRC4AF 17
14200  PhaseMatrix(17, 1) = 22.40;
14201  PhaseMatrix(17, 2) = 0.25000;
14202  PhaseMatrix(18, 0) = PhaseFrac [ 19 ]; //AFM 18
14203  PhaseMatrix(18, 1) = 42.30;
14204  PhaseMatrix(18, 2) = 0.32380;
14205  PhaseMatrix(19, 0) = PhaseFrac [ 20 ]; //FH3 19
14206  PhaseMatrix(19, 1) = 22.40;
14207  PhaseMatrix(19, 2) = 0.24590;
14208  PhaseMatrix(20, 0) = PhaseFrac [ 21 ]; //POZZCSH 20
14209  PhaseMatrix(20, 1) = 22.40;
14210  PhaseMatrix(20, 2) = 0.24590;
14211  PhaseMatrix(21, 0) = PhaseFrac [ 22 ]; //SLAGCSH 21
14212  PhaseMatrix(21, 1) = 22.40;
14213  PhaseMatrix(21, 2) = 0.24590;
14214  PhaseMatrix(22, 0) = PhaseFrac [ 23 ]; //CACL2 22
14215  PhaseMatrix(22, 1) = 42.30;
14216  PhaseMatrix(22, 2) = 0.32380;
14217  PhaseMatrix(23, 0) = PhaseFrac [ 24 ]; //FREIDEL 23
14218  PhaseMatrix(23, 1) = 22.40;
14219  PhaseMatrix(23, 2) = 0.24590;
14220  PhaseMatrix(24, 0) = PhaseFrac [ 25 ]; //STRAT 24
14221  PhaseMatrix(24, 1) = 22.40;
14222  PhaseMatrix(24, 2) = 0.25000;
14223  PhaseMatrix(25, 0) = PhaseFrac [ 26 ]; //GYPSUMS 25
14224  PhaseMatrix(25, 1) = 30.00;
14225  PhaseMatrix(25, 2) = 0.30000;
14226  PhaseMatrix(26, 0) = PhaseFrac [ 27 ]; //CaCO3 26
14227  PhaseMatrix(26, 1) = 60.00;
14228  PhaseMatrix(26, 2) = 0.30000;
14229  PhaseMatrix(27, 0) = PhaseFrac [ 28 ]; //AFMC 27
14230  PhaseMatrix(27, 1) = 42.30;
14231  PhaseMatrix(27, 2) = 0.32380;
14232  PhaseMatrix(28, 0) = PhaseFrac [ 29 ]; //INERTAGG 28
14233  PhaseMatrix(28, 1) = 79.60;
14234  PhaseMatrix(28, 2) = 0.30990;
14235  PhaseMatrix(29, 0) = PhaseFrac [ 30 ]; //ABSGYP 29
14236  PhaseMatrix(29, 1) = 30.00;
14237  PhaseMatrix(29, 2) = 0.30000;
14238  PhaseMatrix(30, 0) = PhaseFrac [ 31 ]; //EMPTYP 30
14239  PhaseMatrix(30, 1) = 0.001;
14240  PhaseMatrix(30, 2) = 0.00100;
14241 
14242  //CSH level
14243  if ( PhaseFrac [ 15 ] == 0. && PhaseFrac [ 32 ] == 0. ) { //beginning of hydration
14244  LevelI(0, 0) = 1.;
14245  LevelI(1, 0) = 0.;
14246  } else {
14247  LevelI(0, 0) = PhaseFrac [ 15 ] / ( PhaseFrac [ 15 ] + PhaseFrac [ 32 ] ); //LDCSH
14248  LevelI(1, 0) = PhaseFrac [ 32 ] / ( PhaseFrac [ 15 ] + PhaseFrac [ 32 ] ); //HDCSH
14249  }
14250 
14251  LevelI(0, 1) = 21.7; //21.7 LDCSH
14252  LevelI(0, 2) = 0.24;
14253 
14254  LevelI(1, 1) = 29.4; //29.4 HDCSH
14255  LevelI(1, 2) = 0.24;
14256 
14257  //constructor without parameters
14258  CSH_level.moriTanaka(LevelI, 0);
14259 
14260  //fill actual values into PhaseMatrix
14261  for ( i = 0; i < 31; i++ ) {
14262  PhaseMatrix(i, 0) = PhaseFrac [ i + 1 ];
14263  }
14264 
14265  //cement paste level
14266 
14267  PhaseMatrix(14, 0) = PhaseFrac [ 15 ] + PhaseFrac [ 32 ];
14268  PhaseMatrix(14, 1) = CSH_level.E_hmg;
14269  PhaseMatrix(14, 2) = CSH_level.nu_hmg;
14270 
14271  E_CSH_hmg = CSH_level.E_hmg; //E from CSH level
14272  nu_CSH_hmg = CSH_level.nu_hmg; //nu from CSH level
14273 
14274  Paste_level.selfConsistent(PhaseMatrix);
14275 
14276  E = Paste_level.E_hmg;
14277  nu = Paste_level.nu_hmg;
14279  ( void ) E_CSH_hmg;
14280  ( void ) nu_CSH_hmg;
14281 }
14282 
14283 //use results from cement paste level and add SCM, inert filler, entrained air, ITZ, FA, CA
14284 void 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)
14285 {
14286  Homogenize Paste_level, Mortar_level, Concrete_level;
14287 
14288  //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
14290  FloatMatrix PhaseMatrix(4, 3), Mortar(4, 3), Concrete(4, 3);
14291 
14292  PhaseMatrix(0, 0) = ( Vol_cement_clinker_gypsum + Vol_water ) / vol_tot_paste; //cement paste (reference medium)
14293  PhaseMatrix(0, 1) = E_paste_inp;
14294  PhaseMatrix(0, 2) = nu_paste_inp;
14295  PhaseMatrix(1, 0) = Vol_cement_SCM / vol_tot_paste; //SCM
14296  PhaseMatrix(1, 1) = Young_SCM;
14297  PhaseMatrix(1, 2) = Poisson_SCM;
14298  PhaseMatrix(2, 0) = Vol_inert_filler / vol_tot_paste; //inert filler
14299  PhaseMatrix(2, 1) = Young_inert;
14300  PhaseMatrix(2, 2) = Poisson_inert;
14301  PhaseMatrix(3, 0) = Vol_entrained_entrapped_air / vol_tot_paste; //entrained + entrapped air
14302  PhaseMatrix(3, 1) = 0.001;
14303  PhaseMatrix(3, 2) = 0.001;
14304 
14305  Paste_level.moriTanaka(PhaseMatrix, 0);
14306  * E_paste = Paste_level.E_hmg;
14307  * nu_paste = Paste_level.nu_hmg;
14308 
14309  //MORTAR LEVEL - homogenize cement paste with fine aggregates including ITZ via Herve-Zaoui scheme
14310  //ITZ covers all aggregates, therefore its fraction associated with mortar and concrete has to be determined
14311  //ITZ occupies additional space
14312  double n_FA, n_CA, vol_ITZ_FA, vol_ITZ_CA;
14313  n_FA = Vol_FA / ( 4. / 3. * M_PI * pow(0.01 * Grain_average_FA / 2., 3.) ); //amount of FA particles
14314  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]
14315  n_CA = Vol_CA / ( 4. / 3. * M_PI * pow(0.01 * Grain_average_CA / 2., 3) ); //amount of CA particles
14316  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]
14317  double vol_tot_mortar = vol_tot_paste + Vol_FA;
14318 
14319  Mortar(0, 0) = Vol_FA / vol_tot_mortar; //Fine aggregates
14320  Mortar(0, 1) = Young_FA;
14321  Mortar(0, 2) = Poisson_FA;
14322  Mortar(1, 0) = vol_ITZ_FA / vol_tot_mortar; //ITZ
14323  Mortar(1, 1) = * E_paste * ITZ_Young_red;
14324  Mortar(1, 2) = * nu_paste;
14325  Mortar(2, 0) = ( vol_tot_paste - vol_ITZ_FA ) / vol_tot_mortar; //cement paste
14326  Mortar(2, 1) = * E_paste;
14327  Mortar(2, 2) = * nu_paste;
14328  Mortar(3, 0) = 0.; //vol. fraction must be zero - reference medium
14329  Mortar(3, 1) = 10.; //arbitrary value
14330  Mortar(3, 2) = 0.3; //arbitrary value
14331 
14332  Mortar_level.herveZaoui(Mortar);
14333  * E_mortar = Mortar_level.E_hmg;
14334  * nu_mortar = Mortar_level.nu_hmg;
14335 
14336  //CONCRETE LEVEL
14337  double vol_tot_concrete = vol_tot_mortar + Vol_CA;
14338 
14339  Concrete(0, 0) = Vol_CA / vol_tot_concrete; //Coarse aggregates
14340  Concrete(0, 1) = Young_CA;
14341  Concrete(0, 2) = Poisson_CA;
14342  Concrete(1, 0) = vol_ITZ_CA / vol_tot_concrete; //ITZ
14343  Concrete(1, 1) = * E_paste * ITZ_Young_red;
14344  Concrete(1, 2) = * nu_paste;
14345  Concrete(2, 0) = ( vol_tot_mortar - vol_ITZ_CA ) / vol_tot_concrete; //mortar
14346  Concrete(2, 1) = * E_mortar;
14347  Concrete(2, 2) = * nu_mortar;
14348  Concrete(3, 0) = 0.; //vol. fraction must be zero - reference medium
14349  Concrete(3, 1) = 10.; //arbitrary value
14350  Concrete(3, 2) = 0.3; //arbitrary value
14351 
14352  Concrete_level.herveZaoui(Concrete);
14353  E_concrete = Concrete_level.E_hmg;
14354  nu_concrete = Concrete_level.nu_hmg;
14355 }
14356 
14357 //at least one cycle has to pass, volume fraction
14358 void CemhydMatStatus :: GetInitClinkerPhases(double &c3s, double &c2s, double &c3a, double &c4af, double &gypsum, double &hemi, double &anh)
14359 {
14360  double sum = c3sinit + c2sinit + c3ainit + c4afinit + ncsbar + heminit + anhinit;
14361 
14362  if ( icyc > 1 ) {
14363  c3s = ( double ) c3sinit / sum;
14364  c2s = ( double ) c2sinit / sum;
14365  c3a = ( double ) c3ainit / sum;
14366  c4af = ( double ) c4afinit / sum;
14367  gypsum = ( double ) ncsbar / sum;
14368  hemi = ( double ) heminit / sum;
14369  anh = ( double ) anhinit / sum;
14370  }
14371 }
14372 
14373 
14374 #ifdef __TM_MODULE //transport module for OOFEM
14375 void
14377 {
14379  if(!tStep->isIcApply()){//not very efficient here due to averaging in each call
14380  CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
14381  cemhydmat->clearWeightTemperatureProductVolume(this->gp->giveElement());
14382  cemhydmat->storeWeightTemperatureProductVolume(this->gp->giveElement(), tStep);
14383  cemhydmat->averageTemperature();
14384  }
14385 };
14386 
14388 {
14389  CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
14390  CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( cemhydmat->giveStatus(gp) );
14391  double ret;
14392 
14393  if ( !cemhydmat->eachGP ) {
14394  ret = cemhydmat->MasterCemhydMatStatus->averageTemperature;
14395  } else {
14396  ret = ms->giveField().at(1);
14397  }
14398 
14399  return ret;
14400 }
14401 
14402 
14403 void
14405 {
14406  CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() );
14407  CemhydMatStatus *ms = this;
14408  if ( cemhydmat->MasterCemhydMatStatus ) {
14409  ms = cemhydmat->MasterCemhydMatStatus;
14410  }
14411 
14413  fprintf(file, " status {");
14414  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) );
14416  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 ]);
14417  }
14418 
14419 
14420  if ( !cemhydmat->eachGP ) {
14421  if ( cemhydmat->giveStatus(gp) == cemhydmat->MasterCemhydMatStatus ) {
14422  fprintf( file, " master material %d", cemhydmat->giveNumber() );
14423  } else {
14424  fprintf( file, " slave of material %d", cemhydmat->giveNumber() );
14425  }
14426  } else {
14427  fprintf( file, " independent microstructure %p from material %d", this, cemhydmat->giveNumber() );
14428  }
14429 
14430  fprintf(file, "}\n");
14431 }
14432 #endif
14433 
14434 
14435 #ifdef CEMPY
14436 // constructors
14438 {
14439  PartHeat = 0.;
14440  temp_cur = 0.;
14441  #ifdef PRINTF
14442  printf("Constructor of CemhydMatStatus called\n");
14443  fflush(stdout);
14444  #endif
14445 }
14446 
14447 
14448 void
14449 CemhydMatStatus :: InitializePy(const char *inp)
14450 {
14452  readInputFileAndInitialize(inp, ( bool ) 1);
14453 }
14454 
14455 #endif //CEMPY
14456 } //end of namespace oofem
14457 
14458 
14459 
14460 #ifdef CEMPY
14461  #include <boost/python.hpp>
14462 BOOST_PYTHON_MODULE(cemhydmodule)
14463 {
14464  //boost::python::class_< oofem::CemhydMatStatus >("cemhydmatstatus", init<std::string>() ) - does not work, why ?
14465  boost :: python :: class_< oofem :: CemhydMatStatus >("cemhydmatstatus") //use default class constructor instead
14466  .def("InitializePy", & oofem :: CemhydMatStatus :: InitializePy)
14467  .def("MoveCycles", & oofem :: CemhydMatStatus :: MoveCycles)
14468  ;
14469 }
14470 #endif
void measuresurf(void)
Definition: cemhydmat.C:6260
int movehem(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
Definition: cemhydmat.C:9191
void free_vector(float *v, int nl)
InternalStateType
Type representing the physical meaning of element or constitutive model internal variable.
int moveas(int xcur, int ycur, int zcur, int finalstep)
Definition: cemhydmat.C:10422
long int nair[1500]
Definition: cemhydmat.h:557
virtual void updateYourself(TimeStep *tStep)
Update equilibrium history variables according to temp-variables.
int procair(int nsearch)
Definition: cemhydmat.C:3000
int burnset(int d1, int d2, int d3)
Definition: cemhydmat.C:7829
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Returns the integration point corresponding value in full form.
Definition: element.C:1257
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Returns material status of receiver in given integration point.
Definition: material.C:244
void outputImageFileUnperc(char ***m)
Definition: cemhydmat.C:6374
void GetInputParams(char *my_string)
Definition: cemhydmat.C:14073
double GiveTotHeat(void)
Definition: cemhydmat.C:7534
int movecaco3(int xcur, int ycur, int zcur, int finalstep)
Definition: cemhydmat.C:10572
int burn3d(int npix, int d1, int d2, int d3)
Definition: cemhydmat.C:7604
double giveTotalVolume(void)
Definition: cemhydmat.h:224
Class and object Domain.
Definition: domain.h:115
double GiveDoHLastCyc(void)
Definition: cemhydmat.C:7563
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Access method for default integration rule.
Definition: element.h:822
int gsphere(int numgen, long int *numeach, int *sizeeach, int *pheach)
Definition: cemhydmat.C:1616
void dealloc_int_3D(int ***(&mask), long SYSIZE)
Definition: cemhydmat.C:1055
int maketemp(int size)
Definition: cemhydmat.C:2684
int ** imatrix(int nrl, int nrh, int ncl, int nch)
Definition: cemhydmat.C:13817
double Vol_cement_clinker_gypsum
Definition: cemhydmat.h:772
fcomplex_cem Conjg(fcomplex_cem z)
Definition: cemhydmat.C:13964
int IsSolidPhase(int phase)
Definition: cemhydmat.C:12849
#define _IFT_CemhydMat_densitytype
Definition: cemhydmat.h:62
int readInputFileAndInitialize(const char *inp, bool generateMicrostructure)
Definition: cemhydmat.C:1248
void free_dmatrix(double **m, int nrl, int nrh, int ncl)
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition: femcmpnn.h:82
int moveone(int *xloc, int *yloc, int *zloc, int *act, int sumold)
Definition: cemhydmat.C:8197
std::string XMLfileName
XML input file name for CEMHYD3D.
Definition: cemhydmat.h:142
void addrand(int randid, long int nneed)
Definition: cemhydmat.C:6216
unsigned int * CSH_vicinity
Definition: cemhydmat.h:672
void free_imatrix(int **m, int nrl, int nrh, int ncl)
Class for elastic homogenization.
Definition: homogenize.h:50
long int *** micpart
Definition: cemhydmat.h:501
int extettr(int xpres, int ypres, int zpres, int etype)
Definition: cemhydmat.C:8639
void nrerror(const char *error_text)
Definition: cemhydmat.C:13721
void zero()
Sets all component to zero.
Definition: intarray.C:52
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
struct percolatedpath * last
Definition: cemhydmat.h:757
double PartHeat
The last incremental heat returned from a GP.
Definition: cemhydmat.h:241
void extpozz(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:10895
float rhcalc(int phin)
Definition: cemhydmat.C:2822
struct cluster ** clust
Definition: cemhydmat.h:532
ValueModeType
Type representing the mode of UnknownType or CharType, or similar types.
Definition: valuemodetype.h:78
double giveCastingTime()
Definition: material.h:156
CemhydMatStatus(int n, Domain *d, GaussPoint *gp, CemhydMatStatus *CemStat, CemhydMat *cemhydmat, bool withMicrostructure)
Create status in an integration point.
Definition: cemhydmat.C:459
int eachGP
Assign a separate microstructure in each integration point.
Definition: cemhydmat.h:140
int chksph(int xin, int yin, int zin, int radd, int wflg, int phasein, int phase2)
Definition: cemhydmat.C:1539
struct ants * tailant
Definition: cemhydmat.h:735
double GiveCp(void)
Definition: cemhydmat.C:7540
fcomplex_cem Csqrt(fcomplex_cem z)
Definition: cemhydmat.C:14011
void hydrate(int fincyc, int stepmax, float chpar1, float chpar2, float hgpar1, float hgpar2, float fhpar1, float fhpar2, float gypar1, float gypar2)
Definition: cemhydmat.C:12307
void free_ivector(int *v, int nl)
int MoveToTime(double GiveTemp, double TargTime)
Definition: cemhydmat.C:7520
#define _IFT_CemhydMat_conductivitytype
Definition: cemhydmat.h:60
void GetInitClinkerPhases(double &c3s, double &c2s, double &c3a, double &c4af, double &gypsum, double &hemi, double &anh)
Definition: cemhydmat.C:14358
virtual void updateYourself(TimeStep *tStep)
Update equilibrium history variables according to temp-variables.
Definition: cemhydmat.C:14376
int movepix(int ntomove, int ph1, int ph2)
Definition: cemhydmat.C:3025
void AnalyticHomogenizationPaste(double &E, double &nu, int perc_unperc_flag)
Definition: cemhydmat.C:14095
const char * __MatResponseModeToString(MatResponseMode _value)
Definition: cltypes.C:326
long int volume[50]
Definition: cemhydmat.h:554
int movecacl2(int xcur, int ycur, int zcur, int finalstep)
Definition: cemhydmat.C:9923
int * ivector(int nl, int nh)
Definition: cemhydmat.C:13742
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Returns the integration point corresponding value in Reduced form.
virtual void printOutputAt(FILE *file, TimeStep *tStep)
Print receiver&#39;s output to given stream.
int movecsh(int xcur, int ycur, int zcur, int finalstep, int cycorig)
Definition: cemhydmat.C:8420
double giveTargetTime()
Returns target time.
Definition: timestep.h:146
void free_convert_matrix(float **b, int nrl)
void WriteUnsortedList(int px, int py, int pz)
Definition: cemhydmat.C:13605
Abstract base class for all finite elements.
Definition: element.h:145
double giveAverageTemperature(void)
Definition: cemhydmat.C:14387
Element * giveElement()
Returns corresponding element to receiver.
Definition: gausspoint.h:188
double averageTemperature
Average temperature through integration points.
Definition: cemhydmat.h:210
This class implements a transport material status information.
int countbox(int boxsize, int qx, int qy, int qz)
Definition: cemhydmat.C:4543
long cy(int x, int y, int z, int a, int b, int c)
Definition: cemhydmat.C:14084
void alloc_char_3D(char ***(&mic), long SYSIZE)
Definition: cemhydmat.C:981
int IsConnected(int cx, int cy, int cz, int dx, int dy, int dz)
Definition: cemhydmat.C:13213
fcomplex_cem Cadd(fcomplex_cem a, fcomplex_cem b)
Definition: cemhydmat.C:13932
double * dvector(int nl, int nh)
Definition: cemhydmat.C:13754
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
MatResponseMode
Describes the character of characteristic material matrix.
struct percolatedpath * prev
Definition: cemhydmat.h:754
int reinforcementDegree
Degree of reinforcement, if defined, reinforcement effect for conductivity and capacity is accounted ...
Definition: cemhydmat.h:138
void initializeMicrostructure(void)
Definition: cemhydmat.C:563
int movegyp(int xcur, int ycur, int zcur, int finalstep)
Definition: cemhydmat.C:9638
void alloc_shortint_3D(short int ***(&mic), long SYSIZE)
Definition: cemhydmat.C:1070
void free_submatrix(float *b, int nrl)
int countboxc(int boxsize, int qx, int qy, int qz)
Definition: cemhydmat.C:4599
long int *** cemreal
Definition: cemhydmat.h:519
double MoveCycles(double GiveTemp, int cycles)
Definition: cemhydmat.C:7460
double GiveCycTime(void)
Definition: cemhydmat.C:7592
virtual double giveDoHActual(GaussPoint *gp)
Returns DoH of the closest CEMHYD3D cycle after the target time.
Definition: cemhydmat.C:157
struct ants * headant
Definition: cemhydmat.h:735
FloatArray scaling
Array containing scaling factors for density, conductivity and capacity.
Definition: cemhydmat.h:136
double Concrete_bulk_density
Definition: cemhydmat.h:693
double init_material_time
Inital material time for growing problems.
Definition: cemhydmat.h:214
long int nsolid[1500]
Definition: cemhydmat.h:557
float ** convert_matrix(float *a, int nrl, int nrh, int ncl, int nch)
Definition: cemhydmat.C:13907
virtual double giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep)
Returns concrete thermal capacity depending on chosen type.
Definition: cemhydmat.C:199
void extafm(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:10677
void zroots(fcomplex_cem a[], int m, fcomplex_cem roots[], int polish)
Definition: cemhydmat.C:12558
void QueryNumAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, int &val)
Definition: cemhydmat.C:1132
virtual double computeVolumeAround(GaussPoint *gp)
Returns volume related to given integration point.
Definition: element.h:518
IntArray nowarnings
Array containing warnings supression for density, conductivity, capacity, high temperature.
Definition: cemhydmat.h:134
void extfh3(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:8558
int chkfloc(int xin, int yin, int zin, int radd)
Definition: cemhydmat.C:1959
int surfpix(int xin, int yin, int zin)
Definition: cemhydmat.C:2754
GaussPoint * gp
Stores GP of the CemhydMatStatus.
Definition: cemhydmat.h:253
void disrealnew_init(void)
Definition: cemhydmat.C:6971
#define E(p)
Definition: mdm.C:368
virtual MaterialStatus * CreateStatus(GaussPoint *gp) const
Creates new copy of associated status and inserts it into given integration point.
Definition: cemhydmat.C:450
CemhydMatStatus * MasterCemhydMatStatus
Pointer to master CemhydMatStatus, which is shared among related integration points (on element...
Definition: cemhydmat.h:148
const FloatArray & giveField()
Return last field.
double GiveWcr(void)
Definition: cemhydmat.C:14064
#define M_PI
Definition: mathfem.h:52
void sysscan(int ph1, int ph2)
Definition: cemhydmat.C:2948
int conductivityType
Use different methods to evaluate material parameters.
Definition: cemhydmat.h:132
#define OOFEM_ERROR(...)
Definition: error.h:61
long cz(int x, int y, int z, int a, int b, int c)
Definition: cemhydmat.C:14089
struct percolatedpath * current
Definition: cemhydmat.h:757
virtual void averageTemperature()
Perform averaging on a master CemhydMatStatus.
Definition: cemhydmat.C:399
int movec4a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
Definition: cemhydmat.C:11760
void dealloc_long_3D(long ***(&mic), long SYSIZE)
Definition: cemhydmat.C:1025
void GenerateConnNumbers(void)
Definition: cemhydmat.C:13305
#define _IFT_CemhydMat_nowarnings
Definition: cemhydmat.h:64
void alloc_long_3D(long ***(&mic), long SYSIZE)
Definition: cemhydmat.C:1010
double GiveDensity(void)
Definition: cemhydmat.C:7557
int movec3a(int xcur, int ycur, int zcur, int finalstep, float nucprob)
Definition: cemhydmat.C:11213
int edgecnt(int xck, int yck, int zck, int ph1, int ph2, int ph3)
Definition: cemhydmat.C:8308
void outputImageFilePerc(void)
Definition: cemhydmat.C:13559
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Returns the integration point corresponding value in Reduced form.
Definition: cemhydmat.C:303
short int *** faces
Definition: cemhydmat.h:671
This class implements an isotropic linear heat material.
Definition: isoheatmat.h:58
virtual double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep)
Returns concrete heat conductivity depending on chosen type.
Definition: cemhydmat.C:168
virtual void printOutputAt(FILE *file, TimeStep *tStep)
Print receiver&#39;s output to given stream.
Definition: cemhydmat.C:14404
Material * giveMaterial()
Returns reference to material associated to related element of receiver.
Definition: gausspoint.h:197
void dealloc_double_3D(double ***(&mic), long SYSIZE)
Definition: cemhydmat.C:1115
void extc3ah6(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:11141
int extstrat(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:9557
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
int extfreidel(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:9476
fcomplex_cem RCmul(float x, fcomplex_cem a)
Definition: cemhydmat.C:14042
virtual ~CemhydMat()
Destructor.
Definition: cemhydmat.C:100
virtual double giveConcreteDensity(GaussPoint *gp, TimeStep *tStep)
Returns concrete density depending on chosen type.
Definition: cemhydmat.C:230
Abstract base class representing a material status information.
Definition: matstatus.h:84
void dealloc_char_3D(char ***(&mic), long SYSIZE)
Definition: cemhydmat.C:995
int movecas2(int xcur, int ycur, int zcur, int finalstep)
Definition: cemhydmat.C:10174
int moveettr(int xcur, int ycur, int zcur, int finalstep)
Definition: cemhydmat.C:10752
Class representing vector of real numbers.
Definition: floatarray.h:82
void selfConsistent(FloatMatrix &PhaseMatrix)
Self-consistent homogenization method of Hill and Budiansky for spherical isotropic inclusions...
Definition: homogenize.C:246
int AdjCoord(int coord)
Definition: cemhydmat.C:13623
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
Definition: isoheatmat.C:56
int Calculate_elastic_homogenization
Flag to proceed percolation filtering and elastic homogenization.
Definition: cemhydmat.h:249
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
long int volpart[47]
Definition: cemhydmat.h:526
double nu_hmg
Effective Poisson&#39;s ratio.
Definition: homogenize.h:131
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
void burn_phases(int d1, int d2, int d3)
Definition: cemhydmat.C:12858
XMLDocument * xmlFile
Definition: cemhydmat.h:465
double E_hmg
Effective Young&#39;s modulus or the lower bound.
Definition: homogenize.h:125
void makeinert(long int ndesire)
Definition: cemhydmat.C:4657
int loccsh(int xcur, int ycur, int zcur, int extent)
Definition: cemhydmat.C:4469
struct percolatedpath * next
Definition: cemhydmat.h:753
void free_dvector(double *v, int nl)
#define _IFT_CemhydMat_capacitytype
Definition: cemhydmat.h:61
void laguer(fcomplex_cem a[], int m, fcomplex_cem *x, float eps, int polish)
Definition: cemhydmat.C:12499
void moriTanaka(FloatMatrix &PhaseMatrix, int refRow)
Mori-Tanaka homogenization method for spherical isotropic inclusions.
Definition: homogenize.C:176
virtual int initMaterial(Element *element)
Optional function to call specific procedures when initializing a material.
Definition: cemhydmat.C:354
void disrealnew(double GiveTemp, double TargTime, int flag)
Definition: cemhydmat.C:7129
Class representing the general Input Record.
Definition: inputrecord.h:101
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)
Definition: cemhydmat.C:14284
void sysinit(int ph1, int ph2)
Definition: cemhydmat.C:2896
float Cabs(fcomplex_cem z)
Definition: cemhydmat.C:13991
void dissolve(int cycle)
Definition: cemhydmat.C:4874
#define _IFT_CemhydMat_inputFileName
Definition: cemhydmat.h:67
double ran1(int *idum)
Definition: cemhydmat.C:1452
void PercolateForOutput(void)
Definition: cemhydmat.C:14058
double ** dmatrix(int nrl, int nrh, int ncl, int nch)
Definition: cemhydmat.C:13793
void QueryStringAttributeExt(XMLDocument *xmlFile, const char *elementName, int position, char *chars)
Definition: cemhydmat.C:1212
void alloc_double_3D(double ***(&mic), long SYSIZE)
Definition: cemhydmat.C:1100
long int target_anhydrite
Definition: cemhydmat.h:527
double Concrete_thermal_conductivity
Definition: cemhydmat.h:693
float ** submatrix(float **a, int oldrl, int oldrh, int oldcl, int oldch, int newrl, int newcl)
Definition: cemhydmat.C:13842
void rand3d(int phasein, int phaseout, float xpt)
Definition: cemhydmat.C:3366
int MoveToDoH(double GiveTemp, double DesiredDoH, int maxcyc)
Definition: cemhydmat.C:7498
double GiveDoHActual(void)
Return degree of hydration of the receiver.
Definition: cemhydmat.C:7569
virtual double give(int aProperty, GaussPoint *gp, TimeStep *tStep)
Definition: isoheatmat.C:69
int countem(int xp, int yp, int zp, int phin)
Definition: cemhydmat.C:2853
void dealloc_shortint_3D(short int ***(&mic), long SYSIZE)
Definition: cemhydmat.C:1085
int moveanh(int xcur, int ycur, int zcur, int finalstep, float nucprgyp)
Definition: cemhydmat.C:8905
void passone(int low, int high, int cycid, int cshexflag)
Definition: cemhydmat.C:4371
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
Definition: cemhydmat.C:407
virtual double giveTimeOfCycle(GaussPoint *gp)
Returns time of the CEMHYD3D at the first cycle after the target time.
Definition: cemhydmat.C:145
long int surface[50]
Definition: cemhydmat.h:554
long int *** cement
Definition: cemhydmat.h:517
virtual void storeWeightTemperatureProductVolume(Element *element, TimeStep *tStep)
Store temperatures multiplied with volume around GPs - need before temperature averaging.
Definition: cemhydmat.C:385
virtual ~CemhydMatStatus()
Definition: cemhydmat.C:865
void sinter3d(int ph1id, int ph2id, float rhtarget)
Definition: cemhydmat.C:3171
int chckedge(int xck, int yck, int zck)
Definition: cemhydmat.C:4322
void extslagcsh(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:4781
short int *** cshage
Definition: cemhydmat.h:669
fcomplex_cem Csub(fcomplex_cem a, fcomplex_cem b)
Definition: cemhydmat.C:13940
fcomplex_cem Cmul(fcomplex_cem a, fcomplex_cem b)
Definition: cemhydmat.C:13948
CemhydMat(int n, Domain *d)
Constructor.
Definition: cemhydmat.C:95
int movefh3(int xcur, int ycur, int zcur, int finalstep, float nucprob)
Definition: cemhydmat.C:10969
#define _IFT_CemhydMat_scaling
Definition: cemhydmat.h:65
void drawfloc(int xin, int yin, int zin, int radd, int phasein, int phase2)
Definition: cemhydmat.C:1901
virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode)
Computes the internal source vector of receiver.
Definition: cemhydmat.C:105
REGISTER_Material(DummyMaterial)
double castingTime
Casting time.
Definition: material.h:113
float * vector(int nl, int nh)
Definition: cemhydmat.C:13730
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
bool isIcApply()
Check if receiver is solution step when initial conditions should apply.
Definition: timestep.C:144
virtual void clearWeightTemperatureProductVolume(Element *element)
Clear temperatures multiplied with volume around GPs - need before temperature averaging.
Definition: cemhydmat.C:375
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
long cx(int x, int y, int z, int a, int b, int c)
Definition: cemhydmat.C:14078
double GivePower(double GiveTemp, double TargTime)
Definition: cemhydmat.C:7372
the oofem namespace is to define a context or scope in which all oofem names are defined.
void setAverageTemperatureVolume(double temperature, double volume)
Auxiliary function for temperature averaging over GPs.
Definition: cemhydmat.h:217
fcomplex_cem Cdiv(fcomplex_cem a, fcomplex_cem b)
Definition: cemhydmat.C:13972
double * last_values
Array for storing temporary values (elastic properties etc.)
Definition: cemhydmat.h:247
float ** matrix_cem(int nrl, int nrh, int ncl, int nch)
Definition: cemhydmat.C:13769
int movech(int xcur, int ycur, int zcur, int finalstep, float nucprob)
Definition: cemhydmat.C:11026
int procsol(int nsearch)
Definition: cemhydmat.C:2973
void free_matrix(float **m, int nrl, int nrh, int ncl)
#define IR_GIVE_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:69
void readhydrparam(void)
Definition: cemhydmat.C:6418
int giveNumber() const
Definition: femcmpnn.h:107
double computeConcreteCapacityBentz(void)
Definition: cemhydmat.C:7547
#define _IFT_CemhydMat_eachgp
Definition: cemhydmat.h:63
void CSHbox(unsigned int *CSH_vicinity)
Definition: cemhydmat.C:13684
void alloc_int_3D(int ***(&mask), long SYSIZE)
Definition: cemhydmat.C:1040
Class representing integration point in finite element program.
Definition: gausspoint.h:93
#define OOFEM_WARNING(...)
Definition: error.h:62
double GiveTotCemHeat(void)
Definition: cemhydmat.C:7528
fcomplex_cem ComplexCemhyd(float re, float im)
Definition: cemhydmat.C:13956
int NumSol(int cx, int cy, int cz)
Definition: cemhydmat.C:13637
Class representing solution step.
Definition: timestep.h:80
double IPVolume
Volume associated to master IP of one CemhydMat.
Definition: cemhydmat.h:212
void herveZaoui(FloatMatrix &PhaseMatrix)
Herve and Zaoui&#39;s homogenization scheme for n-spherical isotropic domains and arbitrary number of iso...
Definition: homogenize.C:344
void extgyps(int xpres, int ypres, int zpres)
Definition: cemhydmat.C:8826
virtual double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
Compute heat thermal capacity per volume.
Definition: cemhydmat.C:260
double Vol_entrained_entrapped_air
Definition: cemhydmat.h:772
#define _IFT_CemhydMat_reinforcementDegree
Definition: cemhydmat.h:66
const char * __ValueModeTypeToString(ValueModeType _value)
Definition: cltypes.C:322
virtual int giveCycleNumber(GaussPoint *gp)
Returns cycle number at the closest cycle after the target time.
Definition: cemhydmat.C:135
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631
int icyc
Cycle of celular automata.
Definition: cemhydmat.h:245

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:27 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011