File: magneticModels.py

package info (click to toggle)
python-escript 5.6-10
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 144,304 kB
  • sloc: python: 592,074; cpp: 136,909; ansic: 18,675; javascript: 9,411; xml: 3,384; sh: 738; makefile: 207
file content (226 lines) | stat: -rw-r--r-- 7,452 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
__copyright__ = "Copyright (c) 2020 by University of Queensland http://www.uq.edu.au"
__license__   = "Licensed under the Apache License, version 2.0 http://www.apache.org/licenses/LICENSE-2.0"
__credits__   = "Lutz Gross, Andrea Codd"

from esys.escript import *
from esys.escript.linearPDEs import LinearSinglePDE, SolverOptions

class MagneticModel2D(object):
    """
    This class is a simple wrapper for a 2D magnetic PDE model.  
    It solves PDE
        - div (grad u) = -div(k Bh)
    where 
       k  is magnetic susceptibility and 
       Bh is background magnetic field.
       u  is computed anomaly potential

    Possible boundary conditions are Dirichlet on 
       - one corner (bottom left),
       - vertical sides, or 
       - base.

    Requires domain and possibly boundary condition choice.  
    
    Default boundary conditions 
       - fix the left bottom corner.  
    Otherwise add 
       - fixVert = True (for all vertical surfaces fixed) or 
       - fixBase = True (for base fixed).  

    It has functions 
       - setSusceptibility
       - getSusceptibility
       - setBackgroundMagneticField
       - getAnomalyPotential
       - getMagneticFieldAnomaly.
    """

    def __init__(self, domain, fixVert=False, fixBase=False):
        """
        Initialise the class with domain and boundary conditions.
        Setup PDE, susceptibility and background magnetic field.
        : param domain: the domain 
        : type domain: `Domain`
        : param fixBase: if true the magnetic field at the bottom is set to zero. 
        : type fixBase: `bool`
        : param fixVert: if true the magnetic field on all vertical sudes is set to zero.
        : type fixVert: `bool`
        : if fixBase and fixVert are False then magnetic field is set to zero at bottom, front, left corner.
        """
        self.domain  = domain
        self.fixVert = fixVert
        self.fixBase = fixBase
        assert self.domain.getDim() == 2
        self.pde=self.__createPDE()
        self.setSusceptibility()
        self.setBackgroundMagneticField()

    def __createPDE(self):
        """
        Create the PDE and set boundary conditions.
        """
        pde=LinearSinglePDE(self.domain, isComplex=False)
        optionsG=pde.getSolverOptions()
        optionsG.setSolverMethod(SolverOptions.PCG)
        pde.setSymmetryOn()
        pde.setValue(A=kronecker(self.domain.getDim()))
        x=self.domain.getX()
        pde.setValue(A=kronecker(self.domain))
        if self.fixVert:
            pde.setValue(q = whereZero(x[0]-inf(x[0])) + whereZero(x[0]-sup(x[0]))) 
        elif self.fixBase:
            pde.setValue(q=whereZero(x[1]-inf(x[1]))) 
        else:
            pde.setValue(q = whereZero(x[0]-inf(x[0]))*whereZero(x[1]-inf(x[1]))) 
        if hasFeature('trilinos'):
            optionsG.setPackage(SolverOptions.TRILINOS)
            optionsG.setPreconditioner(SolverOptions.AMG)
        return pde
             
    def setSusceptibility(self, k=0):
        """
        set susceptibility
        : param k: susceptibility
        : type k: `Data` or `float`
        """
        self.k=k
        self.reset=True

    def getSusceptibility(self):
        """
        returns susceptibility
        : returns: k
        """
        return self.k
        
    def setBackgroundMagneticField(self, Bh=[ 0., 45000.0] ):
        """
        sets background magnetic field in nT

        """
        self.Bh=Bh
        self.reset=True
    
    def getAnomalyPotential(self):
        """
        get the potential of the the magnetic anomaly
        """
        if self.reset:
            self.pde.setValue(X = self.k*self.Bh)
        return self.pde.getSolution()

    def getMagneticFieldAnomaly(self):
        """
        get the total Magnetic field
        """
        return -grad(self.getAnomalyPotential(), ReducedFunction(self.pde.getDomain()))

