| package org.eclipse.stem.diseasemodels.standard.impl; |
| |
| /******************************************************************************* |
| * Copyright (c) 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.util.BasicEList; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.impl.ENotificationImpl; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.stem.core.STEMObjectPool; |
| import org.eclipse.stem.core.graph.DynamicLabel; |
| import org.eclipse.stem.core.graph.Edge; |
| import org.eclipse.stem.core.graph.EdgeLabel; |
| import org.eclipse.stem.core.graph.Exchange; |
| import org.eclipse.stem.core.graph.ExchangePool; |
| import org.eclipse.stem.core.graph.ExchangeType; |
| import org.eclipse.stem.core.graph.GraphFactory; |
| import org.eclipse.stem.core.graph.IntegrationLabel; |
| import org.eclipse.stem.core.graph.IntegrationLabelValue; |
| import org.eclipse.stem.core.graph.Node; |
| import org.eclipse.stem.core.graph.NodeLabel; |
| import org.eclipse.stem.core.model.STEMTime; |
| import org.eclipse.stem.definitions.labels.AreaLabel; |
| import org.eclipse.stem.definitions.labels.CommonBorderRelationshipLabelValue; |
| import org.eclipse.stem.definitions.labels.PopulationLabel; |
| import org.eclipse.stem.definitions.labels.RoadTransportRelationshipLabelValue; |
| import org.eclipse.stem.definitions.labels.impl.CommonBorderRelationshipLabelImpl; |
| import org.eclipse.stem.definitions.labels.impl.RoadTransportRelationshipLabelImpl; |
| import org.eclipse.stem.definitions.labels.impl.RoadTransportRelationshipLabelValueImpl; |
| import org.eclipse.stem.definitions.nodes.Region; |
| import org.eclipse.stem.diseasemodels.Activator; |
| import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabelValue; |
| import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModel; |
| import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModelLabel; |
| import org.eclipse.stem.diseasemodels.standard.StandardDiseaseModelLabelValue; |
| import org.eclipse.stem.diseasemodels.standard.StandardPackage; |
| import org.eclipse.stem.populationmodels.standard.StandardPopulationModelLabel; |
| |
| /** |
| * <!-- begin-user-doc --> An implementation of the model object ' |
| * <em><b>Disease Model</b></em>'. <!-- end-user-doc --> |
| * <p> |
| * The following features are implemented: |
| * <ul> |
| * <li>{@link org.eclipse.stem.diseasemodels.standard.impl.StandardDiseaseModelImpl#getReferencePopulationDensity <em>Reference Population Density</em>}</li> |
| * <li>{@link org.eclipse.stem.diseasemodels.standard.impl.StandardDiseaseModelImpl#getRoadNetworkInfectiousProportion <em>Road Network Infectious Proportion</em>}</li> |
| * <li>{@link org.eclipse.stem.diseasemodels.standard.impl.StandardDiseaseModelImpl#getCharacteristicMixingDistance <em>Characteristic Mixing Distance</em>}</li> |
| * </ul> |
| * </p> |
| * |
| * @generated |
| */ |
| public abstract class StandardDiseaseModelImpl extends DiseaseModelImpl |
| implements StandardDiseaseModel { |
| |
| /** |
| * The default value of the '{@link #getReferencePopulationDensity() <em>Reference Population Density</em>}' attribute. |
| * <!-- begin-user-doc |
| * --> <!-- end-user-doc --> |
| * @see #getReferencePopulationDensity() |
| * @generated |
| * @ordered |
| */ |
| protected static final double REFERENCE_POPULATION_DENSITY_EDEFAULT = 100.0; |
| |
| /** |
| * The cached value of the '{@link #getReferencePopulationDensity() <em>Reference Population Density</em>}' attribute. |
| * <!-- begin-user-doc |
| * --> <!-- end-user-doc --> |
| * @see #getReferencePopulationDensity() |
| * @generated |
| * @ordered |
| */ |
| protected double referencePopulationDensity = REFERENCE_POPULATION_DENSITY_EDEFAULT; |
| |
| /** |
| * The default value of the '{@link #getRoadNetworkInfectiousProportion() |
| * <em>Road Network Infectious Proportion</em>}' attribute. <!-- |
| * begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @see #getRoadNetworkInfectiousProportion() |
| * @generated |
| * @ordered |
| */ |
| protected static final double ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT = 0.01; |
| |
| /** |
| * The cached value of the '{@link #getRoadNetworkInfectiousProportion() |
| * <em>Road Network Infectious Proportion</em>}' attribute. <!-- |
| * begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @see #getRoadNetworkInfectiousProportion() |
| * @generated |
| * @ordered |
| */ |
| protected double roadNetworkInfectiousProportion = ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT; |
| |
| /** |
| * The default value of the '{@link #getCharacteristicMixingDistance() <em>Characteristic Mixing Distance</em>}' attribute. |
| * <!-- begin-user-doc |
| * --> <!-- end-user-doc --> |
| * @see #getCharacteristicMixingDistance() |
| * @generated |
| * @ordered |
| */ |
| protected static final double CHARACTERISTIC_MIXING_DISTANCE_EDEFAULT = 2.25; |
| |
| /** |
| * The cached value of the '{@link #getCharacteristicMixingDistance() <em>Characteristic Mixing Distance</em>}' attribute. |
| * <!-- begin-user-doc |
| * --> <!-- end-user-doc --> |
| * @see #getCharacteristicMixingDistance() |
| * @generated |
| * @ordered |
| */ |
| protected double characteristicMixingDistance = CHARACTERISTIC_MIXING_DISTANCE_EDEFAULT; |
| |
| /** |
| * Pool of label values used to reduce object creation. Key'd by the population identifier (different types of label values for different populations are possible) |
| */ |
| |
| protected HashMap<String, STEMObjectPool> labelValueObjectPools = new HashMap<String, STEMObjectPool>(); |
| |
| /** |
| * Pool of list to keep edges of certain type for a node |
| */ |
| |
| protected STEMObjectPool edgeListObjectPool = new STEMObjectPool(5, 5) { |
| |
| @Override |
| protected Object createNewObject() { |
| return new ArrayList<Edge>(); |
| } |
| |
| }; |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| protected StandardDiseaseModelImpl() { |
| super(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| protected EClass eStaticClass() { |
| return StandardPackage.Literals.STANDARD_DISEASE_MODEL; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| public double getReferencePopulationDensity() { |
| return referencePopulationDensity; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setReferencePopulationDensity( |
| double newReferencePopulationDensity) { |
| double oldReferencePopulationDensity = referencePopulationDensity; |
| referencePopulationDensity = newReferencePopulationDensity; |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY, oldReferencePopulationDensity, referencePopulationDensity)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| public double getRoadNetworkInfectiousProportion() { |
| return roadNetworkInfectiousProportion; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setRoadNetworkInfectiousProportion( |
| double newRoadNetworkInfectiousProportion) { |
| double oldRoadNetworkInfectiousProportion = roadNetworkInfectiousProportion; |
| roadNetworkInfectiousProportion = newRoadNetworkInfectiousProportion; |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION, oldRoadNetworkInfectiousProportion, roadNetworkInfectiousProportion)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| public double getCharacteristicMixingDistance() { |
| return characteristicMixingDistance; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setCharacteristicMixingDistance( |
| double newCharacteristicMixingDistance) { |
| double oldCharacteristicMixingDistance = characteristicMixingDistance; |
| characteristicMixingDistance = newCharacteristicMixingDistance; |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE, oldCharacteristicMixingDistance, characteristicMixingDistance)); |
| } |
| |
| |
| |
| /** |
| * calculateDelta will use the current label values updated by the disease |
| * model and upon return the delta label values are set with an estimate of |
| * the derivatives to advance to the next step |
| * |
| * @param time |
| * current time |
| * @param t |
| * The continuous time variable (specified by integrator) |
| * @param timeDelta |
| * delta time step |
| * @param labels |
| * The labels to update |
| */ |
| @Override |
| public void calculateDelta(STEMTime time, double t, long timeDelta, |
| EList<DynamicLabel> labels) { |
| |
| synchronized(this) { |
| if(labelValueObjectPools.size() == 0) |
| for(final String pop:this.getAllLabelIdentifiers()) { |
| labelValueObjectPools.put(pop, new STEMObjectPool(5, 5) { |
| |
| @Override |
| protected Object createNewObject() { |
| return StandardDiseaseModelImpl.this.createDiseaseModelLabelValue(pop); |
| } |
| }); |
| } |
| } |
| |
| // Iterate through each of the labels we need to update. |
| // Place holders to keep delta values. |
| |
| for(int i=0;i<labels.size();++i) { |
| //for (final Iterator<DynamicLabel> currentStateLabelIter = labels |
| // .iterator(); currentStateLabelIter.hasNext();) { |
| final StandardDiseaseModelLabel diseaseLabel = (StandardDiseaseModelLabel) labels.get(i); |
| |
| |
| assert diseaseLabel.getPopulationLabel().getPopulationIdentifier() |
| .equals(getPopulationIdentifier()); |
| |
| // This current state of the disease for this label probed for the |
| // next delta |
| |
| final StandardDiseaseModelLabelValue currentProbeState = (StandardDiseaseModelLabelValue) diseaseLabel |
| .getProbeValue(); |
| |
| // This is the delta disease label |
| final StandardDiseaseModelLabelValue deltaState = (StandardDiseaseModelLabelValue) diseaseLabel.getDeltaValue(); |
| |
| // Reset the state |
| deltaState.reset(); |
| |
| // Compute delta changes |
| computeDiseaseDeltas( |
| time, t, currentProbeState, diseaseLabel, timeDelta, |
| deltaState); |
| |
| |
| // 2) Set the departures |
| while(deltaState.getArrivals().size()>0) ExchangePool.POOL.release(deltaState.getArrivals().remove(0)); |
| while(deltaState.getDepartures().size()>0) ExchangePool.POOL.release(deltaState.getDepartures().remove(0)); |
| |
| if (deltaState.getDiseaseDeaths() > 0.0) { |
| Exchange deathExchange = (Exchange)ExchangePool.POOL.get(); |
| |
| deathExchange.setType(ExchangeType.BIRTHS_AND_DEATHS); |
| deathExchange |
| .setCount(deltaState.getDiseaseDeaths()); |
| deltaState.getDepartures().add(deathExchange); |
| |
| } |
| |
| } // for |
| } |
| |
| @Override |
| public void applyExternalDeltas(STEMTime time, double t, long timeDelta, |
| EList<DynamicLabel> labels) { |
| for(int i=0;i<labels.size();++i) { |
| //for (final Iterator<DynamicLabel> currentStateLabelIter = labels |
| // .iterator(); currentStateLabelIter.hasNext();) { |
| final StandardDiseaseModelLabel diseaseLabel = (StandardDiseaseModelLabel) labels.get(i); |
| |
| StandardDiseaseModelLabelValue myDelta = (StandardDiseaseModelLabelValue) diseaseLabel |
| .getDeltaValue(); |
| Node n = diseaseLabel.getNode(); |
| |
| // Find other labels on the node that wants to exchange data |
| |
| EList<NodeLabel> labs = n.getLabels(); |
| for(int j=0;j<labs.size();++j) { |
| NodeLabel l = labs.get(j); |
| if (l instanceof IntegrationLabel |
| && !l.equals(diseaseLabel) |
| && ((IntegrationLabel) l).getIdentifier().equals( |
| diseaseLabel.getIdentifier())) { |
| IntegrationLabelValue sdeLabelValue = (IntegrationLabelValue) ((IntegrationLabel) l) |
| .getDeltaValue(); |
| EList<Exchange> arrivals = sdeLabelValue.getArrivals(); |
| EList<Exchange> departures = sdeLabelValue.getDepartures(); |
| if (arrivals == null || departures == null) { |
| Activator.logError( |
| "Error, null arrivals or departures for label " |
| + l, new Exception()); |
| continue; |
| } |
| |
| // Arrivals |
| for(int k=0;k<arrivals.size();++k) { |
| Exchange entry = arrivals.get(k); |
| // for(Node n2:arrivals.keySet()) { |
| if (entry.getType() == ExchangeType.BIRTHS_AND_DEATHS) { |
| // Births go into the S state. |
| myDelta.setS(myDelta.getS() + entry.getCount()); |
| } else if (entry.getType() == ExchangeType.MIGRATION) { |
| double inflow = entry.getCount(); |
| // Find the corresponding disease label on the other |
| // node |
| Node otherNode = (Node) entry.getOtherLabel() |
| .getIdentifiable(); |
| for(int m=0;m<otherNode.getLabels().size();++m) { |
| NodeLabel nl = otherNode.getLabels().get(m); |
| if (nl instanceof StandardDiseaseModelLabel |
| && ((StandardDiseaseModelLabel) nl) |
| .getDecorator().equals(this) |
| && ((StandardDiseaseModelLabel) nl) |
| .getPopulationModelLabel() |
| .getPopulationIdentifier() |
| .equals(diseaseLabel |
| .getIdentifier())) { |
| String pop = diseaseLabel.getIdentifier(); |
| StandardDiseaseModelLabelValue value = (StandardDiseaseModelLabelValue)labelValueObjectPools.get(pop).get(); |
| value.set(((StandardDiseaseModelLabel) nl).getTempValue()); |
| |
| double factor = inflow / value.getPopulationCount(); |
| |
| if (!Double.isInfinite(factor) && !Double.isNaN(factor)) { |
| value.scale(factor); |
| } |
| |
| // Remember disease deaths since it'll be |
| // overwritten in the add |
| double diseaseDeaths = myDelta |
| .getDiseaseDeaths(); |
| myDelta.add((IntegrationLabelValue) value); |
| myDelta.setDiseaseDeaths(diseaseDeaths); |
| labelValueObjectPools.get(pop).release(value); |
| |
| } |
| } |
| } else if (entry.getType() == ExchangeType.AGING) { |
| // Find the disease label of the other age group |
| String otherAgeGroup = ((StandardPopulationModelLabel) entry |
| .getOtherLabel()).getPopulationIdentifier(); |
| |
| for(int m=0;m<labs.size();++m) { |
| NodeLabel nl = labs.get(m); |
| if (nl instanceof StandardDiseaseModelLabel) { |
| StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) nl; |
| |
| if (otherDiseaseLabel.getDecorator() |
| .equals(this) |
| && otherDiseaseLabel |
| .getIdentifier().equals( |
| otherAgeGroup)) { |
| String pop = otherDiseaseLabel.getIdentifier(); |
| StandardDiseaseModelLabelValue value = (StandardDiseaseModelLabelValue)labelValueObjectPools.get(pop).get(); |
| value.set(((StandardDiseaseModelLabel) nl).getTempValue()); |
| |
| if (value.getPopulationCount() > 0.0) { |
| value.scale(entry.getCount() |
| / value.getPopulationCount()); |
| } |
| |
| double diseaseDeaths = myDelta |
| .getDiseaseDeaths(); |
| myDelta.add((IntegrationLabelValue) value); |
| myDelta.setDiseaseDeaths(diseaseDeaths); |
| labelValueObjectPools.get(pop).release(value); |
| } |
| } |
| } |
| } |
| } |
| |
| // Departures |
| for(int k=0;k<departures.size();++k) { |
| Exchange entry = departures.get(k); |
| String pop = diseaseLabel.getIdentifier(); |
| // Departures are either deaths or population moving to |
| // other nodes, hence we substract from the local node. |
| |
| StandardDiseaseModelLabelValue currentState = null; |
| if (entry.getType() == ExchangeType.BIRTHS_AND_DEATHS |
| || entry.getType() == ExchangeType.AGING) { |
| currentState = (StandardDiseaseModelLabelValue)labelValueObjectPools.get(pop).get(); |
| currentState.set(((StandardDiseaseModelLabel) diseaseLabel).getProbeValue()); |
| } |
| else if (entry.getType() == ExchangeType.MIGRATION) { |
| currentState = (StandardDiseaseModelLabelValue)labelValueObjectPools.get(pop).get(); |
| currentState.set(((StandardDiseaseModelLabel) diseaseLabel).getTempValue()); |
| // Need to use |
| // temp value |
| // for migration |
| // or an |
| // inbalance |
| // will occyr |
| } |
| double populationCount = currentState |
| .getPopulationCount(); |
| |
| double outflow = entry.getCount(); |
| double factor = outflow / populationCount; |
| if (Double.isNaN(factor) || Double.isInfinite(factor)) |
| factor = 0.0; // safe |
| currentState.scale(factor); |
| // Remember disease deaths since they will be |
| // overwritten by sub |
| double diseaseDeaths = myDelta.getDiseaseDeaths(); |
| myDelta.sub((IntegrationLabelValue) currentState); |
| myDelta.setDiseaseDeaths(diseaseDeaths); |
| labelValueObjectPools.get(pop).release(currentState); |
| |
| } |
| } |
| |
| } |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public Object eGet(int featureID, boolean resolve, boolean coreType) { |
| switch (featureID) { |
| case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY: |
| return getReferencePopulationDensity(); |
| case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION: |
| return getRoadNetworkInfectiousProportion(); |
| case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE: |
| return getCharacteristicMixingDistance(); |
| } |
| return super.eGet(featureID, resolve, coreType); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public void eSet(int featureID, Object newValue) { |
| switch (featureID) { |
| case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY: |
| setReferencePopulationDensity((Double)newValue); |
| return; |
| case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION: |
| setRoadNetworkInfectiousProportion((Double)newValue); |
| return; |
| case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE: |
| setCharacteristicMixingDistance((Double)newValue); |
| return; |
| } |
| super.eSet(featureID, newValue); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public void eUnset(int featureID) { |
| switch (featureID) { |
| case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY: |
| setReferencePopulationDensity(REFERENCE_POPULATION_DENSITY_EDEFAULT); |
| return; |
| case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION: |
| setRoadNetworkInfectiousProportion(ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT); |
| return; |
| case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE: |
| setCharacteristicMixingDistance(CHARACTERISTIC_MIXING_DISTANCE_EDEFAULT); |
| return; |
| } |
| super.eUnset(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public boolean eIsSet(int featureID) { |
| switch (featureID) { |
| case StandardPackage.STANDARD_DISEASE_MODEL__REFERENCE_POPULATION_DENSITY: |
| return referencePopulationDensity != REFERENCE_POPULATION_DENSITY_EDEFAULT; |
| case StandardPackage.STANDARD_DISEASE_MODEL__ROAD_NETWORK_INFECTIOUS_PROPORTION: |
| return roadNetworkInfectiousProportion != ROAD_NETWORK_INFECTIOUS_PROPORTION_EDEFAULT; |
| case StandardPackage.STANDARD_DISEASE_MODEL__CHARACTERISTIC_MIXING_DISTANCE: |
| return characteristicMixingDistance != CHARACTERISTIC_MIXING_DISTANCE_EDEFAULT; |
| } |
| return super.eIsSet(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public String toString() { |
| if (eIsProxy()) return super.toString(); |
| |
| StringBuffer result = new StringBuffer(super.toString()); |
| result.append(" (referencePopulationDensity: "); //$NON-NLS-1$ |
| result.append(referencePopulationDensity); |
| result.append(", roadNetworkInfectiousProportion: "); //$NON-NLS-1$ |
| result.append(roadNetworkInfectiousProportion); |
| result.append(", characteristicMixingDistance: "); //$NON-NLS-1$ |
| result.append(characteristicMixingDistance); |
| result.append(')'); |
| return result.toString(); |
| } |
| |
| /** |
| * This method replaces the onsiteInfectious value with an |
| * effectiveInfectious population size based on mixing with neighboring |
| * sites. In this implementation the edges are bidirectional and have a |
| * fixed weight based on getPhysicallyAdjacentInfectiousProportion() (called |
| * in the helper method getInfectiousChangeFromMixing(). But the mixing is |
| * also weighted by the areas and populations of a site relative to the area |
| * and population of it's neighbors. Note that the value returned must be |
| * NORMALIZED by the total population because the product beta * S * |
| * Ieffective must have units of persons. Since S has units of persons the |
| * Ieffective must be dimensionless (normalized to the population). beta is |
| * the infection rate and has units of inverse time. |
| * |
| * @see org.eclipse.stem.diseasemodels.standard.SI.getNormalizedEffectiveInfectious |
| * @param node |
| * the node we are currently looking at to compute the next |
| * disease state |
| * @param diseaseLabel |
| * the label for the current disease computation |
| * @param onsiteInfectious |
| * the number of infectious people on site (at the node above) |
| * @param infectiousAttribute |
| * Attribute representing the infectious compartment |
| * @generated NOT |
| */ |
| public double getNormalizedEffectiveInfectious(final Node node, |
| final StandardDiseaseModelLabel diseaseLabel, |
| final double onsiteInfectious, EAttribute infectiousAttribute) { |
| double infectiousChangeFromMixing = 0.0; |
| double populationChangeFromMixing = 0.0; |
| |
| // For performance, check if mixing parameters are zero. If so, just |
| // return the unmixed result |
| |
| if(getCharacteristicMixingDistance() == 0.0 && getRoadNetworkInfectiousProportion() == 0.0) { |
| double totalPopulation = ((StandardDiseaseModelLabelValue) diseaseLabel |
| .getTempValue()).getPopulationCount(); |
| double retVal = 0.0; |
| |
| if (totalPopulation > 0.0) |
| retVal = onsiteInfectious / totalPopulation; |
| return retVal; |
| } |
| |
| List<Edge>cEdges = (List<Edge>)edgeListObjectPool.get(); |
| cEdges.clear(); |
| CommonBorderRelationshipLabelImpl.getCommonBorderEdgesFromNode(node, cEdges); |
| for(int i=0;i<cEdges.size();++i) { |
| Edge borderEdge = cEdges.get(i); |
| // If it exists, we're looking for the label this disease model |
| // updates on the node at the other end of the border edge. |
| // sum up the changes from each connected node. |
| // NOTE: some of these changes could be negative |
| |
| final Node otherNode = borderEdge.getOtherNode(node); |
| double borderLength = ((CommonBorderRelationshipLabelValue) borderEdge |
| .getLabel().getCurrentValue()).getBorderLength(); |
| |
| if (otherNode instanceof Region) { |
| double otherArea = 0.0; |
| double otherPopulation = 0.0; |
| double otherInfective = 0.0; |
| |
| EList<NodeLabel>labs = otherNode.getLabels(); |
| for(int j=0;j<labs.size();++j) { |
| NodeLabel otherLabel = labs.get(j); |
| if (otherLabel instanceof AreaLabel) { |
| otherArea = ((AreaLabel) otherLabel) |
| .getCurrentAreaValue().getArea(); |
| } else if (otherLabel instanceof StandardDiseaseModelLabel) { |
| StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) otherLabel; |
| |
| if (otherDiseaseLabel.getDecorator() == this |
| && otherDiseaseLabel.getIdentifier().equals( |
| diseaseLabel.getIdentifier())) { |
| otherPopulation = ((StandardDiseaseModelLabelValue) otherDiseaseLabel |
| .getTempValue()).getPopulationCount(); |
| |
| if (frequencyDependent) { |
| otherInfective = otherDiseaseLabel |
| .getTempValue().get( |
| infectiousAttribute); |
| } else { |
| // TODO |
| } |
| } |
| } |
| } |
| |
| double mixingFactor = Math.min(characteristicMixingDistance |
| * borderLength / otherArea, 1.0); |
| |
| if (otherArea == 0.0) { |
| mixingFactor = 0.0; |
| } |
| |
| infectiousChangeFromMixing += mixingFactor * otherInfective; |
| populationChangeFromMixing += mixingFactor * otherPopulation; |
| } |
| } // for each border edge |
| edgeListObjectPool.release(cEdges); |
| |
| List<Edge>rEdges = (List<Edge>)edgeListObjectPool.get(); |
| rEdges.clear(); |
| RoadTransportRelationshipLabelImpl.getRoadEdgesFromNode(node, rEdges); |
| for(int i=0;i<rEdges.size();++i) { |
| Edge roadEdge = rEdges.get(i); |
| // find the number of edges from the road edge - could be more than |
| // one |
| // also, roads have differenct capacities |
| EdgeLabel edgeLabel = roadEdge.getLabel(); |
| double numCrossings = ((RoadTransportRelationshipLabelValue) edgeLabel |
| .getCurrentValue()).getNumberCrossings(); |
| double infectiousProportion = Math.min( |
| roadNetworkInfectiousProportion * numCrossings, 1.0); |
| |
| // If it exists, we're looking for the label this disease model |
| // updates on the node at the other end of the border edge. |
| Node otherNode = roadEdge.getOtherNode(node); |
| double otherPopulation = 0.0; |
| double otherInfective = 0.0; |
| |
| EList<NodeLabel>labs = otherNode.getLabels(); |
| for(int j=0;j<labs.size();++j) { |
| NodeLabel otherLabel = labs.get(j); |
| if (otherLabel instanceof StandardDiseaseModelLabel) { |
| StandardDiseaseModelLabel otherDiseaseLabel = (StandardDiseaseModelLabel) otherLabel; |
| |
| if (otherDiseaseLabel.getDecorator() == this |
| && otherDiseaseLabel.getIdentifier().equals( |
| diseaseLabel.getIdentifier())) { |
| otherPopulation = ((StandardDiseaseModelLabelValue) otherDiseaseLabel |
| .getTempValue()).getPopulationCount(); |
| |
| if (frequencyDependent) { |
| otherInfective = otherDiseaseLabel |
| .getTempValue().get(infectiousAttribute); |
| } else { |
| // TODO |
| } |
| } |
| } |
| } |
| |
| infectiousChangeFromMixing += infectiousProportion * otherInfective; |
| populationChangeFromMixing += infectiousProportion |
| * otherPopulation; |
| } // for each road edge |
| |
| edgeListObjectPool.release(rEdges); |
| |
| // return the sum normalized to the total population |
| double totalPopulation = ((StandardDiseaseModelLabelValue) diseaseLabel |
| .getTempValue()).getPopulationCount() |
| + populationChangeFromMixing; |
| double retVal = 0.0; |
| |
| if (totalPopulation > 0.0) { |
| retVal = (onsiteInfectious + infectiousChangeFromMixing) |
| / totalPopulation; |
| } |
| |
| return retVal; |
| |
| } // getNormalizedEffectiveInfectious |
| |
| |
| /** |
| * @param populationLabel |
| * the population label that labels the node |
| * @return the area of the node associated with the label |
| */ |
| public double getArea(final PopulationLabel populationLabel) { |
| double retValue = 0.0; |
| |
| // The population label could have an area specified for the population |
| // that we should use instead of the area of the region labeled by the |
| // population label. This value would be specified if the population was |
| // densely packed into a small area of the larger region, for instance |
| // like a city in an otherwise large desert. |
| |
| retValue = populationLabel.getPopulatedArea(); |
| |
| // Is there an area specified for the population? |
| if (retValue == 0.0) { |
| // No |
| // Ok, go find the area label and return the area of the region |
| for (final Iterator<NodeLabel> labelIter = populationLabel |
| .getNode().getLabels().iterator(); labelIter.hasNext();) { |
| final NodeLabel nodeLabel = labelIter.next(); |
| // Is this an area label? |
| if (nodeLabel instanceof AreaLabel) { |
| // Yes |
| final AreaLabel areaLabel = (AreaLabel) nodeLabel; |
| retValue = areaLabel.getCurrentAreaValue().getArea(); |
| break; |
| } |
| } // for |
| } // If no population area specified |
| |
| return retValue; |
| } // getArea |
| |
| /** |
| * computeDiseaseDeltas. This method calculates the delta changes for each |
| * disease state depending on disease parameters and mixing factors |
| * |
| * @param time |
| * STEM time |
| * @param t |
| * Continuous time determined by integrator |
| * @param currentState |
| * the current state of the population |
| * @param diseaseLabel |
| * the disease label for which the state transitions are being |
| * computed. |
| * @param timeDelta |
| * the time period (milliseconds) over which the population |
| * members transition to new states |
| * @param cycle |
| * the simulation cycle we're in |
| * @return a disease state label value that contains the delta changes in |
| * population members for each state. |
| */ |
| |
| public abstract StandardDiseaseModelLabelValue computeDiseaseDeltas( |
| final STEMTime time, |
| final double t, |
| final StandardDiseaseModelLabelValue currentState, |
| final StandardDiseaseModelLabel diseaseLabel, final long timeDelta, |
| DiseaseModelLabelValue returnValue); |
| |
| } // StandardDiseaseModelImpl |