/* * #%L * IsisFish data * %% * Copyright (C) 2006 - 2011 Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin * %% * 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 2 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.ResultStorage; 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 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.ResultName; import scripts.SiMatrix; import java.util.List; import static org.nuiton.i18n.I18n._; 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 DefaultSimulator_F implements Simulator { /** to use log facility, just put in your code: log.info("..."); */ static private Log log = LogFactory.getLog(DefaultSimulator.class); /** * Called by isis don't modify signature */ public void simulate(SimulationContext context) throws Exception { SimulationParameter param = context.getSimulationStorage() .getParameter(); SimulationControl control = context.getSimulationControl(); int lastYear = param.getNumberOfYear(); int lastStep = lastYear * Month.NUMBER_OF_MONTH; TimeStep step = control.getStep(); ResultManager resManager = context.getResultManager(); TopiaContext db = context.getDB(); SiMatrix siMatrix = SiMatrix.getSiMatrix(context); GravityModel gravityModel = new GravityModel(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(ResultName.MATRIX_ABUNDANCE); 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.getDB().commitTransaction(); // // 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(_("begin step " + step)); // // Reload parameters for current step // control.setText(_("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(ResultName.MATRIX_NO_ACTIVITY)) { MatrixND mat = metierMonitor.getOrCreateNoActivity(step, ResultName.MATRIX_NO_ACTIVITY, siMatrix .getStrategies(step), siMatrix .getMetiers(step)); resManager.addResult(step, mat); } } // // 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); } } } // // Keep modification's information done in rule // if (resManager.isEnabled(ResultName.MATRIX_METIER_ZONE)) { MatrixND metierZone = siMatrix.getMetierZone(step); resManager.addResult(step, metierZone); } // // 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 // //if (resManager // .isEnabled(ResultName.MATRIX_TOTAL_FISHING_MORTALITY)) { // MatrixND totalFishingMortality = siMatrix.totalFishingMortality(step, pop, context.getSimulationStorage().getResultStorage()); // pop, // resManager.addResult(step, totalFishingMortality); //} // only if there are one or more strategy if (siMatrix.getStrategies(step).size() > 0) { control.setText("Add some results"); if (resManager .isEnabled(ResultName.MATRIX_EFFORT_PER_STRATEGY_MET)) { MatrixND effortPerStrategyMet = siMatrix .matrixEffortPerStrategyMet(step); resManager.addResult(step, effortPerStrategyMet); } if (resManager.isEnabled(ResultName.MATRIX_EFFORT_NOMINAL_PER_STRATEGY_MET)) { MatrixND effortNominalPerStrategyMet = siMatrix.matrixEffortNominalPerStrategyMet(step); resManager.addResult(step, effortNominalPerStrategyMet); } // // Add economics results // if (!"false".equalsIgnoreCase(param.getTagValue().get( "ecoResult"))) { control.setText("Add economics results"); saveGravityModel(step, resManager, gravityModel); } } // // Add economics results // if (resManager.isEnabled(ResultName.MATRIX_PRICE)) { for (Population pop : siMatrix.getPopulations(step)) { MatrixND matPrice = siMatrix.matrixPrice(step, pop); resManager.addResult(step, pop, matPrice); } } // // 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( ResultName.MATRIX_DISCARDS_PER_STR_MET_PER_ZONE_POP, 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(ResultName.MATRIX_DISCARDS_WEIGHT_PER_STR_MET_PER_ZONE_POP)) { MatrixND discardWeightPerStrategyMet = siMatrix .matrixDiscardWeightPerStrategyMetPerZonePop( pop, step, discard); resManager.addResult(step, pop, discardWeightPerStrategyMet); } } // // add landing result // if (resManager.isEnabled(ResultName.MATRIX_LANDING_PER_MET)) { MatrixND landing = MatrixFactory.getInstance().create( populationMonitor.getCatch(pop)); if (discard != null) { landing = landing.minus(discard); } landing.setName(ResultName.MATRIX_LANDING_PER_MET); resManager.addResult(step, pop, landing); } } } // // revert modification for next step // control.setText("Rollback rules changes"); db.rollbackTransaction(); // // commit result // control.setText("Commit results"); TopiaContext tx = context.getDbResult(); tx.commitTransaction(); // // Go next step // step = step.next(); } } 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 ResultStorage resManager = context.getSimulationStorage() .getResultStorage(); 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); if (resManager.isEnabled(ResultName.MATRIX_BIOMASS)) { MatrixND biomass = siMatrix.matrixBiomass(N, pop, step); 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); //Recrutement 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, 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(ResultName.MATRIX_ABUNDANCE_BEGIN_MONTH)) { MatrixND abondanceBM = siMatrix.matrixAbondanceBeginMonth(N, pop, step); resManager.addResult(step, pop, abondanceBM); } if (resManager.isEnabled(ResultName.MATRIX_BIOMASS_BEGIN_MONTH)) { MatrixND biomassBM = siMatrix.matrixBiomassBeginMonth(N, pop, step); resManager.addResult(step, pop, biomassBM); } 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; if (isEffortByCell(context)) { abundance = siMatrix.matrixAbundance(N, pop, step); catchPerStrategyMetPerZonePop = siMatrix .matrixCatchPerStrategyMetPerZonePop(N, pop, step); } else { // en zone MatrixND matrixFishingMortality = siMatrix .matrixFishingMortality(step, pop); resManager.addResult(step, pop, matrixFishingMortality); abundance = siMatrix.matrixAbundance(N, pop, step, matrixFishingMortality); // this matrix is necessary for matrixCatchPerStrategyMet MatrixND catchRatePerStrategyMet = siMatrix .matrixCatchRatePerStrategyMetPerZone(pop, step, matrixFishingMortality); resManager.addResult(step, pop, catchRatePerStrategyMet); catchPerStrategyMetPerZonePop = siMatrix .matrixCatchPerStrategyMetPerZone(N, pop, step, catchRatePerStrategyMet); } popMon.holdCatch(pop, catchPerStrategyMetPerZonePop); resManager.addResult(step, pop, catchPerStrategyMetPerZonePop); if (resManager .isEnabled(ResultName.MATRIX_CATCH_WEIGHT_PER_STRATEGY_MET_PER_ZONE_POP)) { MatrixND catchWeightPerStrategyMet = siMatrix .matrixCatchWeightPerStrategyMetPerZonePop(step, pop, catchPerStrategyMetPerZonePop); resManager.addResult(step, pop, catchWeightPerStrategyMet); } if (isEffortByCell(context)) { MatrixND catchPerStrategyMetPerZoneMet = siMatrix .matrixCatchPerStrategyMetPerZoneMet(N, pop, step); resManager.addResult(step, pop, catchPerStrategyMetPerZoneMet); if (resManager .isEnabled(ResultName.MATRIX_CATCH_WEIGHT_PER_STRATEGY_MET_PER_ZONE_MET)) { MatrixND catchWeightPerStrategyMet = siMatrix .matrixCatchWeightPerStrategyMetPerZoneMet(step, pop, catchPerStrategyMetPerZoneMet); resManager.addResult(step, pop, catchWeightPerStrategyMet); } } if (resManager .isEnabled(ResultName.MATRIX_TOTAL_FISHING_MORTALITY)) { MatrixND totalFishingMortality = siMatrix.totalFishingMortality(step, pop, context.getSimulationStorage().getResultStorage()); // pop, resManager.addResult(step, pop, totalFishingMortality); } } 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 */ private void saveGravityModel(TimeStep step, ResultManager resManager, GravityModel gravityModel) throws IsisFishException, TopiaException { if (resManager .isEnabled(ResultName.MATRIX_FISHING_TIME_PER_MONTH_PER_VESSEL)) { MatrixND mat = gravityModel .matrixFishingTimePerMonthPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_FUEL_COSTS_OF_TRAVEL_PER_VESSEL)) { MatrixND mat = gravityModel.matrixFuelCostsOfTravelPerVessel(step); resManager.addResult(step, mat); } if (resManager.isEnabled(ResultName.MATRIX_COSTS_OF_FISHING_PER_VESSEL)) { MatrixND mat = gravityModel.matrixCostsOfFishingPerVessel(step); resManager.addResult(step, mat); } if (resManager.isEnabled(ResultName.MATRIX_FUEL_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel.matrixFuelCostsOfTravelPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_REPAIR_AND_MAINTENANCE_GEAR_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel .matrixRepairAndMaintenanceGearCostsPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_OTHER_RUNNING_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel.matrixOtherRunningCostsPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_SHARED_NOT_FIXED_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel .matrixSharedNotFixedCostsPerVessel(step); resManager.addResult(step, mat); } // if (resManager.isEnabled(ResultName.MATRIX_SHARED_FIXED_COSTS_PER_VESSEL_PER_MET)) { // MatrixND mat = gravityModel.matrixSharedFixedCostsPerVesselPerMet(date); // resManager.addResult(date, mat); // } if (resManager .isEnabled(ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_SPECIES_PER_STRATEGY_MET)) { MatrixND mat = gravityModel .matrixGrossValueOfLandingsPerSpeciesPerStrategyMet(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_STRATEGY_MET)) { MatrixND mat = gravityModel .matrixGrossValueOfLandingsPerStrategyMet(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel .matrixGrossValueOfLandingsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET)) { MatrixND mat = gravityModel .matrixNetValueOfLandingsPerStrategyMet(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel .matrixNetValueOfLandingsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_NET_RENEVUE_TO_SHARE_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel .matrixNetRenevueToSharePerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_CREW_SHARE_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel .matrixCrewSharePerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_OWNER_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel .matrixOwnerMarginOverVariableCostsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_VESSEL_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel .matrixVesselMarginOverVariableCostsPerStrategyMetPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_OWNER_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_PER_VESSEL)) { MatrixND mat = gravityModel .matrixOwnerMarginOverVariableCostsPerStrategyPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_OWNER_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY)) { MatrixND mat = gravityModel .matrixOwnerMarginOverVariableCostsPerStrategy(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_VESSEL_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_PER_VESSEL)) { MatrixND mat = gravityModel .matrixVesselMarginOverVariableCostsPerStrategyPerVessel(step); resManager.addResult(step, mat); } if (resManager .isEnabled(ResultName.MATRIX_VESSEL_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY)) { MatrixND mat = gravityModel .matrixVesselMarginOverVariableCostsPerStrategy(step); resManager.addResult(step, mat); } } }