K itemAtIndex(K a, I i) { // Return i-th item from any type as K - TODO: oom wherever this is used I at=a->t; if( 0< at)R ci(a); if(-4==at)R Ks(kS(a)[i]); //could refactor all this if(-3==at)R Kc(kC(a)[i]); if(-2==at)R Kf(kF(a)[i]); if(-1==at)R Ki(kI(a)[i]); R ci(kK(a)[i]); }
static PyObject* _get_Kf(PyObject* self, PyObject* ko) { K kobj; int ok; ok = ko && IS_K(ko); if (!ok) goto fail; kobj = ((_K*)ko)->kobj; if (kobj && kobj->t == 2) { double f = Kf(kobj); return Py_BuildValue("f", f); } fail: PyErr_BadArgument(); return NULL; }
static PyObject* _set_Kf(PyObject* self, PyObject* args) { PyObject* ko; double f; if (PyArg_ParseTuple(args, "O!d", &_KType, &ko, &f)) { K k = ((_K*)ko)->kobj; if (k && k->t == 2) { Kf(k) = f; Py_INCREF(ko); return ko; } else { PyErr_SetString(PyExc_TypeError, "wrong k type"); return NULL; } } PyErr_BadArgument(); return NULL; }
vector< SingleReactionData > Make_Irreversible( vector< SingleReactionData > Reactions, const vector< ThermodynamicData > Thermodynamics, double Initial_Temperature, /// use initial temperature from initial data double Range // specify +/- rang around initial temperature ) { /* 2002 CODATA values */ //double R = 8.314472e0; // Ea is internally given in Kelvin, therefore R is not needed vector< SingleReactionData > Irreversible_Scheme; int i,j,k; int Number_Species = (int)Thermodynamics.size(); int Number_Reactions = (int)Reactions.size(); double Temperature; vector< double > Local_Delta_N = Get_Delta_N(Reactions); // check temperature and range provided, else use default if(Initial_Temperature == 0) { Initial_Temperature = 298.15; } if(Range == 0) { Range = 25; } // check we don't end up below 0K if(Initial_Temperature - Range <= 0) { Range = Initial_Temperature - 1; } vector< ReactionParameter > LocalReactionParameters; vector< TrackSpecies > LocalReactantsForReactions; vector< TrackSpecies > LocalProductsForReactions; vector< TrackSpecies > LocalSpeciesLossAll; LocalReactionParameters = Process_Reaction_Parameters(Reactions); LocalReactantsForReactions = Reactants_ForReactionRate(Reactions); LocalProductsForReactions = Products_ForReactionRate(Reactions,false); LocalSpeciesLossAll = PrepareSpecies_ForSpeciesLoss(Reactions); // Local copy of the global version. Needed to work out rate constants, but are based on data in Reactions array vector< vector< double > > allkreverse; vector< vector< double > > SensitivityMatrix; // called X in the paper vector< double > OneTempSensitivityMatrix; OneTempSensitivityMatrix.resize(3); vector< CalculatedThermodynamics > CalculatedThermo(Number_Species); vector< double > Kf(Number_Reactions) ; vector< double > Kr(Number_Reactions) ; // let us use 25 steps in either direction of the temperature for(i=0;i<50;i++) { Temperature = Initial_Temperature - Range + (i*Range/25); // +/- Range, 25 Steps in either direction Evaluate_Thermodynamic_Parameters(CalculatedThermo, Thermodynamics, Temperature); Calculate_Rate_Constant(Kf, Kr, Temperature,LocalReactionParameters, CalculatedThermo, LocalSpeciesLossAll, Local_Delta_N); for(j=0;j<(int)Kr.size();j++) { Kr[j] = log(Kr[j]); } allkreverse.push_back(Kr); OneTempSensitivityMatrix[0] = 1; OneTempSensitivityMatrix[1] = log(Temperature); OneTempSensitivityMatrix[2] = 1/Temperature; SensitivityMatrix.push_back(OneTempSensitivityMatrix); } // At this point we now have a collection of kr as well as the sensitivity matrix vector< vector< double > > SensitivityMatrixTranspose; // called X in the paper vector< double > RowSensitivityMatrixTranspose; RowSensitivityMatrixTranspose.resize(SensitivityMatrix.size()); // stupid way to give the matrix 3 rows SensitivityMatrixTranspose.push_back(RowSensitivityMatrixTranspose); SensitivityMatrixTranspose.push_back(RowSensitivityMatrixTranspose); SensitivityMatrixTranspose.push_back(RowSensitivityMatrixTranspose); for(i=0;i<3;i++) { for(j=0;j<(int)SensitivityMatrix.size();j++) { SensitivityMatrixTranspose[i][j] = SensitivityMatrix[j][i]; } } // Now we need to calculate our betas. // First on the list, SensitivityMatrixTranspose times SensitivityMatrix vector< vector< double > > SMtxSM; // Sensitivity Matrix transpose times (x) Sensitivity Matrix vector< double > SMt; // Sensitivity Matrix transpose times SMt.resize(3); // result is a 3x3 matrix SMtxSM.push_back(SMt); SMtxSM.push_back(SMt); SMtxSM.push_back(SMt); for(i=0;i<3;i++) { for(j=0;j<3;j++) { for(k=0;k<(int)SensitivityMatrix.size();k++) { SMtxSM[i][j] = SMtxSM[i][j] + SensitivityMatrixTranspose[i][k] * SensitivityMatrix[k][j]; } } } /* Now we need the inverse of the matrix. * * a , b , c * d , e , f * g , h , k * * divisor = cdh - cge - bdk + bgf + aek - ahf * * So matrix is, every entry divided by divisor, rest * * ek - hf , -dk + gf , dh - ge * ch - bk , -cg + ak , bg - ah * - ce + bf , cd - af , -bd + ae */ double determinant = SMtxSM[0][2]*SMtxSM[1][0]*SMtxSM[2][1] - SMtxSM[0][2]*SMtxSM[2][0]*SMtxSM[1][1] - SMtxSM[0][1]*SMtxSM[1][0]*SMtxSM[2][2] + SMtxSM[0][1]*SMtxSM[2][0]*SMtxSM[1][2] + SMtxSM[0][0]*SMtxSM[1][1]*SMtxSM[2][2] - SMtxSM[0][0]*SMtxSM[2][1]*SMtxSM[1][2]; vector< vector< double > > SMtxSMInv; // Sensitivity Matrix transpose times (x) Sensitivity Matrix vector< double > SMtInv; // Sensitivity Matrix transpose times SMtInv.resize(3); // Stupid way of creating an inverse matrix... but it is only 3*3 SMtxSMInv.push_back(SMtInv); SMtxSMInv.push_back(SMtInv); SMtxSMInv.push_back(SMtInv); SMtxSMInv[0][0] = SMtxSM[1][1]*SMtxSM[2][2] - SMtxSM[2][1]*SMtxSM[1][2]; SMtxSMInv[0][1] = - SMtxSM[1][0]*SMtxSM[2][2] + SMtxSM[2][0]*SMtxSM[1][2]; SMtxSMInv[0][2] = SMtxSM[1][0]*SMtxSM[2][1] - SMtxSM[2][0]*SMtxSM[1][1]; SMtxSMInv[1][0] = SMtxSM[0][2]*SMtxSM[2][1] - SMtxSM[0][1]*SMtxSM[2][2]; SMtxSMInv[1][1] = - SMtxSM[0][2]*SMtxSM[2][0] + SMtxSM[0][0]*SMtxSM[2][2]; SMtxSMInv[1][2] = SMtxSM[0][1]*SMtxSM[2][0] - SMtxSM[0][0]*SMtxSM[2][1]; SMtxSMInv[2][0] = - SMtxSM[0][2]*SMtxSM[1][1] + SMtxSM[0][1]*SMtxSM[1][2]; SMtxSMInv[2][1] = SMtxSM[0][2]*SMtxSM[1][0] - SMtxSM[0][0]*SMtxSM[1][2]; SMtxSMInv[2][2] = - SMtxSM[0][1]*SMtxSM[1][0] + SMtxSM[0][0]*SMtxSM[1][1]; // Don't forget dividing by the determinant for(i=0;i<3;i++) { for(j=0;j<3;j++) { SMtxSMInv[i][j] = SMtxSMInv[i][j] / determinant; } } // now transpose times the logarithms of k_r to get a 3 entry vector... vector< vector< double > > InvMxSM; vector< double > xSM; xSM.resize(SensitivityMatrix.size()); InvMxSM.push_back(xSM); InvMxSM.push_back(xSM); InvMxSM.push_back(xSM); // matrix mult: row x column for(i=0;i<3;i++) { for(j=0;j<(int)SensitivityMatrix.size();j++) { for(k=0;k<3;k++) { InvMxSM[i][j] = InvMxSM[i][j] + SMtxSMInv[i][k] * SensitivityMatrixTranspose[k][j]; } } } SingleReactionData SingleReaction; // assemble the arrays for writing a new reactions array vector< double > ReactantData; // Reactant Information ReactantData.resize(Number_Species); vector< double > ProductData; // Product Information ProductData.resize(Number_Species); vector< double > ReactionParameters; ReactionParameters.resize(4); for(i=0;i<Number_Reactions;i++) { // 1) retain the old forward reaction SingleReaction.Reactants = Reactions[i].Reactants; SingleReaction.Products = Reactions[i].Products; SingleReaction.paramA = Reactions[i].paramA; SingleReaction.paramN = Reactions[i].paramN; SingleReaction.paramEa = Reactions[i].paramEa; // switch reaction to irreversible: SingleReaction.Reversible = false; SingleReaction.IsDuplicate = Reactions[i].IsDuplicate; /* printf("Reaction %u Forward: %.3e %.3e %.3e %.3e || ",i, ReactionParamaters[0],ReactionParamaters[1], ReactionParamaters[2],ReactionParamaters[3]); // Works :) */ Irreversible_Scheme.push_back(SingleReaction); // Calculate the parameters vector< double > beta; beta.resize(3); // check if the reaction was reversible - if yes, calculate irreversible form if(Reactions[i].Reversible) { for(j=0;j<3;j++) { for(k=0;k<(int)SensitivityMatrix.size();k++) { beta[j] = beta[j] + InvMxSM[j][k] * allkreverse[k][i]; } } // Write out reverse reaction: // And now the reverse Reaction - Products and Reactants reversed for(j=0;j<Number_Species;j++) { ReactantData[j] = - Reactions[i].Products[j]; ProductData[j] = - Reactions[i].Reactants[j]; } SingleReaction.Reactants = ReactantData; SingleReaction.Products = ProductData; SingleReaction.paramA = exp(beta[0]); SingleReaction.paramN = beta[1]; SingleReaction.paramEa = -beta[2]; // retain reaction as irreversible: SingleReaction.Reversible = false; SingleReaction.IsDuplicate = Reactions[i].IsDuplicate; /* printf("Reverse %.3e %.3e %.3e %.3e \n", ReactionParamaters[0],ReactionParamaters[1], ReactionParamaters[2],ReactionParamaters[3]); // Works :) */ Irreversible_Scheme.push_back(SingleReaction); } } return Irreversible_Scheme; }
/* XXX unfortunately API function gnk of which pyk.gk is based is a vararg function and therefore cannot be portably exported to Python. It would be better if libk20 supplied a function gnk_(I, K*) in addition to gnk(I,...) which would take an array of K objects as the second argument */ static PyObject* _gk(PyObject* self, PyObject* args) { int n = PyTuple_Size(args); if (!n) { return _mk_K(gtn(0,0)); } int i, type = INT_MAX; K* ks = (K*)malloc(n*sizeof(K)); K kobj; for(i = 0; i < n; i++) { K ki; int t; PyObject* argi = PyTuple_GET_ITEM(args, i); if (!IS_K(argi)) { goto fail; } ks[i] = ki = ((_K*)argi)->kobj; t = ki->t; if (INT_MAX == type) { type = t; } else if (t > 4 || t < 1 || t != type) { type = 0; } } kobj = gtn((type>0 && type<5)?-type:0, n); if (!kobj) { free(ks); return PyErr_Format(PyExc_TypeError, "gtn(%d,%d) returned null", -type, n); } switch (type) { case 1: for (i = 0; i < n; i++) { KI(kobj)[i] = Ki(ks[i]); } break; case 2: for (i = 0; i < n; i++) { KF(kobj)[i] = Kf(ks[i]); } break; case 3: for (i = 0; i < n; i++) { KC(kobj)[i] = Kc(ks[i]); } break; case 4: for (i = 0; i < n; i++) { KS(kobj)[i] = Ks(ks[i]); } break; default: memcpy(KK(kobj), ks, n*sizeof(K)); for (i = 0; i < n; i++) { ci(ks[i]); } break; } free(ks); return _mk_K(kobj); fail: free(ks); PyErr_BadArgument(); return NULL; }
K gf(F x) {K z=newK(2,1); Kf(z)=x; R z;}
int main(int argc, char** argv) { F pi = atan(1.0)*4; K a = gi(2); K b = gi(3); K c = gi(4); K* v; cd(ksk("",0)); tst(Ki(a)==2); tst(Ki(b) + 1 == Ki(c)); cd(a); cd(b); cd(c); b = gf(1.0); c = gf(2); tst(Kf(b) + 1 == Kf(c)); cd(b); cd(c); a = gs(sp("foo")); b = ksk("`foo", 0); tst(Ks(a) == Ks(b)); cd(a); cd(b); a = ksk("2 + 3", 0); tst(Ki(a) == 5); cd(a); a = ksk("_ci 65", 0); tst(Kc(a) == 'A'); // XXX this should return type 1 uniform vector a=gnk(3,gi(11),gi(22),gi(33)); tst(a->t == 0); v = (K*)a->k; tst(Ki(v[0])+Ki(v[1])==Ki(v[2])); cd(a); { b = gsk("pi",gf(pi)); kap(&KTREE, &b); a = X(".pi"); tst(Kf(a) == pi); cd(a); } { K dir = gtn(5,0); K t; t = gsk("x",gi(1)); kap(&dir, &t); t = gsk("y",gi(2)); kap(&dir, &t); t = gsk("z",dir); kap(&KTREE, &t); a = X(".z.x"); tst(Ki(a) == 1); cd(a); a = X(".z.y"); tst(Ki(a) == 2); cd(a); } { I i; K d = gtn(5,0); K c0 = gtn(0,0); K c1 = gtn(-1,0); K t0, t1, e; t0 = gsk("a", c0); kap(&d,&t0); t1 = gsk("b", c1); kap(&d,&t1); e = gp("hello1"); kap(&c0,&e); e = gp("hello2"); kap(&c0,&e); KK(KK(d)[0])[1] = c0; i = 1; kap(&KK(KK(d)[1])[1], &i); i = 2; kap(&KK(KK(d)[1])[1], &i); //i = 1; kap(&c1, &i); //i = 2; kap(&c1, &i); //KK(KK(d)[1])[1] = c1; show(d); } //b = ksk("+/", a); //tst(Ki(b) == 66); //argc--;argv++; //DO(i, argc, {a=ksk(argv[i], 0); //ksk("`0:,/$!10;`0:,\"\n\"", 0); fprintf(stderr, "Pass:%4d, fail:%4d\n", pass, fail); if (argc > 1 && strcmp(argv[1], "-i") == 0) { boilerplate(); attend(); } }