void MixedSolventElectrolyte::s_update_dlnActCoeff_dlnN_diag() const { int delAK, delBK; double XA, XB, XK, g0, g1; double T = temperature(); double RT = GasConstant*T; dlnActCoeffdlnN_diag_.assign(m_kk, 0); for (size_t iK = 0; iK < m_kk; iK++) { XK = moleFractions_[iK]; for (size_t i = 0; i < numBinaryInteractions_; i++) { size_t iA = m_pSpecies_A_ij[i]; size_t iB = m_pSpecies_B_ij[i]; delAK = 0; delBK = 0; if (iA==iK) { delAK = 1; } else if (iB==iK) { delBK = 1; } XA = moleFractions_[iA]; XB = moleFractions_[iB]; g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT; g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT; dlnActCoeffdlnN_diag_[iK] += 2*(delBK-XB)*(g0*(delAK-XA)+g1*(2*(delAK-XA)*XB+XA*(delBK-XB))); // double gfac = g0 + g1 * XB; // double gggg = (delBK - XB) * g1; // dlnActCoeffdlnN_diag_[iK] += gfac * delAK * ( - XB + delBK); // dlnActCoeffdlnN_diag_[iK] += gfac * delBK * ( - XA + delAK); // dlnActCoeffdlnN_diag_[iK] += gfac * (2.0 * XA * XB - delAK * XB - XA * delBK); // dlnActCoeffdlnN_diag_[iK] += (delAK * XB + XA * delBK - XA * XB) * g1 * (-XB + delBK); // dlnActCoeffdlnN_diag_[iK] += gggg * ( - 2.0 * XA * XB + delAK * XB + XA * delBK); // dlnActCoeffdlnN_diag_[iK] += - g1 * XA * XB * (- XB + delBK); } dlnActCoeffdlnN_diag_[iK] = XK*dlnActCoeffdlnN_diag_[iK];//-XK; } }
void watch(const FuncT& f) { for(;;) { wait_for_data(); f( wetness(), temperature(), atmospheric_pressure(), illumination() ); } }
void ConstDensityThermo::getChemPotentials(doublereal* mu) const { doublereal vdp = (pressure() - m_spthermo->refPressure())/ molarDensity(); doublereal xx; doublereal rt = temperature() * GasConstant; const array_fp& g_RT = gibbs_RT(); for (int k = 0; k < m_kk; k++) { xx = fmaxx(SmallNumber, moleFraction(k)); mu[k] = rt*(g_RT[k] + log(xx)) + vdp; } }
void Reactor::updateState(doublereal* y) { // The components of y are [0] the total mass, [1] the total volume, // [2] the total internal energy, [3...K+3] are the mass fractions of each // species, and [K+3...] are the coverages of surface species on each wall. m_mass = y[0]; m_vol = y[1]; m_thermo->setMassFractions_NoNorm(y+3); if (m_energy) { // Use a damped Newton's method to determine the mixture temperature. // Tight tolerances are required both for Jacobian evaluation and for // sensitivity analysis to work correctly. doublereal U = y[2]; doublereal T = temperature(); double dT = 100; double dUprev = 1e10; double dU = 1e10; int i = 0; double damp = 1.0; while (abs(dT / T) > 10 * DBL_EPSILON) { dUprev = dU; m_thermo->setState_TR(T, m_mass / m_vol); double dUdT = m_thermo->cv_mass() * m_mass; dU = m_thermo->intEnergy_mass() * m_mass - U; dT = dU / dUdT; // Reduce the damping coefficient if the magnitude of the error // isn't decreasing if (std::abs(dU) < std::abs(dUprev)) { damp = 1.0; } else { damp *= 0.8; } dT = std::min(dT, 0.5 * T) * damp; T -= dT; i++; if (i > 100) { throw CanteraError("Reactor::updateState", "no convergence\nU/m = {}\nT = {}\nrho = {}\n", U / m_mass, T, m_mass / m_vol); } } } else { m_thermo->setDensity(m_mass/m_vol); } updateSurfaceState(y + m_nsp + 3); // save parameters needed by other connected reactors m_enthalpy = m_thermo->enthalpy_mass(); m_pressure = m_thermo->pressure(); m_intEnergy = m_thermo->intEnergy_mass(); m_thermo->saveState(m_state); }
//function is fed with a priority queue of action-values //generates Boltzmann distribution of these action-values //and selects an action based on probabilities float selectAction(PriorityQueue<float, double>& a_queue, unsigned long iterations) { typedef std::vector<std::pair<float, double>> VecPair ; //turn priority queue into a vector of pairs VecPair vec = a_queue.saveOrderedQueueAsVector(); //sum for partition function double sum = 0; // calculate partition function by iterating over action-values for (VecPair::iterator iter = vec.begin(), end = vec.end(); iter < end; ++iter) { sum += std::exp((iter->second) / temperature(iterations)); } //compute Boltzmann factors for action-values and enqueue to vec for (VecPair::iterator iter = vec.begin(); iter < vec.end(); ++iter) { iter->second = std::exp(iter->second / temperature(iterations)) / sum; } //calculate cumulative probability distribution for (VecPair::iterator iter = vec.begin()++, end = vec.end(); iter < end; ++iter) { //second member of pair becomes addition of its current value //and that of the index before it iter->second += (iter-1)->second; } //generate RN between 0 and 1 double rand_num = static_cast<double>(rand()) / RAND_MAX; // choose action based on random number relation to priorities within action queue for (VecPair::iterator iter = vec.begin(), end = vec.end(); iter < end; ++iter) { if (rand_num < iter->second)return iter->first; } return -10; //note that this line should never be reached }
void StatisticsSampler::saveToFile(System &system, ofstream &file) { // Convert all energy per atom, use eV file << setw(15) << UnitConverter::timeToSI(system.steps()) << " " << setw(15) << UnitConverter::timeToSI(system.time()) << " " << setw(15) << UnitConverter::temperatureToSI(temperature()) << " " << setw(15) << UnitConverter::energyToEv(kineticEnergy()/system.atoms().size()) << " " << setw(15) << UnitConverter::energyToEv(potentialEnergy()/system.atoms().size()) << " " << setw(15) << UnitConverter::energyToEv(totalEnergy()/system.atoms().size()) << " " << setw(15) << diffusionConstant() << " " << setw(15) << m_rSquared << std::endl; }
/* * cv_mole(): * * Molar heat capacity at constant volume of the mixture. * Units: J/kmol/K. * * For single species, we go directory to the * general Cp - Cv relation * * Cp = Cv + alpha**2 * V * T / beta * * where * alpha = volume thermal expansion coefficient * beta = isothermal compressibility */ doublereal SingleSpeciesTP::cv_mole() const { doublereal cvbar = cp_mole(); doublereal alpha = thermalExpansionCoeff(); doublereal beta = isothermalCompressibility(); doublereal molecW = molecularWeight(0); doublereal V = molecW/density(); doublereal T = temperature(); if (beta != 0.0) { cvbar -= alpha * alpha * V * T / beta; } return cvbar; }
void LatticePhase::_updateThermo() const { doublereal tnow = temperature(); if (m_tlast != tnow) { m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0], &m_s0_R[0]); m_tlast = tnow; for (size_t k = 0; k < m_kk; k++) { m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; } m_tlast = tnow; } }
int tester(const std::string & input_file) { //temperature std::vector<Scalar> T0,Tz; read_temperature<Scalar>(T0,Tz,input_file); gsl_interp_accel * acc = gsl_interp_accel_alloc(); gsl_spline * spline = gsl_spline_alloc(gsl_interp_cspline, T0.size()); // GLS takes only double, raaaaahhhh std::vector<double> gsl_x_point(T0.size(),0); std::vector<double> gsl_y_point(T0.size(),0); for(unsigned int i = 0; i < T0.size(); i++) { gsl_x_point[i] = (const double)Tz[i]; gsl_y_point[i] = (const double)T0[i]; } const double * x = &gsl_x_point[0]; const double * y = &gsl_y_point[0]; gsl_spline_init(spline, x, y, T0.size()); Planet::AtmosphericTemperature<Scalar,std::vector<Scalar> > temperature(Tz,T0); //neutral, ionic, altitude int return_flag(0); const Scalar tol = (std::numeric_limits<Scalar>::epsilon() * 100. < 6e-17)?6e-17: std::numeric_limits<Scalar>::epsilon() * 100.; for(Scalar z = 600.; z < 1401.; z += 10) { Scalar neu_temp = gsl_spline_eval(spline,z,acc); Scalar neu_dtemp = gsl_spline_eval_deriv(spline,z,acc); Scalar ion_temp = gsl_spline_eval(spline,z,acc); Scalar ion_dtemp = gsl_spline_eval_deriv(spline,z,acc); Scalar e_temp = electron_temperature(z); Scalar de_dtemp = delectron_temperature(z); return_flag = check(temperature.neutral_temperature(z), neu_temp, tol, "neutral temperature") || check(temperature.dneutral_temperature_dz(z), neu_dtemp, tol, "neutral temperature differentiate") || check(temperature.ionic_temperature(z), ion_temp, tol, "ionic temperature") || check(temperature.dionic_temperature_dz(z), ion_dtemp, tol, "ionic temperature differentiate") || check(temperature.electronic_temperature(z), e_temp, tol, "electron temperature") || check(temperature.delectronic_temperature_dz(z), de_dtemp, tol, "electron temperature differentiate") || return_flag; } gsl_spline_free(spline); gsl_interp_accel_free(acc); return return_flag; }
void ConstDensityThermo::_updateThermo() const { doublereal tnow = temperature(); if (m_tlast != tnow) { m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0], &m_s0_R[0]); m_tlast = tnow; int k; for (k = 0; k < m_kk; k++) { m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; } m_tlast = tnow; } }
void VPSSMgr_IdealGas::_updateStandardStateThermo() { doublereal pp = log(m_plast / m_p0); doublereal v = temperature() *GasConstant /m_plast; for (size_t k = 0; k < m_kk; k++) { m_hss_RT[k] = m_h0_RT[k]; m_cpss_R[k] = m_cp0_R[k]; m_sss_R[k] = m_s0_R[k] - pp; m_gss_RT[k] = m_hss_RT[k] - m_sss_R[k]; m_Vss[k] = v; } }
void RedlichKisterVPSSTP::s_update_dlnActCoeff_dlnX_diag() const { doublereal T = temperature(); dlnActCoeffdlnX_diag_.assign(m_kk, 0.0); for (size_t i = 0; i < numBinaryInteractions_; i++) { size_t iA = m_pSpecies_A_ij[i]; size_t iB = m_pSpecies_B_ij[i]; double XA = moleFractions_[iA]; double XB = moleFractions_[iB]; doublereal deltaX = XA - XB; size_t N = m_N_ij[i]; doublereal poly = 1.0; doublereal sum = 0.0; vector_fp& he_vec = m_HE_m_ij[i]; vector_fp& se_vec = m_SE_m_ij[i]; doublereal sumMm1 = 0.0; doublereal polyMm1 = 1.0; doublereal polyMm2 = 1.0; doublereal sumMm2 = 0.0; for (size_t m = 0; m < N; m++) { doublereal A_ge = (he_vec[m] - T * se_vec[m]) / (GasConstant * T);; sum += A_ge * poly; poly *= deltaX; if (m >= 1) { sumMm1 += (A_ge * polyMm1 * m); polyMm1 *= deltaX; } if (m >= 2) { sumMm2 += (A_ge * polyMm2 * m * (m - 1.0)); polyMm2 *= deltaX; } } for (size_t k = 0; k < m_kk; k++) { if (iA == k) { dlnActCoeffdlnX_diag_[k] += XA * (- (1-XA+XB) * sum + 2*(1.0 - XA) * XB * sumMm1 + sumMm1 * (XB *(1.0 - 2.0 * XA + XB) - XA * (1.0 - XA + 2*XB) ) + 2 * XA * XB * sumMm2 * (1.0 - XA + XB)); } else if (iB == k) { dlnActCoeffdlnX_diag_[k] += XB * (- (1-XB+XA) * sum - 2*(1.0 - XB) * XA * sumMm1 + sumMm1 * (XA * (XB - XA - (1.0 - XB)) -XB * (-2.0*XA + XB - 1) ) - 2 * XA * XB * sumMm2 * (-XA - (1.0 - XB))); } } } }
doublereal WaterSSTP::vaporFraction() const { if (temperature() >= m_sub.Tcrit()) { double dens = density(); if (dens >= m_sub.Rhocrit()) { return 0.0; } return 1.0; } /* * If below tcrit we always return 0 from this class */ return 0.0; }
void SingleSpeciesTP::setState_HP(doublereal h, doublereal p, doublereal tol) { doublereal dt; setPressure(p); for (int n = 0; n < 50; n++) { dt = clip((h - enthalpy_mass())/cp_mass(), -100.0, 100.0); setState_TP(temperature() + dt, p); if (fabs(dt) < tol) { return; } } throw CanteraError("setState_HP","no convergence. dt = " + fp2str(dt)); }
void Reactor::updateState(doublereal* y) { ThermoPhase& mix = *m_thermo; // define for readability // The components of y are the total internal energy, // the total volume, and the mass of each species. // Set the mass fractions and density of the mixture. doublereal u = y[0]; m_vol = y[1]; doublereal* mss = y + 2; doublereal mass = accumulate(y+2, y+2+m_nsp, 0.0); m_thermo->setMassFractions(mss); m_thermo->setDensity(mass/m_vol); doublereal temp = temperature(); mix.setTemperature(temp); if (m_energy) { // Decreased the tolerance on delta_T to 1.0E-7 so that T is // accurate to 9 sig digits, because this is // used in the numerical jacobian routines where relative values // of 1.0E-7 are used in the deltas. m_thermo->setState_UV(u/mass,m_vol/mass, 1.0e-7); temp = mix.temperature(); //mix.setTemperature(temp); } //m_state[0] = temp; size_t loc = m_nsp + 2; SurfPhase* surf; for (size_t m = 0; m < m_nwalls; m++) { surf = m_wall[m]->surface(m_lr[m]); if (surf) { // surf->setTemperature(temp); //surf->setCoverages(y+loc); m_wall[m]->setCoverages(m_lr[m], y+loc); loc += surf->nSpecies(); } } // save parameters needed by other connected reactors m_enthalpy = m_thermo->enthalpy_mass(); m_pressure = m_thermo->pressure(); m_intEnergy = m_thermo->intEnergy_mass(); m_thermo->saveState(m_state); }
void LatticeSolidPhase::_updateThermo() const { doublereal tnow = temperature(); if (m_tlast != tnow) { getMoleFractions(DATA_PTR(m_x)); size_t strt = 0; for (size_t n = 0; n < m_nlattice; n++) { m_lattice[n]->setTemperature(tnow); m_lattice[n]->setMoleFractions(DATA_PTR(m_x) + strt); m_lattice[n]->setPressure(m_press); strt += m_lattice[n]->nSpecies(); } m_tlast = tnow; } }
Real IdealGasFluidProperties::g(Real v, Real e) const { // g(p,T) for SGEOS is given by Equation (37) in the following reference: // // Ray A. Berry, Richard Saurel, Olivier LeMetayer // The discrete equation method (DEM) for fully compressible, two-phase flows in // ducts of spatially varying cross-section // Nuclear Engineering and Design 240 (2010) p. 3797-3818 // const Real p = pressure(v, e); const Real T = temperature(v, e); return _gamma * _cv * T - _cv * T * std::log(std::pow(T, _gamma) / std::pow(p, _gamma - 1.0)); }
void WaterSSTP::setPressure(doublereal p) { double T = temperature(); double dens = density(); int waterState = WATER_GAS; double rc = m_sub.Rhocrit(); if (dens > rc) { waterState = WATER_LIQUID; } doublereal dd = m_sub.density(T, p, waterState, dens); if (dd <= 0.0) { throw CanteraError("setPressure", "error"); } setDensity(dd); }
void MaskellSolidSolnPhase::_updateThermo() const { assert(m_kk == 2); static const int cacheId = m_cache.getId(); CachedScalar cached = m_cache.getScalar(cacheId); // Update the thermodynamic functions of the reference state. doublereal tnow = temperature(); if (!cached.validate(tnow)) { m_spthermo->update(tnow, m_cp0_R.data(), m_h0_RT.data(), m_s0_R.data()); for (size_t k = 0; k < m_kk; k++) { m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; } } }
void RedlichKisterVPSSTP::s_update_lnActCoeff() const { doublereal T = temperature(); lnActCoeff_Scaled_.assign(m_kk, 0.0); /* * Scaling: I moved the division of RT higher so that we are always dealing with G/RT dimensionless terms * within the routine. There is a severe problem with roundoff error in these calculations. The * dimensionless terms help. */ for (size_t i = 0; i < numBinaryInteractions_; i++) { size_t iA = m_pSpecies_A_ij[i]; size_t iB = m_pSpecies_B_ij[i]; double XA = moleFractions_[iA]; double XB = moleFractions_[iB]; doublereal deltaX = XA - XB; size_t N = m_N_ij[i]; vector_fp& he_vec = m_HE_m_ij[i]; vector_fp& se_vec = m_SE_m_ij[i]; doublereal poly = 1.0; doublereal polyMm1 = 1.0; doublereal sum = 0.0; doublereal sumMm1 = 0.0; doublereal sum2 = 0.0; for (size_t m = 0; m < N; m++) { doublereal A_ge = (he_vec[m] - T * se_vec[m]) / (GasConstant * T); sum += A_ge * poly; sum2 += A_ge * (m + 1) * poly; poly *= deltaX; if (m >= 1) { sumMm1 += (A_ge * polyMm1 * m); polyMm1 *= deltaX; } } doublereal oneMXA = 1.0 - XA; doublereal oneMXB = 1.0 - XB; for (size_t k = 0; k < m_kk; k++) { if (iA == k) { lnActCoeff_Scaled_[k] += (oneMXA * XB * sum) + (XA * XB * sumMm1 * (oneMXA + XB)); } else if (iB == k) { lnActCoeff_Scaled_[k] += (oneMXB * XA * sum) + (XA * XB * sumMm1 * (-oneMXB - XA)); } else { lnActCoeff_Scaled_[k] += -(XA * XB * sum2); } } // Debug against formula in literature } }
void DiffusionCoefficient<EvalT, Traits>:: evaluateFields(typename Traits::EvalData workset) { // Diffusion Coefficient for (std::size_t cell=0; cell < workset.numCells; ++cell) { for (std::size_t qp=0; qp < numQPs; ++qp) { diffusionCoefficient(cell,qp) = Dpre(cell,qp)* std::exp(-1.0*Qdiff(cell,qp)/ Rideal/temperature(cell,qp)); } } }
doublereal WaterSSTP::dthermalExpansionCoeffdT() const { doublereal pres = pressure(); doublereal dens_save = density(); double T = temperature(); double tt = T - 0.04; doublereal dd = m_sub.density(tt, pres, WATER_LIQUID, dens_save); if (dd < 0.0) { throw CanteraError("WaterSSTP::dthermalExpansionCoeffdT", "Unable to solve for the density at T = {}, P = {}", tt, pres); } doublereal vald = m_sub.coeffThermExp(); m_sub.setState_TR(T, dens_save); doublereal val2 = m_sub.coeffThermExp(); return (val2 - vald) / 0.04; }
void LatticePhase::_updateThermo() const { doublereal tnow = temperature(); if (fabs(molarDensity() - m_molar_density)/m_molar_density > 0.0001) { throw CanteraError("_updateThermo","molar density changed from " +fp2str(m_molar_density)+" to "+fp2str(molarDensity())); } if (m_tlast != tnow) { m_spthermo->update(tnow, &m_cp0_R[0], &m_h0_RT[0], &m_s0_R[0]); m_tlast = tnow; for (size_t k = 0; k < m_kk; k++) { m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; } m_tlast = tnow; } }
Func for_each_dim(Func func) { func(angle()); func(solid_angle()); func(length()); func(mass()); func(time()); func(temperature()); func(electric_current()); func(number_of_cycles()); func(number_of_decays()); func(luminous_intensity()); func(amount_of_substance()); func(amount_of_information()); return std::move(func); }
void SurfPhase::_updateThermo(bool force) const { doublereal tnow = temperature(); if (m_tlast != tnow || force) { m_spthermo->update(tnow, DATA_PTR(m_cp0), DATA_PTR(m_h0), DATA_PTR(m_s0)); m_tlast = tnow; doublereal rt = GasConstant * tnow; for (size_t k = 0; k < m_kk; k++) { m_h0[k] *= rt; m_s0[k] *= GasConstant; m_cp0[k] *= GasConstant; m_mu0[k] = m_h0[k] - tnow*m_s0[k]; } m_tlast = tnow; } }
void MixedSolventElectrolyte::s_update_dlnActCoeff_dlnN() const { double T = temperature(); double RT = GasConstant*T; dlnActCoeffdlnN_.zero(); /* * Loop over the activity coefficient gamma_k */ for (size_t iK = 0; iK < m_kk; iK++) { for (size_t iM = 0; iM < m_kk; iM++) { double XM = moleFractions_[iM]; for (size_t i = 0; i < numBinaryInteractions_; i++) { size_t iA = m_pSpecies_A_ij[i]; size_t iB = m_pSpecies_B_ij[i]; double delAK = 0.0; double delBK = 0.0; double delAM = 0.0; double delBM = 0.0; if (iA==iK) { delAK = 1.0; } else if (iB==iK) { delBK = 1.0; } if (iA==iM) { delAM = 1.0; } else if (iB==iM) { delBM = 1.0; } double XA = moleFractions_[iA]; double XB = moleFractions_[iB]; double g0 = (m_HE_b_ij[i] - T * m_SE_b_ij[i]) / RT; double g1 = (m_HE_c_ij[i] - T * m_SE_c_ij[i]) / RT; dlnActCoeffdlnN_(iK,iM) += g0*((delAM-XA)*(delBK-XB)+(delAK-XA)*(delBM-XB)); dlnActCoeffdlnN_(iK,iM) += 2*g1*((delAM-XA)*(delBK-XB)*XB+(delAK-XA)*(delBM-XB)*XB+(delBM-XB)*(delBK-XB)*XA); } dlnActCoeffdlnN_(iK,iM) = XM*dlnActCoeffdlnN_(iK,iM); } } }
void WaterSSTP::getStandardVolumes_ref(doublereal* vol) const { doublereal p = pressure(); double T = temperature(); double dens = density(); int waterState = WATER_GAS; double rc = m_sub.Rhocrit(); if (dens > rc) { waterState = WATER_LIQUID; } doublereal dd = m_sub.density(T, OneAtm, waterState, dens); if (dd <= 0.0) { throw CanteraError("setPressure", "error"); } *vol = meanMolecularWeight() /dd; dd = m_sub.density(T, p, waterState, dens); }
void SingleSpeciesTP::setState_UV(doublereal u, doublereal v, doublereal tol) { doublereal dt; setDensity(1.0/v); for (int n = 0; n < 50; n++) { dt = (u - intEnergy_mass())/cv_mass(); if (dt > 100.0) dt = 100.0; else if (dt < -100.0) dt = -100.0; setTemperature(temperature() + dt); if (fabs(dt) < tol) { return; } } throw CanteraError("setState_UV", "no convergence. dt = " + fp2str(dt)+"\n" +"u = "+fp2str(u)+" v = "+fp2str(v)+"\n"); }
void WaterSSTP::getEnthalpy_RT_ref(doublereal* hrt) const { doublereal p = pressure(); double T = temperature(); double dens = density(); int waterState = WATER_GAS; double rc = m_sub.Rhocrit(); if (dens > rc) { waterState = WATER_LIQUID; } doublereal dd = m_sub.density(T, OneAtm, waterState, dens); if (dd <= 0.0) { throw CanteraError("setPressure", "error"); } doublereal h = m_sub.enthalpy(); *hrt = (h + EW_Offset) / (GasConstant * T); dd = m_sub.density(T, p, waterState, dens); }
wxString grib_pi::GetLongDescription() { return _("GRIB PlugIn for OpenCPN\n\ Provides basic GRIB file overlay capabilities for several GRIB file types\n\ and a request function to get GRIB files by eMail.\n\n\ Supported GRIB data include:\n\ - wind direction and speed (at 10 m)\n\ - wind gust\n\ - surface pressure\n\ - rainfall\n\ - cloud cover\n\ - significant wave height and direction\n\ - air surface temperature (at 2 m)\n\ - sea surface temperature\n\ - surface current direction and speed\n\ - Convective Available Potential Energy (CAPE)\n\ - wind, altitude, temperature and relative humidity at 300, 500, 700, 850 hPa." ); }