class MagneticModel3D(object):
    """
    This class is a simple wrapper for a 3D magnetic forward model.  
    It solves PDE
        - div (grad u) = -div(k Bh)
    where 
       k  is magnetic susceptibility and 
       Bh is background magnetic field.
    Possible boundary conditions are Dirichlet on 
       - one corner (bottom left), 
       - vertical sides, or 
       - base.

    Input is domain and boundary condition choice.  
    Default boundary conditions fix the left front bottom corner.  
    Otherwise add 
       - fixVert = True or 
       - fixBase = True.  

    It has functions 
       - setSusceptibility
       - getSusceptibility
       - setBackgroundMagneticField
       - getAnomalyPotential
       - getMagneticFieldAnomaly.
    """

    def __init__(self, domain, fixVert=False, fixBase=False):
        """
        Initialise the class with domain and boundary conditions.
        Setup PDE, susceptibility and background magnetic field.
        :param domain: the domain 
        :type domain: `Domain`
        :param fixBase: if true the magnetic field at the bottom is set to zero. .
        :type fixBottom: `bool`
        :param fixVert: if true the magnetic field on all vertical sudes is set to zero.
        :type fixBottom: `bool`
        :if fixBottom and fixBase are False then magnetic field is set to zero at bottom, front, left corner.
        """
        self.domain  = domain
        self.fixVert = fixVert
        self.fixBase = fixBase
        assert self.domain.getDim() == 3
        self.pde=self.__createPDE()
        self.setSusceptibility()
        self.setBackgroundMagneticField()

    def __createPDE(self):
        """
        Create the PDE and set boundary conditions.
        """
        pde=LinearSinglePDE(self.domain, isComplex=False)
        optionsG=pde.getSolverOptions()
        optionsG.setSolverMethod(SolverOptions.PCG)
        pde.setSymmetryOn()
        pde.setValue(A=kronecker(self.domain.getDim()))
        x=self.domain.getX()
        pde.setValue(A=kronecker(self.domain))
        if self.fixVert:
            pde.setValue(q = whereZero(x[0]-inf(x[0])) + whereZero(x[0]-sup(x[0])) + whereZero(x[1]-inf(x[1])) + whereZero(x[1]-sup(x[1])))
        elif self.fixBase:
            pde.setValue(q=whereZero(x[2]-inf(x[2]))) 
        else:
            pde.setValue(q = whereZero(x[0]-inf(x[0]))*whereZero(x[1]-inf(x[1])) * whereZero(x[2]-inf(x[2]))) 
        if hasFeature('trilinos'):
            optionsG.setPackage(SolverOptions.TRILINOS)
            optionsG.setPreconditioner(SolverOptions.AMG)
        return pde
             
    def setSusceptibility(self, k=0):
        """
        sets susceptibility
        : param k: susceptibility
        : type k: `Data` or `float`
        """
        self.k=k
        self.reset=True

    def getSusceptibility(self):
        """
        returns the susceptibility
        : returns: k
        """
        return self.k
        
    def setBackgroundMagneticField(self, Bh=[ 0., 45000.0, 0.] ):
        """
        sets background magnetic field in nT

        """
        self.Bh=Bh
        self.reset=True
    
    def getAnomalyPotential(self):
        """
        get the potential of the the magnetic anomaly
        """
        if self.reset:
            self.pde.setValue(X = self.k*self.Bh)
        return self.pde.getSolution()

    def getMagneticFieldAnomaly(self):
        """
        get the total Magnetic field
        """
        return -grad(self.getAnomalyPotential(), ReducedFunction(self.pde.getDomain()))