0% found this document useful (0 votes)
21 views14 pages

Anit Scratch App

Uploaded by

maguskurdi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views14 pages

Anit Scratch App

Uploaded by

maguskurdi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Implementing an application from scratch

• Implementing a new application from scratch in OpenFOAM® (or any other


high level programming library), can be an incredible daunting task.
• OpenFOAM® comes with many solvers, and as it is today, you do not need
to implement new solvers from scratch.
• Of course, if your goal is to write a new solver, you will need to deal with
programming. What you usually do, is take an existing solver and modify it.
• But in case that you would like to take the road of implementing new
applications from scratch, we are going to give you the basic building blocks.
• We are also going to show how to add basic modifications to existing solvers.
• We want to remind you that this requires some knowledge on C++ and
OpenFOAM® API library.
• Also, you need to understand the FVM, and be familiar with the basic algebra
of tensors.
• Some common sense is also helpful.
Implementing an application from scratch
• Let us do a little bit of high level programming, this is the hard part of working
with OpenFOAM®.
• At this point, you can work in any directory. But we recommend you to work
in your OpenFOAM® user directory, type in the terminal,

1. $> cd $WM_PROJECT_USER_DIR/run

• To create the basic structure of a new application, type in the terminal,

1. $> foamNewApp scratchFoam


2. $> cd scratchFoam

• The utility foamNewApp, will create the directory structure and all the files needed to
create the new application from scratch. The name of the application is
scratchFoam.
• If you want to get more information on how to use foamNewApp, type in the terminal,

1. $> foamNewApp –help


Implementing an application from scratch
Directory structure of the new boundary condition
scratchFoam/
├── createFields.H Does not exist, we will create it later
├── scratchFoam.C
└── Make
├── files
└── options

The scratchFoam directory contains the source code of the solver.


• scratchFoam.C: contains the starting point to implement the new application.
• createFields.H: in this file we declare all the field variables and initializes the solution.
This file does not exist at this point, we will create it later.
• The Make directory contains compilation instructions.
• Make/files: names all the source files (.C), it specifies the name of the solver and
location of the output file.
• Make/options: specifies directories to search for include files and libraries to link the
solver against.
• To compile the new application, we use the command wmake.
Implementing an application from scratch
• Open the file scratchFoam.C using your favorite text editor, we will use gedit.
• At this point you should have this file, this does not do anything. We need to add the
statements to create a working applications.
• This is the starting point for new applications.
This header is extremely important, it will add all the class
30 declarations needed to access mesh, fields, tensor algebra, fvm/fvc
31 #include "fvCFD.H" operators, time, parallel communication, linear algebra, and so on.
32
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34
35 int main(int argc, char *argv[])
36 {
37 #include "setRootCase.H"
38 #include "createTime.H"
39
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41
42 Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
43 << " ClockTime = " << runTime.elapsedClockTime() << " s"
44 << nl << endl;
45
46 Info<< "End\n" << endl;
47
48 return 0;
49 }
50
Implementing an application from scratch
• Stating from line 31, add the following statements.
• We are going to use the PISO control options, even if we do not have to deal with
velocity-pressure coupling.

30
31 #include "fvCFD.H“

32 #include "pisoControl.H" Solution control using PISO class


