37
37
#include "simpleControl.H"
38
38
39
39
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40
+ // Some helper functions in order to investigate this case
41
+ namespace Functions {
42
+ double get_rhs (const double x , const double y , const double alpha , const double beta )
43
+ {
44
+ return beta - 2 - 2 * alpha ;
45
+ }
46
+ double get_solution (const double x , const double y ,
47
+ const double alpha , const double beta , const double time )
48
+ {
49
+ return 1 + std ::pow (x , 2 ) + (alpha * std ::pow (y , 2 )) + (beta * time );
50
+ }
51
+
52
+ void compute_and_print_errors (const Foam ::fvMesh & mesh , const double alpha ,
53
+ const double beta , const double time )
54
+ {
55
+ double error = 0 ;
56
+ const Foam ::volScalarField * T_ (& mesh .lookupObject < volScalarField > ("T "));
57
+
58
+ double max_error = std ::numeric_limits < double > ::min ();
59
+
60
+ // Get the locations of the volume centered mesh vertices
61
+ const vectorField & CellCenters = mesh .C ();
62
+ unsigned int numDataLocations = CellCenters .size ();
63
+ for (int i = 0 ; i < CellCenters .size (); i ++ ) {
64
+ const double coord_x = CellCenters [i ].x ();
65
+ const double coord_y = CellCenters [i ].y ();
66
+ const double exact_solution = Functions ::get_solution (coord_x , coord_y , alpha , beta , time );
67
+ const auto result = (exact_solution - T_ -> internalField ()[i ]) *
68
+ (exact_solution - T_ -> internalField ()[i ]);
69
+ error += result ;
70
+ max_error = std ::max (result , max_error );
71
+ }
72
+
73
+ Info << "\nError metrics at t = " << time << "s:\n" ;
74
+ Info << "l2 error (sqrt(sum(err^2)/n)):\t\t" << std ::sqrt (error / numDataLocations ) << endl ;
75
+ Info << "Maximum absolute error (max(err)):\t" << std ::sqrt (max_error ) << endl ;
76
+ Info << "Global absolute error (sum(err^2)):\t" << error << "\n" ;
77
+ Info << endl ;
78
+ }
79
+ } // namespace Functions
40
80
41
81
int main (int argc , char * argv [])
42
82
{
@@ -61,8 +101,8 @@ int main(int argc, char *argv[])
61
101
62
102
const double alpha = 3 ;
63
103
const double beta = 1.2 ;
64
- const double rhs = beta - 2 - 2 * alpha ;
65
104
105
+ // Initialize the RHS with zero
66
106
volScalarField f (
67
107
IOobject (
68
108
"RHS ",
@@ -74,7 +114,32 @@ int main(int argc, char *argv[])
74
114
dimensionedScalar (
75
115
"Tdim ",
76
116
dimensionSet (0 , 0 , -1 , 1 , 0 , 0 , 0 ),
77
- Foam ::scalar (rhs )));
117
+ Foam ::scalar (0 )));
118
+
119
+ // Now assign the respective values to the RHS
120
+ //(strictly speaking not required here, only for space-dependent RHS functions)
121
+ // Get the locations of the volume centered mesh vertices
122
+ const vectorField & CellCenters = mesh .C ();
123
+ for (int i = 0 ; i < CellCenters .size (); i ++ ) {
124
+ const double coord_x = CellCenters [i ].x ();
125
+ const double coord_y = CellCenters [i ].y ();
126
+ f .ref ()[i ] = Functions ::get_rhs (coord_x , coord_y , alpha , beta );
127
+ }
128
+
129
+ for (int j = 0 ; j < mesh .boundaryMesh ().size () - 1 ; ++ j ) {
130
+ // Get the face centers of the current patch
131
+ const vectorField faceCenters =
132
+ mesh .boundaryMesh ()[j ].faceCentres ();
133
+
134
+ // Assign the (x,y,z) locations to the vertices
135
+ for (int i = 0 ; i < faceCenters .size (); i ++ ) {
136
+ const double coord_x = faceCenters [i ].x ();
137
+ const double coord_y = faceCenters [i ].y ();
138
+ f .boundaryFieldRef ()[j ][i ] = Functions ::get_rhs (coord_x , coord_y , alpha , beta );
139
+ }
140
+ }
141
+
142
+ Functions ::compute_and_print_errors (mesh , alpha , beta , runTime .value ());
78
143
79
144
while (simple .loop ()) {
80
145
Info << "Time = " << runTime .timeName () << nl << endl ;
0 commit comments