diff --git a/pom.xml b/pom.xml
index a449560d1d..c03dbb0f75 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,7 @@
vcell-cli
vcell-rest
vcell-restclient
+ vcell-nativelib
diff --git a/vcell-nativelib/pom.xml b/vcell-nativelib/pom.xml
new file mode 100644
index 0000000000..c548fec056
--- /dev/null
+++ b/vcell-nativelib/pom.xml
@@ -0,0 +1,167 @@
+
+
+ 4.0.0
+
+ org.vcell
+ vcell-pom
+ 0.0.1-SNAPSHOT
+
+
+ vcell-nativelib
+
+
+ 23
+ 23
+ UTF-8
+ 0.10.4
+ ${java.specification.version}
+ ${java.specification.version}
+ sbml_to_fvsolver
+ org.vcell.pyvcell.SBMLSpatialTest
+
+
+
+
+ org.vcell
+ vcell-core
+ 0.0.1-SNAPSHOT
+ compile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.1
+
+
+ java
+
+ java
+
+
+ ${mainClass}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ ${maven.compiler.source}
+ ${maven.compiler.source}
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.3.0
+
+
+
+ true
+ ${mainClass}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.6.0
+
+
+ package
+
+ single
+
+
+
+
+
+
+ true
+ ${mainClass}
+
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
+
+
+ native
+
+
+
+ org.graalvm.buildtools
+ native-maven-plugin
+ ${native.maven.plugin.version}
+ true
+
+
+ build-native
+
+ compile-no-fork
+
+ package
+
+
+ test-native
+
+ test
+
+ test
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vcell-nativelib/src/main/java/org/vcell/Main.java b/vcell-nativelib/src/main/java/org/vcell/Main.java
new file mode 100644
index 0000000000..dcecd9c406
--- /dev/null
+++ b/vcell-nativelib/src/main/java/org/vcell/Main.java
@@ -0,0 +1,58 @@
+package org.vcell;
+
+import cbit.util.xml.VCLoggerException;
+import cbit.vcell.biomodel.BioModel;
+import cbit.vcell.mapping.MappingException;
+import cbit.vcell.mapping.SimulationContext;
+import cbit.vcell.parser.ExpressionException;
+import cbit.vcell.solver.Simulation;
+import cbit.vcell.solver.SolverException;
+import cbit.vcell.solver.TimeBounds;
+import cbit.vcell.solver.UniformOutputTimeSpec;
+import org.apache.logging.log4j.Logger;
+import org.vcell.sbml.SBMLFakeSpatialBioModel;
+import org.vcell.sbml.vcell.SBMLExporter;
+import org.vcell.sbml.vcell.SBMLImporter;
+
+import java.beans.PropertyVetoException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+public class Main {
+
+ private static Logger logger = org.apache.logging.log4j.LogManager.getLogger(Main.class);
+
+ public static void sbmlToFiniteVolumeInput(File sbmlFile, File outputDir) throws FileNotFoundException, MappingException, VCLoggerException, PropertyVetoException, SolverException, ExpressionException {
+ SBMLExporter.MemoryVCLogger vcl = new SBMLExporter.MemoryVCLogger();
+ boolean bValidateSBML = true;
+ InputStream is = new FileInputStream(sbmlFile);
+ SBMLImporter importer = new SBMLImporter(is, vcl, bValidateSBML);
+ BioModel bioModel = importer.getBioModel();
+ bioModel.updateAll(false);
+
+ final double duration = 5.0; // endpoint arg
+ final double time_step = 0.1; // endpoint arg
+ //final ISize meshSize = new ISize(10, 10, 10); // future endpoint arg
+ SimulationContext simContext = bioModel.getSimulationContext(0);
+ Simulation sim = new Simulation(simContext.getMathDescription(), simContext);
+ sim.getSolverTaskDescription().setTimeBounds(new TimeBounds(0.0, duration));
+ sim.getSolverTaskDescription().setOutputTimeSpec(new UniformOutputTimeSpec(time_step));
+
+ SBMLFakeSpatialBioModel.writeInputFilesOnly(outputDir, sim);
+ }
+
+
+
+
+ public static void main(String[] args) {
+ try {
+ File sbml_file = new File("/Users/jimschaff/Documents/workspace/vcell/vcell-rest/src/test/resources/TinySpacialProject_Application0.xml");
+ sbmlToFiniteVolumeInput(sbml_file, new File("/Users/jimschaff/Documents/workspace/vcell/vcell-rest/src/test/resources/"));
+ System.out.println("Hello, World!");
+ } catch (Exception e) {
+ logger.error("Error processing spatial model", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/vcell-nativelib/src/main/java/org/vcell/pyvcell/FiniteVolumeUtils.java b/vcell-nativelib/src/main/java/org/vcell/pyvcell/FiniteVolumeUtils.java
new file mode 100644
index 0000000000..e6b3d7f2fe
--- /dev/null
+++ b/vcell-nativelib/src/main/java/org/vcell/pyvcell/FiniteVolumeUtils.java
@@ -0,0 +1,4 @@
+package org.vcell.pyvcell;
+
+public class FiniteVolumeUtils {
+}
diff --git a/vcell-nativelib/src/test/java/org/vcell/pyvcell/SBMLSpatialTest.java b/vcell-nativelib/src/test/java/org/vcell/pyvcell/SBMLSpatialTest.java
new file mode 100644
index 0000000000..3cb37d26a7
--- /dev/null
+++ b/vcell-nativelib/src/test/java/org/vcell/pyvcell/SBMLSpatialTest.java
@@ -0,0 +1,143 @@
+package org.vcell.pyvcell;
+
+
+import cbit.vcell.biomodel.BioModel;
+import cbit.vcell.field.FieldDataIdentifierSpec;
+import cbit.vcell.mapping.SimulationContext;
+import cbit.vcell.messaging.server.SimulationTask;
+import cbit.vcell.parser.ExpressionException;
+import cbit.vcell.resource.PropertyLoader;
+import cbit.vcell.solver.*;
+import cbit.vcell.solvers.FVSolverStandalone;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Logger;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.vcell.sbml.vcell.SBMLExporter;
+import org.vcell.sbml.vcell.SBMLImporter;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+
+@Tag("SBML_IT")
+public class SBMLSpatialTest {
+
+ private static File workingDir;
+
+ public static class MyFiniteVolumeSolver extends FVSolverStandalone {
+ public MyFiniteVolumeSolver(SimulationTask simulationTask, File dataDir) throws SolverException {
+ super(simulationTask, dataDir, false);
+ }
+ @Override
+ public void initialize() throws SolverException {
+ super.initialize();
+ }
+ }
+
+ public static class SBMLSpatialSolver {
+
+ private static class TempSimulationJob extends SimulationJob {
+ public TempSimulationJob(TempSimulation argSim, int jobIndex, FieldDataIdentifierSpec[] argFDIS) {
+ super(argSim, jobIndex, argFDIS);
+ }
+ @Override
+ public TempSimulation getSimulation() {
+ return (TempSimulation)super.getSimulation();
+ }
+ }
+
+ public static void simulate(File workingDir, Simulation simulation) throws SolverException, ExpressionException {
+
+ TempSimulation tempSimulation = new TempSimulation(simulation,false);
+ tempSimulation.setSimulationOwner(simulation.getSimulationOwner());
+ TempSimulationJob tempSimulationJob = new TempSimulationJob(tempSimulation, 0, null);
+
+ SimulationTask simTask = new SimulationTask(tempSimulationJob, 0);
+ MyFiniteVolumeSolver solver = new MyFiniteVolumeSolver(simTask, workingDir);
+ solver.runSolver();
+ }
+
+ public static void writeInputFilesOnly(File workingDir, Simulation simulation) throws SolverException, ExpressionException {
+
+ TempSimulation tempSimulation = new TempSimulation(simulation,false);
+ tempSimulation.setSimulationOwner(simulation.getSimulationOwner());
+ TempSimulationJob tempSimulationJob = new TempSimulationJob(tempSimulation, 0, null);
+
+ SimulationTask simTask = new SimulationTask(tempSimulationJob, 0);
+ MyFiniteVolumeSolver solver = new MyFiniteVolumeSolver(simTask, workingDir);
+ solver.initialize();
+ }
+ }
+
+ @BeforeAll
+ public static void before() throws IOException {
+ PropertyLoader.setProperty(PropertyLoader.installationRoot, "..");
+ Logger.getLogger(SBMLExporter.class).addAppender(new ConsoleAppender());
+ // create temporary working directory
+ workingDir = Files.createTempDirectory("sbml-test-suite-working-dir-").toFile();
+ }
+
+ @AfterAll
+ public static void after() {
+ // delete temporary working directory
+ try {
+ Files.delete(workingDir.toPath());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static InputStream getFileFromResourceAsStream(String path) {
+ InputStream inputStream = SBMLSpatialTest.class.getResourceAsStream(path);
+ if (inputStream == null) {
+ throw new RuntimeException("file not found! " + path);
+ } else {
+ return inputStream;
+ }
+ }
+
+ @Test
+ public void testSbmlTestSuiteImport() throws Exception{
+ TLogger vcl = new TLogger();
+ InputStream testFileInputStream = getFileFromResourceAsStream("/TinySpacialProject_Application0.xml"); // endpoint arg
+ boolean bValidateSBML = true;
+ SBMLImporter importer = new SBMLImporter(testFileInputStream, vcl, bValidateSBML);
+ try {
+ BioModel bioModel = importer.getBioModel();
+ bioModel.updateAll(false);
+
+ final double duration = 5.0; // endpoint arg
+ final double time_step = 0.1; // endpoint arg
+ //final ISize meshSize = new ISize(10, 10, 10); // future endpoint arg
+ SimulationContext simContext = bioModel.getSimulationContext(0);
+ Simulation sim = new Simulation(simContext.getMathDescription(), simContext);
+ sim.getSolverTaskDescription().setTimeBounds(new TimeBounds(0.0, duration));
+ sim.getSolverTaskDescription().setOutputTimeSpec(new UniformOutputTimeSpec(time_step));
+
+ System.out.println("INPUT FILES ONLY");
+ SBMLSpatialSolver.writeInputFilesOnly(workingDir, sim);
+ printWorkingDir();
+
+ System.out.println("ALL FILES INCLUDING OUTPUT");
+ SBMLSpatialSolver.simulate(workingDir, sim);
+ printWorkingDir();
+
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ private static void printWorkingDir() {
+ // print contents of workingDir
+ File[] files = workingDir.listFiles();
+ for (File file : files) {
+ System.out.println(file.getName());
+ }
+ }
+
+}
+
diff --git a/vcell-nativelib/src/test/java/org/vcell/pyvcell/TLogger.java b/vcell-nativelib/src/test/java/org/vcell/pyvcell/TLogger.java
new file mode 100644
index 0000000000..a86e8044b7
--- /dev/null
+++ b/vcell-nativelib/src/test/java/org/vcell/pyvcell/TLogger.java
@@ -0,0 +1,37 @@
+package org.vcell.pyvcell;
+
+import cbit.util.xml.VCLogger;
+import cbit.util.xml.VCLoggerException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TLogger extends VCLogger {
+ public final List highPriority = new ArrayList<>();
+ public final List medPriority = new ArrayList<>();
+ public final List lowPriority = new ArrayList<>();
+
+ @Override
+ public boolean hasMessages() {
+ return false;
+ }
+
+ @Override
+ public void sendAllMessages() {
+ }
+
+ @Override
+ public void sendMessage(Priority p, ErrorType et, String message)
+ throws VCLoggerException {
+ String msg = p + " " + et + ": " + message;
+ if (p == Priority.HighPriority) {
+ highPriority.add(msg);
+ } else if (p == Priority.MediumPriority) {
+ medPriority.add(msg);
+ } else if (p == Priority.LowPriority) {
+ lowPriority.add(msg);
+ }
+ System.err.println(p + " " + et + ": " + message);
+ }
+
+}
\ No newline at end of file
diff --git a/vcell-nativelib/src/test/resources/TinySpacialProject_Application0.xml b/vcell-nativelib/src/test/resources/TinySpacialProject_Application0.xml
new file mode 100644
index 0000000000..51a2a9d86d
--- /dev/null
+++ b/vcell-nativelib/src/test/resources/TinySpacialProject_Application0.xml
@@ -0,0 +1,239 @@
+
+
+
+
+ Exported by VCell 7.3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vcell-rest/src/test/resources/SimID_1784145872_0_.functions b/vcell-rest/src/test/resources/SimID_1784145872_0_.functions
new file mode 100644
index 0000000000..badda39958
--- /dev/null
+++ b/vcell-rest/src/test/resources/SimID_1784145872_0_.functions
@@ -0,0 +1,10 @@
+##---------------------------------------------
+## /Users/jimschaff/Documents/workspace/vcell/vcell-rest/src/test/resources/SimID_1784145872_0_.functions
+##---------------------------------------------
+
+subdomain0::J_r0; (s0 - (0.5 * s1)); ; Volume_VariableType; false
+subdomain0::s0_init_umol_l_1; (100000.0 * x); ; Volume_VariableType; false
+subdomain0::s1_init_umol_l_1; (10.0 - (100000.0 * x)); ; Volume_VariableType; false
+subdomain0::Size_c0; vcRegionVolume('subdomain0'); ; Volume_Region_VariableType; false
+subdomain0::vobj_subdomain00_size; vcRegionVolume('subdomain0'); ; Volume_Region_VariableType; false
+
diff --git a/vcell-rest/src/test/resources/SimID_1784145872_0_.fvinput b/vcell-rest/src/test/resources/SimID_1784145872_0_.fvinput
new file mode 100644
index 0000000000..407e4ef4bb
--- /dev/null
+++ b/vcell-rest/src/test/resources/SimID_1784145872_0_.fvinput
@@ -0,0 +1,51 @@
+# Simulation Parameters
+SIMULATION_PARAM_BEGIN
+SOLVER SUNDIALS_PDE_SOLVER 1.0E-7 1.0E-9 0.1
+BASE_FILE_NAME /Users/jimschaff/Documents/workspace/vcell/vcell-rest/src/test/resources/SimID_1784145872_0_
+ENDING_TIME 5.0
+TIME_STEP 0.1
+KEEP_EVERY 1
+SIMULATION_PARAM_END
+
+# Model description: FEATURE name handle boundary_conditions
+MODEL_BEGIN
+FEATURE subdomain0 0 flux flux
+MODEL_END
+
+# Mesh file
+MESH_BEGIN
+VCG_FILE /Users/jimschaff/Documents/workspace/vcell/vcell-rest/src/test/resources/SimID_1784145872_0_.vcg
+MESH_END
+
+# Variables : type name domain time_dependent_flag advection_flag grad_flag solve_whole_mesh_flag solve_regions
+VARIABLE_BEGIN
+VOLUME_PDE s0 subdomain0 false false false false subdomain0
+VOLUME_PDE s1 subdomain0 false false false false subdomain0
+VARIABLE_END
+
+POST_PROCESSING_BLOCK_BEGIN
+POST_PROCESSING_BLOCK_END
+
+COMPARTMENT_BEGIN subdomain0
+
+EQUATION_BEGIN s0
+INITIAL (100000.0 * x);
+RATE - (s0 - (0.5 * s1));
+DIFFUSION 1.0E-9;
+VELOCITY_X 0.0;
+BOUNDARY_XM 0.0;
+BOUNDARY_XP 0.0;
+EQUATION_END
+
+EQUATION_BEGIN s1
+INITIAL (10.0 - (100000.0 * x));
+RATE (s0 - (0.5 * s1));
+DIFFUSION 1.0E-9;
+VELOCITY_X 0.0;
+BOUNDARY_XM 0.0;
+BOUNDARY_XP 0.0;
+EQUATION_END
+
+COMPARTMENT_END
+
+
diff --git a/vcell-rest/src/test/resources/SimID_1784145872_0_.subdomains b/vcell-rest/src/test/resources/SimID_1784145872_0_.subdomains
new file mode 100644
index 0000000000..da35e333bd
--- /dev/null
+++ b/vcell-rest/src/test/resources/SimID_1784145872_0_.subdomains
@@ -0,0 +1,3 @@
+# CompartmentSubDomain name, handle
+# MembraneSubDomain name, inside compartment name, handle, outside compartment name, handle
+CompartmentSubDomain, subdomain0, 0
diff --git a/vcell-rest/src/test/resources/SimID_1784145872_0_.vcg b/vcell-rest/src/test/resources/SimID_1784145872_0_.vcg
new file mode 100644
index 0000000000..d8118ab316
--- /dev/null
+++ b/vcell-rest/src/test/resources/SimID_1784145872_0_.vcg
@@ -0,0 +1,10 @@
+name spatialGeom
+dimension 1
+size 10.0
+origin 0.0
+volumeRegions 1
+subdomain00 10.0 0
+membraneRegions 0
+volumeSamples 200
+789C636018058309000001900001
+cells 0