Peano
Loading...
Searching...
No Matches
PDE.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3import sympy
4import numpy
5
6
7class PDE(object):
8 def __init__(self, unknowns, auxiliary_variables, dimensions):
9 self.unknowns = unknowns
10 self.auxiliary_variables = auxiliary_variables
11 self.dimensions = dimensions
12 self.Q = sympy.symarray("Q", (unknowns + auxiliary_variables))
13 self.delta_Q = sympy.symarray("deltaQ", (unknowns + auxiliary_variables))
14 self.initial_values = sympy.symarray("Q0", (unknowns + auxiliary_variables))
15 self.boundary_values = sympy.symarray("Qb", (unknowns + auxiliary_variables))
16 self.x = sympy.symarray("x", (dimensions))
17 self.h = sympy.symarray("h", (dimensions))
18 pass
19
21 """
22 Returns identifier for the unknowns.
23 Use this one to feed set_plot_description of your solver.
24 """
25 result = ""
26 for i in range(0, self.unknowns + self.auxiliary_variables):
27 if i != 0:
28 result += ","
29 result += str(self.Q[i])
30 return result
31
33 self, is_cell_mapping=True, is_boundary=False, has_delta=False
34 ):
35 """
36 Return the C code that maps the quantities from Q onto
37 properly labelled quantities
38 """
39 result = ""
40 for i in range(0, self.unknowns + self.auxiliary_variables):
41 result += "[[maybe_unused]] const "
42 result += "double "
43 result += sympy.printing.cxxcode(self.Q[i])
44 if is_boundary:
45 result += " = Qinside[" + str(i) + "];\n"
46 result += "nonCriticalAssertion(Qinside[" + str(i) + "] == Qinside[" + str(i) + "]);\n"
47 else:
48 result += " = Q[" + str(i) + "];\n"
49 result += "nonCriticalAssertion(Q[" + str(i) + "] == Q[" + str(i) + "]);\n"
50 result += "assertion(!std::isnan(" + sympy.printing.cxxcode(self.Q[i]) + "));\n"
51
52 if has_delta:
53 for i in range(0, self.unknowns + self.auxiliary_variables):
54 result += "nonCriticalAssertion(deltaQ[" + str(i) + "] == deltaQ[" + str(i) + "]);\n"
55 result += "[[maybe_unused]] const "
56 result += "double "
57 result += sympy.printing.cxxcode(self.delta_Q[i])
58 result += " = deltaQ[" + str(i) + "];\n"
59 result += "assertion(!std::isnan(" + sympy.printing.cxxcode(self.delta_Q[i]) + "));\n"
60
61 for i in range(0, self.dimensions):
62 result += "const double x_"
63 result += str(i)
64 result += " = "
65 if is_cell_mapping:
66 result += "volumeCentre"
67 else:
68 result += "faceCentre"
69 result += "(" + str(i) + ");\n"
70 for i in range(0, self.dimensions):
71 result += "const double h_"
72 result += str(i)
73 result += " = "
74 result += "volumeH"
75 result += "(" + str(i) + ");\n"
76
77 return result
78
79 def name_Q_entry(self, offset_in_Q, name):
80 """
81 Q covers both unknowns plus auxiliary variables. They simply are concatenated.
82 So if you have 10 unknowns and 2 auxiliary variables, the name you assign the
83 10s Q entry is the one for the first auxiliary variable.
84 There's also a dedicated routine for auxiliary variables if you prefer this one.
85 @see name_auxiliary_variable
86 """
87 self.Q[offset_in_Q] = sympy.symbols(name)
88 return self.Q[offset_in_Q]
89
90 def name_auxiliary_variable(self,number,name):
91 self.Q[number + self.unknowns] = sympy.symbols(name)
92 return self.Q[number + self.unknowns]
93
94 def name_Q_entries(self, offset_in_Q, cardinality, name):
95 new_entry = sympy.symarray(name, cardinality)
96 for i in range(0, cardinality):
97 self.Q[offset_in_Q + i] = new_entry[i]
98 return new_entry
99
100 def grad(self, Q):
101 if isinstance(Q, numpy.ndarray): # Q is vector
102 offset_in_delta_Q = numpy.where(self.Q == Q[0])[0][0]
103 cardinality = len(Q)
104 name = Q[0].name.split("_")[0]
105 new_entry = sympy.symarray("delta_" + name, cardinality)
106 for i in range(0, cardinality):
107 self.delta_Q[offset_in_delta_Q + i] = new_entry[i]
108 return new_entry
109 else: # Q is scalar
110 offset_in_delta_Q = numpy.where(self.Q == Q)[0][0]
111 cardinality = 1
112 name = Q.name
113 self.delta_Q[offset_in_delta_Q] = sympy.symbols("delta_" + name)
114 return self.delta_Q[offset_in_delta_Q]
115
117 result = "assertion(normal >= 0);\n"
118 result += "//assertion(normal < Dimensions);\n"
119 for i in range(0, self.unknowns + self.auxiliary_variables):
120 result += "assertion(!std::isnan(Qoutside[" + str(i) + "]));\n"
121 result += "assertion(!std::isnan(Qinside[" + str(i) + "]));\n"
122 result += "nonCriticalAssertion(Qinside[" + str(i) + "] == Qinside[" + str(i) + "]);\n"
123 result += "Qoutside[" + str(i) + "] = Qinside[" + str(i) + "];\n"
124 result += "nonCriticalAssertion(Qoutside[" + str(i) + "] == Qoutside[" + str(i) + "]);\n"
125 return result
126
127 def implementation_of_boundary_conditions(self, invoke_evalf_before_output=False):
128 """
129 invoke_evalf_before_output: boolean
130 If your expression is a symbolic expression (default) then we use evalf
131 before we pipe it into the output. If your expression is something numeric,
132 then evalf will fail (as it is not defined for scalar quantities).
133 """
134 result = "assertion(normal >= 0);\n"
135 result += "//assertion(normal < Dimensions);\n"
137 is_cell_mapping=False, is_boundary=True
138 )
139 for i in range(0, self.unknowns + self.auxiliary_variables):
140 if invoke_evalf_before_output:
141 result += sympy.printing.cxxcode(
142 self.boundary_values[i].evalf(), assign_to="Q[" + str(i) + "]"
143 )
144 else:
145 result += (
146 "Qoutside["
147 + str(i)
148 + "] = "
149 + sympy.printing.cxxcode(self.boundary_values[i])
150 + ";"
151 )
152 result += "\n"
153 return result
154
155 def implementation_of_initial_conditions(self, invoke_evalf_before_output=False):
156 """
157 invoke_evalf_before_output: boolean
158 If your expression is a symbolic expression (default) then we use evalf
159 before we pipe it into the output. If your expression is something numeric,
160 then evalf will fail (as it is not defined for scalar quantities).
161 """
163 is_cell_mapping=True
164 )
165 for i in range(0, self.unknowns + self.auxiliary_variables):
166 if invoke_evalf_before_output:
167 result += sympy.printing.cxxcode(
168 self.initial_values[i].evalf(), assign_to="Q[" + str(i) + "]"
169 )
170 else:
171 result += (
172 "Q["
173 + str(i)
174 + "] = "
175 + sympy.printing.cxxcode(self.initial_values[i])
176 + ";"
177 )
178 result += "\n"
179 result += "assertion(!std::isnan(Q[" + str(i) + "]));\n"
180 return result
name_Q_entries(self, offset_in_Q, cardinality, name)
Definition PDE.py:94
__init__(self, unknowns, auxiliary_variables, dimensions)
Definition PDE.py:8
_implementation_of_mapping_onto_named_quantities(self, is_cell_mapping=True, is_boundary=False, has_delta=False)
Return the C code that maps the quantities from Q onto properly labelled quantities.
Definition PDE.py:34
implementation_of_boundary_conditions(self, invoke_evalf_before_output=False)
invoke_evalf_before_output: boolean If your expression is a symbolic expression (default) then we use...
Definition PDE.py:127
unknown_identifier_for_plotter(self)
Returns identifier for the unknowns.
Definition PDE.py:20
implementation_of_initial_conditions(self, invoke_evalf_before_output=False)
invoke_evalf_before_output: boolean If your expression is a symbolic expression (default) then we use...
Definition PDE.py:155
implementation_of_homogeneous_Neumann_BC(self)
Definition PDE.py:116
name_auxiliary_variable(self, number, name)
Definition PDE.py:90
name_Q_entry(self, offset_in_Q, name)
Q covers both unknowns plus auxiliary variables.
Definition PDE.py:79