33
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35
36 int main(int argc, char *argv[])
37 {
38 #include "setRootCase.H“ Set directory structure

39 #include "createTime.H“ Create time (object runtime)

40 #include "createMesh.H“ Create time (object mesh)

41 #include "createFields.H“ Initialize fields


This source file does not exist yet, we need to create it
42 #include "CourantNo.H“ Calculates and outputs the Courant Number

43 #include "initContinuityErrs.H“ Declare and initialize the cumulative continuity error


44
Assign PISO controls to object mesh. Creates object piso.
45 pisoControl piso(mesh);
Alternatively, you can use the header file createControl.H
46
47 Info<< "\nStarting time loop\n" << endl; Output some information
48
Implementing an application from scratch
• We are going to use the PISO control options, even if we do not have to deal with
velocity-pressure coupling.

49 while (runTime.loop()) Time loop


50 {
51 Info<< "Time = " << runTime.timeName() << nl << endl;
52
53 #include "CourantNo.H" Calculates and outputs the Courant Number
54
55 while (piso.correct()) PISO options (correct loop)
56 {
PISO options (non orthogonal corrections
57 while (piso.correctNonOrthogonal())
loop)
58 {
59 fvScalarMatrix Teqn Create object TEqn.
fvScalarMatrix is a scalar instance of fvMatrix
60 (
61 fvm::ddt(T) Model equation (convection-diffusion)
62 + fvm::div(phi, T) We need to create the scalar field T, vector
63 - fvm::laplacian(DT, T) field U (used in phi or face fluxes), and the
64 ); constant DT.
We will declare these variables in the
createFields.H header file.
In the dictionary fvSchemes, you will need to
define how to compute the differential
65 operators, that is,
66 TEqn.solve(); ddt(T)
67 } div(phi, T)
Solve TEqn
68 } laplacian(DT, T)
At this point the object
69
TEqn holds the solution.
Implementing an application from scratch
• We are going to use the PISO control options, even if we do not have to deal with
velocity-pressure coupling.

If you want to compute the CPU time of each iteration,


69
70 #include "continuityErrs.H" Computes continuity errors
71

add the same statement inside the time loop


Write CPU time at the end of the time loop.
72 runTime.write(); Write the solution in the runtime folder
It will write the data requested in the file createFields.H

73 } At this point we are outside of the time loop


74
75 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
76
77 Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
78 << " ClockTime = " << runTime.elapsedClockTime() << " s"
79 << nl << endl;
80
81 Info<< "End\n" << endl; Output this message
82

83 return 0; End of the program (exit status).


84 } If everything went fine, the program should return 0.
85 To now the return value, type in the terminal,
86 $> echo $?
Implementing an application from scratch
• Let us create the file createFields.H, type in the terminal,

1. $> touch createFields.H

• Now open the file with your favorite editor, and start to add the following information,

1 Info<< "Reading field T\n" << endl;


