/* * #%L * IsisFish data * %% * Copyright (C) 2006 - 2015 Ifremer, Code Lutin, Cedric Pineau, Benjamin Poussin, Chatellier Eric * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . * #L% */ package simulators; import fr.ifremer.isisfish.IsisFishException; import fr.ifremer.isisfish.datastore.StorageException; import fr.ifremer.isisfish.entities.Metier; import fr.ifremer.isisfish.entities.Population; import fr.ifremer.isisfish.entities.PopulationSeasonInfo; import fr.ifremer.isisfish.rule.Rule; import fr.ifremer.isisfish.simulator.MetierMonitor; import fr.ifremer.isisfish.simulator.PopulationMonitor; import fr.ifremer.isisfish.simulator.ResultManager; import fr.ifremer.isisfish.simulator.RuleMonitor; import fr.ifremer.isisfish.simulator.SimulationContext; import fr.ifremer.isisfish.simulator.SimulationControl; import fr.ifremer.isisfish.simulator.SimulationParameter; import fr.ifremer.isisfish.simulator.Simulator; import fr.ifremer.isisfish.types.Month; import fr.ifremer.isisfish.types.TimeStep; import resultinfos.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.math.matrix.MatrixFactory; import org.nuiton.math.matrix.MatrixND; import org.nuiton.topia.TopiaContext; import org.nuiton.topia.TopiaException; import scripts.GravityModel; import scripts.SiMatrix; import java.util.List; import static org.nuiton.i18n.I18n.t; import static org.nuiton.i18n.I18n.n; /** * DefaultSimulator.java * * Created: 21 aout 2006 10:57:46 * * @author poussin * @version $Revision: 1.19 $ * * Last update: $Date: 2007-11-06 18:16:14 $ * by : $Author: bpoussin $ */ public class DefaultSimulatorResultBeforeCondition implements Simulator { /** to use log facility, just put in your code: log.info("..."); */ static private Log log = LogFactory.getLog(DefaultSimulatorResultBeforeCondition.class); /** * When you create new simulator with specific SiMatrix you must * overwrite this method to return you SiMatrix version * @param context * @return * @throws TopiaException */ protected SiMatrix newSiMatrix(SimulationContext context) throws TopiaException { return new SiMatrix(context); } /** * When you create new simulator with specific GravityModel you must * overwrite this method to return you GravityModel version * @param context * @param siMatrix * @return * @throws TopiaException * @throws StorageException */ protected GravityModel newGravityModel(SimulationContext context, SiMatrix siMatrix) throws TopiaException, StorageException { return new GravityModel(context, siMatrix); } /** * Called by isis don't modify signature */ public void simulate(SimulationContext context) throws Exception { SimulationParameter param = context.getSimulationStorage() .getParameter(); SimulationControl control = context.getSimulationControl(); int lastStep = param.getNumberOfMonths(); TimeStep step = control.getStep(); ResultManager resManager = context.getResultManager(); TopiaContext db = context.getDB(); // for database init SiMatrix siMatrix = newSiMatrix(context); GravityModel gravityModel = newGravityModel(context, siMatrix); PopulationMonitor populationMonitor = context.getPopulationMonitor(); MetierMonitor metierMonitor = context.getMetierMonitor(); RuleMonitor ruleMonitor = context.getRuleMonitor(); List allpops = siMatrix.getPopulations(step); populationMonitor.init(allpops); for (Population pop : allpops) { MatrixND N = param.getNumberOf(pop); N.setName(MatrixAbundance.NAME); populationMonitor.setN(pop, N); } // reload context parameters with context.getDB() context param.reloadContextParameters(); // // Rule initialisation // List rules = param.getRules(); control.setText("Rules initialisation:" + rules); for (Rule rule : rules) { rule.init(context); log.info("Rule " + rule.getClass().getSimpleName() + " initialized"); } // // Commit all change done un init rules methods. // context.validateDBChanges(); // // Simulation loop // while (step.getStep() < lastStep) { // // if user stop simulation before last year // if (control.isStopSimulationRequest()) { break; } control.setStep(step); control.setProgress(step.getStep()); control.setText(t("begin step " + step)); // // Reload parameters for current step // control.setText(t("Reloading parameters")); // reload context parameters with db.rollbackTransaction() context param.reloadContextParameters(); rules = param.getRules(); // raz des metiers interdits et des licences metierMonitor.clear(); if (step.getMonth().equals(Month.JANUARY)) { populationMonitor.clearCatch(); } // only if there are one or more strategy if (siMatrix.getStrategies(step).size() > 0) { if (resManager.isEnabled(MatrixNoActivity.NAME)) { MatrixND mat = metierMonitor.getOrCreateNoActivity(step, MatrixNoActivity.NAME, siMatrix .getStrategies(step), siMatrix .getMetiers(step)); resManager.addResult(step, mat); } } // // Keep modification's information done in rule // if (siMatrix.getStrategies(step).size() > 0) { if (resManager.isEnabled(MatrixMetierZone.NAME)) { MatrixND metierZone = siMatrix.getMetierZone(step); resManager.addResult(step, metierZone); } } //Add results before conditions and pre-actions for (Population pop : siMatrix.getPopulations(step)) { // to add result PopulationMonitor popMon = context.getPopulationMonitor(); MatrixND N = popMon.getN(pop); // add N and biomass result now, before computation // N is reassigned during computation resManager.addResult(step, pop, N); MatrixND biomass = siMatrix.matrixBiomass(N, pop, step); if (resManager.isEnabled(MatrixBiomass.NAME)) { resManager.addResult(step, pop, biomass); } } // // Rule condition evaluation // control.setText("Evaluate rules conditions (" + rules.size() + " rules)"); for (Rule rule : rules) { for (Metier metier : siMatrix.getMetiers(step)) { boolean active = false; try { active = rule.condition(context, step, metier); } catch (Exception eee) { if (log.isWarnEnabled()) { log.warn("Can't evaluate rule condition for: " + rule, eee); } } ruleMonitor.setEvaluationCondition(step, rule, metier, active); if (active) { log.info("Activate rule: " + rule.getClass().getSimpleName()); resManager.addActiveRule(step, rule); } } } // // Rule pre action // control.setText("Do pre action Rules"); for (Rule rule : rules) { for (Metier metier : siMatrix.getMetiers(step)) { boolean condition = ruleMonitor.getEvalutionCondition(step, rule, metier); if (condition) { rule.preAction(context, step, metier); } } } // // Simulate one step for all pop // control.setText("Simulate one month"); for (Population pop : siMatrix.getPopulations(step)) { computeMonth(context, siMatrix, step, pop); } // // Add some result not population dependante // // only if there are one or more strategy if (siMatrix.getStrategies(step).size() > 0) { control.setText("Add some results"); if (resManager .isEnabled(MatrixEffortPerStrategyMet.NAME)) { MatrixND effortPerStrategyMet = siMatrix .matrixEffortPerStrategyMet(step); resManager.addResult(step, effortPerStrategyMet); } if (resManager.isEnabled(MatrixEffortNominalPerStrategyMet.NAME)) { MatrixND effortNominalPerStrategyMet = siMatrix.matrixEffortNominalPerStrategyMet(step); resManager.addResult(step, effortNominalPerStrategyMet); } } // // Rule post action // control.setText("Do post action Rules"); for (Rule rule : rules) { for (Metier metier : siMatrix.getMetiers(step)) { if (ruleMonitor.getEvalutionCondition(step, rule, metier)) { rule.postAction(context, step, metier); } } } // discard and landing must be done after post action rules // only if there are one or more strategy if (siMatrix.getStrategies(step).size() > 0) { control.setText("Compute discard and landing"); for (Population pop : siMatrix.getPopulations(step)) { // // discard computation // MatrixND discard = populationMonitor.getDiscard(step, pop); if (discard != null || step.getStep() == 0) { // force discard for the first month to have discard in result if (discard == null) { discard = MatrixFactory.getInstance().create( MatrixDiscardsPerStrMetPerZonePop.NAME, new List[] { siMatrix.getStrategies(step), siMatrix.getMetiers(step), pop.getPopulationGroup(), pop.getPopulationZone() }, new String[] { n("Strategies"), n("Metiers"), n("Groups"), n("Zones") }); } resManager.addResult(step, pop, discard); if (resManager .isEnabled(MatrixDiscardsWeightPerStrMetPerZonePop.NAME)) { MatrixND discardWeightPerStrategyMet = siMatrix .matrixDiscardWeightPerStrategyMetPerZonePop( pop, step, discard); resManager.addResult(step, pop, discardWeightPerStrategyMet); } } // // add landing result // if (resManager.isEnabled(MatrixLandingPerMet.NAME)) { MatrixND landing = populationMonitor.getCatch(pop).copy(); landing.setName(MatrixLandingPerMet.NAME); if (discard != null) { landing = landing.minus(discard); } resManager.addResult(step, pop, landing); } if (resManager.isEnabled(MatrixLandingWeight.NAME)) { MatrixND landing = populationMonitor.getCatch(pop).copy(); if (discard != null) { landing = landing.minus(discard); } MatrixND landingweight = siMatrix.matrixToWeightMatrix(step, 2, MatrixLandingWeight.NAME, landing); resManager.addResult(step, pop, landingweight); } // F and Fbar if (resManager.isEnabled(MatrixFishingMortalityPerGroup.NAME)) { MatrixND fishingMortalityPerGroup = siMatrix.fishingMortalityPerGroup(step, pop, context.getResultManager()); resManager.addResult(step, pop, fishingMortalityPerGroup); // MatrixTotalFishingMortality.NAME depends on MatrixFishingMortalityPerGroup.NAME if (resManager.isEnabled(MatrixTotalFishingMortality.NAME)) { MatrixND totalFishingMortality = siMatrix.totalFishingMortality( step, pop, fishingMortalityPerGroup); resManager.addResult(step, pop, totalFishingMortality); } } } // // Add economics results // if (!"false".equalsIgnoreCase(param.getTagValue().get( "ecoResult"))) { control.setText("Add economics results"); saveGravityModel(step, resManager, gravityModel); } if (resManager.isEnabled(MatrixPrice.NAME)) { for (Population pop : siMatrix.getPopulations(step)) { MatrixND matPrice = siMatrix.matrixPrice(step, pop); resManager.addResult(step, pop, matPrice); } } } // // Go next step // // do next before rollbackTransaction to permit export to take // current database value and export them. step = step.next(); // // revert modification for next step // control.setText("Rollback rules changes"); context.rollbackRuleChanges(); } } protected boolean isEffortByCell(SimulationContext context) { boolean result = "true".equalsIgnoreCase(context.getSimulationStorage() .getParameter().getTagValue().get("effortByCell")); return result; } protected void computeMonth(SimulationContext context, SiMatrix siMatrix, TimeStep step, Population pop) throws IsisFishException, TopiaException { // to add result ResultManager resManager = context.getResultManager(); PopulationMonitor popMon = context.getPopulationMonitor(); MatrixND N = popMon.getN(pop); if (log.isInfoEnabled()) { log.info("====================== begin " + step + " - " + pop + " =========================== " + System.currentTimeMillis()); log.info("N: " + N); } // add N and biomass result now, before computation // N is reassigned during computation //resManager.addResult(step, pop, N); MatrixND biomass = siMatrix.matrixBiomass(N, pop, step); //if (resManager.isEnabled(MatrixBiomass.NAME)) { // resManager.addResult(step, pop, biomass); //} Month month = step.getMonth(); PopulationSeasonInfo info = pop.getPopulationSeasonInfo(month); // group change MatrixND CA; if (step.getStep() == 0) { CA = MatrixFactory.getInstance().matrixId( pop.sizePopulationGroup() * pop.sizePopulationZone()); } else { CA = info.getGroupChangeMatrix(month); } log.debug("CA: " + CA); //migration MatrixND M = info.getMigrationMatrix(month, N); log.debug("M: " + M); //emigration MatrixND EM = info.getEmigrationMatrix(month, N); log.debug("EM: " + EM); //immigration MatrixND IM = info.getImmigrationMatrix(month, N).transpose(); log.debug("IM: " + IM); // pour les premiers calculs on met N en une matrice 1D MatrixND N1D = pop.N2DToN1D(N); log.debug("N1D: " + N1D); MatrixND tmp0 = N1D.mult(CA); MatrixND tmp1 = M.minus(EM); MatrixND tmp2 = tmp0.mult(tmp1); MatrixND tmp3 = tmp2.add(IM); log.debug("N1D after mig: " + tmp3); // On reconvertie en une matrice Semantique N = pop.split2D(tmp3); log.debug("N after mig: " + N); // reproduction MatrixND R = info.getReproductionMatrix(month, N); log.debug("R: " + R); // ajout de la matrice R dans le suivi de la pop comme etant // la reproduction pour le mois courant. popMon.setReproduction(step, pop, N, biomass, R); // recrutement MatrixND recruitment = popMon.getRecruitment(step, pop); log.debug("recruitment: " + recruitment); // mortalite de la reproduction popMon.applyReproductionMortality(pop); N = N.add(recruitment); log.debug("N after recru: " + N); if (resManager.isEnabled(MatrixAbundanceBeginMonth.NAME)) { MatrixND abondanceBM = siMatrix.matrixAbondanceBeginMonth(N, pop, step); resManager.addResult(step, pop, abondanceBM); } if (resManager.isEnabled(MatrixBiomassBeginMonth.NAME)) { MatrixND biomassBM = siMatrix.matrixBiomassBeginMonth(N, pop, step); resManager.addResult(step, pop, biomassBM); } if (resManager.isEnabled(MatrixLbar.NAME)) { MatrixND Lbar = siMatrix.Lbar(step, pop, N); resManager.addResult(step, pop, Lbar); } if (resManager.isEnabled(MatrixLbarTotal.NAME)) { MatrixND Lbar = siMatrix.LbarTotal(step, pop, N); resManager.addResult(step, pop, Lbar); } if (resManager.isEnabled(MatrixRecruitment.NAME)) { MatrixND Recruitment = siMatrix.Recruitment(step, pop); resManager.addResult(step, pop, Recruitment); } MatrixND abundance; // compute fishing matrix only if there are one or more strategy if (siMatrix.getStrategies(step).size() > 0) { // compute some Matrix and add result // this matrix is necessary for PopulationMonitor.holdCatch (reused in rule) MatrixND catchPerStrategyMetPerZonePop; abundance = siMatrix.matrixAbundance(N, pop, step); catchPerStrategyMetPerZonePop = siMatrix .matrixCatchPerStrategyMetPerZone(N, pop, step); popMon.holdCatch(pop, catchPerStrategyMetPerZonePop); resManager.addResult(step, pop, catchPerStrategyMetPerZonePop); if (resManager .isEnabled(MatrixCatchWeightPerStrategyMetPerZonePop.NAME)) { MatrixND catchWeightPerStrategyMet = siMatrix .matrixCatchWeightPerStrategyMetPerZonePop(step, pop, catchPerStrategyMetPerZonePop); resManager.addResult(step, pop, catchWeightPerStrategyMet); } siMatrix.computeMonthExtra(step, pop, N); } else { // no strategies // compute only if fishing mortality =0 to apply Natural Mortality abundance = siMatrix.matrixAbundanceSsF(N, pop, step); } log.debug("abundance: " + abundance); // Keep new N popMon.setN(pop, abundance); log.debug("====================== end " + step + " - " + pop + " ==========================="); } /** * @param step * @param resManager * @throws IsisFishException * @throws TopiaException */ protected void saveGravityModel(TimeStep step, ResultManager resManager, GravityModel gravityModel) throws IsisFishException, TopiaException { if (resManager .isEnabled(MatrixFishingTimePerMonthPerVessel.NAME)) { MatrixND mat = gravityModel .matrixFishingTimePerMonthPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixFuelCostsOfTravelPerVessel.NAME)) { MatrixND mat = gravityModel.matrixFuelCostsOfTravelPerVessel(step); resManager.addResult(step, mat); } if (resManager.isEnabled(MatrixCostsOfFishingPerVessel.NAME)) { MatrixND mat = gravityModel.matrixCostsOfFishingPerVessel(step); resManager.addResult(step, mat); } if (resManager.isEnabled(MatrixFuelCostsPerVessel.NAME)) { MatrixND mat = gravityModel.matrixFuelCostsOfTravelPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixRepairAndMaintenanceGearCostsPerVessel.NAME)) { MatrixND mat = gravityModel .matrixRepairAndMaintenanceGearCostsPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixOtherRunningCostsPerVessel.NAME)) { MatrixND mat = gravityModel.matrixOtherRunningCostsPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixSharedNotFixedCostsPerVessel.NAME)) { MatrixND mat = gravityModel .matrixSharedNotFixedCostsPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixGrossValueOfLandingsPerSpeciesPerStrategyMet.NAME)) { MatrixND mat = gravityModel .matrixGrossValueOfLandingsPerSpeciesPerStrategyMet(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixGrossValueOfLandingsPerStrategyMet.NAME)) { MatrixND mat = gravityModel .matrixGrossValueOfLandingsPerStrategyMet(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixGrossValueOfLandingsPerStrategyMetPerVessel.NAME)) { MatrixND mat = gravityModel .matrixGrossValueOfLandingsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixNetValueOfLandingsPerStrategyMet.NAME)) { MatrixND mat = gravityModel .matrixNetValueOfLandingsPerStrategyMet(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixNetValueOfLandingsPerStrategyMetPerVessel.NAME)) { MatrixND mat = gravityModel .matrixNetValueOfLandingsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixNetRevenueToSharePerStrategyMetPerVessel.NAME)) { MatrixND mat = gravityModel .matrixNetRenevueToSharePerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixCrewSharePerStrategyPerVessel.NAME)) { MatrixND mat = gravityModel .matrixCrewSharePerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixOwnerMarginOverVariableCostsPerStrategyMetPerVessel.NAME)) { MatrixND mat = gravityModel .matrixOwnerMarginOverVariableCostsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixVesselMarginOverVariableCostsPerStrategyMetPerVessel.NAME)) { MatrixND mat = gravityModel .matrixVesselMarginOverVariableCostsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixOwnerMarginOverVariableCostsPerStrategyPerVessel.NAME)) { MatrixND mat = gravityModel .matrixOwnerMarginOverVariableCostsPerStrategyPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixOwnerMarginOverVariableCostsPerStrategy.NAME)) { MatrixND mat = gravityModel .matrixOwnerMarginOverVariableCostsPerStrategy(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixVesselMarginOverVariableCostsPerStrategyPerVessel.NAME)) { MatrixND mat = gravityModel .matrixVesselMarginOverVariableCostsPerStrategyPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(MatrixVesselMarginOverVariableCostsPerStrategy.NAME)) { MatrixND mat = gravityModel .matrixVesselMarginOverVariableCostsPerStrategy(step); resManager.addResult(step, mat); } } }