use of cbit.vcell.math.JumpCondition in project vcell by virtualcell.
the class Xmlproducer method getXML.
/**
* This method returns a XML representation of a MembraneSubDomain object.
* Creation date: (3/2/2001 5:40:17 PM)
* @return Element
* @param param cbit.vcell.math.MembraneSubDomain
*/
private Element getXML(MembraneSubDomain param) throws XmlParseException {
Element membrane = new Element(XMLTags.MembraneSubDomainTag);
// Add attributes
membrane.setAttribute(XMLTags.NameAttrTag, mangle(param.getName()));
membrane.setAttribute(XMLTags.InsideCompartmentTag, mangle(param.getInsideCompartment().getName()));
membrane.setAttribute(XMLTags.OutsideCompartmentTag, mangle(param.getOutsideCompartment().getName()));
// Add boundaryType subelements
Element boundary;
// Xm
boundary = new Element(XMLTags.BoundaryTypeTag);
boundary.setAttribute(XMLTags.BoundaryAttrTag, XMLTags.BoundaryAttrValueXm);
boundary.setAttribute(XMLTags.BoundaryTypeAttrTag, param.getBoundaryConditionXm().boundaryTypeStringValue());
membrane.addContent(boundary);
// Xp
boundary = new Element(XMLTags.BoundaryTypeTag);
boundary.setAttribute(XMLTags.BoundaryAttrTag, XMLTags.BoundaryAttrValueXp);
boundary.setAttribute(XMLTags.BoundaryTypeAttrTag, param.getBoundaryConditionXp().boundaryTypeStringValue());
membrane.addContent(boundary);
// Ym
boundary = new Element(XMLTags.BoundaryTypeTag);
boundary.setAttribute(XMLTags.BoundaryAttrTag, XMLTags.BoundaryAttrValueYm);
boundary.setAttribute(XMLTags.BoundaryTypeAttrTag, param.getBoundaryConditionYm().boundaryTypeStringValue());
membrane.addContent(boundary);
// Yp
boundary = new Element(XMLTags.BoundaryTypeTag);
boundary.setAttribute(XMLTags.BoundaryAttrTag, XMLTags.BoundaryAttrValueYp);
boundary.setAttribute(XMLTags.BoundaryTypeAttrTag, param.getBoundaryConditionYp().boundaryTypeStringValue());
membrane.addContent(boundary);
// Zm
boundary = new Element(XMLTags.BoundaryTypeTag);
boundary.setAttribute(XMLTags.BoundaryAttrTag, XMLTags.BoundaryAttrValueZm);
boundary.setAttribute(XMLTags.BoundaryTypeAttrTag, param.getBoundaryConditionZm().boundaryTypeStringValue());
membrane.addContent(boundary);
// Zp
boundary = new Element(XMLTags.BoundaryTypeTag);
boundary.setAttribute(XMLTags.BoundaryAttrTag, XMLTags.BoundaryAttrValueZp);
boundary.setAttribute(XMLTags.BoundaryTypeAttrTag, param.getBoundaryConditionZp().boundaryTypeStringValue());
membrane.addContent(boundary);
// Add Equation subelements
Enumeration<Equation> enum1 = param.getEquations();
while (enum1.hasMoreElements()) {
Equation equ = enum1.nextElement();
membrane.addContent(getXML(equ));
}
// Add JumConditions
Enumeration<JumpCondition> enum2 = param.getJumpConditions();
while (enum2.hasMoreElements()) {
JumpCondition jc = (JumpCondition) enum2.nextElement();
membrane.addContent(getXML(jc));
}
// Add FastSystem (if there is)
if (param.getFastSystem() != null) {
membrane.addContent(getXML(param.getFastSystem()));
}
for (ParticleProperties pp : param.getParticleProperties()) {
membrane.addContent(getXML(pp));
}
for (ParticleJumpProcess pjp : param.getParticleJumpProcesses()) {
membrane.addContent(getXML(pjp));
}
Mutable<Element> velocity = new MutableObject<>();
addVelocityMaybe(velocity, XMLTags.XAttrTag, param.getVelocityX());
addVelocityMaybe(velocity, XMLTags.YAttrTag, param.getVelocityY());
if (velocity.getValue() != null) {
membrane.addContent(velocity.getValue());
}
return membrane;
}
use of cbit.vcell.math.JumpCondition in project vcell by virtualcell.
the class MathDescriptionCellRenderer method getTreeCellRendererComponent.
/**
* Insert the method's description here.
* Creation date: (7/27/2000 6:41:57 PM)
* @return java.awt.Component
*/
public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
JLabel component = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
boolean bLoaded = false;
//
try {
if (value instanceof BioModelNode) {
BioModelNode node = (BioModelNode) value;
if (node.getUserObject() instanceof PdeEquation) {
PdeEquation pdeEquation = (PdeEquation) node.getUserObject();
Variable var = pdeEquation.getVariable();
component.setToolTipText("PDE Equation");
// \u2207 = nabla ... del operator
// \u2219 = dot
String DEL = "\u2207";
// "\u2202"; // '\u2202' is partial differentiation 'd' is regular diff
String PARTIAL_DIFF = "d";
String Super2 = "\u00b2";
String DOT = "\u2219";
// String diffusionTerm = DEL+" "+DOT+" "+"("+pdeEquation.getDiffusionExpression()+" "+DEL+" "+var.getName()+")";
String diffusionTerm = "";
if (pdeEquation.getVelocityX() != null || pdeEquation.getVelocityY() != null || pdeEquation.getVelocityZ() != null) {
if (pdeEquation.getDiffusionExpression().isZero()) {
// reaction/advection
diffusionTerm = "- " + DEL + " " + DOT + "( velocity " + var.getName() + " )";
} else {
// reaction/diffusion/advection
diffusionTerm = DEL + " " + DOT + " (" + pdeEquation.getDiffusionExpression().infix() + " " + DEL + " " + var.getName() + " - velocity " + var.getName() + ")";
}
} else {
diffusionTerm = "(" + pdeEquation.getDiffusionExpression().infix() + ") " + DEL + Super2 + " " + var.getName();
}
String gradTerm = "";
if (pdeEquation.getGradientX() != null && !pdeEquation.getGradientX().isZero()) {
gradTerm += " + " + PARTIAL_DIFF + "[" + pdeEquation.getGradientX().infix() + "]/" + PARTIAL_DIFF + "x";
}
if (pdeEquation.getGradientY() != null && !pdeEquation.getGradientY().isZero()) {
gradTerm += " + " + PARTIAL_DIFF + "[" + pdeEquation.getGradientY().infix() + "]/" + PARTIAL_DIFF + "y";
}
if (pdeEquation.getGradientZ() != null && !pdeEquation.getGradientZ().isZero()) {
gradTerm += " + " + PARTIAL_DIFF + "[" + pdeEquation.getGradientZ().infix() + "]/" + PARTIAL_DIFF + "z";
}
String sourceTerm = pdeEquation.getRateExpression().infix();
if (!sourceTerm.equals("0.0")) {
component.setText(PARTIAL_DIFF + "[" + var.getName() + "]/" + PARTIAL_DIFF + "t = " + diffusionTerm + gradTerm + " + " + sourceTerm);
} else {
component.setText(PARTIAL_DIFF + "[" + var.getName() + "]/" + PARTIAL_DIFF + "t = " + diffusionTerm + gradTerm);
}
} else if (node.getUserObject() instanceof OdeEquation) {
OdeEquation odeEquation = (OdeEquation) node.getUserObject();
Variable var = odeEquation.getVariable();
component.setToolTipText("ODE Equation");
component.setText("d[" + var.getName() + "]/dt = " + odeEquation.getRateExpression().infix());
} else if (node.getUserObject() instanceof MembraneRegionEquation) {
MembraneRegionEquation membraneRegionEquation = (MembraneRegionEquation) node.getUserObject();
Variable var = membraneRegionEquation.getVariable();
component.setToolTipText("Membrane Region Equation");
component.setText("Membrane Region Equation for " + var.getName());
} else if (node.getUserObject() instanceof JumpCondition) {
JumpCondition jumpCondition = (JumpCondition) node.getUserObject();
Variable var = jumpCondition.getVariable();
component.setToolTipText("Jump Condition");
component.setText("Flux for " + var.getName());
} else if (node.getUserObject() instanceof Constant) {
Constant constant = (Constant) node.getUserObject();
component.setToolTipText("Constant");
component.setText(constant.getName() + " = " + constant.getExpression().infix());
} else if (node.getUserObject() instanceof Function) {
Function function = (Function) node.getUserObject();
component.setToolTipText("Function");
component.setText(function.getName() + " = " + function.getExpression().infix());
} else if (node.getUserObject() instanceof SubDomain) {
SubDomain subDomain = (SubDomain) node.getUserObject();
component.setToolTipText("SubDomain");
component.setText(subDomain.getName());
} else if (node.getUserObject() instanceof FastSystem) {
component.setToolTipText("Fast System");
component.setText("Fast System");
} else if (node.getUserObject() instanceof FastInvariant) {
FastInvariant fi = (FastInvariant) node.getUserObject();
component.setToolTipText("Fast Invariant");
component.setText("fast invariant: " + fi.getFunction().infix());
} else if (node.getUserObject() instanceof FastRate) {
FastRate fr = (FastRate) node.getUserObject();
component.setToolTipText("Fast Rate");
component.setText("fast rate: " + fr.getFunction().infix());
} else if (node.getUserObject() instanceof Annotation) {
Annotation annotation = (Annotation) node.getUserObject();
component.setToolTipText("Annotation");
component.setText("\"" + annotation + "\"");
} else {
}
if (selectedFont == null && component.getFont() != null) {
selectedFont = component.getFont().deriveFont(Font.BOLD);
}
if (unselectedFont == null && component.getFont() != null) {
unselectedFont = component.getFont().deriveFont(Font.PLAIN);
}
if (bLoaded) {
component.setFont(selectedFont);
} else {
component.setFont(unselectedFont);
}
}
} catch (Throwable e) {
e.printStackTrace(System.out);
}
//
return component;
}
use of cbit.vcell.math.JumpCondition in project vcell by virtualcell.
the class MathDescriptionTreeModel method createBaseTree.
/**
* Insert the method's description here.
* Creation date: (11/28/00 1:06:51 PM)
* @return cbit.vcell.desktop.BioModelNode
* @param docManager cbit.vcell.clientdb.DocumentManager
*/
private BioModelNode createBaseTree() {
if (getMathDescription() == null) {
return new BioModelNode(" ", false);
}
//
// make root node
//
BioModelNode rootNode = new BioModelNode("math description", true);
//
// create subTree of Constants
//
BioModelNode constantRootNode = new BioModelNode("constants", true);
Enumeration<Constant> enum1 = getMathDescription().getConstants();
while (enum1.hasMoreElements()) {
Constant constant = enum1.nextElement();
BioModelNode constantNode = new BioModelNode(constant, false);
constantRootNode.add(constantNode);
}
if (constantRootNode.getChildCount() > 0) {
rootNode.add(constantRootNode);
}
//
// create subTree of Functions
//
BioModelNode functionRootNode = new BioModelNode("functions", true);
Enumeration<Function> enum2 = getMathDescription().getFunctions();
while (enum2.hasMoreElements()) {
Function function = enum2.nextElement();
BioModelNode functionNode = new BioModelNode(function, false);
functionRootNode.add(functionNode);
}
if (functionRootNode.getChildCount() > 0) {
rootNode.add(functionRootNode);
}
//
// create subTree of VolumeSubDomains and MembraneSubDomains
//
BioModelNode volumeRootNode = new BioModelNode("volume domains", true);
BioModelNode membraneRootNode = new BioModelNode("membrane domains", true);
Enumeration<SubDomain> enum3 = getMathDescription().getSubDomains();
while (enum3.hasMoreElements()) {
SubDomain subDomain = enum3.nextElement();
if (subDomain instanceof cbit.vcell.math.CompartmentSubDomain) {
CompartmentSubDomain volumeSubDomain = (CompartmentSubDomain) subDomain;
BioModelNode volumeSubDomainNode = new BioModelNode(volumeSubDomain, true);
if (// stochastic subtree
getMathDescription().isNonSpatialStoch()) {
// add stoch variable initial conditions
BioModelNode varIniConditionNode = new BioModelNode("variable_initial_conditions", true);
for (VarIniCondition varIni : volumeSubDomain.getVarIniConditions()) {
BioModelNode varIniNode = new BioModelNode(varIni, false);
varIniConditionNode.add(varIniNode);
}
volumeSubDomainNode.add(varIniConditionNode);
// add jump processes
for (JumpProcess jp : volumeSubDomain.getJumpProcesses()) {
BioModelNode jpNode = new BioModelNode(jp, true);
// add probability rate.
String probRate = "P_" + jp.getName();
BioModelNode prNode = new BioModelNode("probability_rate = " + probRate, false);
jpNode.add(prNode);
// add Actions
Enumeration<Action> actions = Collections.enumeration(jp.getActions());
while (actions.hasMoreElements()) {
Action action = actions.nextElement();
BioModelNode actionNode = new BioModelNode(action, false);
jpNode.add(actionNode);
}
volumeSubDomainNode.add(jpNode);
}
} else // non-stochastic subtree
{
//
// add equation children
//
Enumeration<Equation> eqnEnum = volumeSubDomain.getEquations();
while (eqnEnum.hasMoreElements()) {
Equation equation = eqnEnum.nextElement();
BioModelNode equationNode = new BioModelNode(equation, false);
volumeSubDomainNode.add(equationNode);
}
//
// add fast system
//
FastSystem fastSystem = volumeSubDomain.getFastSystem();
if (fastSystem != null) {
BioModelNode fsNode = new BioModelNode(fastSystem, true);
Enumeration<FastInvariant> enumFI = fastSystem.getFastInvariants();
while (enumFI.hasMoreElements()) {
FastInvariant fi = enumFI.nextElement();
fsNode.add(new BioModelNode(fi, false));
}
Enumeration<FastRate> enumFR = fastSystem.getFastRates();
while (enumFR.hasMoreElements()) {
FastRate fr = enumFR.nextElement();
fsNode.add(new BioModelNode(fr, false));
}
volumeSubDomainNode.add(fsNode);
}
}
volumeRootNode.add(volumeSubDomainNode);
} else if (subDomain instanceof MembraneSubDomain) {
MembraneSubDomain membraneSubDomain = (MembraneSubDomain) subDomain;
BioModelNode membraneSubDomainNode = new BioModelNode(membraneSubDomain, true);
//
// add equation children
//
Enumeration<Equation> eqnEnum = membraneSubDomain.getEquations();
while (eqnEnum.hasMoreElements()) {
Equation equation = eqnEnum.nextElement();
BioModelNode equationNode = new BioModelNode(equation, false);
membraneSubDomainNode.add(equationNode);
}
//
// add jump condition children
//
Enumeration<JumpCondition> jcEnum = membraneSubDomain.getJumpConditions();
while (jcEnum.hasMoreElements()) {
JumpCondition jumpCondition = jcEnum.nextElement();
BioModelNode jcNode = new BioModelNode(jumpCondition, false);
membraneSubDomainNode.add(jcNode);
}
//
// add fast system
//
FastSystem fastSystem = membraneSubDomain.getFastSystem();
if (fastSystem != null) {
BioModelNode fsNode = new BioModelNode(fastSystem, true);
Enumeration<FastInvariant> enumFI = fastSystem.getFastInvariants();
while (enumFI.hasMoreElements()) {
FastInvariant fi = enumFI.nextElement();
fsNode.add(new BioModelNode(fi, false));
}
Enumeration<FastRate> enumFR = fastSystem.getFastRates();
while (enumFR.hasMoreElements()) {
FastRate fr = enumFR.nextElement();
fsNode.add(new BioModelNode(fr, false));
}
membraneSubDomainNode.add(fsNode);
}
membraneRootNode.add(membraneSubDomainNode);
}
}
if (volumeRootNode.getChildCount() > 0) {
rootNode.add(volumeRootNode);
}
if (membraneRootNode.getChildCount() > 0) {
rootNode.add(membraneRootNode);
}
return rootNode;
}
use of cbit.vcell.math.JumpCondition in project vcell by virtualcell.
the class FiniteVolumeFileWriter method writeMembrane_jumpConditions.
/**
*JUMP_CONDITION_BEGIN r
*INFLUX 0.0;
*OUTFLUX 0.0;
*JUMP_CONDITION_END
* @throws ExpressionException
* @throws MathException
*/
private void writeMembrane_jumpConditions(MembraneSubDomain msd) throws ExpressionException, MathException {
Enumeration<JumpCondition> enum1 = msd.getJumpConditions();
// equations for boundaryValues for inner compartment subdomain
CompartmentSubDomain innerCompSubDomain = msd.getInsideCompartment();
Enumeration<Equation> innercompSubDomEqnsEnum = innerCompSubDomain.getEquations();
while (innercompSubDomEqnsEnum.hasMoreElements()) {
Equation eqn = innercompSubDomEqnsEnum.nextElement();
if (eqn instanceof PdeEquation) {
PdeEquation pdeEqn = (PdeEquation) eqn;
BoundaryConditionValue boundaryValue = pdeEqn.getBoundaryConditionValue(msd.getName());
if (boundaryValue != null) {
// check if the type of BoundaryConditionSpec for this membraneSubDomain (msd) in the (inner) compartmentSubDomain is Flux; if not, it cannot be handled.
BoundaryConditionSpec bcs = innerCompSubDomain.getBoundaryConditionSpec(msd.getName());
if (bcs == null) {
throw new MathException("No Boundary type specified for '" + msd.getName() + "' in '" + innerCompSubDomain.getName() + "'.");
}
if (bcs != null && !bcs.getBoundaryConditionType().compareEqual(BoundaryConditionType.getNEUMANN()) && !bChomboSolver) {
throw new MathException("Boundary type '" + bcs.getBoundaryConditionType().boundaryTypeStringValue() + "' for compartmentSubDomain '" + innerCompSubDomain.getName() + "' not handled by the chosen solver. Expecting boundary condition of type 'Flux'.");
}
if (pdeEqn.getVariable().getDomain() == null || pdeEqn.getVariable().getDomain().getName().equals(msd.getInsideCompartment().getName())) {
printWriter.println("JUMP_CONDITION_BEGIN " + pdeEqn.getVariable().getName());
Expression flux = subsituteExpression(boundaryValue.getBoundaryConditionExpression(), VariableDomain.VARIABLEDOMAIN_MEMBRANE);
String infix = replaceVolumeVariable(getSimulationTask(), msd, flux);
printWriter.println(bcs.getBoundaryConditionType().boundaryTypeStringValue().toUpperCase() + " " + msd.getInsideCompartment().getName() + " " + infix + ";");
printWriter.println("JUMP_CONDITION_END");
printWriter.println();
}
}
}
}
// equations for boundaryValues for outer compartment subdomain
CompartmentSubDomain outerCompSubDomain = msd.getOutsideCompartment();
Enumeration<Equation> outerCompSubDomEqnsEnum = outerCompSubDomain.getEquations();
while (outerCompSubDomEqnsEnum.hasMoreElements()) {
Equation eqn = outerCompSubDomEqnsEnum.nextElement();
if (eqn instanceof PdeEquation) {
PdeEquation pdeEqn = (PdeEquation) eqn;
BoundaryConditionValue boundaryValue = pdeEqn.getBoundaryConditionValue(msd.getName());
if (boundaryValue != null) {
// check if the type of BoundaryConditionSpec for this membraneSubDomain (msd) in the (inner) compartmentSubDomain is Flux; if not, it cannot be handled.
BoundaryConditionSpec bcs = outerCompSubDomain.getBoundaryConditionSpec(msd.getName());
if (bcs != null && !bcs.getBoundaryConditionType().compareEqual(BoundaryConditionType.getNEUMANN()) && !bChomboSolver) {
throw new MathException("Boundary type '" + bcs.getBoundaryConditionType().boundaryTypeStringValue() + "' for compartmentSubDomain '" + outerCompSubDomain.getName() + "' not handled by the chosen solver. Expecting boundary condition of type 'Flux'.");
}
if (pdeEqn.getVariable().getDomain() == null || pdeEqn.getVariable().getDomain().getName().equals(msd.getOutsideCompartment().getName())) {
printWriter.println("JUMP_CONDITION_BEGIN " + pdeEqn.getVariable().getName());
Expression flux = subsituteExpression(boundaryValue.getBoundaryConditionExpression(), VariableDomain.VARIABLEDOMAIN_MEMBRANE);
String infix = replaceVolumeVariable(getSimulationTask(), msd, flux);
printWriter.println(bcs.getBoundaryConditionType().boundaryTypeStringValue().toUpperCase() + " " + msd.getOutsideCompartment().getName() + " " + infix + ";");
printWriter.println("JUMP_CONDITION_END");
printWriter.println();
}
}
}
}
while (enum1.hasMoreElements()) {
JumpCondition jc = enum1.nextElement();
printWriter.println("JUMP_CONDITION_BEGIN " + jc.getVariable().getName());
// influx
if (jc.getVariable().getDomain() == null || jc.getVariable().getDomain().getName().equals(msd.getInsideCompartment().getName())) {
Expression flux = subsituteExpression(jc.getInFluxExpression(), VariableDomain.VARIABLEDOMAIN_MEMBRANE);
String infix = replaceVolumeVariable(getSimulationTask(), msd, flux);
printWriter.println(BoundaryConditionType.NEUMANN_STRING.toUpperCase() + " " + msd.getInsideCompartment().getName() + " " + infix + ";");
}
if (jc.getVariable().getDomain() == null || jc.getVariable().getDomain().getName().equals(msd.getOutsideCompartment().getName())) {
// outflux
Expression flux = subsituteExpression(jc.getOutFluxExpression(), VariableDomain.VARIABLEDOMAIN_MEMBRANE);
String infix = replaceVolumeVariable(simTask, msd, flux);
printWriter.println(BoundaryConditionType.NEUMANN_STRING.toUpperCase() + " " + msd.getOutsideCompartment().getName() + " " + infix + ";");
}
printWriter.println("JUMP_CONDITION_END");
printWriter.println();
}
}
use of cbit.vcell.math.JumpCondition in project vcell by virtualcell.
the class ComsolModelBuilder method getVCCModel.
public static VCCModel getVCCModel(SimulationJob vcellSimJob) throws ExpressionException {
MathDescription vcellMathDesc = vcellSimJob.getSimulation().getMathDescription();
Geometry vcellGeometry = vcellMathDesc.getGeometry();
GeometrySpec vcellGeometrySpec = vcellGeometry.getGeometrySpec();
int vcellDim = vcellGeometrySpec.getDimension();
VCCModel model = new VCCModel("Model", vcellDim);
model.modelpath = "D:\\Developer\\eclipse\\workspace_refactor\\comsol_java\\src";
model.comments = "Untitled\n\n";
VCCModelNode comp1 = new VCCModelNode("comp1");
model.modelnodes.add(comp1);
// if (vcellDim != 2){
// throw new RuntimeException("expecting 2D simulation");
// }
//
// assume initial geometry is circle centered at 0.5, 0.5 of radius 0.3
//
// String comsolOutsideDomainName = "dif1";
// String comsolInsideDomainName = "c1";
VCCGeomSequence geom1 = new VCCGeomSequence("geom1", vcellDim);
model.geometrysequences.add(geom1);
VCCMeshSequence mesh1 = new VCCMeshSequence("mesh1", geom1);
model.meshes.add(mesh1);
VCCStudy std1 = new VCCStudy("std1");
model.study = std1;
TimeBounds timeBounds = vcellSimJob.getSimulation().getSolverTaskDescription().getTimeBounds();
TimeStep timeStep = vcellSimJob.getSimulation().getSolverTaskDescription().getTimeStep();
String beginTime = Double.toString(timeBounds.getStartingTime());
String endTime = Double.toString(timeBounds.getEndingTime());
String step = Double.toString(timeStep.getDefaultTimeStep());
VCCStudyFeature time = new VCCTransientStudyFeature("time", beginTime, step, endTime);
std1.features.add(time);
if (vcellGeometrySpec.getImage() != null) {
throw new RuntimeException("image-based geometries not yet supported by VCell's COMSOL model builder");
}
if (vcellGeometrySpec.getNumSubVolumes() == 0) {
throw new RuntimeException("no subvolumes defined in geometry");
}
if (vcellGeometrySpec.getNumAnalyticOrCSGSubVolumes() != vcellGeometrySpec.getNumSubVolumes()) {
throw new RuntimeException("only analytic and CSG subvolumes currently supported by VCell's COMSOL model builder");
}
//
// add geometry for all subvolumes
//
HashMap<String, VCCGeomFeature> subvolumeNameFeatureMap = new HashMap<String, VCCGeomFeature>();
SubVolume[] subVolumes = vcellGeometrySpec.getSubVolumes();
for (int i = 0; i < subVolumes.length; i++) {
SubVolume subvolume = subVolumes[i];
if (subvolume instanceof CSGObject) {
CSGObject vcellCSGObject = (CSGObject) subvolume;
CSGNode vcellCSGNode = vcellCSGObject.getRoot();
ArrayList<VCCGeomFeature> geomFeatureList = new ArrayList<VCCGeomFeature>();
VCCGeomFeature feature = csgVisitor(vcellCSGNode, geomFeatureList, subvolume.getName());
geom1.geomfeatures.addAll(geomFeatureList);
if (i == 0) {
// first subvolume (on top in ordinals) doesn't need any differencing
subvolumeNameFeatureMap.put(subvolume.getName(), feature);
} else {
// have to subtract union of prior subvolumes
ArrayList<VCCGeomFeature> priorFeatures = new ArrayList<VCCGeomFeature>();
for (int j = 0; j < i; j++) {
CSGObject priorCSGObject = (CSGObject) subVolumes[j];
CSGNode priorCSGNode = priorCSGObject.getRoot();
geomFeatureList.clear();
VCCGeomFeature priorFeature = csgVisitor(priorCSGNode, geomFeatureList, subvolume.getName());
priorFeatures.add(priorFeature);
geom1.geomfeatures.addAll(geomFeatureList);
}
VCCDifference diff = new VCCDifference("diff" + subvolume.getName(), Keep.off);
diff.input.add(feature);
diff.input2.addAll(priorFeatures);
geom1.geomfeatures.add(diff);
subvolumeNameFeatureMap.put(subvolume.getName(), diff);
}
} else {
throw new RuntimeException("only CSG subvolumes currently supported by VCell's COMSOL model builder");
}
}
//
// add geometry for all surfaceClasses
//
HashMap<String, VCCGeomFeature> surfaceclassNameFeatureMap = new HashMap<String, VCCGeomFeature>();
SurfaceClass[] surfaceClasses = vcellGeometry.getGeometrySurfaceDescription().getSurfaceClasses();
for (int i = 0; i < surfaceClasses.length; i++) {
SurfaceClass surfaceClass = surfaceClasses[i];
Set<SubVolume> adjacentSubvolumes = surfaceClass.getAdjacentSubvolumes();
if (adjacentSubvolumes.size() != 2) {
throw new RuntimeException("expecting two adjacent subvolumes for surface " + surfaceClass.getName() + " in COMSOL model builder");
}
// find adjacent Geometry Features (for subvolumes)
Iterator<SubVolume> svIter = adjacentSubvolumes.iterator();
SubVolume subvolume0 = svIter.next();
SubVolume subvolume1 = svIter.next();
ArrayList<VCCGeomFeature> adjacentFeatures = new ArrayList<VCCGeomFeature>();
adjacentFeatures.add(subvolumeNameFeatureMap.get(subvolume0.getName()));
adjacentFeatures.add(subvolumeNameFeatureMap.get(subvolume1.getName()));
String name = "inter_" + subvolume0.getName() + "_" + subvolume1.getName();
// surfaces are dimension N-1
int entitydim = vcellDim - 1;
VCCIntersectionSelection intersect_subvolumes = new VCCIntersectionSelection(name, entitydim);
intersect_subvolumes.input.addAll(adjacentFeatures);
geom1.geomfeatures.add(intersect_subvolumes);
surfaceclassNameFeatureMap.put(surfaceClass.getName(), intersect_subvolumes);
}
SimulationSymbolTable symbolTable = new SimulationSymbolTable(vcellSimJob.getSimulation(), vcellSimJob.getJobIndex());
//
for (SubDomain subDomain : Collections.list(vcellMathDesc.getSubDomains())) {
for (Equation equ : subDomain.getEquationCollection()) {
if (equ instanceof PdeEquation || equ instanceof OdeEquation) {
VCCGeomFeature geomFeature = null;
final int dim;
if (subDomain instanceof CompartmentSubDomain) {
geomFeature = subvolumeNameFeatureMap.get(subDomain.getName());
dim = vcellDim;
} else if (subDomain instanceof MembraneSubDomain) {
geomFeature = surfaceclassNameFeatureMap.get(subDomain.getName());
dim = vcellDim - 1;
} else {
throw new RuntimeException("subdomains of type '" + subDomain.getClass().getSimpleName() + "' not yet supported in COMSOL model builder");
}
if (geomFeature == null) {
throw new RuntimeException("cannot find COMSOL geometry feature named " + subDomain.getName() + " in COMSOL model builder");
}
VCCConvectionDiffusionEquation cdeq = new VCCConvectionDiffusionEquation("cdeq_" + equ.getVariable().getName(), geom1, geomFeature, dim);
cdeq.fieldName = equ.getVariable().getName();
cdeq.initial = MathUtilities.substituteModelParameters(equ.getInitialExpression(), symbolTable).flatten().infix();
cdeq.sourceTerm_f = MathUtilities.substituteModelParameters(equ.getRateExpression(), symbolTable).flatten().infix();
if (equ instanceof PdeEquation) {
PdeEquation pde = (PdeEquation) equ;
cdeq.diffTerm_c = MathUtilities.substituteModelParameters(pde.getDiffusionExpression(), symbolTable).flatten().infix();
if (subDomain instanceof CompartmentSubDomain) {
CompartmentSubDomain compartmentSubdomain = (CompartmentSubDomain) subDomain;
ArrayList<String> be = new ArrayList<String>();
if (pde.getVelocityX() != null) {
be.add(MathUtilities.substituteModelParameters(pde.getVelocityX(), symbolTable).flatten().infix());
} else {
be.add("0");
}
if (vcellDim >= 2) {
if (pde.getVelocityY() != null) {
be.add(MathUtilities.substituteModelParameters(pde.getVelocityY(), symbolTable).flatten().infix());
} else {
be.add("0");
}
}
if (vcellDim == 3) {
if (pde.getVelocityY() != null) {
be.add(MathUtilities.substituteModelParameters(pde.getVelocityZ(), symbolTable).flatten().infix());
} else {
be.add("0");
}
}
cdeq.advection_be = be.toArray(new String[vcellDim]);
//
// look for membrane boundary conditions for this variable
//
MembraneSubDomain[] membraneSubdomains = vcellMathDesc.getMembraneSubDomains(compartmentSubdomain);
for (MembraneSubDomain membraneSubdomain : membraneSubdomains) {
JumpCondition jumpCondition = membraneSubdomain.getJumpCondition((VolVariable) pde.getVariable());
if (jumpCondition != null) {
Expression fluxExpr = null;
if (membraneSubdomain.getInsideCompartment() == compartmentSubdomain) {
fluxExpr = jumpCondition.getInFluxExpression();
} else if (membraneSubdomain.getOutsideCompartment() == compartmentSubdomain) {
fluxExpr = jumpCondition.getOutFluxExpression();
}
String name = equ.getVariable().getName() + "_flux_" + membraneSubdomain.getName();
VCCGeomFeature selection = surfaceclassNameFeatureMap.get(membraneSubdomain.getName());
VCCFluxBoundary fluxBoundary = new VCCFluxBoundary(name, selection, vcellDim - 1);
fluxBoundary.flux_g = MathUtilities.substituteModelParameters(fluxExpr, symbolTable).flatten().infix();
cdeq.features.add(fluxBoundary);
}
}
}
}
model.physics.add(cdeq);
}
}
}
//
return model;
}
Aggregations