use of cbit.vcell.geometry.surface.SurfaceGeometricRegion in project vcell by virtualcell.
the class ClientRequestManager method createMathModel.
/**
* Insert the method's description here. Creation date: (5/24/2004 12:22:11 PM)
*
* @param windowID java.lang.String
*/
private MathModel createMathModel(String name, Geometry geometry) {
MathModel mathModel = new MathModel(null);
MathDescription mathDesc = mathModel.getMathDescription();
try {
mathDesc.setGeometry(geometry);
if (geometry.getDimension() == 0) {
mathDesc.addSubDomain(new CompartmentSubDomain("Compartment", CompartmentSubDomain.NON_SPATIAL_PRIORITY));
} else {
try {
if (geometry.getDimension() > 0 && geometry.getGeometrySurfaceDescription().getGeometricRegions() == null) {
geometry.getGeometrySurfaceDescription().updateAll();
}
} catch (ImageException e) {
e.printStackTrace(System.out);
throw new RuntimeException("Geometric surface generation error: \n" + e.getMessage());
} catch (GeometryException e) {
e.printStackTrace(System.out);
throw new RuntimeException("Geometric surface generation error: \n" + e.getMessage());
}
SubVolume[] subVolumes = geometry.getGeometrySpec().getSubVolumes();
for (int i = 0; i < subVolumes.length; i++) {
mathDesc.addSubDomain(new CompartmentSubDomain(subVolumes[i].getName(), subVolumes[i].getHandle()));
}
//
// add only those MembraneSubDomains corresponding to surfaces that acutally
// exist in geometry.
//
GeometricRegion[] regions = geometry.getGeometrySurfaceDescription().getGeometricRegions();
for (int i = 0; i < regions.length; i++) {
if (regions[i] instanceof SurfaceGeometricRegion) {
SurfaceGeometricRegion surfaceRegion = (SurfaceGeometricRegion) regions[i];
SubVolume subVolume1 = ((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[0]).getSubVolume();
SubVolume subVolume2 = ((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[1]).getSubVolume();
CompartmentSubDomain compartment1 = mathDesc.getCompartmentSubDomain(subVolume1.getName());
CompartmentSubDomain compartment2 = mathDesc.getCompartmentSubDomain(subVolume2.getName());
MembraneSubDomain membraneSubDomain = mathDesc.getMembraneSubDomain(compartment1, compartment2);
if (membraneSubDomain == null) {
SurfaceClass surfaceClass = geometry.getGeometrySurfaceDescription().getSurfaceClass(subVolume1, subVolume2);
membraneSubDomain = new MembraneSubDomain(compartment1, compartment2, surfaceClass.getName());
mathDesc.addSubDomain(membraneSubDomain);
}
}
}
}
mathDesc.isValid();
mathModel.setName(name);
} catch (Exception e) {
e.printStackTrace(System.out);
}
return mathModel;
}
use of cbit.vcell.geometry.surface.SurfaceGeometricRegion in project vcell by virtualcell.
the class GeomDbDriver method getSurfaceDescription.
/**
* Insert the method's description here.
* Creation date: (7/29/00 2:10:42 PM)
* @param con java.sql.Connection
* @param geom cbit.vcell.geometry.Geometry
*/
private void getSurfaceDescription(Connection con, Geometry geom) throws SQLException, DataAccessException {
// System.out.println(sql);
Statement stmt = con.createStatement();
try {
String sql = null;
//
// read sampleSize and filterFrequency from GeometrySurfaceTable.
//
sql = " SELECT " + geoSurfaceTable.getTableName() + ".* " + " FROM " + geoSurfaceTable.getTableName() + " WHERE " + geoSurfaceTable.geometryRef.getQualifiedColName() + " = " + geom.getVersion().getVersionKey();
if (lg.isTraceEnabled())
lg.trace(sql);
ResultSet rset = stmt.executeQuery(sql);
if (rset.next()) {
geoSurfaceTable.populateGeometrySurfaceDescription(rset, geom.getGeometrySurfaceDescription());
rset.close();
} else {
if (lg.isWarnEnabled()) {
lg.warn("surface description not found for geometry " + geom.getVersion().toString());
}
rset.close();
return;
}
//
// read volume regions from GeometricRegionTable
//
sql = " SELECT " + geoRegionTable.name.getQualifiedColName() + ", " + geoRegionTable.size.getQualifiedColName() + ", " + geoRegionTable.sizeUnit.getQualifiedColName() + ", " + geoRegionTable.subVolumeRef.getQualifiedColName() + ", " + geoRegionTable.regionID.getQualifiedColName() + " FROM " + geoRegionTable.getTableName() + " WHERE " + geoRegionTable.geometryRef.getQualifiedColName() + " = " + geom.getVersion().getVersionKey() + " AND " + geoRegionTable.type + " = " + GeometricRegionTable.TYPE_VOLUME;
if (lg.isTraceEnabled())
lg.trace(sql);
rset = stmt.executeQuery(sql);
Vector<GeometricRegion> regionList = new Vector<GeometricRegion>();
while (rset.next()) {
VolumeGeometricRegion volumeRegion = geoRegionTable.getVolumeRegion(rset, geom);
regionList.add(volumeRegion);
}
VolumeGeometricRegion[] volumeRegions = (VolumeGeometricRegion[]) BeanUtils.getArray(regionList, VolumeGeometricRegion.class);
//
// read surface regions from GeometricRegionTable
//
sql = " SELECT " + "surfTable." + geoRegionTable.name.getUnqualifiedColName() + ", " + "surfTable." + geoRegionTable.size.getUnqualifiedColName() + ", " + "surfTable." + geoRegionTable.sizeUnit.getUnqualifiedColName() + ", " + "vol1Table.name as " + GeometricRegionTable.VOLUME1_NAME_COLUMN + ", " + "vol2Table.name as " + GeometricRegionTable.VOLUME2_NAME_COLUMN + " " + " FROM " + geoRegionTable.getTableName() + " surfTable, " + geoRegionTable.getTableName() + " vol1Table, " + geoRegionTable.getTableName() + " vol2Table " + " WHERE surfTable." + geoRegionTable.geometryRef.getUnqualifiedColName() + " = " + geom.getVersion().getVersionKey() + " AND vol1Table.id = surfTable." + geoRegionTable.volRegion1.getUnqualifiedColName() + " AND vol2Table.id = surfTable." + geoRegionTable.volRegion2.getUnqualifiedColName() + " AND surfTable." + geoRegionTable.type.getUnqualifiedColName() + " = " + GeometricRegionTable.TYPE_SURFACE;
if (lg.isTraceEnabled())
lg.trace(sql);
rset = stmt.executeQuery(sql);
while (rset.next()) {
SurfaceGeometricRegion surfaceRegion = geoRegionTable.getSurfaceRegion(rset, volumeRegions, geom.getUnitSystem());
regionList.add(surfaceRegion);
}
//
// set regions onto the geometrySurfaceDescription
//
GeometricRegion[] regions = (GeometricRegion[]) BeanUtils.getArray(regionList, GeometricRegion.class);
geom.getGeometrySurfaceDescription().setGeometricRegions(regions);
} catch (Exception e) {
throw new DataAccessException(e.toString(), e);
} finally {
// Release resources include resultset
stmt.close();
}
}
use of cbit.vcell.geometry.surface.SurfaceGeometricRegion in project vcell by virtualcell.
the class GeomDbDriver method insertGeometrySurfaceDescriptionSQL.
/**
* This method was created in VisualAge.
* @param vcimage cbit.image.VCImage
* @param userid java.lang.String
* @exception java.rmi.RemoteException The exception description.
*/
// default access for this method, to allow retrofitting surfaces to geometries.
void insertGeometrySurfaceDescriptionSQL(InsertHashtable hash, Connection con, Geometry geom, KeyValue geomKey) throws SQLException, cbit.image.ImageException, DataAccessException, ObjectNotFoundException {
String sql;
GeometrySurfaceDescription geoSurfaceDescription = geom.getGeometrySurfaceDescription();
//
// store GeometrySurfaceDescription (sampleSize and filterFrequency for now)
//
KeyValue newGeomSurfDescKey = keyFactory.getNewKey(con);
sql = "INSERT INTO " + geoSurfaceTable.getTableName() + " " + geoSurfaceTable.getSQLColumnList() + " VALUES " + geoSurfaceTable.getSQLValueList(newGeomSurfDescKey, geoSurfaceDescription, geomKey);
// System.out.println(sql);
updateCleanSQL(con, sql);
//
// store GeometricRegions
//
GeometricRegion[] regions = geoSurfaceDescription.getGeometricRegions();
// }
if (regions == null) {
throw new DataAccessException("geometry '" + geom.getName() + " didn't have region information");
}
//
for (int i = 0; i < regions.length; i++) {
if (regions[i] instanceof VolumeGeometricRegion) {
VolumeGeometricRegion volumeRegion = (VolumeGeometricRegion) regions[i];
if (hash.getDatabaseKey(volumeRegion) == null) {
KeyValue newVolumeRegionKey = keyFactory.getNewKey(con);
KeyValue subvolumeKey = hash.getDatabaseKey(volumeRegion.getSubVolume());
sql = "INSERT INTO " + geoRegionTable.getTableName() + " " + geoRegionTable.getSQLColumnList() + " VALUES " + geoRegionTable.getSQLValueList(newVolumeRegionKey, volumeRegion, subvolumeKey, geomKey);
// System.out.println(sql);
updateCleanSQL(con, sql);
hash.put(volumeRegion, newVolumeRegionKey);
}
}
}
//
for (int i = 0; i < regions.length; i++) {
if (regions[i] instanceof SurfaceGeometricRegion) {
SurfaceGeometricRegion surfaceRegion = (SurfaceGeometricRegion) regions[i];
if (hash.getDatabaseKey(surfaceRegion) == null) {
KeyValue newSurfaceRegionKey = keyFactory.getNewKey(con);
KeyValue volumeRegion1Key = hash.getDatabaseKey((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[0]);
KeyValue volumeRegion2Key = hash.getDatabaseKey((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[1]);
sql = "INSERT INTO " + geoRegionTable.getTableName() + " " + geoRegionTable.getSQLColumnList() + " VALUES " + geoRegionTable.getSQLValueList(newSurfaceRegionKey, surfaceRegion, volumeRegion1Key, volumeRegion2Key, geomKey);
// System.out.println(sql);
updateCleanSQL(con, sql);
hash.put(surfaceRegion, newSurfaceRegionKey);
}
}
}
}
use of cbit.vcell.geometry.surface.SurfaceGeometricRegion in project vcell by virtualcell.
the class SmoldynFileWriter method writeSurfaces.
private void writeSurfaces() throws SolverException, ImageException, PropertyVetoException, GeometryException, ExpressionException {
GeometrySurfaceDescription geometrySurfaceDescription = resampledGeometry.getGeometrySurfaceDescription();
SurfaceClass[] surfaceClasses = geometrySurfaceDescription.getSurfaceClasses();
GeometrySpec geometrySpec = resampledGeometry.getGeometrySpec();
SubVolume[] surfaceGeometrySubVolumes = geometrySpec.getSubVolumes();
GeometricRegion[] AllGeometricRegions = resampledGeometry.getGeometrySurfaceDescription().getGeometricRegions();
ArrayList<SurfaceGeometricRegion> surfaceRegionList = new ArrayList<SurfaceGeometricRegion>();
ArrayList<VolumeGeometricRegion> volumeRegionList = new ArrayList<VolumeGeometricRegion>();
for (GeometricRegion geometricRegion : AllGeometricRegions) {
if (geometricRegion instanceof SurfaceGeometricRegion) {
surfaceRegionList.add((SurfaceGeometricRegion) geometricRegion);
} else if (geometricRegion instanceof VolumeGeometricRegion) {
volumeRegionList.add((VolumeGeometricRegion) geometricRegion);
} else {
throw new SolverException("unsupported geometric region type " + geometricRegion.getClass());
}
}
printWriter.println("# geometry");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.dim + " " + dimension);
if (bHasNoSurface) {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + surfaceGeometrySubVolumes.length);
} else {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + (surfaceGeometrySubVolumes.length + 1));
// plus the surface which are bounding walls
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_surface + " " + (surfaceClasses.length + dimension));
}
printWriter.println();
// write boundaries and wall surfaces
writeWallSurfaces();
// for 3D ... smoldyn normal convension is triangle right-hand-rule normal points to the outside compartment subdomain.
if (!bHasNoSurface) {
membraneSubdomainTriangleMap = new HashMap<MembraneSubDomain, ArrayList<TrianglePanel>>();
// write surfaces
printWriter.println("# surfaces");
int triangleGlobalCount = 0;
int membraneIndex = -1;
SurfaceCollection surfaceCollection = geometrySurfaceDescription.getSurfaceCollection();
// pre-allocate collections used repeatedly in following loops; clear before reusing
HashMap<Node, Set<String>> nodeTriMap = new HashMap<>();
ArrayList<TrianglePanel> triList = new ArrayList<TrianglePanel>();
// use a sorted set to ensure neighbors written out is same order for reproducibility
SortedSet<String> neighborsForCurrentNode = new TreeSet<String>();
for (int sci = 0; sci < surfaceClasses.length; sci++) {
nodeTriMap.clear();
triList.clear();
int triLocalCount = 0;
SurfaceClass surfaceClass = surfaceClasses[sci];
GeometricRegion[] geometricRegions = geometrySurfaceDescription.getGeometricRegions(surfaceClass);
for (GeometricRegion gr : geometricRegions) {
SurfaceGeometricRegion sgr = (SurfaceGeometricRegion) gr;
VolumeGeometricRegion volRegion0 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[0];
VolumeGeometricRegion volRegion1 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[1];
SubVolume subVolume0 = volRegion0.getSubVolume();
SubVolume subVolume1 = volRegion1.getSubVolume();
CompartmentSubDomain compart0 = mathDesc.getCompartmentSubDomain(subVolume0.getName());
CompartmentSubDomain compart1 = mathDesc.getCompartmentSubDomain(subVolume1.getName());
MembraneSubDomain membraneSubDomain = mathDesc.getMembraneSubDomain(compart0, compart1);
if (membraneSubDomain == null) {
throw new SolverException(VCellErrorMessages.getSmoldynUnexpectedSurface(compart0, compart1));
}
int exteriorRegionID = volRegion0.getRegionID();
int interiorRegionID = volRegion1.getRegionID();
if (membraneSubDomain.getInsideCompartment() == compart0) {
exteriorRegionID = volRegion1.getRegionID();
interiorRegionID = volRegion0.getRegionID();
}
for (int j = 0; j < surfaceCollection.getSurfaceCount(); j++) {
Surface surface = surfaceCollection.getSurfaces(j);
if ((surface.getInteriorRegionIndex() == exteriorRegionID && surface.getExteriorRegionIndex() == interiorRegionID) || (surface.getInteriorRegionIndex() == interiorRegionID && surface.getExteriorRegionIndex() == exteriorRegionID)) {
// Polygon polygon = surface.getPolygons(k);
for (Polygon polygon : surface) {
if (polygonMembaneElementMap != null) {
membraneIndex = polygonMembaneElementMap.get(polygon).getMembraneIndex();
}
Node[] nodes = polygon.getNodes();
if (dimension == 2) {
// ignore z
Vect3d unitNormal = new Vect3d();
polygon.getUnitNormal(unitNormal);
unitNormal.set(unitNormal.getX(), unitNormal.getY(), 0);
int point0 = 0;
Vect3d v0 = new Vect3d(nodes[point0].getX(), nodes[point0].getY(), 0);
int point1 = 1;
Vect3d v1 = null;
for (point1 = 1; point1 < nodes.length; point1++) {
if (v0.getX() != nodes[point1].getX() || v0.getY() != nodes[point1].getY()) {
v1 = new Vect3d(nodes[point1].getX(), nodes[point1].getY(), 0);
break;
}
}
if (v1 == null) {
throw new RuntimeException("failed to generate surface");
}
Vect3d v01 = Vect3d.sub(v1, v0);
Vect3d unit01n = v01.cross(unitNormal);
unit01n.unit();
if (Math.abs(unit01n.getZ() - 1.0) < 1e-6) {
// v0 to v1 opposes vcell surface normal. it's already flipped.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// we have to flipped it back
triangle = new Triangle(nodes[point1], nodes[point0], null);
} else {
triangle = new Triangle(nodes[point0], nodes[point1], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else if (Math.abs(unit01n.getZ() + 1.0) < 1e-6) {
// v0 to v1 is in direction of vcell surface normal.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
triangle = new Triangle(nodes[point0], nodes[point1], null);
} else {
triangle = new Triangle(nodes[point1], nodes[point0], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else {
throw new RuntimeException("failed to generate surface");
}
} else if (dimension == 3) {
Triangle triangle1;
Triangle triangle2;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// interior
triangle1 = new Triangle(nodes[0], nodes[1], nodes[2]);
triangle2 = new Triangle(nodes[0], nodes[2], nodes[3]);
} else {
triangle1 = new Triangle(nodes[2], nodes[1], nodes[0]);
triangle2 = new Triangle(nodes[3], nodes[2], nodes[0]);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle1));
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle2));
}
}
}
}
}
// add triangles to node hash
for (TrianglePanel triPanel : triList) {
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
Set<String> triNameSet = nodeTriMap.get(node);
if (triNameSet == null) {
triNameSet = new HashSet<String>();
nodeTriMap.put(node, triNameSet);
}
triNameSet.add(triPanel.name);
}
}
SubVolume[] adjacentSubvolums = surfaceClass.getAdjacentSubvolumes().toArray(new SubVolume[0]);
CompartmentSubDomain csd0 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[0].getName());
CompartmentSubDomain csd1 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[1].getName());
MembraneSubDomain membraneSubDomain = simulation.getMathDescription().getMembraneSubDomain(csd0, csd1);
membraneSubdomainTriangleMap.put(membraneSubDomain, triList);
final boolean initialMoleculesOnMembrane = (closestTriangles != null);
if (initialMoleculesOnMembrane) {
findClosestTriangles(membraneSubDomain, triList);
}
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.start_surface + " " + surfaceClass.getName());
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.action + " " + SmoldynVCellMapper.SmoldynKeyword.all + "(" + SmoldynVCellMapper.SmoldynKeyword.all + ") " + SmoldynVCellMapper.SmoldynKeyword.both + " " + SmoldynVCellMapper.SmoldynKeyword.reflect);
// printWriter.println(SmoldynKeyword.action + " " + SmoldynKeyword.all + "(" + SmoldynKeyword.up + ") " + SmoldynKeyword.both + " " + SmoldynKeyword.reflect);
// get color after species
Color c = colors[sci + particleVariableList.size()];
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.color + " " + SmoldynVCellMapper.SmoldynKeyword.both + " " + c.getRed() / 255.0 + " " + c.getGreen() / 255.0 + " " + c.getBlue() / 255.0 + " 0.1");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.front + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.back + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_panels + " " + SmoldynVCellMapper.SmoldynKeyword.tri + " " + triList.size());
for (TrianglePanel trianglePanel : triList) {
Triangle triangle = trianglePanel.triangle;
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.panel + " " + SmoldynVCellMapper.SmoldynKeyword.tri);
switch(dimension) {
case 1:
printWriter.print(" " + triangle.getNodes(0).getX());
break;
case 2:
printWriter.print(" " + triangle.getNodes(0).getX() + " " + triangle.getNodes(0).getY());
printWriter.print(" " + triangle.getNodes(1).getX() + " " + triangle.getNodes(1).getY());
break;
case 3:
for (Node node : triangle.getNodes()) {
printWriter.print(" " + node.getX() + " " + node.getY() + " " + node.getZ());
}
break;
}
printWriter.println(" " + trianglePanel.name);
}
for (TrianglePanel triPanel : triList) {
neighborsForCurrentNode.clear();
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
neighborsForCurrentNode.addAll(nodeTriMap.get(node));
}
neighborsForCurrentNode.remove(triPanel.name);
// printWriter.print(SmoldynKeyword.neighbors + " " +triPanel.name);
// to allow smoldyn read line length as 256, chop the neighbors to multiple lines
int maxNeighborCount = 4;
//
int count = 0;
for (String neigh : neighborsForCurrentNode) {
if (count % maxNeighborCount == 0) {
printWriter.println();
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.neighbors + " " + triPanel.name);
}
printWriter.print(" " + neigh);
count++;
}
}
printWriter.println();
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.end_surface);
printWriter.println();
}
// write compartment
// printWriter.println("# bounding wall compartment");
// printWriter.println(SmoldynKeyword.start_compartment + " " + VCellSmoldynKeyword.bounding_wall_compartment);
// printWriter.println(SmoldynKeyword.surface + " " + VCellSmoldynKeyword.bounding_wall_surface_X);
// if (dimension > 1) {
// printWriter.println(SmoldynKeyword.surface + " " + VCellSmoldynKeyword.bounding_wall_surface_Y);
// if (dimension > 2) {
// printWriter.println(SmoldynKeyword.surface + " " + VCellSmoldynKeyword.bounding_wall_surface_Z);
// }
// }
// printWriter.println(SmoldynKeyword.end_compartment);
// printWriter.println();
}
}
use of cbit.vcell.geometry.surface.SurfaceGeometricRegion in project vcell by virtualcell.
the class SmoldynSurfaceTessellator method writeSurfaces.
protected void writeSurfaces() throws SolverException, ImageException, PropertyVetoException, GeometryException, ExpressionException {
GeometrySurfaceDescription geometrySurfaceDescription = resampledGeometry.getGeometrySurfaceDescription();
SurfaceClass[] surfaceClasses = geometrySurfaceDescription.getSurfaceClasses();
GeometrySpec geometrySpec = resampledGeometry.getGeometrySpec();
SubVolume[] surfaceGeometrySubVolumes = geometrySpec.getSubVolumes();
GeometricRegion[] AllGeometricRegions = resampledGeometry.getGeometrySurfaceDescription().getGeometricRegions();
ArrayList<SurfaceGeometricRegion> surfaceRegionList = new ArrayList<SurfaceGeometricRegion>();
ArrayList<VolumeGeometricRegion> volumeRegionList = new ArrayList<VolumeGeometricRegion>();
for (GeometricRegion geometricRegion : AllGeometricRegions) {
if (geometricRegion instanceof SurfaceGeometricRegion) {
surfaceRegionList.add((SurfaceGeometricRegion) geometricRegion);
} else if (geometricRegion instanceof VolumeGeometricRegion) {
volumeRegionList.add((VolumeGeometricRegion) geometricRegion);
} else {
throw new SolverException("unsupported geometric region type " + geometricRegion.getClass());
}
}
printWriter.println("# geometry");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.dim + " " + dimension);
if (bHasNoSurface) {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + surfaceGeometrySubVolumes.length);
} else {
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_compartment + " " + (surfaceGeometrySubVolumes.length + 1));
// plus the surface which are bounding walls
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_surface + " " + (surfaceClasses.length + dimension));
}
printWriter.println();
// write boundaries and wall surfaces
writeWallSurfaces();
// for 3D ... smoldyn normal convension is triangle right-hand-rule normal points to the outside compartment subdomain.
if (!bHasNoSurface) {
membraneSubdomainTriangleMap = new HashMap<MembraneSubDomain, ArrayList<TrianglePanel>>();
// write surfaces
printWriter.println("# surfaces");
int triangleGlobalCount = 0;
int membraneIndex = -1;
SurfaceCollection surfaceCollection = geometrySurfaceDescription.getSurfaceCollection();
// pre-allocate collections used repeatedly in following loops; clear before reusing
HashMap<Node, Set<String>> nodeTriMap = new HashMap<>();
ArrayList<TrianglePanel> triList = new ArrayList<TrianglePanel>();
// use a sorted set to ensure neighbors written out is same order for reproducibility
SortedSet<String> neighborsForCurrentNode = new TreeSet<String>();
for (int sci = 0; sci < surfaceClasses.length; sci++) {
nodeTriMap.clear();
triList.clear();
int triLocalCount = 0;
SurfaceClass surfaceClass = surfaceClasses[sci];
GeometricRegion[] geometricRegions = geometrySurfaceDescription.getGeometricRegions(surfaceClass);
for (GeometricRegion gr : geometricRegions) {
SurfaceGeometricRegion sgr = (SurfaceGeometricRegion) gr;
VolumeGeometricRegion volRegion0 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[0];
VolumeGeometricRegion volRegion1 = (VolumeGeometricRegion) sgr.getAdjacentGeometricRegions()[1];
SubVolume subVolume0 = volRegion0.getSubVolume();
SubVolume subVolume1 = volRegion1.getSubVolume();
CompartmentSubDomain compart0 = mathDesc.getCompartmentSubDomain(subVolume0.getName());
CompartmentSubDomain compart1 = mathDesc.getCompartmentSubDomain(subVolume1.getName());
MembraneSubDomain membraneSubDomain = mathDesc.getMembraneSubDomain(compart0, compart1);
if (membraneSubDomain == null) {
throw new SolverException(VCellErrorMessages.getSmoldynUnexpectedSurface(compart0, compart1));
}
int exteriorRegionID = volRegion0.getRegionID();
int interiorRegionID = volRegion1.getRegionID();
if (membraneSubDomain.getInsideCompartment() == compart0) {
exteriorRegionID = volRegion1.getRegionID();
interiorRegionID = volRegion0.getRegionID();
}
for (int j = 0; j < surfaceCollection.getSurfaceCount(); j++) {
Surface surface = surfaceCollection.getSurfaces(j);
if ((surface.getInteriorRegionIndex() == exteriorRegionID && surface.getExteriorRegionIndex() == interiorRegionID) || (surface.getInteriorRegionIndex() == interiorRegionID && surface.getExteriorRegionIndex() == exteriorRegionID)) {
// Polygon polygon = surface.getPolygons(k);
for (Polygon polygon : surface) {
if (polygonMembaneElementMap != null) {
membraneIndex = polygonMembaneElementMap.get(polygon).getMembraneIndex();
}
Node[] nodes = polygon.getNodes();
if (dimension == 2) {
// ignore z
Vect3d unitNormal = new Vect3d();
polygon.getUnitNormal(unitNormal);
unitNormal.set(unitNormal.getX(), unitNormal.getY(), 0);
int point0 = 0;
Vect3d v0 = new Vect3d(nodes[point0].getX(), nodes[point0].getY(), 0);
int point1 = 1;
Vect3d v1 = null;
for (point1 = 1; point1 < nodes.length; point1++) {
if (v0.getX() != nodes[point1].getX() || v0.getY() != nodes[point1].getY()) {
v1 = new Vect3d(nodes[point1].getX(), nodes[point1].getY(), 0);
break;
}
}
if (v1 == null) {
throw new RuntimeException("failed to generate surface");
}
Vect3d v01 = Vect3d.sub(v1, v0);
Vect3d unit01n = v01.cross(unitNormal);
unit01n.unit();
if (Math.abs(unit01n.getZ() - 1.0) < 1e-6) {
// v0 to v1 opposes vcell surface normal. it's already flipped.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// we have to flipped it back
triangle = new Triangle(nodes[point1], nodes[point0], null);
} else {
triangle = new Triangle(nodes[point0], nodes[point1], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else if (Math.abs(unit01n.getZ() + 1.0) < 1e-6) {
// v0 to v1 is in direction of vcell surface normal.
Triangle triangle;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
triangle = new Triangle(nodes[point0], nodes[point1], null);
} else {
triangle = new Triangle(nodes[point1], nodes[point0], null);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle));
} else {
throw new RuntimeException("failed to generate surface");
}
} else if (dimension == 3) {
Triangle triangle1;
Triangle triangle2;
if (surface.getInteriorRegionIndex() == interiorRegionID) {
// interior
triangle1 = new Triangle(nodes[0], nodes[1], nodes[2]);
triangle2 = new Triangle(nodes[0], nodes[2], nodes[3]);
} else {
triangle1 = new Triangle(nodes[2], nodes[1], nodes[0]);
triangle2 = new Triangle(nodes[3], nodes[2], nodes[0]);
}
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle1));
triList.add(new TrianglePanel(triLocalCount++, triangleGlobalCount++, membraneIndex, triangle2));
}
}
}
}
}
// add triangles to node hash
for (TrianglePanel triPanel : triList) {
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
Set<String> triNameSet = nodeTriMap.get(node);
if (triNameSet == null) {
triNameSet = new HashSet<String>();
nodeTriMap.put(node, triNameSet);
}
triNameSet.add(triPanel.name);
}
}
SubVolume[] adjacentSubvolums = surfaceClass.getAdjacentSubvolumes().toArray(new SubVolume[0]);
CompartmentSubDomain csd0 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[0].getName());
CompartmentSubDomain csd1 = simulation.getMathDescription().getCompartmentSubDomain(adjacentSubvolums[1].getName());
MembraneSubDomain membraneSubDomain = simulation.getMathDescription().getMembraneSubDomain(csd0, csd1);
membraneSubdomainTriangleMap.put(membraneSubDomain, triList);
final boolean initialMoleculesOnMembrane = (closestTriangles != null);
if (initialMoleculesOnMembrane) {
findClosestTriangles(membraneSubDomain, triList);
}
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.start_surface + " " + surfaceClass.getName());
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.action + " " + SmoldynVCellMapper.SmoldynKeyword.all + "(" + SmoldynVCellMapper.SmoldynKeyword.all + ") " + SmoldynVCellMapper.SmoldynKeyword.both + " " + SmoldynVCellMapper.SmoldynKeyword.reflect);
// printWriter.println(SmoldynKeyword.action + " " + SmoldynKeyword.all + "(" + SmoldynKeyword.up + ") " + SmoldynKeyword.both + " " + SmoldynKeyword.reflect);
Color c = colorForSurface(sci);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.color + " " + SmoldynVCellMapper.SmoldynKeyword.both + " " + c.getRed() / 255.0 + " " + c.getGreen() / 255.0 + " " + c.getBlue() / 255.0 + " 0.1");
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.front + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.polygon + " " + SmoldynVCellMapper.SmoldynKeyword.back + " " + SmoldynVCellMapper.SmoldynKeyword.edge);
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.max_panels + " " + SmoldynVCellMapper.SmoldynKeyword.tri + " " + triList.size());
for (TrianglePanel trianglePanel : triList) {
Triangle triangle = trianglePanel.triangle;
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.panel + " " + SmoldynVCellMapper.SmoldynKeyword.tri);
switch(dimension) {
case 1:
printWriter.print(" " + triangle.getNodes(0).getX());
break;
case 2:
printWriter.print(" " + triangle.getNodes(0).getX() + " " + triangle.getNodes(0).getY());
printWriter.print(" " + triangle.getNodes(1).getX() + " " + triangle.getNodes(1).getY());
break;
case 3:
for (Node node : triangle.getNodes()) {
printWriter.print(" " + node.getX() + " " + node.getY() + " " + node.getZ());
}
break;
}
printWriter.println(" " + trianglePanel.name);
}
for (TrianglePanel triPanel : triList) {
neighborsForCurrentNode.clear();
for (Node node : triPanel.triangle.getNodes()) {
if (node == null) {
continue;
}
neighborsForCurrentNode.addAll(nodeTriMap.get(node));
}
neighborsForCurrentNode.remove(triPanel.name);
// printWriter.print(SmoldynKeyword.neighbors + " " +triPanel.name);
// to allow smoldyn read line length as 256, chop the neighbors to multiple lines
int maxNeighborCount = 4;
//
int count = 0;
for (String neigh : neighborsForCurrentNode) {
if (count % maxNeighborCount == 0) {
printWriter.println();
printWriter.print(SmoldynVCellMapper.SmoldynKeyword.neighbors + " " + triPanel.name);
}
printWriter.print(" " + neigh);
count++;
}
}
printWriter.println();
printWriter.println(SmoldynVCellMapper.SmoldynKeyword.end_surface);
printWriter.println();
}
}
}
Aggregations