blob: 4d905a36bdf14b986fc4a901ae5190537b5acbc4 [file] [log] [blame]
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