First, we initialize the new worksheet; Note:
BoundaryAndInitialData.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"
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();
This tutorial demostrates the definition, resp. the import of data for boundary and initial values.
In order to demonstrate the usage, we employ the exemplaric Poisson solver.
using BoSSS.Application.SipPoisson;
We use the following helper function to create a template for the multiple solver runs.
Func<SipControl> PreDefinedControl = delegate() {
SipControl c = new SipControl();
c.SetDGdegree(2);
c.GridFunc = delegate() {
// define a grid of 10x10 cells
double[] nodes = GenericBlas.Linspace(-1, 1, 11);
var grd = Grid2D.Cartesian2DGrid(nodes, nodes);
// set the entire boundary to Dirichlet b.c.
grd.DefineEdgeTags(delegate (double[] X) {
return BoundaryType.Dirichlet.ToString();
});
return grd;
};
c.SetDatabase(wmg.DefaultDatabase);
c.savetodb = true;
return c;
};
Again, we are using the workflow management
BoSSSshell.WorkflowMgm.Init("Demo_BoundaryAndInitialData");
Project name is set to 'Demo_BoundaryAndInitialData'. Default Execution queue is chosen for the database. Creating database '\\fdygitrunner\BoSSStests\Demo_BoundaryAndInitialData'.
SipControl c1 = PreDefinedControl();
Provide initial data as a text:
c1.AddInitialValue("RHS","X => Math.Sin(X[0])*Math.Cos(X[1])",
TimeDependent:false);
Finally, all initial data is stored in the
AppControl.InitialValues
dictionary and
all boundary data is stored in the
AppControl.BoundaryValues
dictionary.
The common interface for all varinats to specify boundary
and initial data is IBoundaryAndInitialData
The snippet above is only a shortcut to add a Formula
object,
which implements the IBoundaryAndInitialData
interface.
c1.InitialValues
key |
---|
RHS |
c1.InitialValues["RHS"]
In BoSSSpad, such objects can also be extracted from static methods of classes; note that these should not depend on any other object in the worksheet.
Formula BndyFormula = new Formula(
"BndyValue.BndyFunction",
false,
"static class BndyValue {"+
" public static double BndyFunction(double[] X) {"+
" return 1.0;"+
" }"+
"}");
c1.AddBoundaryValue(BoundaryType.Dirichlet.ToString(),
"T",
BndyFormula);
Creates a Job named J1 and runs it
var J1 = c1.RunBatch();
Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_1 ... Control object contains grid function. Trying to Serialize the grid... Grid Edge Tags changed. Control object modified. Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\Demo_BoundaryAndInitialData-ipPoisson2023Dec05_001823.724709 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished.
The next line prints the Status of the Job J1
.
BoSSSshell.WorkflowMgm.BlockUntilAllJobsTerminate(3600*4);
All jobs finished.
We can print the Status of the Job J1
.
J1.Status
We can also check via a method if the Job J1
is truly finished
NUnit.Framework.Assert.IsTrue(J1.Status == JobStatus.FinishedSuccessful);
Splines can be used to interpolate nodal data onto a DG field; currently, only 1D is supported.
SipControl c2 = PreDefinedControl();
// create test data for the spline
double[] xNodes = GenericBlas.Linspace(-2,2,13);
double[] yNodes = xNodes.Select(x => x*0.4).ToArray();
var rhsSpline = new Spline1D(xNodes, yNodes,
0,
Spline1D.OutOfBoundsBehave.Extrapolate);
/// BoSSScmdSilent
double err = 0;
// test the spline: a line must be interpolated exactly.
foreach(double xtst in GenericBlas.Linspace(-3,3,77)) {
double sVal = rhsSpline.Evaluate(new double[] {xtst , 0, 0 }, 0.0);
double rVal = xtst*0.4;
err += Math.Abs(sVal - rVal);
}
NUnit.Framework.Assert.Less(err, 1.0e-10, "Slpine implementation fail.");
c2.AddInitialValue("RHS", rhsSpline);
var J2 = c2.RunBatch();
Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_2 ... Control object contains grid function. Trying to Serialize the grid... Grid Edge Tags changed. An equivalent grid (5dd19fe9-7251-4dbf-bf6e-0b141f6a9b93) is already present in the database -- the grid will not be saved. Control object modified. Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\Demo_BoundaryAndInitialData-ipPoisson2023Dec05_001922.498703 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished.
BoSSSshell.WorkflowMgm.BlockUntilAllJobsTerminate(3600*4);
All jobs finished.
J2.Status
/// BoSSScmdSilent
NUnit.Framework.Assert.IsTrue(J2.Status == JobStatus.FinishedSuccessful);
For demonstrational purposes, we use the result (i.e. the last time-step) of a previous calculation as a right-hand-side for the next calculation.
var j2Sess = J2.LatestSession;
j2Sess
Demo_BoundaryAndInitialData UnnamedJob_2 12/05/2023 00:19:41 bd21f59e...
j2Sess.Timesteps
#0: { Time-step: 0; Physical time: 0s; Fields: T, ResidualKP1, Error, MgLevel_0, MgLevel_1, MgLevel_2, MgLevel_3, MgLevel_4, MPIrank; Name: } #1: { Time-step: 1; Physical time: 0s; Fields: T, ResidualKP1, Error, MgLevel_0, MgLevel_1, MgLevel_2, MgLevel_3, MgLevel_4, MPIrank; Name: }
var lastTimeStep = j2Sess.Timesteps.Last();
We encapsulate the value T
in the ForeignGridValue
object,
which allows interpolation between different meshes:
var newForeignMesh = new ForeignGridValue(lastTimeStep,"T");
/// Use different mesh in the control file:
SipControl c3 = PreDefinedControl();
c3.GridFunc = delegate() {
// define a grid of *triangle* cells
double[] nodes = GenericBlas.Linspace(-1, 1, 11);
var grd = Grid2D.UnstructuredTriangleGrid(nodes, nodes);
// set the entire boundary to Dirichlet b.c.
grd.DefineEdgeTags(delegate (double[] X) {
return BoundaryType.Dirichlet.ToString();
});
return grd;
};
// we also save the RHS in the database
c3.AddFieldOption("RHS", SaveOpt: FieldOpts.SaveToDBOpt.TRUE);
/// finally, we define the RHS:
c3.AddInitialValue("RHS", newForeignMesh);
/// BoSSScmdSilent
double orgProbe = newForeignMesh.Evaluate(new double[] {0.5,0.5}, 0.0);
double newProbe = lastTimeStep.GetField("T").ProbeAt(new double[] {0.5,0.5});
NUnit.Framework.Assert.Less(Math.Abs(orgProbe - newProbe), 1.0e-10, "Check (1) on ForeignGridValue failed");
var J3 = c3.RunBatch();
Deployments so far (0): ; Success: 0 job submit count: 0
unable to determine job status - unknown
Deploying job UnnamedJob_3 ... Control object contains grid function. Trying to Serialize the grid... Grid Edge Tags changed. Control object modified. Deploying executables and additional files ... Deployment directory: \\fdygitrunner\BoSSStests\Demo_BoundaryAndInitialData-ipPoisson2023Dec05_002000.712680 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished.
BoSSSshell.WorkflowMgm.BlockUntilAllJobsTerminate(3600*4);
All jobs finished.
J3.Status
/// BoSSScmdSilent
NUnit.Framework.Assert.IsTrue(J3.Status == JobStatus.FinishedSuccessful);
Since the quadrilateral mesh used for the original right-hand-side is geometrically embedded in the triangular mesh the interpolation error should be zero (up to machine precision).
var firstTimeStep = J3.LatestSession.Timesteps.First();
DGField RhsOnTriangles = firstTimeStep.GetField("rhs"); // case-insensitive!
DGField RhsOriginal = lastTimeStep.GetField("T");
// note: we have to cast DGField to ConventionalDGField in order to use
// the 'L2Distance' function:
((ConventionalDGField)RhsOnTriangles).L2Distance((ConventionalDGField)RhsOriginal)
/// BoSSScmdSilent
var H1err = ((ConventionalDGField)RhsOnTriangles).H1Distance((ConventionalDGField)RhsOriginal);
NUnit.Framework.Assert.Less(H1err, 1.0e-10, "Check (2) on ForeignGridValue failed.");
Dummy sessions are kind of fake siolver runs, with the only purpose of using them for a restart.
DGField RHSforRestart = firstTimeStep.GetField("RHS");
We save the DG field RHSforRestart
in the database;
This automatically creates a timestep and a session which host the DG field:
var RestartTimestep = wmg.DefaultDatabase.SaveTimestep(RHSforRestart);
RestartTimestep
{ Time-step: 0; Physical time: 0s; Fields: RHS; Name: }
RestartTimestep.Session
Demo_BoundaryAndInitialData InitialValueSession 12/05/2023 00:20:39 2da702e0...
This time step can be used as a restart value.:
var c4 = PreDefinedControl();
c4.InitialValues.Clear();
c4.SetRestart(RestartTimestep);
var J4 = c4.RunBatch();
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\Demo_BoundaryAndInitialData-ipPoisson2023Dec05_002043.151058 copied 37 files. written file: control.obj copied 'win\amd64' runtime. deployment finished.
BoSSSshell.WorkflowMgm.BlockUntilAllJobsTerminate(3600*4);
All jobs finished.
J4.Status
/// BoSSScmdSilent
NUnit.Framework.Assert.IsTrue(J4.Status == JobStatus.FinishedSuccessful);
Since no mesh interpolation is performed for the restart, it is much faster
than ForeignGridValue
but less flexible
(a restart is always performed on the same mesh).
To avoid multiple mesh interpolations (e.g. when multiple runs are required)
one coudl therefore speed up the process by doing the
mesh interpolation once use ProjectFromForeignGrid
in BoSSSpad and
save the interpolation in a dummy session.