double mitk::GeneralizedLinearModel::Predict( const vnl_vector<double> &c) { LogItLinking link; double mu = 0; int cols = m_B.size(); for (int i = 0; i < cols; ++i) { if (!m_AddConstantColumn) mu += c(i)* m_B(i); else if ( i == 0) mu += 1* m_B(i); else mu += c(i-1)*m_B(i); } return link.InverseLink(mu); }
vnl_vector<double> mitk::GeneralizedLinearModel::ExpMu(const vnl_matrix<double> &x) { LogItLinking link; vnl_vector<double> mu(x.rows()); int cols = m_B.size(); for (unsigned int r = 0 ; r < mu.size(); ++r) { mu(r) = 0; for (int c = 0; c < cols; ++c) { if (!m_AddConstantColumn) mu(r) += x(r,c)*m_B(c); else if ( c == 0) mu(r) += m_B(c); else mu(r) += x(r,c-1)*m_B(c); } mu(r) = exp(-mu(r)); } return mu; }
/* * * Solve for the diffusional velocities in the Stefan-Maxwell equations * */ void LiquidTransport::stefan_maxwell_solve() { doublereal tmp; size_t VIM = m_nDim; m_B.resize(m_nsp, VIM); //! grab a local copy of the molecular weights const vector_fp& M = m_thermo->molecularWeights(); /* * Update the concentrations in the mixture. */ update_conc(); double T = m_thermo->temperature(); m_thermo->getStandardVolumes(DATA_PTR(volume_specPM_)); m_thermo->getActivityCoefficients(DATA_PTR(actCoeffMolar_)); /* * Calculate the electrochemical potential gradient. This is the * driving force for relative diffusional transport. * * Here we calculate * * c_i * (grad (mu_i) + S_i grad T - M_i / dens * grad P * * This is Eqn. 13-1 p. 318 Newman. The original equation is from * Hershfeld, Curtis, and Bird. * * S_i is the partial molar entropy of species i. This term will cancel * out a lot of the grad T terms in grad (mu_i), therefore simplifying * the expression. * * Ok I think there may be many ways to do this. One way is to do it via basis * functions, at the nodes, as a function of the variables in the problem. * * For calculation of molality based thermo systems, we current get * the molar based values. This may change. * * Note, we have broken the symmetry of the matrix here, due to * consideratins involving species concentrations going to zero. * */ for (size_t i = 0; i < m_nsp; i++) { double xi_denom = m_molefracs_tran[i]; for (size_t a = 0; a < VIM; a++) { m_ck_Grad_mu[a*m_nsp + i] = m_chargeSpecies[i] * concTot_ * Faraday * m_Grad_V[a] + concTot_ * (volume_specPM_[i] - M[i]/dens_) * m_Grad_P[a] + concTot_ * GasConstant * T * m_Grad_lnAC[a*m_nsp+i] / actCoeffMolar_[i] + concTot_ * GasConstant * T * m_Grad_X[a*m_nsp+i] / xi_denom; } } if (m_thermo->activityConvention() == cAC_CONVENTION_MOLALITY) { int iSolvent = 0; double mwSolvent = m_thermo->molecularWeight(iSolvent); double mnaught = mwSolvent/ 1000.; double lnmnaught = log(mnaught); for (size_t i = 1; i < m_nsp; i++) { for (size_t a = 0; a < VIM; a++) { m_ck_Grad_mu[a*m_nsp + i] -= m_concentrations[i] * GasConstant * m_Grad_T[a] * lnmnaught; } } } /* * Just for Note, m_A(i,j) refers to the ith row and jth column. * They are still fortran ordered, so that i varies fastest. */ switch (VIM) { case 1: /* 1-D approximation */ m_B(0,0) = 0.0; for (size_t j = 0; j < m_nsp; j++) { m_A(0,j) = M[j] * m_concentrations[j]; } for (size_t i = 1; i < m_nsp; i++){ m_B(i,0) = m_ck_Grad_mu[i] / (GasConstant * T); m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++){ if (j != i) { tmp = m_concentrations[j] / m_DiffCoeff_StefMax(i,j); m_A(i,i) += tmp; m_A(i,j) = - tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); break; case 2: /* 2-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; for (size_t j = 0; j < m_nsp; j++) { m_A(0,j) = M[j] * m_concentrations[j]; } for (size_t i = 1; i < m_nsp; i++){ m_B(i,0) = m_ck_Grad_mu[i] / (GasConstant * T); m_B(i,1) = m_ck_Grad_mu[m_nsp + i] / (GasConstant * T); m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_concentrations[j] / m_DiffCoeff_StefMax(i,j); m_A(i,i) += tmp; m_A(i,j) = - tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); break; case 3: /* 3-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; m_B(0,2) = 0.0; for (size_t j = 0; j < m_nsp; j++) { m_A(0,j) = M[j] * m_concentrations[j]; } for (size_t i = 1; i < m_nsp; i++){ m_B(i,0) = m_ck_Grad_mu[i] / (GasConstant * T); m_B(i,1) = m_ck_Grad_mu[m_nsp + i] / (GasConstant * T); m_B(i,2) = m_ck_Grad_mu[2*m_nsp + i] / (GasConstant * T); m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_concentrations[j] / m_DiffCoeff_StefMax(i,j); m_A(i,i) += tmp; m_A(i,j) = - tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); break; default: printf("uninmplemetnd\n"); throw CanteraError("routine", "not done"); break; } for (size_t a = 0; a < VIM; a++) { for (size_t j = 0; j < m_nsp; j++) { m_flux(j,a) = M[j] * m_concentrations[j] * m_B(j,a); } } }
void AqueousTransport::stefan_maxwell_solve() { size_t VIM = 2; m_B.resize(m_nsp, VIM); // grab a local copy of the molecular weights const vector_fp& M = m_thermo->molecularWeights(); // get the mean molecular weight of the mixture //double M_mix = m_thermo->meanMolecularWeight(); // get the concentration of the mixture //double rho = m_thermo->density(); //double c = rho/M_mix; m_thermo->getMoleFractions(DATA_PTR(m_molefracs)); double T = m_thermo->temperature(); /* electrochemical potential gradient */ for (size_t i = 0; i < m_nsp; i++) { for (size_t a = 0; a < VIM; a++) { m_Grad_mu[a*m_nsp + i] = m_chargeSpecies[i] * Faraday * m_Grad_V[a] + (GasConstant*T/m_molefracs[i]) * m_Grad_X[a*m_nsp+i]; } } /* * Just for Note, m_A(i,j) refers to the ith row and jth column. * They are still fortran ordered, so that i varies fastest. */ switch (VIM) { case 1: /* 1-D approximation */ m_B(0,0) = 0.0; for (size_t j = 0; j < m_nsp; j++) { m_A(0,j) = 1.0; } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_concentrations[i] * m_Grad_mu[i] / (GasConstant * T); for (size_t j = 0; j < m_nsp; j++) { if (j != i) { m_A(i,j) = m_molefracs[i] / (M[j] * m_DiffCoeff_StefMax(i,j)); m_A(i,i) -= m_molefracs[j] / (M[i] * m_DiffCoeff_StefMax(i,j)); } else if (j == i) { m_A(i,i) = 0.0; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B.ptrColumn(0)); m_flux = m_B; break; case 2: /* 2-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; for (size_t j = 0; j < m_nsp; j++) { m_A(0,j) = 1.0; } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_concentrations[i] * m_Grad_mu[i] / (GasConstant * T); m_B(i,1) = m_concentrations[i] * m_Grad_mu[m_nsp + i] / (GasConstant * T); for (size_t j = 0; j < m_nsp; j++) { if (j != i) { m_A(i,j) = m_molefracs[i] / (M[j] * m_DiffCoeff_StefMax(i,j)); m_A(i,i) -= m_molefracs[j] / (M[i] * m_DiffCoeff_StefMax(i,j)); } else if (j == i) { m_A(i,i) = 0.0; } } } //! invert and solve the system Ax = b. Answer is in m_B //solve(m_A, m_B); m_flux = m_B; break; case 3: /* 3-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; m_B(0,2) = 0.0; for (size_t j = 0; j < m_nsp; j++) { m_A(0,j) = 1.0; } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_concentrations[i] * m_Grad_mu[i] / (GasConstant * T); m_B(i,1) = m_concentrations[i] * m_Grad_mu[m_nsp + i] / (GasConstant * T); m_B(i,2) = m_concentrations[i] * m_Grad_mu[2*m_nsp + i] / (GasConstant * T); for (size_t j = 0; j < m_nsp; j++) { if (j != i) { m_A(i,j) = m_molefracs[i] / (M[j] * m_DiffCoeff_StefMax(i,j)); m_A(i,i) -= m_molefracs[j] / (M[i] * m_DiffCoeff_StefMax(i,j)); } else if (j == i) { m_A(i,i) = 0.0; } } } //! invert and solve the system Ax = b. Answer is in m_B //solve(m_A, m_B); m_flux = m_B; break; default: printf("unimplemented\n"); throw CanteraError("routine", "not done"); break; } }
void LiquidTransport::stefan_maxwell_solve() { doublereal tmp; m_B.resize(m_nsp, m_nDim, 0.0); m_A.resize(m_nsp, m_nsp, 0.0); //! grab a local copy of the molecular weights const vector_fp& M = m_thermo->molecularWeights(); //! grad a local copy of the ion molar volume (inverse total ion concentration) const doublereal vol = m_thermo->molarVolume(); /* * Update the temperature, concentrations and diffusion coefficients in the mixture. */ update_T(); update_C(); if (!m_diff_temp_ok) { updateDiff_T(); } double T = m_thermo->temperature(); update_Grad_lnAC(); m_thermo->getActivityCoefficients(DATA_PTR(m_actCoeff)); /* * Calculate the electrochemical potential gradient. This is the * driving force for relative diffusional transport. * * Here we calculate * * X_i * (grad (mu_i) + S_i grad T - M_i / dens * grad P * * This is Eqn. 13-1 p. 318 Newman. The original equation is from * Hershfeld, Curtis, and Bird. * * S_i is the partial molar entropy of species i. This term will cancel * out a lot of the grad T terms in grad (mu_i), therefore simplifying * the expression. * * Ok I think there may be many ways to do this. One way is to do it via basis * functions, at the nodes, as a function of the variables in the problem. * * For calculation of molality based thermo systems, we current get * the molar based values. This may change. * * Note, we have broken the symmetry of the matrix here, due to * considerations involving species concentrations going to zero. */ for (size_t a = 0; a < m_nDim; a++) { for (size_t i = 0; i < m_nsp; i++) { m_Grad_mu[a*m_nsp + i] = m_chargeSpecies[i] * Faraday * m_Grad_V[a] + GasConstant * T * m_Grad_lnAC[a*m_nsp+i]; } } if (m_thermo->activityConvention() == cAC_CONVENTION_MOLALITY) { int iSolvent = 0; double mwSolvent = m_thermo->molecularWeight(iSolvent); double mnaught = mwSolvent/ 1000.; double lnmnaught = log(mnaught); for (size_t a = 0; a < m_nDim; a++) { for (size_t i = 1; i < m_nsp; i++) { m_Grad_mu[a*m_nsp + i] -= m_molefracs[i] * GasConstant * m_Grad_T[a] * lnmnaught; } } } /* * Just for Note, m_A(i,j) refers to the ith row and jth column. * They are still fortran ordered, so that i varies fastest. */ double condSum1; const doublereal invRT = 1.0 / (GasConstant * T); switch (m_nDim) { case 1: /* 1-D approximation */ m_B(0,0) = 0.0; //equation for the reference velocity for (size_t j = 0; j < m_nsp; j++) { if (m_velocityBasis == VB_MOLEAVG) { m_A(0,j) = m_molefracs_tran[j]; } else if (m_velocityBasis == VB_MASSAVG) { m_A(0,j) = m_massfracs_tran[j]; } else if ((m_velocityBasis >= 0) && (m_velocityBasis < static_cast<int>(m_nsp))) { // use species number m_velocityBasis as reference velocity if (m_velocityBasis == static_cast<int>(j)) { m_A(0,j) = 1.0; } else { m_A(0,j) = 0.0; } } else { throw CanteraError("LiquidTransport::stefan_maxwell_solve", "Unknown reference velocity provided."); } } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_Grad_mu[i] * invRT; m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_molefracs_tran[j] * m_bdiff(i,j); m_A(i,i) -= tmp; m_A(i,j) = tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); condSum1 = 0; for (size_t i = 0; i < m_nsp; i++) { condSum1 -= Faraday*m_chargeSpecies[i]*m_B(i,0)*m_molefracs_tran[i]/vol; } break; case 2: /* 2-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; //equation for the reference velocity for (size_t j = 0; j < m_nsp; j++) { if (m_velocityBasis == VB_MOLEAVG) { m_A(0,j) = m_molefracs_tran[j]; } else if (m_velocityBasis == VB_MASSAVG) { m_A(0,j) = m_massfracs_tran[j]; } else if ((m_velocityBasis >= 0) && (m_velocityBasis < static_cast<int>(m_nsp))) { // use species number m_velocityBasis as reference velocity if (m_velocityBasis == static_cast<int>(j)) { m_A(0,j) = 1.0; } else { m_A(0,j) = 0.0; } } else { throw CanteraError("LiquidTransport::stefan_maxwell_solve", "Unknown reference velocity provided."); } } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_Grad_mu[i] * invRT; m_B(i,1) = m_Grad_mu[m_nsp + i] * invRT; m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_molefracs_tran[j] * m_bdiff(i,j); m_A(i,i) -= tmp; m_A(i,j) = tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); break; case 3: /* 3-D approximation */ m_B(0,0) = 0.0; m_B(0,1) = 0.0; m_B(0,2) = 0.0; //equation for the reference velocity for (size_t j = 0; j < m_nsp; j++) { if (m_velocityBasis == VB_MOLEAVG) { m_A(0,j) = m_molefracs_tran[j]; } else if (m_velocityBasis == VB_MASSAVG) { m_A(0,j) = m_massfracs_tran[j]; } else if ((m_velocityBasis >= 0) && (m_velocityBasis < static_cast<int>(m_nsp))) { // use species number m_velocityBasis as reference velocity if (m_velocityBasis == static_cast<int>(j)) { m_A(0,j) = 1.0; } else { m_A(0,j) = 0.0; } } else { throw CanteraError("LiquidTransport::stefan_maxwell_solve", "Unknown reference velocity provided."); } } for (size_t i = 1; i < m_nsp; i++) { m_B(i,0) = m_Grad_mu[i] * invRT; m_B(i,1) = m_Grad_mu[m_nsp + i] * invRT; m_B(i,2) = m_Grad_mu[2*m_nsp + i] * invRT; m_A(i,i) = 0.0; for (size_t j = 0; j < m_nsp; j++) { if (j != i) { tmp = m_molefracs_tran[j] * m_bdiff(i,j); m_A(i,i) -= tmp; m_A(i,j) = tmp; } } } //! invert and solve the system Ax = b. Answer is in m_B solve(m_A, m_B); break; default: printf("unimplemented\n"); throw CanteraError("routine", "not done"); break; } for (size_t a = 0; a < m_nDim; a++) { for (size_t j = 0; j < m_nsp; j++) { m_Vdiff(j,a) = m_B(j,a); m_flux(j,a) = concTot_ * M[j] * m_molefracs_tran[j] * m_B(j,a); } } }
mitk::GeneralizedLinearModel::GeneralizedLinearModel(const vnl_matrix<double> &xData, const vnl_vector<double> &yData, bool addConstantColumn) : m_AddConstantColumn(addConstantColumn) { EstimatePermutation(xData); DistSimpleBinominal dist; LogItLinking link; vnl_matrix<double> x; int rows = xData.rows(); int cols = m_Permutation.size(); vnl_vector<double> mu(rows); vnl_vector<double> eta(rows); vnl_vector<double> weightedY(rows); vnl_matrix<double> weightedX(rows, cols); vnl_vector<double> oldB(cols); _UpdatePermXMatrix(xData, m_AddConstantColumn, m_Permutation, x); _InitMuEta(&dist, &link, yData, mu, eta); int iter = 0; int iterLimit = 100; double sqrtEps = sqrt(std::numeric_limits<double>::epsilon()); double convertCriterion =1e-6; m_B.set_size(m_Permutation.size()); m_B.fill(0); while (iter <= iterLimit) { ++iter; oldB = m_B; // Do Row-wise operation. No Vector oepration at this point. for (int r = 0; r<rows; ++r) { double deta = link.DLink(mu(r)); double zBuffer = eta(r) + (yData(r) - mu(r))*deta; double sqrtWeight = 1 / (std::abs(deta) * dist.SqrtVariance(mu(r))); weightedY(r) = zBuffer * sqrtWeight; for (int c=0; c<cols; ++c) { weightedX(r,c) = x(r,c) * sqrtWeight; } } vnl_qr<double> qr(weightedX); m_B = qr.solve(weightedY); eta = x * m_B; for (int r = 0; r < rows; ++r) { mu(r) = link.InverseLink(eta(r)); } bool stayInLoop = false; for(int c= 0; c < cols; ++c) { stayInLoop |= std::abs( m_B(c) - oldB(c)) > convertCriterion * std::max(sqrtEps, std::abs(oldB(c))); } if (!stayInLoop) break; } _FinalizeBVector(m_B, m_Permutation, xData.cols()); }