— Agostino De Marco, University of Naples Federico II
JPAD stands for Java Program toolchain for Aircraft Designers. JPAD is a Java software library containing classes and utility functions that can be used to build software systems. Typically, these are calculation programs providing aerodynamic and performance predictions for given aircraft designs.
JPAD is open source and its public repository is on GitHub.
This Jupyter notebook uses the BeakerX Java kernel. The purpose is demonstrating:
Let us print the current directory content. We are Java users, so let start using Java in our first code cell to this purpose:
import java.nio.file.*;
Files.list(Paths.get("."))
.forEach(System.out::println);
This notebook is named Test_JPAD_2.ipynb
. The jar
subdirectory contains the two Jar files
JPADConfigs_DDMM2018.jar
JPADCore_v2_DDMM2018.jar
where JPAD is bundled, and all the Jar's that JPAD depends upon.
In addition, the The lib
subdirectory contains all the native libraries (Win64) needed for JPAD to work correctly.
The BeakerX kernel for this notebook is launched on Windows with the following beakerx-jpad.bat
file:
setlocal
set PATH=%PATH%;.\lib;.\jar;
set JUPYTER_RUNTIME_DIR=%JUPYTER_RUNTIME_DIR%;.\lib
set JUPYTER_EXEC="beakerx"
%JUPYTER_EXEC%
It adds lib
and jar
directories to the PATH
environment variables as well as to the JUPYTER_RUNTIME_DIR
. Then, it runs Jupyter with the beakerx
command. Once Jupyter with the BeakerX kernel is set up and running, the notebook file can be opened and executed.
The following cell uses BeakerX magic command %classpath
that directs the Java kernel to include all the Jar files located in the path ./jar
. The command %classpath
alone prints out all the included Jars.
%classpath add jar .\jar\*
%classpath
The native libs stored in the ./lib
directory are listed by the following code cell.
import java.nio.file.*;
Files.list(Paths.get("./lib")) // a stream of paths
.map(path -> path.toString().toLowerCase())
.filter(name -> name.matches("([^\\s]+(\\.(?i)(lib|dll))$)")) // use regex
.forEach(System.out::println);
At this point we can start using the JPAD API functions.
The following are BeakerX magics, a bunch of %import
commands that make a set of Java packages globally visible by all the subsequent code cells.
%import java.io.File
%import java.io.IOException
%import java.io.OutputStream
%import java.io.PrintStream
%import java.nio.file.Path
%import java.nio.file.Paths
%import java.nio.file.Files
%import java.util.ArrayList
%import java.util.List
%import java.util.stream.Collectors
%import javax.measure.quantity.*
%import javax.measure.unit.SI
%import javax.measure.unit.NonSI
%import org.jscience.physics.amount.Amount
%import org.apache.poi.openxml4j.exceptions.InvalidFormatException
%import ncsa.hdf.hdf5lib.exceptions.HDF5LibraryException
%import configuration.*
%import configuration.enumerations.*
%import aircraft.*
%import aircraft.components.*
%import aircraft.components.FuelTank
%import aircraft.components.fuselage.*
%import aircraft.components.liftingSurface.*
%import aircraft.components.liftingSurface.creator.*
%import aircraft.components.nacelles.*
%import aircraft.components.powerplant.*
// TODO: analyses
// TODO: cad
%import calculators.*
%import calculators.aerodynamics.*
%import calculators.balance.*
%import calculators.costs.*
%import calculators.geometry.*
%import calculators.performance.*
%import calculators.stability.*
%import calculators.weights.*
%import database.*
%import database.databasefunctions.*
%import database.databasefunctions.aerodynamics.*
%import database.databasefunctions.aerodynamics.fusDes.*
%import database.databasefunctions.aerodynamics.vedsc.*
%import database.databasefunctions.engine.*
%import standaloneutils.*
%import standaloneutils.atmosphere.*
%import standaloneutils.cpacs.*
%import standaloneutils.customdata.*
%import standaloneutils.database.*
%import standaloneutils.jsbsim.*
%import standaloneutils.launchers.*
%import standaloneutils.mathtools.*
%import standaloneutils.aerotools.*
%import standaloneutils.aircraft.*
%import writers.*
JPADTest
¶We will read the input file ../in/aircraft_IRON_NEW.xml
that defines a specific aircraft design named IRON. The following image is a top view of this airplane.
To do so we create a package named test.jpad
that wraps a test class named JPADTest
. Objects of this class incorporate the paths to all the files necessary for JPAD to work correctly.
package test.jpad;
public class JPADTest {
public String pathToXML;
public String aircraftFileName;
public String dirAirfoil;
public String dirFuselages;
public String dirLiftingSurfaces;
public String dirEngines;
public String dirNacelles;
public String dirLandingGears;
public String dirCabinConfiguration;
public String databaseFolderPath;
public String inputFolderPath;
public String outputFolderPath;
public AerodynamicDatabaseReader aeroDatabaseReader;
public HighLiftDatabaseReader highLiftDatabaseReader;
public FusDesDatabaseReader fusDesDatabaseReader;
public VeDSCDatabaseReader veDSCDatabaseReader;
public Aircraft aircraft; // the main recipient object
public JPADTest(String fileName) {
aircraftFileName = fileName;
System.out.println("--------------------------");
System.out.println("Initialize JPADTest");
System.out.println("--------------------------");
MyConfiguration.setDir(
FoldersEnum.DATABASE_DIR,
Paths.get("../data").toString()
);
MyConfiguration.setDir(
FoldersEnum.INPUT_DIR,
Paths.get("../in").toString()
);
MyConfiguration.setDir(
FoldersEnum.OUTPUT_DIR,
Paths.get("../out").toString()
);
String aerodynamicDatabaseFileName = "Aerodynamic_Database_Ultimate.h5";
String highLiftDatabaseFileName = "HighLiftDatabase.h5";
String fusDesDatabaseFilename = "FusDes_database.h5";
String vedscDatabaseFilename = "VeDSC_database.h5";
databaseFolderPath = MyConfiguration.getDir(FoldersEnum.DATABASE_DIR);
inputFolderPath = MyConfiguration.getDir(FoldersEnum.INPUT_DIR);
outputFolderPath = MyConfiguration.getDir(FoldersEnum.OUTPUT_DIR);
System.out.println("Database dir: " + databaseFolderPath);
System.out.println("Input dir: " + inputFolderPath);
System.out.println("Output dir: " + outputFolderPath);
aeroDatabaseReader = DatabaseManager.initializeAeroDatabase(
new AerodynamicDatabaseReader(
databaseFolderPath,
aerodynamicDatabaseFileName
),
databaseFolderPath
);
highLiftDatabaseReader = DatabaseManager.initializeHighLiftDatabase(
new HighLiftDatabaseReader(
databaseFolderPath,
highLiftDatabaseFileName),
databaseFolderPath
);
fusDesDatabaseReader = DatabaseManager.initializeFusDes(
new FusDesDatabaseReader(
databaseFolderPath,
fusDesDatabaseFilename),
databaseFolderPath
);
veDSCDatabaseReader = DatabaseManager.initializeVeDSC(
new VeDSCDatabaseReader(
databaseFolderPath,
vedscDatabaseFilename),
databaseFolderPath
);
pathToXML = inputFolderPath + "/" + aircraftFileName;
dirAirfoil = inputFolderPath + "/lifting_surfaces/airfoils";
dirFuselages = inputFolderPath + "/fuselages";
dirLiftingSurfaces = inputFolderPath + "/lifting_surfaces";
dirEngines = inputFolderPath + "/engines";
dirNacelles = inputFolderPath + "/nacelles";
dirLandingGears = inputFolderPath + "/landing_gears";
dirCabinConfiguration = inputFolderPath + "/cabin_configurations";
// atmosphere = AtmosphereCalc.getAtmosphere(1000.);
System.out.println("--------------------------");
System.out.println("Initialization done");
System.out.println("--------------------------");
try {
System.out.println("--------------------------");
System.out.println("Aircraft import");
System.out.println("--------------------------");
aircraft = Aircraft.importFromXML(
this.pathToXML,
this.dirLiftingSurfaces,
this.dirFuselages,
this.dirEngines,
this.dirNacelles,
this.dirLandingGears,
this.dirCabinConfiguration,
this.dirAirfoil,
this.aeroDatabaseReader,
this.highLiftDatabaseReader,
this.fusDesDatabaseReader,
this.veDSCDatabaseReader
);
} catch (Throwable t) {
t.printStackTrace();
throw t;
}
}
}
JPADTest
: getting the shape of some airfoils¶For the sake of simplicity, the class JPADTest
has public member variables. Some of them are of types provided by the JPAD API. The class constructor JPADTest()
defines the paths of all auxiliary input files and directories and takes as an input variable the name of the aircraft definition file (a file in XML format).
The following code cell defines an object test
of type JPADTest
, that incorporates all the necessary definitions to read the IRON aircraft design. The object test
is initialized by passing the main aircraft definition file stored ../in/aircraft_IRON_NEW.xml
The test
object has a public member variable aircraft
of type Aircraft
, which is populated with all the necessary data at construction time. The object test.aircraft
models the chosen aircraft design.
package test.jpad;
import aircraft.components.liftingSurface.airfoils.*;
final PrintStream originalOut = System.out;
PrintStream filterStream = new PrintStream(
new OutputStream() {
public void write(int b) {
// write nothing
}
});
Path pathToAirfoilsSVG = Paths.get("./images/IRON-airfoils.svg");
Path pathToAircraftTopViewSVG = Paths.get("./images/IRON-aircraft-topview.svg");
Path pathToAircraftSideViewSVG = Paths.get("./images/IRON-aircraft-sideview.svg");
System.setOut(filterStream); // deactivating System.out
JPADTest test = new JPADTest("aircraft_IRON_NEW.xml");
System.setOut(originalOut); // reactivating System.out
Airfoil airfoil0 = test.aircraft
.getWing().getLiftingSurfaceCreator().getAirfoilList().get(0);
Airfoil airfoil1 = test.aircraft
.getHTail().getLiftingSurfaceCreator().getAirfoilList().get(0);
boolean status = standaloneutils.aircraft.WriteUtils
.writeAirfoilsToSVG(pathToAirfoilsSVG.toString(), "IRON wing/htail airfoils", new Airfoil[]{airfoil0, airfoil1});
System.out.println("--------------------------");
if (status)
System.out.println("File " + pathToAirfoilsSVG.toString() + " created.");
else
System.out.println("No airfoil file created.");
status = standaloneutils.aircraft.WriteUtils
.writeAircraftTopViewToSVG(pathToAircraftTopViewSVG.toString(), "IRON aircraft top view", test.aircraft);
System.out.println("--------------------------");
if (status)
System.out.println("File " + pathToAircraftTopViewSVG.toString() + " created.");
else
System.out.println("No aircraft-topview file created.");
status = standaloneutils.aircraft.WriteUtils
.writeAircraftSideViewToSVG(pathToAircraftSideViewSVG.toString(), "IRON aircraft side view", test.aircraft);
System.out.println("--------------------------");
if (status)
System.out.println("File " + pathToAircraftSideViewSVG.toString() + " created.");
else
System.out.println("No aircraft-sideview file created.");
return status;
The above cell produces some SVG files which are shown below:
And the top view of the aircraft:
And the side view of the aircraft: