package org.openlca.core.math; import org.openlca.core.matrix.ImpactMatrix; import org.openlca.core.matrix.ImpactTable; import org.openlca.core.matrix.Inventory; import org.openlca.core.matrix.InventoryMatrix; import org.openlca.core.matrix.ParameterTable; import org.openlca.core.matrix.cache.MatrixCache; import org.openlca.core.model.descriptors.ImpactMethodDescriptor; import org.openlca.core.results.SimpleResult; import org.openlca.core.results.SimulationResult; import org.openlca.expressions.FormulaInterpreter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A calculator for Monte-Carlo-Simulations. */ public class Simulator { private Logger log = LoggerFactory.getLogger(getClass()); private ImpactMethodDescriptor impactMethod; private MatrixCache cache; private final IMatrixFactory<?> factory; private final IMatrixSolver matrixSolver; private SimulationResult result; private Inventory inventory; private ParameterTable parameterTable; private InventoryMatrix inventoryMatrix; private ImpactTable impactTable; private ImpactMatrix impactMatrix; private CalculationSetup setup; public Simulator(CalculationSetup setup, MatrixCache database, IMatrixSolver solver) { this.impactMethod = setup.impactMethod; this.cache = database; this.setup = setup; this.factory = solver.getMatrixFactory(); this.matrixSolver = solver; } public SimulationResult getResult() { return result; } /** * Generates random numbers and calculates the product system. Returns true * if the calculation was successfully done, otherwise false (this is the * case when the resulting matrix is singular). */ public boolean nextRun() { if (inventory == null || inventoryMatrix == null) setUp(); try { log.trace("next simulation run"); FormulaInterpreter interpreter = parameterTable.simulate(); inventory.simulate(inventoryMatrix, interpreter); LcaCalculator solver = new LcaCalculator(matrixSolver, inventoryMatrix); if (impactMatrix != null) { impactTable.simulate(impactMatrix, interpreter); solver.setImpactMatrix(impactMatrix); } SimpleResult result = solver.calculateSimple(); appendResults(result); return true; } catch (Throwable e) { log.trace("simulation run failed", e); return false; } } private void appendResults(SimpleResult result) { this.result.appendFlowResults(result.totalFlowResults); if (this.result.hasImpactResults()) this.result.appendImpactResults(result.totalImpactResults); } private void setUp() { log.trace("set up inventory"); inventory = DataStructures.createInventory(setup, cache); parameterTable = DataStructures.createParameterTable(cache.getDatabase(), setup, inventory); inventoryMatrix = inventory.createMatrix(factory); result = new SimulationResult(); result.productIndex = inventory.productIndex; result.flowIndex = inventory.flowIndex; if (impactMethod != null) { ImpactTable impactTable = ImpactTable.build(cache, impactMethod.getId(), inventory.flowIndex); if (impactTable.isEmpty()) { return; } this.impactTable = impactTable; this.impactMatrix = impactTable.createMatrix(factory); result.impactIndex = impactTable.categoryIndex; } } }