UNPKG

simclimat-lib

Version:

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0.

832 lines (816 loc) 92.6 kB
function add(num1, num2) { return num1 + num2; } class CLogger { static log(message, logLevel = 'info') { if (!this.debug) { return; } switch (logLevel) { case 'debug': { console.info(message); break; } case 'info': { console.log(message); break; } case 'warning': { console.log('WARNING : ' + message); break; } case 'error': { console.error('ERROR : ' + message); break; } default: { console.log(message); break; } } } // eo log method static setDebug(debug) { this.debug = debug; } } CLogger.debug = false; /** * This class define physics constants and calculated physics constants. * * Instanciation example : * * ```typescript * const instance = new CPhysicsConstants(); * ``` * * @remarks * This method is part of the {@link core-library#Statistics | Statistics subsystem}. * * @author Alain Deseine * * @copyright CEI Alain Deseine 1992-2019 * * @beta */ class CPhysicsConstants { // si 1: calcul Euler explicite // si 2: calcul par decroissance vers équilibre /** * Constructor. * * The constructor of this class calculate calculated physics constants. * * @remarks * This method is part of the {@link core-library#Statistics | Statistics subsystem}. * * @beta */ constructor() { // Set calculated physics constants CLogger.log('physics-constants: appel constructor'); this.t_res_coo_actuel = 280 / 0.083 / (CPhysicsConstants.concentration_coo_2007 / CPhysicsConstants.coo_Gt_2007); // Modification mars 2022 this.t_res_coo_90 = this.t_res_coo_actuel * 0.9; this.t_res_coo_critique = this.t_res_coo_90 + (90 - CPhysicsConstants.niveau_calotte_critique_coo) * -(this.t_res_coo_90 - this.t_res_coo_actuel) / (90 - CPhysicsConstants.niveau_calottes_1750); this.deltaT_last_century = CPhysicsConstants.temperature_actuelle - CPhysicsConstants.temperature_1750; //this.temperature_1900 = CPhysicsConstants.temperature_actuelle - CPhysicsConstants.deltaT_last_century; // en °C ; necessaire dans modele_reset this.G0 = CPhysicsConstants.puissance_recue_zero * (1 - CPhysicsConstants.albedo_1750) / CPhysicsConstants.sigma / Math.exp(4 * Math.log(CPhysicsConstants.Tkelvin + CPhysicsConstants.temperature_1750)); //0.584; // commenté le 19 avril 2024 par Camille car inutile /* this.T_ressentie_actuelle = ( 1. / ( CPhysicsConstants.p0 + CPhysicsConstants.p1 + CPhysicsConstants.p2 + CPhysicsConstants.p3 ) ) * ( CPhysicsConstants.p0 * CPhysicsConstants.temperature_actuelle + CPhysicsConstants.p1 * CPhysicsConstants.temperature_actuelle - CPhysicsConstants.deltaT_last_century / 100 * CPhysicsConstants.deltat1 + CPhysicsConstants.p2 * CPhysicsConstants.temperature_actuelle - CPhysicsConstants.deltaT_last_century / 100 * CPhysicsConstants.deltat2 + CPhysicsConstants.p3 * CPhysicsConstants.temperature_actuelle - CPhysicsConstants.deltaT_last_century / 100 * CPhysicsConstants.deltat3 ); */ this.a_calottes = (CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.niveau_calottes_LGM_noinsol) / (CPhysicsConstants.temperature_1750 - CPhysicsConstants.temperature_LGM) * 0.8; // on suppose qu'une partie de la variation du niveau de calotte est lié à l'effet de la température (ici 40%), et l'autre est liée à l'effet de la variation d'insolation. this.b_calottes = CPhysicsConstants.niveau_calottes_1750 - this.a_calottes * CPhysicsConstants.temperature_1750; this.niveau_calottes_actuel = CPhysicsConstants.niveau_calottes_1750 + (this.a_calottes * CPhysicsConstants.temperature_actuelle + this.b_calottes - CPhysicsConstants.niveau_calottes_1750) * (1. - Math.exp(-100. / CPhysicsConstants.tau_niveau_calottes_deglacement)); CLogger.log('physics-constants: niveau_calottes_actuel= ' + this.niveau_calottes_actuel); //CLogger.log( 'niveau_calottes_1750,temperature_actuelle,niveau_calottes_1750=' + CPhysicsConstants.niveau_calottes_1750 + CPhysicsConstants.temperature_actuelle + CPhysicsConstants.niveau_calottes_1750); //CLogger.log ('a_calottes,b_calottes,tau_niveau_calottes_deglacement=' + this.a_calottes + this.b_calottes + CPhysicsConstants.tau_niveau_calottes_deglacement); // modif CR: 31 oct 2019: Tressentie_act doit correspondre au calcul dans calcul_niveau_mer // this.Tressentie_act = CPhysicsConstants.temperature_actuelle - 0.7; // orig -0.75 this.pond_memoire_mer = Math.exp(-CPhysicsConstants.tmemoire_niveau_mer / CPhysicsConstants.tau_niveau_mer); CLogger.log('physics-constants: pond_memoire_mer= ' + this.pond_memoire_mer); CLogger.log('pond_memoire_mer=' + this.pond_memoire_mer); CLogger.log('temperature_actuelle=' + CPhysicsConstants.temperature_actuelle); CLogger.log('deltaT_last_century=' + this.deltaT_last_century); this.Tressentie_act = CPhysicsConstants.temperature_actuelle - this.pond_memoire_mer * this.deltaT_last_century; // -0.64 this.dilatation_1750 = CPhysicsConstants.dilat * CPhysicsConstants.coef_dilat * (CPhysicsConstants.temperature_1750 - this.Tressentie_act); CLogger.log('dilatation_1750=' + this.dilatation_1750); CLogger.log('dilat=' + CPhysicsConstants.dilat); CLogger.log('coef_dilat=' + CPhysicsConstants.coef_dilat); CLogger.log('temperature_1750=' + CPhysicsConstants.temperature_1750); CLogger.log('Tressentie_act=' + this.Tressentie_act); // Commenté par Camille le 19 avril 2024 car c'est devenu inutile /* this.optim1 = ( 1 + this.dilatation_1750 ) * ( 1 - CPhysicsConstants.fphig2 * Math.pow( CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.niveau_calottes_max, 2 ) - CPhysicsConstants.fphig3 * Math.pow( CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.niveau_calottes_max, 3 ) ) - ( 1 - CPhysicsConstants.fphig2 * Math.pow( this.niveau_calottes_actuel - CPhysicsConstants.niveau_calottes_max, 2 ) - CPhysicsConstants.fphig3 * Math.pow( this.niveau_calottes_actuel - CPhysicsConstants.niveau_calottes_max, 3 ) ); this.optim2 = ( this.niveau_calottes_actuel - CPhysicsConstants.niveau_calottes_max ) - ( 1 + this.dilatation_1750 ) * ( CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.niveau_calottes_max ); this.fphig1 = (CPhysicsConstants.niveau_mer_1750_target / CPhysicsConstants.Hmer_tot - this.optim1 ) / this.optim2; */ // CR avril 2024: Hmer_tot est maintenant ajusté avec le LGM CPhysicsConstants.Hmer_tot = (CPhysicsConstants.niveau_mer_LGM + 10.0) / ((1. - Math.cos((CPhysicsConstants.niveau_calottes_max - this.niveau_calottes_actuel) * CPhysicsConstants.pi / 180)) * Math.pow((1. - this.niveau_calottes_actuel / CPhysicsConstants.niveau_calottes_max), CPhysicsConstants.expmer) - (1. - Math.cos((CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.niveau_calottes_LGM) * CPhysicsConstants.pi / 180)) * Math.pow((1. - CPhysicsConstants.niveau_calottes_LGM / CPhysicsConstants.niveau_calottes_max), CPhysicsConstants.expmer)); CLogger.log('physics-constants: Hmer_tot = ' + CPhysicsConstants.Hmer_tot); CLogger.log('physics-constants: niveau_calottes_actuel=' + this.niveau_calottes_actuel); // CR avril 2024: Hmeract calculé avec la nouvelle formule du niveau mer this.Hmeract = CPhysicsConstants.Hmer_tot * (1. - (1. - Math.cos((CPhysicsConstants.niveau_calottes_max - this.niveau_calottes_actuel) * CPhysicsConstants.pi / 180)) * Math.pow((1. - this.niveau_calottes_actuel / CPhysicsConstants.niveau_calottes_max), CPhysicsConstants.expmer)); CLogger.log('physics-constants: Hmeract = ' + this.Hmeract); /* this.Hmeract = CPhysicsConstants.Hmer_tot * ( 1 - this.fphig1 * ( this.niveau_calottes_actuel - CPhysicsConstants.niveau_calottes_max) - CPhysicsConstants.fphig2 * Math.pow( this.niveau_calottes_actuel - CPhysicsConstants.niveau_calottes_max, 2 ) - CPhysicsConstants.fphig3 * Math.pow( this.niveau_calottes_actuel - CPhysicsConstants.niveau_calottes_max, 3 ) ); */ // modif CR 4 nov 2019: calcul exact de niveau_mer_1750 // this.niveau_mer_1750 = CPhysicsConstants.Hmer_tot * ( 1 + CPhysicsConstants.dilat * 0.5 * ( CPhysicsConstants.temperature_1750 - this.Tressentie_act ) ) * ( 1 // - this.fphig1 * ( CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.niveau_calottes_max) // - CPhysicsConstants.fphig2 * Math.pow( CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.niveau_calottes_max, 2 ) // - CPhysicsConstants.fphig3 * Math.pow( CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.niveau_calottes_max, 3 ) ) - this.Hmeract; // modif CR avril 2024 car on modifie le calcul de niveau mer. this.Hmer_1750 = CPhysicsConstants.Hmer_tot * (1 + this.dilatation_1750) * (1. - (1. - Math.cos((CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.niveau_calottes_1750) * CPhysicsConstants.pi / 180)) * Math.pow((1. - CPhysicsConstants.niveau_calottes_1750 / CPhysicsConstants.niveau_calottes_max), CPhysicsConstants.expmer)); CLogger.log('physics-constants: Hmer_1750 = ' + this.Hmer_1750); CLogger.log('physics-constants: dilatation_1750= ' + this.dilatation_1750); CLogger.log('physics-constants: Hmer_tot= ' + CPhysicsConstants.Hmer_tot); CLogger.log('physics-constants: CPhysicsConstants.niveau_calottes_1750 = ' + CPhysicsConstants.niveau_calottes_1750); this.niveau_mer_1750 = this.Hmer_1750 - this.Hmeract; CLogger.log('physics-constants: niveau_mer_1750 = ' + this.niveau_mer_1750); this.C_alteration_naturel = -CPhysicsConstants.volcanisme_actuel / CPhysicsConstants.concentration_coo_1750; this.deltaT_poce = 0.5 / CPhysicsConstants.A_oce; this.a_H2O = -CPhysicsConstants.q_H2O * (1 - this.G0); this.Tlim_bio_froid = CPhysicsConstants.temperature_froid; this.delta_angle_actuel = (CPhysicsConstants.lat_Mil - CPhysicsConstants.obliquite_actuel) / 360 * 2 * CPhysicsConstants.pi; this.insol_actuel = CPhysicsConstants.puissance_recue_zero * Math.cos(this.delta_angle_actuel); this.albedo_crit = (CPhysicsConstants.albedo_1750 - CPhysicsConstants.albedo_ter * (CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.phig_crit) / (CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.phig_crit)) / (1 - (CPhysicsConstants.niveau_calottes_1750 - CPhysicsConstants.phig_crit) / (CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.phig_crit)); // 0.41 this.albedo_actuel = this.albedo_crit + (this.niveau_calottes_actuel - CPhysicsConstants.phig_crit) / (CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.phig_crit) * (CPhysicsConstants.albedo_ter - this.albedo_crit); this.stockage_max = CPhysicsConstants.flux_co2_stockage_max / CPhysicsConstants.concentration_coo_1750; this.concentration_coo_carbonifere = CPhysicsConstants.concentration_coo_1750 * 2; // modif 7 avril 2009 this.stockage_carbonifere = CPhysicsConstants.flux_co2_stockage_carbonifere / this.concentration_coo_carbonifere; } /** * logModelConstants method. * * this method simply log to the console class properties and methods. * * @remarks * This method is part of the {@link core-library#Statistics | Statistics subsystem}. * * @beta */ logModelConstants() { console.log(this); } /** * toJSON method. * * this method return the public and protected object properties. * * @remarks * This method is part of the {@link core-library#Statistics | Statistics subsystem}. * * @beta */ toJSON() { let properties = Object.getOwnPropertyNames(this); return properties; } } // Constantes mathématiques /** Pi math constant */ CPhysicsConstants.pi = Math.PI; // constantes radiatives CPhysicsConstants.puissance_recue_zero = 1370 / 4.; CPhysicsConstants.distance_ts_actuelle = 1.5e11; CPhysicsConstants.sigma = 5.67e-8; // constantes du calcul de l'albédo CPhysicsConstants.albedo_froid = 0.65; CPhysicsConstants.albedo_chaud = 0.325; CPhysicsConstants.temperature_froid = 262; CPhysicsConstants.temperature_chaud = 286; // constantes des GES (Gaz à effet de serre) // conversions de Gt à ppm: /** 5.13e6 en Gt */ CPhysicsConstants.masse_atmosphere_Gt = 1.4e6; /** Exprimée eng/mol */ CPhysicsConstants.masse_molaire_coo = 44; CPhysicsConstants.masse_molaire_chhhh = 16; CPhysicsConstants.masse_molaire_air = 29; // concentrations actuelles et naturelles CPhysicsConstants.concentration_coo_actuel = 405; // ppm CPhysicsConstants.concentration_coo_2007 = 370; // ppm: ajout mars 2022 CPhysicsConstants.concentration_coo_1750 = 280; CPhysicsConstants.concentration_coo_naturel = 280; CPhysicsConstants.concentration_coo_min = 1e-1; // pour ne pas avoir de nan en prenant le log CPhysicsConstants.coo_Gt_act = 750; // masse de CO2 en Gt CPhysicsConstants.coo_Gt_2007 = 750; // masse de CO2 en Gt: ajout mars 2022 CPhysicsConstants.coo_Gt_1750 = 280 * 750 / 370; // masse de CO2 en Gt CPhysicsConstants.concentration_coo_glaciaire = 180; // ppm // constantes radiatives CPhysicsConstants.a_coo = 22e-3; // 5.35; On peut changer cette valeur sans changer l'equilibre pre-industriel. CPhysicsConstants.concentration_coo_limite = 10000; // en ppm, la limite entre relation linéaire et log pour forcage serre // pour extrapolations lin pour hautes concentrations CPhysicsConstants.concentration_coo_limite_bas = 100; // en ppm,idem pour extrapolation pour basses concnetrations CPhysicsConstants.G_min = 1e-4; // forcage_serre min, pour eviter des nan CPhysicsConstants.t_res_coo_0 = 1.5e6; CPhysicsConstants.niveau_calotte_critique_coo = 20; CPhysicsConstants.niveau_calottes_1750 = 60; // const double facteur_alteration_0=1e-3; // const double facteur_alteration_90=1; // températures CPhysicsConstants.tau_temperature = 30; // en années CPhysicsConstants.temperature_actuelle = 15.5; // en °C ; necessaire dans modele_reset // calculée à la main pour C02=370 et albédo=albédo_actuel // public readonly temperature_1900: number; CPhysicsConstants.temperature_1750 = 14.4; CPhysicsConstants.temperature_LGM = 10; CPhysicsConstants.C_terre = 5e9; // capacité calorifique de la Terre en J/K/m2 CPhysicsConstants.Tkelvin = 273.0; // données radiatives sur l'actuel CPhysicsConstants.albedo_1750 = 0.33; // données et constantes de bidouille sur le niveau de la mer /** Facteur de pondération de la température il y a [[deltat0]] ans */ // constantes commentées par Camille le 19 avril 2024 car sont inutiles // public static readonly p0: number = 1.; // public static readonly p1: number = 5.; // public static readonly p2: number = 3.; // public static readonly p3: number = 1.; /** Retard en temps en année */ CPhysicsConstants.deltat0 = 0.; CPhysicsConstants.deltat1 = 5.; CPhysicsConstants.deltat2 = 20.; CPhysicsConstants.deltat3 = 50.; CPhysicsConstants.C_niveau = 100.; // orig=96 CPhysicsConstants.a_mer = 140; CPhysicsConstants.tmemoire_niveau_mer = 100.; // le 30 janvier 2011: en fait, tau_niveau_mer ne peut dépasser 100 ans car c'est la mémoire maximale d'une simul pour la simul précédente. # c est le pas de temps utilise pour calculer l effet memoire. CPhysicsConstants.tau_niveau_mer = 1000.; // c est l echelle de temps caracteristique de l evolution de la temperature de l ocean // public readonly T_ressentie_actuelle: number; // commenté le 19 avril 2024 par Camille car c'est inutile // niveau mer exprimé en m /t actuel CPhysicsConstants.niveau_mer_LGM = -130; // niveau des calottes CPhysicsConstants.niveau_calottes_LGM = 45; CPhysicsConstants.niveau_calottes_LGM_noinsol = 52; CPhysicsConstants.tau_niveau_calottes_englacement = 5000.; CPhysicsConstants.tau_niveau_calottes_deglacement = 5000.; CPhysicsConstants.niveau_calottes_min = 0; CPhysicsConstants.niveau_calottes_max = 90; CPhysicsConstants.dilat = 2.4e-4; // en °C CPhysicsConstants.coef_dilat = 2.0; // c'est un param ajustable pour ajuster la dilatation. Avant on n'en avait pas besoin parce que Hmer_tot réaliste, mais là, on l'ajuste su le changement de niveau mer du LGM // public readonly optim1: number; // public readonly optim2: number; CPhysicsConstants.expmer = 1.5; // constante ajoutée le 19 avril 2024 par Camille. C'est un exposant qui sert de maramètre ajustable pour que niveau_mer_1750 soit à peu près égale à -0.2 m. // public static readonly niveau_mer_1750_target: number = -0.2; // commenté le 19 avril 2024 par Camille // flux de carbone // const double CO2_biologique_eq=concentration_coo_naturel; // calcul CO2_ocean_eq en fonction temp�rature CPhysicsConstants.a_CO2_eq = 20; // ppm/°C CPhysicsConstants.emit_anthro_coo_act = 12; // Gt: mise à jour mars 2022 CPhysicsConstants.volcanisme_actuel = 0.083; // en Gt/an CPhysicsConstants.puit_ocean_act = 20.0; // en pourcent des emissions anthro absorbées CPhysicsConstants.Tlim_oce = 10; // en °K // const double rel_CO2_temperature=emit_anthro_coo_act/Tlim_oce; CPhysicsConstants.b_ocean = 1 / 5000.0; CPhysicsConstants.Tlim_oce_froid = 275; CPhysicsConstants.A_oce = 3e-2; CPhysicsConstants.Tcrit_oce = 35; CPhysicsConstants.puit_oce_max = 40; // en pourcent CPhysicsConstants.dFdegaz = 0.05; CPhysicsConstants.q_CO2 = 0.26; // CO2=26% de l'effet de serre // retroactions vapeur d'eau CPhysicsConstants.q_H2O = 0.6; // eau=60% de l'effet de serre // public static readonly tau_T: number = 200; // en °K CPhysicsConstants.rapport_H2O_actconst = 1.05719; // rapport pour la température actuelle CPhysicsConstants.a_rankine = 13.7; CPhysicsConstants.b_rankine = 5120.; CPhysicsConstants.pow_H2O = 0.23; // normallement: 0.18 // paramétrisation de A_biologique en fonction de la température CPhysicsConstants.puit_bio_act = 30; // en pourcent CPhysicsConstants.Tlim_bio_chaud = 340; // en K //const double A_biologique_act=-puit_bio_act*emit_anthro_coo_act/(concentration_coo_actuel-concentration_coo_1750); // en an-1 // parametres orbitaux CPhysicsConstants.lat_Mil = 65; CPhysicsConstants.c_calottes = 0.2; //const double precession_actuel=-90; CPhysicsConstants.precession_actuel = 102.7; // modif 31 janv 2009: on prend la même precession que LMDZ // la formule de insol65N n'a pas été modifiée car 2 bugs se compensaient CPhysicsConstants.obliquite_actuel = 23.5; CPhysicsConstants.excentricite_actuel = 0.0167; // albédo CPhysicsConstants.albedo_phi_min = 0.60; CPhysicsConstants.albedo_phi_max = 0.2; CPhysicsConstants.albedo_glace_const = 0.90; CPhysicsConstants.phig_crit = 30.0; // 30 CPhysicsConstants.albedo_ter = 0.25; // calcule de la température CPhysicsConstants.capacite_calorifique = 0.1; // stockage biologique CPhysicsConstants.flux_co2_stockage_max = -10; // GT/an-1 CPhysicsConstants.flux_co2_stockage_carbonifere = -0.396; // en Gt par an d'apres R.A. Berner et D.E. Canfield (1989) // logicals CPhysicsConstants.echantillonage = 1; // if 1: échantillonage direct au pas de temps // if 2: échantillonage en moyennant sur les pas de temps autour du point d'échantillonage CPhysicsConstants.calcul_carbone = 1; const modelVarsConstants = { enable_gl_animations: 0, echeance_min: 100, echeance_max: 10e6, echeance_reset_value: 500, time_slider_reset_value: 0, /** affichage des results */ graphe_one_init: 0 /* graphTypes.TEMPERATURE */, graphe_two_init: 3 /* graphTypes.CONCENTRATION_CO2 */, graphe_three_init: 1 /* graphTypes.WATERLEVEL */, graphe_four_init: 2 /* graphTypes.CALOTTESLEVEL */, /** simulation_type */ fixed_concentration_reset_value: 1, /** concentrations en CO2 en ppm */ coo_concentr_terre_initiale: 0.3e6, coo_concentr_cretace: 1500, coo_concentr_1750: CPhysicsConstants.concentration_coo_1750, coo_concentr_today: CPhysicsConstants.concentration_coo_actuel, coo_concentr_min: 0, coo_concentr_max: 1e6, coo_concentr_reset_value: 0, /** emissions de CO2, en Gt/an. */ /** emissions antropiques */ emit_anthro_coo_actuel: CPhysicsConstants.emit_anthro_coo_act, emit_anthro_coo_2xactuel: CPhysicsConstants.emit_anthro_coo_act * 2, emit_anthro_coo_nul: 0., emit_anthro_coo_min: -2, emit_anthro_coo_max: 50, emit_anthro_coo_reset_value: 0, /** volcanisme */ volcan_actuel: CPhysicsConstants.volcanisme_actuel, volcan_terre_init: 0, /** d'après les flux de chaleurs en fonction du temps depuis formation de la terre données sur www.geo.mtu.edu/svl/GE3320/LECTURE%206.ppt */ /** volcan_terre_600ma=volcan_actuel*2; // d'après la même source */ volcan_min: 0, volcan_max: 0, volcan_reset_value: 0, /** alteration, en % de variation par rapport à la ref=C_alteration_naturel */ alteration_actuel: 100., alteration_min: 0.0, alteration_max: 1000.0, alteration_reset_value: 0, /** stockage biologique */ stockage_biologique_actuel: 0., stockage_biologique_carbonifere: 0, stockage_biologique_min: 0., stockage_biologique_max: 0, stockage_biologique_reset_value: 0., /** albédo */ fixed_albedo_reset_value: 0, albedo_act: 0, albedo_reset_value: 0, albedo_glace: CPhysicsConstants.albedo_glace_const * 100, albedo_terre: CPhysicsConstants.albedo_ter * 100, albedo_min: 0., albedo_max: 100., /** puit biologique */ debranche_biologie_reset_value: 0, puit_bio_actuel: CPhysicsConstants.puit_bio_act, puit_bio_min: -50, puit_bio_max: 100., puit_bio_reset_value: 0, /** puit océanique */ fixed_ocean_reset_value: 1, debranche_ocean_reset_value: 0, puit_ocean_actuel: CPhysicsConstants.puit_ocean_act, puit_ocean_min: -50, puit_ocean_max: 100., puit_ocean_reset_value: 0, /** vapeur d'eau */ fixed_eau_reset_value: 0, rapport_H2O_reset_value: 100., rapport_H2O_actuel: 100. * CPhysicsConstants.rapport_H2O_actconst, rapport_H2O_min: 0., rapport_H2O_max: 1000., /** parametres orbitaux */ /** en fraction d'augmentation par rapport à l'actuel, en % */ puissance_soleil_terre_init: 70, puissance_soleil_actuel: 100, puissance_soleil_min: 0, puissance_soleil_max: 1000, puissance_soleil_reset_value: 0, distance_ts_actuel: 100, distance_ts_min: 0, distance_ts_max: 1000, distance_ts_reset_value: 0, /** paramètres orbitaux */ excentricite_act: CPhysicsConstants.excentricite_actuel, excentricite_reset_value: 0, excentricite_valeur_min: 0., excentricite_valeur_max: 0.06, excentricite_autre_min: 0., excentricite_autre_max: 0.2, obliquite_act: CPhysicsConstants.obliquite_actuel, obliquite_reset_value: 0, obliquite_valeur_min: 21.8, obliquite_valeur_max: 24.4, obliquite_autre_min: 0., obliquite_autre_max: 90., precession_act: CPhysicsConstants.precession_actuel, precession_reset_value: 0, /** 31 janv 2009: on met les min et max à -90 et 90 respectivement, au lieu de -180 et 180, car c'est avec -90 et 90 qu'on a les écarts de température les plus fort. */ precession_valeur_min: 90, precession_valeur_max: 270, precession_autre_min: 0, precession_autre_max: 360 }; class CModelVars { constructor(modelConstants) { /** Merge default constants values with constructor passed values into private modelConstants property. */ if (modelConstants == undefined) { this.modelConstants = Object.assign({}, modelVarsConstants); } else { this.modelConstants = Object.assign(Object.assign({}, modelVarsConstants), modelConstants); } /** Instantiate a CPhysicsConstants object */ let physicConstants = new CPhysicsConstants(); // Set reset vars + some others this.modelConstants.precession_reset_value = this.modelConstants.precession_act; this.modelConstants.obliquite_reset_value = this.modelConstants.obliquite_act; this.modelConstants.excentricite_reset_value = this.modelConstants.excentricite_act; this.modelConstants.distance_ts_reset_value = this.modelConstants.distance_ts_actuel; this.modelConstants.puissance_soleil_reset_value = this.modelConstants.puissance_soleil_actuel; this.modelConstants.puit_ocean_reset_value = this.modelConstants.puit_ocean_actuel; this.modelConstants.puit_bio_reset_value = this.modelConstants.puit_bio_actuel; this.modelConstants.albedo_reset_value = physicConstants.albedo_actuel * 100; this.modelConstants.albedo_act = physicConstants.albedo_actuel * 100; this.modelConstants.stockage_biologique_max = -physicConstants.stockage_max * 1e3; this.modelConstants.stockage_biologique_carbonifere = -physicConstants.stockage_carbonifere * 1e3; this.modelConstants.alteration_reset_value = this.modelConstants.alteration_actuel; this.modelConstants.volcan_reset_value = this.modelConstants.volcan_actuel; this.modelConstants.volcan_terre_init = this.modelConstants.volcan_actuel * 5; this.modelConstants.volcan_max = this.modelConstants.volcan_terre_init * 6; this.modelConstants.emit_anthro_coo_reset_value = this.modelConstants.emit_anthro_coo_nul; this.modelConstants.coo_concentr_reset_value = this.modelConstants.coo_concentr_1750; } logModelConstants() { console.log(this.modelConstants); } } /** * This class calculate climat simulation model. * * Instanciation example : * * ```typescript * const instance = new CModel(); * ``` * * @remarks * This method is part of the {@link core-library#Statistics | Statistics subsystem}. * * @author Alain Deseine * * @copyright CEI Alain Deseine 1992-2019 * * @beta */ class CModel { /** * Constructor. * * The constructor of this class initialise Physics constants and model vars. * * @remarks * This method is part of the {@link core-library#Statistics | Statistics subsystem}. * * @beta */ constructor(modelConstants) { // Instanciate a CModelVars object let modelVars; if (modelConstants == undefined) { modelVars = new CModelVars(); } else { modelVars = new CModelVars(modelConstants); } // Merge default constants values with constructor passed values into private modelConstants property. this.modelConstants = Object.assign({}, modelVars.modelConstants); // Instanciate a CPhysicsConstants object this.modelPhysicsConstants = new CPhysicsConstants(); } // eo constructor logModelConstants() { console.log(this.modelPhysicsConstants); console.log(this.modelConstants); } // eo logModelConstants method /** * Utils methods */ calculT(Teq, Tprec, tau, dt) { let T; T = Tprec + (Teq - Tprec) * (1 - Math.exp(-dt / tau)); return T; } // eo calculT method calcul_forcage_serre_H2O(zrapport_H2O) { let forcage_serre_H2O; CLogger.log('Method calcul_forcage_serre_H2O: zrapport_H2O = ' + zrapport_H2O); if (zrapport_H2O > 1e-5) { // forcage_serre_H2O=a_H2O*(1-exp(pow_H2O*log(zrapport_H2O))); // modif le 7 avril pour éviter rétroactions trop positives // on sature le forcage serre aux hautes concentrations en eau // forcage_serre_H2O = this.modelPhysicsConstants.a_H2O * ( 1 - Math.exp( CPhysicsConstants.pow_H2O * Math.log( zrapport_H2O ) ) ); forcage_serre_H2O = this.modelPhysicsConstants.a_H2O * (1 - Math.exp(CPhysicsConstants.pow_H2O * Math.log(zrapport_H2O))) * (0.3 * Math.exp(-Math.sqrt(Math.abs(zrapport_H2O - 1)) / 10.0) + 0.7); } else { forcage_serre_H2O = this.modelPhysicsConstants.a_H2O; } CLogger.log('Method calcul_forcage_serre_H2O: forcage_serre_H2O = ' + forcage_serre_H2O); return forcage_serre_H2O; } // eo calcul_forcage_serre_H2O method calcul_forcage_serre_CO2(zCO2) { let forcage_serre_CO2; if (zCO2 < CPhysicsConstants.concentration_coo_limite_bas) { CLogger.log('Method calcul_forcage_serre_CO2: relation linéaire, extrapolation basse'); // forcage_serre_CO2 = - 0.2 * this.modelPhysicsConstants.G0 + zCO2 / CPhysicsConstants.concentration_coo_limite_bas * ( 0.2 * this.modelPhysicsConstants.G0 + CPhysicsConstants.a_coo * Math.log( CPhysicsConstants.concentration_coo_limite_bas / CPhysicsConstants.concentration_coo_1750 ) ); forcage_serre_CO2 = -CPhysicsConstants.q_CO2 * this.modelPhysicsConstants.G0 + zCO2 / CPhysicsConstants.concentration_coo_limite_bas * (CPhysicsConstants.q_CO2 * this.modelPhysicsConstants.G0 + CPhysicsConstants.a_coo * Math.log(CPhysicsConstants.concentration_coo_limite_bas / CPhysicsConstants.concentration_coo_1750)); } else if (zCO2 > CPhysicsConstants.concentration_coo_limite) { CLogger.log('Method calcul_forcage_serre_CO2: relation linéaire, extrapolation haute'); // forcage_serre_CO2 = CPhysicsConstants.a_coo * ( Math.log( CPhysicsConstants.concentration_coo_limite / CPhysicsConstants.concentration_coo_1750 ) + zCO2 / CPhysicsConstants.concentration_coo_limite - 1 ); forcage_serre_CO2 = CPhysicsConstants.a_coo * (Math.log(CPhysicsConstants.concentration_coo_limite / CPhysicsConstants.concentration_coo_1750) + 1.0 * (zCO2 / CPhysicsConstants.concentration_coo_limite - 1)); } else { // relation log CLogger.log('Method calcul_forcage_serre_CO2: relation log'); forcage_serre_CO2 = CPhysicsConstants.a_coo * Math.log(zCO2 / CPhysicsConstants.concentration_coo_1750); } CLogger.log('Method calcul_forcage_serre_CO2: forcage_serre_CO2 = ' + forcage_serre_CO2); return forcage_serre_CO2; } // eo calcul_forcage_serre_CO2 method calcul_phieq(zT, insol65N) { let zphieq; // T en degre K CLogger.log('Method calcul_phieq: calcul_phig = ' + zT); CLogger.log('Method calcul_phieq: calcul_phig: a_calottes = ' + this.modelPhysicsConstants.a_calottes); CLogger.log('Method calcul_phieq: calcul_phig: b_calottes = ' + this.modelPhysicsConstants.b_calottes); // zphieq = this.modelPhysicsConstants.a_calottes * ( zT - 273.0 ) + this.modelPhysicsConstants.b_calottes + CPhysicsConstants.c_calottes * ( insol65N - this.modelPhysicsConstants.insol_actuel ); zphieq = this.modelPhysicsConstants.a_calottes * (zT - CPhysicsConstants.Tkelvin) + this.modelPhysicsConstants.b_calottes + CPhysicsConstants.c_calottes * (insol65N - this.modelPhysicsConstants.insol_actuel); if (zphieq > CPhysicsConstants.niveau_calottes_max) { zphieq = CPhysicsConstants.niveau_calottes_max; } if (zphieq < CPhysicsConstants.niveau_calottes_min) { zphieq = CPhysicsConstants.niveau_calottes_min; } CLogger.log('Method calcul_phieq: calcul_phig: a_calottes * ( zT - CPhysicsConstants.Tkelvin ) = ' + this.modelPhysicsConstants.a_calottes * (zT - CPhysicsConstants.Tkelvin)); CLogger.log('Method calcul_phieq: calcul_phig: c_calottes * ( insol65N - insol_actuel ) = ' + CPhysicsConstants.c_calottes * (insol65N - this.modelPhysicsConstants.insol_actuel)); CLogger.log('Method calcul_phieq: calcul_phig: zphieq = ' + zphieq); return zphieq; } // eo calcul_phieq method calcul_tau_niveau_calottes(phieq, zphig_ancien) { let tau_niveau_calottes; if (zphig_ancien < phieq) { CLogger.log('Method calcul_tau_niveau_calottes: désenglacement'); tau_niveau_calottes = CPhysicsConstants.tau_niveau_calottes_deglacement; } else { CLogger.log('Method calcul_tau_niveau_calottes: englacement'); tau_niveau_calottes = CPhysicsConstants.tau_niveau_calottes_englacement; } CLogger.log('Method calcul_tau_niveau_calottes: calcul_phig: tau_niveau_calottes = ' + tau_niveau_calottes); return tau_niveau_calottes; } // eo calcul_tau_niveau_calottes method /* public calcul_niveau_mer_old( zphig: number, zT: number, t: number ): number { // let sv: any = this.experienceValues.back(); // TODO Alain : Revenir la dessus let niveau_mer: number; let Tressentie: number; // modif le 30 jan 2011: tau_niveau_mer est en année, il faut diviser par temps_elem pour l'avoir en nombre de pas // let index: number = Math.max( this.experienceValues.indice_min(), t - Math.trunc( CPhysicsConstants.tau_niveau_mer ) ); // let index: number = Math.max( this.experienceValues.indice_min(), t - Math.trunc( CPhysicsConstants.tau_niveau_mer / this.experienceValues.temps_elem() ) ); // modif CR: 31 oct 2019: index doit pouvoir être soit positif, soit négatif. On met juste des bornes entre -100 et +100 let index: number = t - Math.trunc( CPhysicsConstants.tau_niveau_mer / this.experienceValues.temps_elem() ); index = Math.min( this.experienceValues.indice_max() , index ); index = Math.max( - this.experienceValues.indice_max() , index ); CLogger.log( 'Method calcul_niveau_mer: index = ' + index + ' - indice_min() = ' + this.experienceValues.indice_min() + ' - t = ' + t + ' - tau_niveau_mer = ' + CPhysicsConstants.tau_niveau_mer + ' - temps_elem() = ' + this.experienceValues.temps_elem() ); if ( index < 0 ) { Tressentie = zT * 0.2 + this.simulationValues.temperature_data.get_past( - index ) * 0.8; CLogger.log( 'Method calcul_niveau_mer: index neg: Tpast' + this.simulationValues.temperature_data.get_past( - index ) ); } else { Tressentie = zT * 0.2 + this.simulationValues.temperature_data.get( index ) * 0.8; } CLogger.log( 'Method calcul_niveau_mer: zT = ' + zT + ' - Tressentie = ' + Tressentie ); // le 30 jan 2011: on rajoute facteur 0.5 pour tenir compte de la sous-estimation de la constante de temps de l'océan. // let dilatation: number = CPhysicsConstants.dilat * ( Tressentie - 273 - this.modelPhysicsConstants.Tressentie_act ); let dilatation: number = CPhysicsConstants.dilat * CPhysicsConstants.coef_dilat * ( Tressentie - CPhysicsConstants.Tkelvin - this.modelPhysicsConstants.Tressentie_act ); CLogger.log( 'Method calcul_niveau_mer: Tressentie_act = ' + this.modelPhysicsConstants.Tressentie_act ); CLogger.log( 'Method calcul_niveau_mer: Hmer_tot = ' + CPhysicsConstants.Hmer_tot ); CLogger.log( 'Method calcul_niveau_mer: dilatation = ' + dilatation ); CLogger.log( 'Method calcul_niveau_mer: zphig = ' + zphig ); // CLogger.log( 'Method calcul_niveau_mer: fmax*F(phig_act) = ' + ( -3.8827e-7 * Math.pow( this.modelPhysicsConstants.niveau_calottes_actuel, 3 ) + 1.2689e-4 * Math.pow( this.modelPhysicsConstants.niveau_calottes_actuel, 2 ) -0.0134 * this.modelPhysicsConstants.niveau_calottes_actuel + 0.4615 ) ); // CLogger.log( 'Method calcul_niveau_mer: fmax*F(phig) = ' + ( -3.8827e-7 * Math.pow( zphig, 3 ) + 1.2689e-4 * Math.pow( zphig, 2 ) - 0.0134 * zphig + 0.4615 ) ); CLogger.log( 'Method calcul_niveau_mer: f(phig_act) = ' + this.modelPhysicsConstants.fphig1 * ( zphig - CPhysicsConstants.niveau_calottes_max) + CPhysicsConstants.fphig2 * Math.pow( zphig - CPhysicsConstants.niveau_calottes_max, 2 ) + CPhysicsConstants.fphig3 * Math.pow( zphig - CPhysicsConstants.niveau_calottes_max, 3 ) ); // let Hmer: number = CPhysicsConstants.Hmer_tot * ( 1 + dilatation ) * ( 1 - ( -3.8827e-7 * Math.pow( zphig, 3 ) + 1.2689e-4 * Math.pow( zphig, 2 ) - 0.0134 * zphig + 0.4615 ) ); // let Hmeract: number = CPhysicsConstants.Hmer_tot * ( 1 - ( -3.8827e-7 * Math.pow( this.modelPhysicsConstants.niveau_calottes_actuel, 3 ) + 1.2689e-4 * Math.pow( this.modelPhysicsConstants.niveau_calottes_actuel, 2 ) - 0.0134 * this.modelPhysicsConstants.niveau_calottes_actuel + 0.4615 ) ); let Hmer: number = CPhysicsConstants.Hmer_tot * ( 1 + dilatation ) * ( 1 - this.modelPhysicsConstants.fphig1 * ( zphig - CPhysicsConstants.niveau_calottes_max ) - CPhysicsConstants.fphig2 * Math.pow( zphig - CPhysicsConstants.niveau_calottes_max, 2 ) - CPhysicsConstants.fphig3 * Math.pow( zphig - CPhysicsConstants.niveau_calottes_max, 3 ) ); CLogger.log( 'Method calcul_niveau_mer: Hmer = ' + Hmer ); CLogger.log( 'Method calcul_niveau_mer: Hmeract = ' + this.modelPhysicsConstants.Hmeract ); niveau_mer = Hmer - this.modelPhysicsConstants.Hmeract; CLogger.log( 'Method calcul_niveau_mer: niveau_mer = ' + niveau_mer ); return niveau_mer; } // eo calcul_niveau_mer_old method */ calcul_niveau_mer(zphig, zT, t) { // let sv: any = this.experienceValues.back(); // TODO Alain : Revenir la dessus let niveau_mer; let Tressentie; // modif le 30 jan 2011: tau_niveau_mer est en année, il faut diviser par temps_elem pour l'avoir en nombre de pas // let index: number = Math.max( this.experienceValues.indice_min(), t - Math.trunc( CPhysicsConstants.tau_niveau_mer ) ); // let index: number = Math.max( this.experienceValues.indice_min(), t - Math.trunc( CPhysicsConstants.tau_niveau_mer / this.experienceValues.temps_elem() ) ); // modif CR: 31 oct 2019: index doit pouvoir être soit positif, soit négatif. On met juste des bornes entre -100 et +100 let index = t - Math.trunc(CPhysicsConstants.tmemoire_niveau_mer / this.experienceValues.temps_elem()); index = Math.min(this.experienceValues.indice_max(), index); index = Math.max(-this.experienceValues.indice_max(), index); CLogger.log('Method calcul_niveau_mer: index = ' + index + ' - indice_min() = ' + this.experienceValues.indice_min() + ' - t = ' + t + ' - tau_niveau_mer = ' + CPhysicsConstants.tmemoire_niveau_mer + ' - temps_elem() = ' + this.experienceValues.temps_elem()); if (index < 0) { Tressentie = zT * (1. - this.modelPhysicsConstants.pond_memoire_mer) + this.simulationValues.temperature_data.get_past(-index) * this.modelPhysicsConstants.pond_memoire_mer; CLogger.log('Method calcul_niveau_mer: index neg: Tpast' + this.simulationValues.temperature_data.get_past(-index)); } else { Tressentie = zT * (1. - this.modelPhysicsConstants.pond_memoire_mer) + this.simulationValues.temperature_data.get(index) * this.modelPhysicsConstants.pond_memoire_mer; } CLogger.log('Method calcul_niveau_mer: zT = ' + zT + ' - Tressentie = ' + Tressentie); // le 30 jan 2011: on rajoute facteur 0.5 pour tenir compte de la sous-estimation de la constante de temps de l'océan. // let dilatation: number = CPhysicsConstants.dilat * ( Tressentie - 273 - this.modelPhysicsConstants.Tressentie_act ); let dilatation = CPhysicsConstants.dilat * CPhysicsConstants.coef_dilat * (Tressentie - CPhysicsConstants.Tkelvin - this.modelPhysicsConstants.Tressentie_act); CLogger.log('Method calcul_niveau_mer: Tressentie_act = ' + this.modelPhysicsConstants.Tressentie_act); CLogger.log('Method calcul_niveau_mer: Hmer_tot = ' + CPhysicsConstants.Hmer_tot); CLogger.log('Method calcul_niveau_mer: dilatation = ' + dilatation); CLogger.log('Method calcul_niveau_mer: zphig = ' + zphig); let Hmer = CPhysicsConstants.Hmer_tot * (1 + dilatation) * (1. - (1. - Math.cos((CPhysicsConstants.niveau_calottes_max - zphig) * CPhysicsConstants.pi / 180)) * Math.pow((1. - zphig / CPhysicsConstants.niveau_calottes_max), CPhysicsConstants.expmer)); CLogger.log('Method calcul_niveau_mer: Hmer = ' + Hmer); CLogger.log('Method calcul_niveau_mer: Hmeract = ' + this.modelPhysicsConstants.Hmeract); CLogger.log('Method calcul_niveau_mer: Hmer_tot = ' + CPhysicsConstants.Hmer_tot); niveau_mer = Hmer - this.modelPhysicsConstants.Hmeract; CLogger.log('Method calcul_niveau_mer: niveau_mer = ' + niveau_mer); return niveau_mer; } // eo calcul_niveau_mer method calcul_zA_biologique(zT, A) { let zA; if (zT < this.modelPhysicsConstants.Tlim_bio_froid) { zA = 0; } else if (zT > CPhysicsConstants.Tlim_bio_chaud) { zA = 0; } else { zA = A; } return zA; } // eo calcul_zA_biologique method calcul_zCO2eq(zT) { let zCO2eq; CLogger.log('Method calcul_zCO2eq: calcul zCO2eq_oce: entrée: zT = ' + zT); let Tc = 13.7; let c = 5.0; let b = (CPhysicsConstants.concentration_coo_glaciaire - CPhysicsConstants.concentration_coo_1750 - c * (CPhysicsConstants.temperature_LGM - CPhysicsConstants.temperature_1750)) / (Math.atan(CPhysicsConstants.temperature_LGM - Tc) - Math.atan(CPhysicsConstants.temperature_1750 - Tc)); let a = CPhysicsConstants.concentration_coo_glaciaire - b * Math.atan(CPhysicsConstants.temperature_LGM - Tc) - c * (CPhysicsConstants.temperature_LGM - Tc); zCO2eq = a + b * Math.atan(zT - CPhysicsConstants.Tkelvin - Tc) + c * (zT - CPhysicsConstants.Tkelvin - Tc); CLogger.log('Method calcul_zCO2eq: calcul_zCO2eq: zT = ' + zT + ' - zCO2eq = ' + zCO2eq); return zCO2eq; } // eo calcul_zCO2eq method calcul_zCO2_ocean_eq(zT) { let zCO2_ocean_eq; CLogger.log('Method calcul_zCO2_ocean_eq: zT = ' + zT); zCO2_ocean_eq = CPhysicsConstants.concentration_coo_naturel + CPhysicsConstants.a_CO2_eq * (zT - (CPhysicsConstants.temperature_1750 + CPhysicsConstants.Tkelvin)); CLogger.log('Method calcul_zCO2_ocean_eq: calcul_zCO2eq: zCO2_ocean_eq = ' + zCO2_ocean_eq); return zCO2_ocean_eq; } // eo calcul_zCO2_ocean_eq method calcul_zC_alteration(Cmax, zphig) { let zC_alteration; CLogger.log('Method calcul_zC_alteration: Cmax = ' + Cmax); CLogger.log('Method calcul_zC_alteration: zphig = ' + zphig); if (zphig > CPhysicsConstants.niveau_calotte_critique_coo) { zC_alteration = Cmax; } else if (zphig > 1e-2) { zC_alteration = Cmax * zphig / CPhysicsConstants.niveau_calotte_critique_coo; } else { zC_alteration = 0.; } return zC_alteration; } // eo calcul_zC_alteration method calcul_rapport_H2O(zT) { let zrapport_H2O; CLogger.log('Method calcul_rapport_H2O: zT = ' + zT); CLogger.log('Method calcul_rapport_H2O: temperature_1750 + CPhysicsConstants.Tkelvin = ' + CPhysicsConstants.temperature_1750 + CPhysicsConstants.Tkelvin); // CLogger.log( 'Method calcul_rapport_H2O: tau_T = ' + CPhysicsConstants.tau_T ); // utilisation de la formule de Rankine donnant Psat : zrapport_H2O = (Math.exp(CPhysicsConstants.a_rankine - CPhysicsConstants.b_rankine / zT)) / (Math.exp(CPhysicsConstants.a_rankine - CPhysicsConstants.b_rankine / (CPhysicsConstants.temperature_1750 + CPhysicsConstants.Tkelvin))); CLogger.log('Method calcul_rapport_H2O: zrapport_H2O = ' + zrapport_H2O); return zrapport_H2O; } // eo calcul_rapport_H2O method calcul_albedo(zphig) { let zalbedo; if (zphig > CPhysicsConstants.phig_crit) { zalbedo = this.modelPhysicsConstants.albedo_crit + (zphig - CPhysicsConstants.phig_crit) / (CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.phig_crit) * (CPhysicsConstants.albedo_ter - this.modelPhysicsConstants.albedo_crit); CLogger.log('Method calcul_albedo: albedo_crit = ' + this.modelPhysicsConstants.albedo_crit); CLogger.log('Method calcul_albedo: albedo_actuel = ' + this.modelPhysicsConstants.albedo_actuel); CLogger.log('Method calcul_albedo: zphig > phig_crit'); CLogger.log('Method calcul_albedo: B = ' + (this.modelPhysicsConstants.niveau_calottes_actuel - CPhysicsConstants.phig_crit) / (CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.phig_crit)); CLogger.log('Method calcul_albedo: 1 - B = ' + (1 - (this.modelPhysicsConstants.niveau_calottes_actuel - CPhysicsConstants.phig_crit) / (CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.phig_crit))); CLogger.log('Method calcul_albedo: Aact - B.Ater = ' + (this.modelPhysicsConstants.albedo_actuel - CPhysicsConstants.albedo_ter * (this.modelPhysicsConstants.niveau_calottes_actuel - CPhysicsConstants.phig_crit) / (CPhysicsConstants.niveau_calottes_max - CPhysicsConstants.phig_crit))); } else { zalbedo = CPhysicsConstants.albedo_glace_const + (zphig - CPhysicsConstants.niveau_calottes_min) / (CPhysicsConstants.phig_crit - CPhysicsConstants.niveau_calottes_min) * (this.modelPhysicsConstants.albedo_crit - CPhysicsConstants.albedo_glace_const); } CLogger.log('Method calcul_albedo: zphig = ' + zphig); CLogger.log('Method calcul_albedo: zalbedo = ' + zalbedo); // ASSERT(zalbedo>0); // ASSERT(zalbedo<1); return zalbedo; } // eo calcul_albedo method calcul_poce(zT) { let zpoce; let poce_act = 1 - CPhysicsConstants.puit_ocean_act; if (zT > CPhysicsConstants.temperature_actuelle - CPhysicsConstants.Tkelvin) { zpoce = poce_act + (1 - poce_act) * (1 - Math.exp(-(zT - CPhysicsConstants.temperature_actuelle - CPhysicsConstants.Tkelvin) / this.modelPhysicsConstants.deltaT_poce)); } else { zpoce = poce_act * Math.exp((zT - CPhysicsConstants.temperature_actuelle - CPhysicsConstants.Tkelvin) / this.modelPhysicsConstants.deltaT_poce); } return zpoce; } // eo calcul_poce method calcul_zpuit_oce(zT) { let zpuit_oce; zpuit_oce = (zT - CPhysicsConstants.Tcrit_oce - CPhysicsConstants.Tkelvin) / (CPhysicsConstants.temperature_actuelle - CPhysicsConstants.Tcrit_oce) * CPhysicsConstants.puit_ocean_act / 100.0; CLogger.log('Method calcul_zpuit_oce: zpuit_oce = ' + zpuit_oce); zpuit_oce = Math.max(0., zpuit_oce); // zpuit_oce = Math.min( CPhysicsConstants.puit_oce_max, zpuit_oce ); zpuit_oce = Math.min(CPhysicsConstants.puit_oce_max / 100.0, zpuit_oce); CLogger.log('Method calcul_zpuit_oce: zpuit_oce = ' + zpuit_oce); // TODO Alain : Eclaircir le besoin de ces deux assertions pour éventuellement faire autrement this.assert(zpuit_oce >= 0.); this.assert(zpuit_oce <= CPhysicsConstants.puit_oce_max / 100.0); return zpuit_oce; } // eo calcul_zpuit_oce method calcul_Fdegaz(zT) { let Fdegaz; if (zT - CPhysicsConstants.Tkelvin > CPhysicsConstants.Tcrit_oce) { Fdegaz = (zT - CPhysicsConstants.Tcrit_oce - CPhysicsConstants.Tkelvin) * CPhysicsConstants.dFdegaz; } else { Fdegaz = 0; } // TODO Alain : Eclaircir le besoin de cette assertion pour éventuellement faire autrement this.assert(Fdegaz >= 0.); return Fdegaz; } // eo calcul_Fdegaz method abs(x) { let y; if (x < 0) { y = -x; } else { y = x; } return y; } // eo abs method assert(condition, message = '') { if (!condition) { message = message || "Assertion failed"; if (typeof Error !== "undefined") { throw new Error(message); } throw message; // Fallback } } // eo assert method /** End of Utils methods */ /** * Model execution method */ modelExecute(simulationValue, experienceValue) { CLogger.log('Method modelExecute: Initialisation du modèle ... '); CLogger.log(simulationValue); CLogger.log(experienceValue); simulationValue.set_annee_fin(experienceValue.echeance()); simulationValue.set_resolution(experienceValue.temps_elem()); /** * On mappe l'objet CSimulationValues */ this.simulationValues = simulationValue; this.experienceValues = experienceValue; /** * declarations pour l'integration temporelle */ let oscillation; let zT = 0, zT_ancien, zT_ancien_prec; // température let zCO2 = 0, zCO2_ancien, zCO2_ancien_prec; // CO2 let zphig = 0, zphig_ancien, zphig_ancien_prec = 0; // niveau calotte let zT_moy, zCO2_moy, zphig_moy; let zT_moy1, zCO2_moy1, zphig_moy1; let zT_moy2, zCO2_moy2, zphig_moy2; let zT_moy2save, zCO2_moy2sav