In order to execute the individual solver runs, we are going to employ the mini batch processor, for running the calculations on the local machine. We also have to initialize the workflow management system and create a database.
Note:
convStudy.ipynb
.
One can directly load this into Jupyter to interactively work with the following code examples.BoSSSpad.dll
is required.
You must either set #r "BoSSSpad.dll"
to something which is appropirate for your computer
(e.g. C:\Program Files (x86)\FDY\BoSSS\bin\Release\net5.0\BoSSSpad.dll
if you installed the binary distribution),
or, if you are working with the source code, you must compile BoSSSpad
and put it side-by-side to this worksheet file
(from the original location in the repository, you can use the scripts getbossspad.sh
, resp. getbossspad.bat
).#r "BoSSSpad.dll"
//#r "C:\Users\flori\Documents\BoSSS-kdev2\public\src\L4-application\BoSSSpad\bin\Debug\net6.0\BoSSSpad.dll"
using System;
using System.Collections.Generic;
using System.Linq;
using ilPSP;
using ilPSP.Utils;
using BoSSS.Platform;
using BoSSS.Foundation;
using BoSSS.Foundation.Grid;
using BoSSS.Foundation.Grid.Classic;
using BoSSS.Foundation.IO;
using BoSSS.Solution;
using BoSSS.Solution.Control;
using BoSSS.Solution.GridImport;
using BoSSS.Solution.Statistic;
using BoSSS.Solution.Utils;
using BoSSS.Solution.Gnuplot;
using BoSSS.Application.BoSSSpad;
using BoSSS.Application.XNSE_Solver;
using static BoSSS.Application.BoSSSpad.BoSSSshell;
Init();
using NUnit.Framework;
BoSSSshell.WorkflowMgm.Init("ConvStudyTutorial");
Project name is set to 'ConvStudyTutorial'. Default Execution queue is chosen for the database. Creating database '\\fdygitrunner\BoSSStests\ConvStudyTutorial'.
// In previous versions, it was required to explicitly create a temporary or permanent database;
// This is not required anymore, since the workflow management automatically creates a default database.
//var db = CreateTempDatabase();
The following (deactivated) line would delete all Sessions (i.e. solver runs) which correspond to this project from the database. Hence, on every execution of the worksheet, all simulations would be re-done.
Normally, without the following line, existing simulations from the database will be used; therefore, it is save to close and open the worksheet.
This is handy e.g. when simulations are running on a cluster for a long time, and we usually don't want to re-submit the calculation every time we execute the worksheet.
BoSSSshell.WorkflowMgm.Sessions.ForEach(si => si.Delete(true));
For sake of simplicity, we employ the Poisson solver ipPoisson which is just a benchmarking application, but sufficient for the purpose of this tutorial.
using BoSSS.Application.SipPoisson;
We create multiple grids using resolutions of $2 \times 2$, $4 \times 4$ to $32 \times 32$ cells:
int[] resolutions = new int[] { 2, 4, 8, 16, 32};
var grids = new GridCommons[resolutions.Length];
for(int iRes = 0; iRes < resolutions.Length; iRes++) {
// create nodes:
var Nodes = GenericBlas.Linspace(-Math.PI*0.5, Math.PI*0.5,
resolutions[iRes] + 1); // note: number of nodes = number of cells + 1!
// create grid:
GridCommons grd_i = Grid2D.Cartesian2DGrid(Nodes, Nodes);
// define all boundaries as Dirichlet:
grd_i.EdgeTagNames.Add(1, BoundaryType.Dirichlet.ToString());
grd_i.DefineEdgeTags(delegate (double[] X) {
byte ret = 1;
return ret;
});
// save grid in database
wmg.DefaultDatabase.SaveGrid(ref grd_i);
// remenber reference to grid:
grids[iRes] = grd_i;
}
Grid Edge Tags changed. Grid Edge Tags changed. Grid Edge Tags changed. Grid Edge Tags changed. Grid Edge Tags changed.
First, we implement the exact expressions for the right-hand-side $$ f(x,y)= -2\cos(x)\cos(y)$$ and the exact solution. $$ u_{sol} (x,y)=\cos(x) \cos(y) $$
The exact solution will be used to compute the error of the simulation. Normally, the exact solution is not known; in those cases, we need to compute the experimental convergence against the solution on the finest grid.
string formula_code =
"static class Expressions { " +
" public static double RHS(double[] X) { " +
" double x = X[0]; " +
" double y = X[1]; " +
" return -2.0*Math.Cos(x)*Math.Cos(y); " +
" } " +
" public static double Tex(double[] X) { " +
" double x = X[0]; " +
" double y = X[1]; " +
" return Math.Cos(x)*Math.Cos(y); " +
" } " +
"}";
var RHSfunc = new Formula("Expressions.RHS", false, formula_code);
var TexFunc = new Formula("Expressions.Tex", false, formula_code);
We compute 4 different polynomial orders:
int[] Degrees = new int[] {1, 2, 3, 4};
Setup of all runs...
var Runs = new List<SipControl>();
Runs.Clear(); // start with an empty run list
foreach(int pDeg in Degrees) { // loop over polynomial degrees
foreach(var grd in grids) { // loop over all grids
// create object and remember in list:
SipControl C = new SipControl();
Runs.Add(C);
// set polynomial degree and grid:
C.SetDGdegree(pDeg);
C.SetGrid(grd);
// specify RHS and exact solution (these are realized as initial values
// in the \code{ipPoisson} solver:
C.AddInitialValue("RHS", RHSfunc);
C.AddInitialValue("Tex", TexFunc);
// specify boundary condition:
C.AddBoundaryValue(BoundaryType.Dirichlet.ToString()); // for homogeneous
// boundary conditions, we don not need a value, since the default value
// zero is sufficient.
// the exact solution is a speciality of the SIP Poisson benchmark solver;
// in order to evaluate the exact solution, we have to set the following
// boolean:
C.ExactSolution_provided = true;
}
}
// In the following, we check the correctness of the `Equals`-method for `SipControl`;
// This tutorial is part of the BoSSS test suit, the following is not required for the functionality of the example.
int NC = Runs.Count;
for(int i = 0; i < NC; i++) {
for(int j = 0; j < NC; j++) {
if(i == j)
Assert.IsTrue(Runs[i].Equals(Runs[j]), "Control is not self-equal");
else
Assert.IsFalse(Runs[i].Equals(Runs[j]), "Different Control are wrongly equal");
}
}
...and activate them:
foreach(var C in Runs)
C.RunBatch(); // runs in the default execution queue
Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_1 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002818.701004 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_2 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002830.815379 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_3 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002841.527967 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_4 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002853.637430 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_5 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002905.874054 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_6 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002920.577318 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_7 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002932.702928 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_8 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_002947.346628 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_9 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003002.099461 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_10 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003023.674608 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_11 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003044.795192 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_12 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003105.279816 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_13 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003126.541270 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_14 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003145.724791 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_15 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003209.772458 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_16 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003234.373152 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_17 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003258.723782 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_18 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003323.111218 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_19 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003344.957684 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished. Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_20 ... Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\ConvStudyTutorial-ipPoisson2023Dec05_003407.164401 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished.
The following line ensures that all jobs are complete before post-processing analysis is started, although, there is a one-hour (3600-seconds ) time-out.
BoSSSshell.WorkflowMgm.BlockUntilAllJobsTerminate(3600*4);
All jobs finished.
Note that, in a larger production run study, where jobs may run days or weeks, blocking the worksheet is not really usefull. Instead, one might split process into two workseets (eactly at this line here), one for set-up and job sumbission and another one for the analysis.
BoSSSshell.WorkflowMgm.AllJobs
#0: UnnamedJob_1: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_1: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #1: UnnamedJob_2: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_2: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #2: UnnamedJob_3: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_3: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #3: UnnamedJob_4: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_4: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #4: UnnamedJob_5: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_5: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #5: UnnamedJob_6: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_6: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #6: UnnamedJob_7: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_7: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #7: UnnamedJob_8: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_8: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #8: UnnamedJob_9: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_9: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #9: UnnamedJob_10: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_10: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #10: UnnamedJob_11: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_11: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #11: UnnamedJob_12: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_12: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #12: UnnamedJob_13: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_13: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #13: UnnamedJob_14: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_14: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #14: UnnamedJob_15: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_15: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #15: UnnamedJob_16: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_16: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #16: UnnamedJob_17: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_17: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #17: UnnamedJob_18: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_18: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #18: UnnamedJob_19: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_19: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) #19: UnnamedJob_20: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests) UnnamedJob_20: FinishedSuccessful (MS HPC client MSHPC-AllNodes-test @DC2, @\\fdygitrunner\BoSSStests)
We can take a closer inspection of anything that failed (should not be, anyway).
foreach(var job in BoSSSshell.WorkflowMgm.AllJobs.Values) {
if(job.Status != JobStatus.FinishedSuccessful) {
Console.WriteLine("###############################################");
Console.WriteLine($"Job {job}");
Console.WriteLine("###############################################");
Console.WriteLine(job.Stdout);
Console.WriteLine("===============================================");
Console.WriteLine(job.Stderr);
Console.WriteLine("###############################################");
}
}
As already noted, the computation of the $L^2$ error against the exact solution is handled specially in the ipPoisson solver. However, the following tutorial can serve as a general template of how to extract data from the session table and visualize it.
We aquire a copy of the session table, and from all the columns in there...
var Tab = BoSSSshell.WorkflowMgm.SessionTable;
Tab.GetColumnNames().Take(7) // Take(7) is just to shorten the output. There are a total of 86 ColumnNames.
index | value |
---|---|
0 | ProjectName |
1 | SessionName |
2 | DGdegree:T |
3 | DGdegree:Tex |
4 | Bndtype:Dirichlet |
5 | TimesteppingMode |
6 | GeneratedFromCode |
...we extract those which sound interesting:
Tab = Tab.ExtractColumns(
//"SessionName",
"DGdegree:T", "Grid:NoOfCells", "Grid:hMin", "DOFs",
//"ExactSolution_provided",
"SolL2err");
Tab.Print();
DGdegree:T Grid:NoOfCells Grid:hMin DOFs SolL2err 0: 4 1024 0.0981747704246807 15360 4.193309289152585E-09 1: 4 256 0.19634954084936185 3840 1.349148434699243E-07 2: 4 64 0.39269908169872414 960 4.384872822370366E-06 3: 4 16 0.7853981633974483 240 0.00014578074462366728 4: 4 4 1.5707963267948966 60 0.004890481980291057 5: 3 1024 0.0981747704246807 10240 3.395884553914282E-07 6: 3 256 0.19634954084936185 2560 5.600208133623587E-06 7: 3 64 0.39269908169872414 640 9.937069092458554E-05 8: 3 16 0.7853981633974483 160 0.0019432545281115033 9: 3 4 1.5707963267948966 40 0.03377668103207887 10: 2 1024 0.0981747704246807 6144 2.5727368042089585E-05 11: 2 256 0.19634954084936185 1536 0.00022565400197291664 12: 2 64 0.39269908169872414 384 0.00232386473808822 13: 2 16 0.7853981633974483 96 0.026579555716275863 14: 2 4 1.5707963267948966 24 0.23642809817535057 15: 1 1024 0.0981747704246807 3072 0.014067628445057429 16: 1 256 0.19634954084936185 768 0.05813359610439185 17: 1 64 0.39269908169872414 192 0.2255990104652618 18: 1 16 0.7853981633974483 48 0.6490200242065677 19: 1 4 1.5707963267948966 12 1.1022183738835512
Note: the session table can also be exported, e.g. to Excel or Libre/Open Office Calc, by using the ToCSVFile function.
The columns of the session table can be easily converted to a plot: the $x$-axis is determined by the cell width, the $y$-axis is determined by the $L^2$ error. Furthermore, we want to group our plots according to the DG degree, i.e. have one line for each polynomial degree;
var ErrorPlot = Tab.ToPlot("Grid:hMin", "SolL2err", // column for x- and y
"DGdegree:T"); // column for group
We set logarithmic axes:
ErrorPlot.LogX = true;
ErrorPlot.LogY = true;
ErrorPlot.PlotNow()
Using gnuplot: C:\Program Files (x86)\FDY\BoSSS\bin\native\win\gnuplot-gp510-20160418-win32-mingw\gnuplot\bin\gnuplot.exe Note: In a Jupyter Worksheet, you must NOT have a trailing semicolon in order to see the plot on screen; otherwise, the output migth be surpressed.!
Of course, we can adjust the plot styles:
ErrorPlot.dataGroups[0].Format.PointType = PointTypes.Diamond;
ErrorPlot.dataGroups[1].Format.PointType = PointTypes.Box;
ErrorPlot.dataGroups[2].Format.PointType = PointTypes.LowerTriangle;
ErrorPlot.dataGroups[3].Format.PointType = PointTypes.Asterisk;
foreach(var grp in ErrorPlot.dataGroups) {
grp.Format.PointSize = 0.8;
grp.Format.DashType = DashTypes.Dotted;
grp.Format.LineWidth = 2;
}
ErrorPlot.PlotNow()
Using gnuplot: C:\Program Files (x86)\FDY\BoSSS\bin\native\win\gnuplot-gp510-20160418-win32-mingw\gnuplot\bin\gnuplot.exe Note: In a Jupyter Worksheet, you must NOT have a trailing semicolon in order to see the plot on screen; otherwise, the output migth be surpressed.!
And we can compute the convergence order:
ErrorPlot.Regression()
index | Key | Value |
---|---|---|
0 | DGdegree:T4 | 5.038444733923943 |
1 | DGdegree:T3 | 4.164253998270729 |
2 | DGdegree:T2 | 3.321168082939305 |
3 | DGdegree:T1 | 1.6064593201426463 |
/// BoSSScmdSilent
var reg1 = ErrorPlot.Regression();
double conv1 = reg1.Single(kv => kv.Key.Contains("T1")).Value;
double conv2 = reg1.Single(kv => kv.Key.Contains("T2")).Value;
double conv3 = reg1.Single(kv => kv.Key.Contains("T3")).Value;
double conv4 = reg1.Single(kv => kv.Key.Contains("T4")).Value;
Assert.IsTrue(Math.Abs(conv1 - (+2)) < 0.7, "experimental convergence failed on k = 1");
Assert.IsTrue(Math.Abs(conv2 - (+3)) < 0.7, "experimental convergence failed on k = 2");
Assert.IsTrue(Math.Abs(conv3 - (+4)) < 0.7, "experimental convergence failed on k = 3");
Assert.IsTrue(Math.Abs(conv4 - (+5)) < 0.7, "experimental convergence failed on k = 4");
Note: these plots can also be exported to LaTeX, in a quality that is suitable for print publication: ```csharp ErrorPlot.ToGnuplot().PlotCairolatex().SaveTo("C:\tmp\errplt.tex");
If the exact solution is not known, one can only estimate the convergence behavior experimentally. BoSSS provides some utility for this, the DGFieldComparison class, which has a versatile, yet complex interface.
However, there is a simple interface in the workflow management toolbox.
We can augment the current session table with experimental errors:
BoSSSshell.WorkflowMgm.hConvergence.Update();
var Tab = BoSSSshell.WorkflowMgm.SessionTable;
We observe, that columns have been added to the session table, starting with a prefix L2Error_
Tab.GetColumnNames().Skip(46)
index | value |
---|---|
0 | MemoryInstrumentationLevel |
1 | AlternateDbPaths[0].Item1 |
2 | logFileDirectory |
3 | Paramstudy_ContinueOnError |
4 | DynamicLoadBalancing_RedistributeAtStartup |
5 | PlotAgglomeration |
6 | DynamicLoadBalancing_Period |
7 | DynamicLoadBalancing_ImbalanceThreshold |
8 | DynamicLoadBalancing_On |
9 | AdaptiveMeshRefinement |
10 | AMR_startUpSweeps |
11 | CutCellQuadratureType |
12 | ContinueOnIoError |
13 | BurstSave |
14 | Grid:NoOfCells |
15 | Grid:SpatialDimension |
16 | Grid:hMax |
17 | Grid:hMin |
18 | NoOfCutCellBlocks |
19 | NoOfCutCellDiagBlocks |
20 | NNZMtx |
21 | NNZblk |
22 | MtxMB |
23 | NumberOfMatrixBlox |
24 | minSolRunT |
25 | maxSolRunT |
26 | Conv |
27 | NoIter |
28 | NoOfCells |
29 | DOFs |
30 | BlockSize |
31 | maxBlkSize |
32 | minBlkSize |
33 | SolL2err |
34 | Session |
35 | RegularTerminated |
36 | L2Error_T |
37 | L2Error_ResidualKP1 |
38 | L2Error_Error |
39 | L2Error_MgLevel_0 |
40 | L2Error_MgLevel_1 |
41 | L2Error_MPIrank |
Tab = Tab.ExtractColumns(
"DGdegree:T", "Grid:NoOfCells",
"SolL2err", "L2Error_T");
We observe that the \emph{experimental} $L^2$ error is approximately equal to the $L^2$ error against the exact solution, except for the highest resolutions. There, the error of the numerical solution is computed against itself, and thus the error is zero up to round-off errors.
If we would like to extract convergence plots from this table, we need to exclude the rows with the finest solution using e.g. the TableExtensions.ExtractRows method.
Tab.Print();
DGdegree:T Grid:NoOfCells SolL2err L2Error_T 0: 4 1024 4.193309289152585E-09 0 1: 4 256 1.349148434699243E-07 1.3525693946921945E-07 2: 4 64 4.384872822370366E-06 4.384933221935428E-06 3: 4 16 0.00014578074462366728 0.00014578105499889814 4: 4 4 0.004890481980291057 0.004890617405552956 5: 3 1024 3.395884553914282E-07 0 6: 3 256 5.600208133623587E-06 5.613067149691622E-06 7: 3 64 9.937069092458554E-05 9.93769147106256E-05 8: 3 16 0.0019432545281115033 0.0019432634265751907 9: 3 4 0.03377668103207887 0.03377830446497647 10: 2 1024 2.5727368042089585E-05 0 11: 2 256 0.00022565400197291664 0.0002217996255605217 12: 2 64 0.00232386473808822 0.002319839423808102 13: 2 16 0.026579555716275863 0.026574930938825916 14: 2 4 0.23642809817535057 0.23643727012994867 15: 1 1024 0.014067628445057429 0 16: 1 256 0.05813359610439185 0.04421349139797281 17: 1 64 0.2255990104652618 0.21167259296798574 18: 1 16 0.6490200242065677 0.6350953388607918 19: 1 4 1.1022183738835512 1.0884609432628887
Rows could be extracted form a table using a selector function: this is an expression, which is true for all rows that we want to extract;
Tab = Tab.ExtractRows(
(iRow, RowEntries) => Convert.ToInt32(RowEntries["Grid:NoOfCells"]) != 1024);
Tab.Print();
DGdegree:T Grid:NoOfCells SolL2err L2Error_T 0: 4 256 1.349148434699243E-07 1.3525693946921945E-07 1: 4 64 4.384872822370366E-06 4.384933221935428E-06 2: 4 16 0.00014578074462366728 0.00014578105499889814 3: 4 4 0.004890481980291057 0.004890617405552956 4: 3 256 5.600208133623587E-06 5.613067149691622E-06 5: 3 64 9.937069092458554E-05 9.93769147106256E-05 6: 3 16 0.0019432545281115033 0.0019432634265751907 7: 3 4 0.03377668103207887 0.03377830446497647 8: 2 256 0.00022565400197291664 0.0002217996255605217 9: 2 64 0.00232386473808822 0.002319839423808102 10: 2 16 0.026579555716275863 0.026574930938825916 11: 2 4 0.23642809817535057 0.23643727012994867 12: 1 256 0.05813359610439185 0.04421349139797281 13: 1 64 0.2255990104652618 0.21167259296798574 14: 1 16 0.6490200242065677 0.6350953388607918 15: 1 4 1.1022183738835512 1.0884609432628887
As an alternative to working with the session table, which is sometimes not versatile enough, we demonstrate a way to extract data from the sessions in the current project directly.
Create a list in which we store a separate plot for each polynomial degree:
var ExpPlotS = new List<Plot2Ddata>();
foreach(int pDeg in Degrees) { // loop over polynomial degrees
// extract sessions with DG degree pDeg
var pDegSessions = BoSSSshell.WorkflowMgm.Sessions.Where(
// function which is true on all sessions we are interested in:
Si => Convert.ToInt32(Si.KeysAndQueries["DGdegree:T"]) == pDeg
).ToArray();
// now, create a plot from the selected sessions:
// (we could also do other things)
Plot2Ddata pDegPlot =
pDegSessions.ToEstimatedGridConvergenceData("T",
xAxis_Is_hOrDof:false, // false selects DOFs for x-axis
normType:NormType.H1_approximate); // use the H1-Sobolev norm
// remember the freshly created plot object in a list:
ExpPlotS.Add(pDegPlot);
}
We adjust some plot style settings:
ExpPlotS[0].dataGroups[0].Format.PointType = PointTypes.Diamond;
ExpPlotS[1].dataGroups[0].Format.PointType = PointTypes.Box;
ExpPlotS[2].dataGroups[0].Format.PointType = PointTypes.LowerTriangle;
ExpPlotS[3].dataGroups[0].Format.PointType = PointTypes.Asterisk;
ExpPlotS[0].dataGroups[0].Name = "k = 1";
ExpPlotS[1].dataGroups[0].Name = "k = 2";
ExpPlotS[2].dataGroups[0].Name = "k = 3";
ExpPlotS[3].dataGroups[0].Name = "k = 4";
foreach(var p in ExpPlotS) {
p.dataGroups[0].Format.PointSize = 0.8;
p.dataGroups[0].Format.DashType = DashTypes.Dotted;
p.dataGroups[0].Format.LineWidth = 2;
}
and we can merge all four plot objects into a singe one:
var ExpPlot = ExpPlotS[0]; // select 0-th object
foreach(var p in ExpPlotS.Skip(1)) { // loop over other (skip 0-th entry)
ExpPlot = ExpPlot.Merge(p); // merge
}
ExpPlot.PlotNow()
Using gnuplot: C:\Program Files (x86)\FDY\BoSSS\bin\native\win\gnuplot-gp510-20160418-win32-mingw\gnuplot\bin\gnuplot.exe Note: In a Jupyter Worksheet, you must NOT have a trailing semicolon in order to see the plot on screen; otherwise, the output migth be surpressed.!
and we can also verify the slope of the error curves. Note that convergence order by using the $H^1$ norm is one degree lower compared to the $L^2$ norm..
ExpPlot.Regression()
index | Key | Value |
---|---|---|
0 | k = 1 | -1.218444385851357 |
1 | k = 2 | -2.127604331914452 |
2 | k = 3 | -3.0998026345172573 |
3 | k = 4 | -4.050699474719983 |
/// BoSSScmdSilent
var regExp = ExpPlot.Regression();
double conv1 = regExp.Single(kv => kv.Key.Contains("1")).Value;
double conv2 = regExp.Single(kv => kv.Key.Contains("2")).Value;
double conv3 = regExp.Single(kv => kv.Key.Contains("3")).Value;
double conv4 = regExp.Single(kv => kv.Key.Contains("4")).Value;
Assert.IsTrue(Math.Abs(conv1 - (-1)) < 0.7, "experimental convergence failed on k = 1");
Assert.IsTrue(Math.Abs(conv2 - (-2)) < 0.7, "experimental convergence failed on k = 2");
Assert.IsTrue(Math.Abs(conv3 - (-3)) < 0.7, "experimental convergence failed on k = 3");
Assert.IsTrue(Math.Abs(conv4 - (-4)) < 0.7, "experimental convergence failed on k = 4");
If we have more than one plot object, we can arrange them in an array to realize multi-plots:
var multiplot = new Plot2Ddata[2,2];
multiplot[0,0] = ExpPlotS[0];
multiplot[0,1] = ExpPlotS[1];
multiplot[1,0] = ExpPlotS[2];
multiplot[1,1] = ExpPlotS[3];
Now, we can draw an array of plots:
multiplot.PlotNow()
Using gnuplot: C:\Program Files (x86)\FDY\BoSSS\bin\native\win\gnuplot-gp510-20160418-win32-mingw\gnuplot\bin\gnuplot.exe Note: In a Jupyter Worksheet, you must NOT have a trailing semicolon in order to see the plot on screen; otherwise, the output migth be surpressed.!
this already looks neat, but a few formatting tweaks to make the multi-plot look nicer:
multiplot[0,1].dataGroups[0].UseY2 = true; // label right on right column
multiplot[0,1].ShowYtics = false;
multiplot[0,1].ShowY2tics = true;
multiplot[1,1].dataGroups[0].UseY2 = true; // label right on right column
multiplot[1,1].ShowYtics = false;
multiplot[1,1].ShowY2tics = true;
multiplot[0,0].dataGroups[0].UseX2 = true; // label on top on top row
multiplot[0,0].ShowXtics = false;
multiplot[0,0].ShowX2tics = true;
multiplot[0,1].dataGroups[0].UseX2 = true; // label on top on top row
multiplot[0,1].ShowXtics = false;
multiplot[0,1].ShowX2tics = true;
// turn logarithm on for the secondary axis;
multiplot[0,0].LogX2 = true;
multiplot[0,1].LogX2 = true;
multiplot[1,0].LogX2 = true;
multiplot[1,1].LogX2 = true;
multiplot[0,0].LogY2 = true;
multiplot[0,1].LogY2 = true;
multiplot[1,0].LogY2 = true;
multiplot[1,1].LogY2 = true;
// set x ranges
multiplot[0,0].X2rangeMin = 1e0;
multiplot[0,0].X2rangeMax = 1e2;
multiplot[0,1].X2rangeMin = 1e0;
multiplot[0,1].X2rangeMax = 1e2;
multiplot[1,0].XrangeMin = 1e0;
multiplot[1,0].XrangeMax = 1e2;
multiplot[1,1].XrangeMin = 1e0;
multiplot[1,1].XrangeMax = 1e2;
// set y ranges
multiplot[0,0].YrangeMin = 1e-7;
multiplot[0,0].YrangeMax = 1e0;
multiplot[1,0].YrangeMin = 1e-7;
multiplot[1,0].YrangeMax = 1e0;
multiplot[0,1].Y2rangeMin = 1e-7;
multiplot[0,1].Y2rangeMax = 1e0;
multiplot[1,1].Y2rangeMin = 1e-7;
multiplot[1,1].Y2rangeMax = 1e0;
// reduce the whitespace in between the plots:
multiplot[0,0].rmargin = 2;
multiplot[0,1].lmargin = 2;
multiplot[1,0].rmargin = 2;
multiplot[1,1].lmargin = 2;
multiplot[0,0].bmargin = 0.5;
multiplot[1,0].tmargin = 0.5;
multiplot[0,1].bmargin = 0.5;
multiplot[1,1].tmargin = 0.5;
multiplot.PlotNow()
Using gnuplot: C:\Program Files (x86)\FDY\BoSSS\bin\native\win\gnuplot-gp510-20160418-win32-mingw\gnuplot\bin\gnuplot.exe Note: In a Jupyter Worksheet, you must NOT have a trailing semicolon in order to see the plot on screen; otherwise, the output migth be surpressed.!
This tutorial showed how to set-up a parameter study, by looping over a set of parameters (in this case, different grids and polynomial degrees), see sections about MeshCreation and about Setup-And-Execution. Finally, it only requires a simple loop to send all jobs to a compute resource.
Afterwards, c.f. section about ExactConvergence, the session table was used to combine measurements taken in each session (here, the $L^2$ error against the exact solution) into a single table. This table can either be exported to spreadsheet analysis software or visualized internally.