2
3 volScalarField T Create scalar field T
4 (
5 IOobject Create object for input/output operations
6 (
7 "T", Name of the dictionary file to read/write
8 runTime.timeName(), runtime directory
9 mesh, Object registry
10 IOobject::MUST_READ,
11 IOobject::AUTO_WRITE Read the dictionary in the runtime directory
12 ), (MUST_READ, and write the value in the runtime
13 mesh Link object to mesh directory (AUTO_WRITE).
14 ); If you do not want to write the value, use the option
NO_WRITE
Implementing an application from scratch
• Remember, in the file createFields.H, we declare all the variables (or fields) that
we will use (U and T in this case).
• The dimensions of the fields are defined in the input dictionaries, you also have the
option to define the dimensions in the source code.
• You can also define the fields directly in the source file scratchFoam.C, but it is
good practice to do it in the header. This improves code readability.

17 Info<< "Reading field U\n" << endl;


18
19 volVectorField U Create vector field U
20 (
21 IOobject
22 (
23 "U", Name of the dictionary file to read/write
24 runTime.timeName(),
25 mesh,
26 IOobject::MUST_READ,
27 IOobject::AUTO_WRITE
28 ),
29 mesh
30 );
31
Implementing an application from scratch
• We also need to declare the constant DT, that is read from the dictionary
transportProperties.
• The dimensions are defined in the input dictionary.

33 Info<< "Reading transportProperties\n" << endl;


34
35 IOdictionary transportProperties Create object transportProperties used to
36 ( read data
37 IOobject
38 ( Name of the input dictionary
39 "transportProperties",
40 runTime.constant(), Location of the input dictionary, in this case
41 mesh, is located in the directory constant
42 IOobject::MUST_READ_IF_MODIFIED, Re-read data if it is modified
43 IOobject::NO_WRITE
44 ) Do not write anything in the dictionary
45 );
46
47
48 Info<< "Reading diffusivity DT\n" << endl;
49
50 dimensionedScalar DT Create scalar DT (diffusion coefficient)
51 (
52 transportProperties.lookup("DT") Access value of DT in the object
53 ); transportProperties
54
55 #include "createPhi.H" Creates and initializes the relative face-
56 flux field phi.
Implementing an application from scratch
• At this point, we are ready to compile. Type in the terminal,

1. $> wmake

• If everything went fine, you should have a working solver named scratchFoam.
• If you are feeling lazy or you can not fix the compilation errors, you will find the source
code in the directory,

• $PTOFC/101programming/applications/solvers/scratchFoam

• You will find a case ready to run in the directory,

$PTOFC/101programming/applications/solvers/scratchFoam/test_case

• At this point, we are all familiar with the convection-diffusion equation and
OpenFOAM®, so you know how to run the case. Do your magic.
Implementing an application from scratch
• Let us now add a little bit more complexity, a non-uniform initialization of the scalar
field T.
• Remember codeStream? Well, we just need to proceed in a similar way.
• As you will see, initializing directly in the source code of the solver is more intrusive
than using codeStream in the input dicitionaries.
• It also requires recompiling the application.
• Add the following statements to the createFields.H file, recompile and run again
the test case.

16
17 forAll(T, i) We add the initialization of T after the its declaration
18 {
19 const scalar x = mesh.C()[i][0];
20 const scalar y = mesh.C()[i][1]; Access cell center coordinates.
21 const scalar z = mesh.C()[i][2]; In this case y and z coordinates are not used.
22
23 if ( 0.3 < x && x < 0.7) Conditional structure
24 {
25 T[i] = 1.;
26 }
27 }
28 T.write(); Write field T. As the file createFields.H is outside the time loop
the value is saved in the time directory 0
Implementing an application from scratch
• Let us compute a few extra fields. We are going to compute the gradient, divergence,
and Laplacian of T.
• We are going to compute these fields in a explicit way, that is, after finding the
solution of T.
• Therefore we are going to use the operator fvc.
• Add the following statements to the source code of the solver (scratchFoam.C),

68 }
69
70 #include "continuityErrs.H"
71 #include "write.H" Add this header file
72 runTime.write();
73 The file is located in the directory
74 } $PTOFC/101programming/applications/solvers/scratchFoam
In this file we declare and define the new variables, take a look at it

• Recompile the solver and rerun the test case.


• The solver will complain, try to figure out what is the problem (you are missing some
information in the fvSchemes dictionary).
Implementing an application from scratch
• Let us talk about the file write.H,

1 volVectorField gradT(fvc::grad(T)); Compute gradient of T.


2 fvc is the explicit operator, it will compute the
3 volVectorField gradT_vector
requested value using the solution of T
4 (
5 IOobject
6 (
7 "gradT",
8 runTime.timeName(), Save vector field in output dictionary gradT
9 mesh,
10 IOobject::NO_READ,
11 IOobject::AUTO_WRITE
12 ),
13 gradT
14 );
15
...
56
57 volScalarField divGradT
58 (
59 IOobject
60 (
Compute divergence of gradT.
61 "divGradT", The output of this operation is a scalar field.
62 runTime.timeName(), In this case we compute the quantity inside the scalar field
63 mesh, declaration (line 67).
64 IOobject::NO_READ, We use the fvc operator because the solution of gradT is
65 IOobject::AUTO_WRITE already known.
66 ),
67 fvc::div(gradT)
68 ); In the dictionary fvSchemes, you will need to tell the solver how to do
69 ... the interpolation of the term div(grad(T))

You might also like