Compare commits

..
Author SHA1 Message Date
Lindsey Heagy 3cbefac3ba try using list for Jv instead of datapair - has been seen to cause memory leaks 2016-06-29 15:55:34 -07:00
Lindsey Heagy e7e497a06d don't use Zero() in mapping derivs) 2016-06-29 08:45:45 -07:00
Lindsey Heagy 3157aa02cf naming update 2016-06-28 08:15:19 -07:00
Lindsey Heagy c40d11ef53 - better model for testing Parametric casing map
- allow vector containing values in the inactive set to be passed (not just nC in length)
2016-06-26 15:24:33 -07:00
Lindsey Heagy c75e3d0246 use a dictionary to keep track of parametric model parameters. Test mappings on cyl meshes, parametric casing and layer model 2016-06-25 16:51:18 -07:00
Lindsey Heagy 14f0d90f99 debugging derivs 2016-06-23 13:06:15 -07:00
Lindsey Heagy 425b1e292c only accept one source for the prim-sec source 2016-06-21 18:00:41 -07:00
Lindsey Heagy f6cd8696d1 call fields inside of SrcDeriv for primsec 2016-06-21 17:36:53 -07:00
Lindsey Heagy f788d5f05d bug hunting a silly memory issue (don't add vectors to column arrays!). return sparse matrices from mapping derivs for multiplying things 2016-06-21 17:20:02 -07:00
Lindsey Heagy 1521b08af6 remove @property from projPrimary 2016-05-31 23:48:04 -07:00
Lindsey Heagy 8c366463e7 call projection with problem 2016-05-31 23:19:02 -07:00
Lindsey Heagy 6d77ae9a12 pass problem to projection matrix in primsecsrc 2016-05-31 23:08:57 -07:00
Lindsey Heagy ce88c676d4 add a projection map (for re-arranging models)
use current sigmaModel in src
2016-05-31 22:44:39 -07:00
Lindsey Heagy 1e6ed86135 - parametrized layer
- parameterized block in layer inherits parametrized layer
2016-05-31 21:39:59 -07:00
Lindsey Heagy 9061ef5839 start of including primary fields derivs 2016-05-31 21:04:26 -07:00
Lindsey Heagy 0638fa308c start of prim sec src with more derivs 2016-05-30 20:30:00 -07:00
Lindsey Heagy 54478ad05e don't use adjoint when not asking for the adjoint! 2016-05-30 11:40:42 -07:00
Lindsey Heagy 2cf0edb736 bug fix in PrimSec src Deriv 2016-05-30 11:29:24 -07:00
Lindsey Heagy 3b5dfecb46 cleanup imports and class instantiation of prim-sec src in sigma 2016-05-30 10:05:15 -07:00
Lindsey Heagy 93d8ef5921 don't need m on the prim-sec src 2016-05-30 09:37:06 -07:00
Lindsey Heagy 5b0a58b751 typo in src input 2016-05-30 09:26:28 -07:00
Lindsey Heagy 9155a9c474 prim sec src in conductivity 2016-05-30 09:10:53 -07:00
Lindsey Heagy 64510bc606 Merge branch 'dev' into maps/feat-parametrizedBlock 2016-05-29 14:51:11 -07:00
Lindsey 09eb2106ec Merge pull request #307 from simpeg/ref/dev
Ref/dev
2016-05-29 14:50:43 -07:00
Lindsey Heagy d9f0241da3 typo fix in nC (it is mesh.nC) 2016-05-29 14:21:08 -07:00
Lindsey Heagy 9a7225c9f6 - bug fix in parametrized block when active cells are used - need a shape
- add a pole receiver for DC
2016-05-29 13:40:21 -07:00
Lindsey Heagy e8e022fcc6 return a scipy sparse matrix for the deriv (a bit silly - it is dense, but nicer for multiplication). Init Regularization with a nP 2016-05-28 15:40:28 -07:00
Lindsey Heagy 341b98d23a use layer center and layer thickness to parametrize layer 2016-05-28 13:06:19 -07:00
D Fournier 406703f1c6 Merge branch 'dev' into ref/dev
Conflicts:
	docs/examples/DC_Forward_PseudoSection.rst
2016-05-27 11:10:39 -07:00
D Fournier 7b72d3a92d Merge branch 'dev' into ref/dev
Conflicts:
	SimPEG/DCIP/DCIPUtils.py
2016-05-27 10:01:28 -07:00
Lindsey Heagy efbc8f9057 add docs for ParametrizedBlockInLayer, moved docs from rst to python files and automodule the docs for maps 2016-05-26 23:06:57 -07:00
Lindsey Heagy 39ece11d8a Merge branch 'dev' into maps/feat-parametrizedBlock 2016-05-26 21:32:57 -07:00
Lindsey cf89f5f6a2 Merge pull request #322 from simpeg/bug/propmap
Bug/propmap
2016-05-26 20:52:42 -07:00
Lindsey Heagy aa1086eba3 use fixed prop map in EM 2016-05-26 18:03:09 -07:00
Lindsey Heagy 1c53129da6 fix bug in prop map linked derivs 2016-05-26 17:58:30 -07:00
sgkang 6fd3be77de Merge pull request #304 from simpeg/dcip/dev
Dcip/dev
2016-05-26 13:27:44 -07:00
Lindsey Heagy c36b5a600d add parametrized block in a layer map 2016-05-26 10:30:10 -07:00
seogi_macbook 51d82eee26 Minor fixes to be merged to dev 2016-05-26 09:32:19 -07:00
seogi_macbook f6b49c680a Merge branch 'dev' of https://github.com/simpeg/simpeg into dcip/dev
Conflicts:
	SimPEG/EM/Base.py
	SimPEG/EM/FDEM/SurveyFDEM.py
2016-05-26 09:25:43 -07:00
seogi_macbook 339543b893 Incorporate Lindsey's comments on documenting codes 2016-05-25 23:28:58 -07:00
seogi_macbook 44ad57e90d Merge branch 'dcip/spectralIP' of https://github.com/simpeg/simpeg into dcip/dev
Merge spectral IP stuff, and incorporate Lindsey's comments
2016-05-25 14:22:58 -07:00
Lindsey d98eef2560 Merge pull request #313 from simpeg/em/dev
Em/dev: Naming conventions
2016-05-25 10:53:43 -07:00
seogi_macbook 21d817d9a2 fix bug for adjoint problem 2016-05-24 21:53:18 -07:00
seogi_macbook f20fcb4504 Minor type error based upon numpy version
Cross gradient?
2016-05-24 08:45:12 -07:00
Lindsey Heagy 2c87a50d29 add kwargs to raw vec e,m 2016-05-23 12:21:29 -07:00
Lindsey Heagy beca0203df typo fix 2016-05-23 12:11:03 -07:00
Lindsey Heagy e25b496ab0 allow kwarg input of primary fields 2016-05-23 12:07:14 -07:00
Lindsey e5ec512517 Merge pull request #319 from simpeg/targetmisfit
Target Misfit
2016-05-22 12:36:21 -07:00
Lindsey 342414bd25 Merge pull request #302 from simpeg/fix/numpyDependency
Installation (i.e., setup.py) is no longer dependent on Numpy
2016-05-22 12:03:37 -07:00
Lindsey Heagy 8936fa4021 use phi_d_star, chifact in defining target misfit 2016-05-22 11:42:23 -07:00
seogi_macbook 0179631fe3 Starting Cross gradient ... 2016-05-20 01:57:40 -07:00
seogi_macbook c4c97ae054 Ad MultiRegularization for inverting multiple parameters 2016-05-20 00:04:20 -07:00
seogi_macbook e8bd78f63d Working Spectral IP:
- Fwd
	- Jvec
	- Jtvec
2016-05-19 02:09:48 +09:00
Lindsey d0a65dda1b Merge pull request #317 from simpeg/em/ref/dev-cleanup
em/dev cleanup
2016-05-18 08:13:06 -07:00
Lindsey Heagy a506d5c6be Merge branch 'em/dev' into em/ref/dev-cleanup 2016-05-18 07:31:15 -07:00
Lindsey Heagy 10c8791514 update base MT to import ProblemFDEM 2016-05-18 00:33:30 -07:00
Lindsey Heagy c88263234b rename FDEM --> ProblemFDEM 2016-05-17 23:56:06 -07:00
Lindsey Heagy d5219be3d8 Merge branch 'dev' into dcip/dev
# Conflicts:
#	SimPEG/DCIP/DCIPUtils.py
2016-05-17 23:26:17 -07:00
Lindsey Heagy 029171fb1d use .format for strings 2016-05-11 09:09:26 -07:00
Lindsey Heagy a690cab131 simple field receivers are Point receivers 2016-05-11 09:05:13 -07:00
Lindsey Heagy c1b1c2467f import from ProblemFDEM in baseMT, fixed a missed real_or_imag --> component 2016-05-10 19:57:16 -07:00
Lindsey Heagy 11e6b452c9 renamed FDEM.py to ProblemFDEM.py, changed real_or_imag to component 2016-05-10 17:26:16 -07:00
Lindsey Heagy 73c219ff5c updated Problem naming in casing example 2016-05-09 12:29:52 -07:00
Lindsey Heagy abd919e862 Merge branch 'dev' into em/dev 2016-05-09 11:32:59 -07:00
Lindsey 6e00b4c2fe Merge pull request #312 from simpeg/em/ref/fdem_cleanup
Em/ref/fdem cleanup
2016-05-09 08:25:39 -07:00
Lindsey 906cca30f3 Merge pull request #311 from simpeg/feat/cyl2cartinterp
Feat/cyl2cartinterp
2016-05-09 08:24:16 -07:00
seogi_macbook 8803956d83 Working on SIP 2016-05-09 19:58:56 +09:00
Lindsey Heagy 0a714663d3 update Jtvec to work with Rx classes 2016-05-08 13:12:37 -07:00
Lindsey Heagy cb042ac938 cleanup imports, docstrings 2016-05-08 13:00:29 -07:00
Lindsey Heagy f7c46ed83b Rx classes for FDEM 2016-05-08 12:41:06 -07:00
Lindsey Heagy 52747c0926 update example 2016-05-08 11:35:28 -07:00
Lindsey Heagy d8eeb7cd05 use Problem3D_assumption, Fields3D_assumption 2016-05-08 11:18:36 -07:00
Lindsey Heagy 8278230476 Use LocTypeTo to allow interpolation to different grid locations 2016-05-08 10:35:27 -07:00
Lindsey Heagy 069127333d allow interpolation to different cartsian grid locations 2016-05-05 16:41:21 -07:00
Lindsey 79e1378009 Merge pull request #305 from simpeg/feat/sparse-regularization
Feat/sparse regularization
2016-05-04 22:30:06 -07:00
Lindsey Heagy 0379df2bf2 attempt to clean up docs in DCIP utils 2016-05-04 22:27:02 -07:00
Lindsey Heagy 66440b0478 add depreciation warnings to DCIP utils for activeind from topo 2016-05-04 22:14:41 -07:00
Lindsey Heagy dbdcc3cefb use sigma in MfRhoDeriv - due to propmap bug 2016-05-04 22:06:32 -07:00
D Fournier 4e296c4cd5 Update PreCond Directive to allow inactive cells mapping 2016-05-04 16:01:29 -07:00
seogi_macbook c488dabf9a working on IP 2016-05-04 12:48:29 -07:00
Lindsey 5e1de61a71 Merge pull request #308 from simpeg/bug/reg-indactive
if mapping is none, create an identity map that is size indactive.nonzero
2016-05-03 21:20:54 -07:00
seogi_macbook 69ec374415 minor changes 2016-05-03 19:03:41 -07:00
sgkang 224105364d df_dmT + du_dmT has dtype('o')
This seems making problem depending on which machine you are using .... or numpy version. 

We may need to clarify what is sparse and dense for arrays!!
2016-05-03 17:39:07 -07:00
Lindsey Heagy 00bbe0f35e if mapping is none, create an identity map that is size indactive.nonzero for regularization 2016-05-03 15:04:36 -07:00
seogi_macbook a7f89131b4 Playing with 2.5D DC inversion
TODOs:

     Parallelize ky ... (currently pretty slow)
2016-05-03 11:26:28 -07:00
seogi_macbook 6e12bdc57a Moving Dom's DCutils ... 2016-05-03 09:20:58 -07:00
seogi_macbook 354e57f24e Problem3D_CC and _N for IP are all tested
a) fwd
b) jvec, jtvec
c) adjoint
2016-05-02 16:47:16 -07:00
seogi_macbook ddb11096c8 Working on IP 2016-05-02 15:05:31 -07:00
seogi_macbook fa6033c438 Working 3D IP problem (CC and N). 2016-05-02 12:00:39 -07:00
Lindsey Heagy dd45a6a085 name updates in DC_Forward_PseudoSection, DC_Utils, example for Utils_surface2ind_topo 2016-05-02 11:40:02 -07:00
seogi_macbook bd63e67161 working on IP
fix bug in RhoDeriv!!
2016-05-02 10:03:01 -07:00
seogi_macbook d350dc258d minor fix for Fields_N and started IP problem. 2016-05-02 08:55:29 -07:00
seogi_macbook 350818d802 add analytic test for 2D dc problems. 2016-05-01 13:21:48 -07:00
Lindsey Heagy ba8f270b3a start of surface2ind_topo 2016-05-01 13:17:16 -07:00
seogi_macbook 4df6f340d3 Add _e, _j, _charge for field objects
Now it is possible to gram three of them from phiSolution
2016-05-01 13:13:20 -07:00
seogi_macbook 9b2eec0ea3 Working 2.5D nodal discretization (Jvec and Jtvec) 2016-05-01 12:33:39 -07:00
D Fournier 3d1dfc13d7 Change Update_PreConditioner to default False 2016-04-29 15:49:44 -07:00
D Fournier a6e995e9fb Merge branch 'feat/meshutils' into feat/sparse-regularization 2016-04-29 15:42:42 -07:00
D Fournier 056dc09fa6 Fix Update_Precondition directive 2016-04-29 15:10:30 -07:00
Lindsey Heagy 4257ea77b3 remove InjectActiveCellsTopo. you should use InjectActiveCells 2016-04-29 15:09:04 -07:00
Lindsey Heagy a0174e4f30 kwarg name updates 2016-04-29 12:52:45 -07:00
Rowan Cockett 00db6746d4 Add a warnign about mesh attributes 2016-04-29 11:50:56 -07:00
Rowan Cockett 028a16a45a Syntax bug. 2016-04-29 11:44:42 -07:00
Rowan Cockett c83b460672 Surface to Indices (GoCAD and VTK) 2016-04-29 11:43:31 -07:00
D Fournier 225394f74e Latest commit 2016-04-29 11:10:04 -07:00
Lindsey ace9cad016 Merge pull request #303 from simpeg/dcip/ref
Dcip/ref
2016-04-29 10:49:50 -07:00
seogi_macbook 38aef03f9d Working 2.5D fwd (nodal discretization)
On going Jvec and Jtvec
2016-04-29 09:35:03 -07:00
seogi_macbook ef602eaab1 working Jtvec 2016-04-28 18:13:18 -07:00
seogi_macbook 0610289fdf Working Jvec for 2.5D DC code 2016-04-28 11:18:37 -07:00
seogi_macbook d14cd444ac working 2.5D fwd problem. 2016-04-27 23:04:28 -07:00
seogi_macbook 92e2fd67de minor fixes. 2016-04-27 15:25:40 -07:00
seogi_macbook 6a064c5f96 Minor changes 2016-04-25 11:00:32 -07:00
seogi_macbook f944f9b76b 1. Add distributed source for nodal discretization
2. Add Analytic tests
3. Fix simple bug in PlotSlice for nodal variable
4. Add more analytic function (sphere)
2016-04-25 10:58:54 -07:00
seogi_macbook dcd4fbf973 Implemented mixed B.C. to CC problem.
Fix bugs in get fuction getxBCyBC_CC
2016-04-24 15:23:14 -07:00
seogi_macbook edc2c5feb6 Merge branch 'dcip/BC' of https://github.com/simpeg/simpeg into dcip/ref 2016-04-24 13:57:01 -07:00
seogi_macbook 1936a04683 Working on implementing mixed BC to DC problem 2016-04-24 13:56:37 -07:00
seogi_macbook fcc2b8b22a Handling null space of A 2016-04-24 13:32:44 -07:00
seogi_macbook eeee594f09 Problem3D_N is tested! 2016-04-24 13:29:38 -07:00
seogi_macbook a48224ed8b no message 2016-04-24 13:18:36 -07:00
seogi_macbook 0bb001973c workking nodal discretizations 2016-04-24 13:01:03 -07:00
Brendan Smithyman f55d9573a6 Installation (i.e., setup.py) is no longer dependent on Numpy already being present. 2016-04-24 13:21:49 -04:00
D Fournier d8bfb27415 Quick fix to MeshIO 2016-04-23 15:25:44 -07:00
seogi_macbook 0e16645b67 working Jtvec 2016-04-23 11:06:24 -07:00
seogi_macbook 8cac166fba Working Jvec:
Getting closer to understand how modular EM code is working ...
2016-04-23 10:40:47 -07:00
seogi_macbook 73001abfc5 fix bug 2016-04-23 01:24:31 -07:00
seogi_macbook a9362bd38e Merge branch 'dcip/ref' of https://github.com/simpeg/simpeg into dcip/ref
Conflicts:
	SimPEG/EM/Static/DC/ProblemDC.py

Confused about ...  this line

self.mesh.getFaceInnerProduct(self.curModel.rho)(u)
2016-04-23 00:37:06 -07:00
seogi_macbook 64b94861a0 working on DC problem CC and N 2016-04-22 23:09:31 -07:00
Lindsey Heagy 8775364d8f start of the sketch of Jvec (not to be trusted yet!) 2016-04-22 17:48:26 -07:00
Lindsey Heagy 5ec6e79a39 MfRhoIDeriv 2016-04-22 17:47:36 -07:00
D Fournier 79183ae9fb fIX MESH io 2016-04-22 16:05:43 -07:00
D Fournier 606488d152 Major fix to IRLS. 2016-04-21 21:58:40 -07:00
seogi_macbook 2c09be9fc1 Working Mixed boundary conditions and testing ... 2016-04-21 14:44:37 -07:00
Lindsey Heagy cd5339322e sketch of DC 2016-04-21 11:00:20 -07:00
seogi_macbook 28005dde45 change minor bug for meshIO 2016-04-15 17:17:18 -07:00
seogi_macbook 8739ba0f20 working dc fwd 2016-04-15 16:53:43 -07:00
Lindsey Heagy 119bc801c7 start of DC refactor in EM/Static 2016-04-15 14:51:19 -07:00
GudniRos 23d2783bc1 Finalizing the pull request from mt/iss290 in to dev. 2016-04-15 12:31:00 -07:00
GudniRos b58ba55ffd Merge branch 'mt/iss290' into dev 2016-04-15 12:21:57 -07:00
GudniRos 0d6fe5f7a1 Merge branch 'dev' into mt/iss290 2016-04-15 12:03:09 -07:00
seogi_macbook 35bac38c8b working on mixed BC 2016-04-14 22:41:47 -07:00
seogi_macbook 05e3b02b3a Merge branch 'dcip/dev' of https://github.com/simpeg/simpeg into dcip/dev 2016-04-13 16:52:44 -07:00
Lindsey bd318f0092 Merge pull request #294 from simpeg/patch/mutable-arguments
remove mutable arguments.
2016-04-08 17:12:20 -07:00
GudniRos 90b0301408 Fixing bug in write out. 2016-04-08 09:40:26 -07:00
GudniRos 083742cb40 Removing repeated directives 2016-04-08 09:34:30 -07:00
Lindsey 2a351be971 Merge pull request #289 from simpeg/patch/sparse-dcip
Patch/sparse dcip
2016-04-07 18:43:07 -07:00
Rowan Cockett 3e4f47711c remove mutable arguments. 2016-04-07 16:35:47 -07:00
D Fournier e305600de5 Update example list. Add comments for the DC_Forward_PseudoSection example. Fix Z of pseudo section plot. 2016-04-07 13:09:28 -07:00
GudniRos 8a18e479ab Removed the testProjDeriv (not needed, included in Jvec). 2016-04-07 11:48:17 -07:00
D Fournier d13c540be0 Uppercase on class names. Add flag for Directive.Update_Wj. Remove trailing spaces. Remove old DC example. 2016-04-07 09:25:20 -07:00
GudniRos f15a628136 Moved the osr import into the projection function. 2016-04-07 09:01:30 -07:00
GudniRos fb60f45a3c Fixed osr import in ediFilesUtils, moved into class which imports only on build up.
Fixed the boolean error in Directives.
2016-04-07 08:46:51 -07:00
D Fournier 822f6d333d Minor revisions + remove trailing white spaces 2016-04-06 22:29:57 -07:00
D Fournier 6000034826 Merge branch 'dcip/dev' into patch/sparse-dcip 2016-04-06 22:18:31 -07:00
D Fournier 16c6cc8d74 Update speudo plot and allow app_res, app_con, volt 2016-04-06 22:17:34 -07:00
Lindsey Heagy 636d178fbf removed examples that are in Examples PR 2016-04-06 16:19:39 -07:00
Lindsey 0575490f56 Merge pull request #288 from simpeg/feat/gitter-badge
Add gitter chat
2016-04-06 16:15:59 -07:00
Lindsey Heagy ae9ca6cec9 Merge branch 'feat/sparse-regularization' into patch/sparse-dcip
# Conflicts:
#	SimPEG/Examples/__init__.py
#	SimPEG/Optimization.py
2016-04-06 14:53:45 -07:00
D Fournier f799733a9d Fix TwoSphere example and Utils.pseudoPlot 2016-04-06 14:43:33 -07:00
Rowan Cockett 2bd5829b42 Add gitter chat 2016-04-06 13:15:03 -07:00
D Fournier 8b94cd4dfe Change flag for convertObs_DC3D_to_2D, which broke the example 2016-04-06 09:14:14 -07:00
D Fournier 09f3f7b55b Merge branch 'dev' into dcip/dev 2016-04-06 09:03:37 -07:00
D Fournier 15d59a5b50 Fix typos in Directives.update_Wj. overseer @lheagy 2016-04-06 09:00:13 -07:00
D Fournier e646211e7d Review Utils.gen_DCIPsurvey ... lets keep it. 2016-04-06 08:55:52 -07:00
D Fournier ba977206ea Create sensitivity re-weighting directive
Adapt Map/polymap for actInd (topography)
2016-04-06 07:22:18 -07:00
seogi_macbook fb1ff4e867 Merge branch 'dev' of https://github.com/simpeg/simpeg into dcip/dev 2016-04-05 21:50:03 -07:00
seogi_macbook a31319b46e Merge branch 'master' of https://github.com/simpeg/simpeg into dcip/dev 2016-04-05 21:49:38 -07:00
Lindsey Heagy d8aec96080 Merge branch 'master' into dev 2016-04-05 17:51:27 -07:00
Lindsey aad596a8cc Merge pull request #282 from simpeg/example/EM_FDEM_1D_Inversion/patch
Better list comprehension.
2016-04-05 17:41:05 -07:00
Rowan Cockett 8d6bd65923 Better list comprehension. 2016-04-05 14:26:45 -07:00
D Fournier df620b42bd Fix plotting for Linear_IRLS example 2016-04-05 13:23:08 -07:00
Lindsey 31d418bed8 Merge pull request #253 from simpeg/bug/opt/projected-gradient
Allow moving off bounds in projected gradient
2016-04-05 12:27:48 -07:00
D Fournier 7a6f4e0780 Merge branch 'master' into feat/sparse-regularization 2016-04-03 17:26:57 -07:00
D Fournier 2ee158e5d7 Add distance weighting to example
TO DO: Create example with and without distance weights
2016-04-03 17:26:04 -07:00
D Fournier 8f73b2e7be Update directives
Add IRLS example
2016-04-03 17:18:39 -07:00
D Fournier 16d62a6d0a Merge branch 'Examples' into feat/sparse-regularization
Conflicts:
	SimPEG/Examples/__init__.py
2016-04-03 11:11:35 -07:00
Lindsey Heagy 5d9d746932 kwarg for stepping off bounds in projected gradient 2016-04-03 10:42:28 -07:00
Lindsey df3d32cb35 Merge pull request #269 from simpeg/feat/casingexample
Feat/casingexample
2016-04-02 08:47:25 -07:00
Lindsey Heagy f59cfa9481 Merge branch 'dev' into em/dev 2016-04-02 08:35:09 -07:00
Lindsey 99ed4ad50e Merge pull request #274 from simpeg/ref/fforfields
use `f` for fields and `u` for a solution vector
2016-04-02 08:34:04 -07:00
Lindsey Heagy b531c162a2 tab so we don't cut off the first characters in the docstring 2016-03-31 23:50:35 -07:00
Lindsey a220c75d78 Merge pull request #273 from simpeg/em/patch/srcIntegration
make integrate = False default for all sources
2016-03-31 11:17:54 -07:00
Lindsey Heagy c7883673bf added the figshare doi link for the example 2016-03-31 09:36:55 -07:00
Lindsey Heagy d8d8915f94 f for fields in data misfit, directives etc. Previously, f was used in the InvProblem to be the function value for the objective function --> this has been renamed to phi 2016-03-31 09:28:48 -07:00
Lindsey 35c6d50db1 Merge pull request #272 from simpeg/em/dev
Em/dev
2016-03-30 07:17:54 -07:00
Lindsey Heagy 9c220ef37c default is mrefInSmooth = False 2016-03-29 23:05:04 -07:00
Lindsey Heagy 0a0caceaca Problem.Jvec, Problem.Jtvec, Problem.fields, DataMisfit, survey.dpred take a fields object f (not a solution vector, u) 2016-03-29 22:49:03 -07:00
Lindsey Heagy 936a7aaadc make integrate = False default for all sources 2016-03-29 21:32:08 -07:00
Lindsey 44049bb48c Merge pull request #270 from simpeg/master
bumpversion
2016-03-29 20:57:15 -07:00
Lindsey 1d208a8747 Merge pull request #267 from simpeg/em/ref/notation
Em/ref/notation
2016-03-29 15:46:16 -07:00
Lindsey Heagy b6438688d8 removed link for Schenkel paper (it seems to time-out) 2016-03-29 15:40:06 -07:00
Lindsey Heagy 824ce64c7e more descriptive titles 2016-03-29 14:56:56 -07:00
Lindsey Heagy 7aa5599211 improve the description 2016-03-29 14:41:45 -07:00
Lindsey Heagy fbec011983 typo fix 2016-03-29 14:29:39 -07:00
Lindsey Heagy 5fb8cdb88c example casing forward simulation to calculate vertical current 2016-03-29 13:00:37 -07:00
Lindsey Heagy b765699d2f seperated out smallness and smoothness contributions 2016-03-25 23:26:52 -07:00
Lindsey Heagy b4f329f65a Bump version: 0.1.9 → 0.1.10 2016-03-23 13:04:18 -07:00
Lindsey 82c1afd128 Merge pull request #265 from simpeg/dev
Dev
2016-03-23 12:43:33 -07:00
D Fournier fdc081970e Merge branch 'feat/sparse-regularization' into dcip/dev 2016-03-21 15:03:59 -07:00
Lindsey Heagy c66db805af typo fix 2016-03-20 14:44:34 -07:00
Lindsey Heagy 579f1d7a65 FDEM uses f (so the u kwarg breaks). replace with f across the entire codebase?? 2016-03-20 13:36:19 -07:00
Lindsey Heagy c51afa4aad s_m, s_e are vectors (so they should not be capitalized) 2016-03-20 13:04:02 -07:00
Lindsey Heagy cc9d2e5ac7 we don't support m is none 2016-03-20 12:18:07 -07:00
Lindsey Heagy 055061ac3b abstracted FDEM survey to BaseEMSurvey (with methods eval and eval deriv) as this should be common to FDEM and TDEM problems (only implemented on FDEM problem, TDEM inheritance will be taken care of on the TDEM refactor branch) 2016-03-20 12:15:52 -07:00
Lindsey Heagy d5f73d0fd3 f_src is actually u_src 2016-03-20 11:56:58 -07:00
Lindsey Heagy 3d11431f2f use f where we are talking about fields 2016-03-20 11:47:57 -07:00
D Fournier f92ff1301d Add reference model in compact term. 2016-03-17 18:45:09 -07:00
D Fournier d302a59b2c Change the projection from 3D to 2D 2016-03-16 11:43:25 -07:00
D Fournier ef467efce0 Small change to directive 2016-03-15 20:56:38 -07:00
Lindsey Heagy 7fd6ddf62a Merge branch 'master' into dev 2016-03-13 11:18:05 -07:00
D Fournier d226186c8e Add auto-beta adjustment. 2016-03-11 15:09:31 -08:00
D Fournier 38b4079f0b Move cell-based weights (i.e. distance weighting) inside regularization.
Fix gamma parameter update
TO DO: Check inversion print screen -> values don't match reality.
2016-03-11 11:40:47 -08:00
D Fournier 9d4e2488f3 Merge branch 'dcip/dev' of https://github.com/simpeg/simpeg into dcip/dev
Conflicts:
	SimPEG/DCIP/DCIPUtils.py
2016-03-10 14:33:06 -08:00
Lindsey Heagy 838035adae fixed indentation level on test_regularization 2016-03-10 14:30:43 -08:00
Lindsey Heagy ef4513bcd4 some cleanup inside of sparse regularization 2016-03-10 14:25:53 -08:00
D Fournier 4fefccc97d Add readPUBC_DC2Dpre 2016-03-10 14:25:27 -08:00
seogi_macbook 1946e1f69e minor change for plotting 2016-03-09 15:49:08 -08:00
Lindsey Heagy 33c9059e4e SparseRegularization --> Sparse 2016-03-08 16:40:02 -08:00
Lindsey 46a8707b64 Merge pull request #257 from simpeg/em/dev
Em/dev
2016-03-08 16:36:30 -08:00
Lindsey 6a2caf5efc Merge pull request #263 from simpeg/em/ref/FDEMJvec
Em/ref/fdem jvec
2016-03-07 16:42:35 -08:00
Lindsey Heagy ab1108c9c2 - _fieldType --> _solutionType
- light cleanup of conversion to numpy arrays in Jvec
2016-03-07 13:31:15 -08:00
Lindsey Heagy b30fe88a7a fieldType --> solutionType 2016-03-07 13:07:25 -08:00
Lindsey 25cd9c16a7 Merge pull request #261 from simpeg/em/ref/eqlocs
eqlocs --> formulation in em
2016-03-06 23:21:16 -08:00
Lindsey Heagy d9b3c038c4 Merge branch 'dev' into feat/sparse-regularization
# Conflicts:
#	SimPEG/Regularization.py
#	SimPEG/Survey.py
2016-03-06 23:01:59 -08:00
Lindsey Heagy 8412ad90c2 eqlocs --> formulation in em 2016-03-06 21:01:58 -08:00
Lindsey cb2151b1d6 Merge pull request #236 from simpeg/dcip/dev
DC merge.
2016-03-06 08:08:13 -08:00
seogi_macbook 20c35f3d16 clean up import solver 2016-03-04 11:04:11 -08:00
seogi_macbook 5d67f79257 Reduce size of the test.
Travis is not using pymatsolver for dcip branch. This should be fixed.
2016-03-04 10:45:28 -08:00
seogi_macbook 9062f6d326 trying to pass travis 2016-03-04 10:35:20 -08:00
seogi_macbook db63779b9b change gen_DCIPsurvey to output survey class 2016-03-03 16:19:53 -08:00
seogi_macbook d31ef027d7 comment regularizations 2016-03-03 15:14:49 -08:00
seogi_macbook f73d0a3b4a Merge branch 'dcip/dev' of https://github.com/simpeg/simpeg into dcip/dev
Conflicts:
	SimPEG/Regularization.py
2016-03-03 15:12:05 -08:00
seogi_macbook e4506a8773 blah 2016-03-03 14:54:00 -08:00
seogi_macbook e4cbc584dc ss 2016-03-03 14:06:18 -08:00
Lindsey Heagy 2f8b8a36bf smoothModel --> mrefInSmooth 2016-03-02 09:46:50 -08:00
Lindsey Heagy 834de58284 projectFields --> eval 2016-03-01 18:02:33 -08:00
Lindsey Heagy cba52c3b81 Merge branch 'dev' into dcip/dev
# Conflicts:
#	SimPEG/Examples/Inversion_Linear.py
2016-03-01 17:56:10 -08:00
Lindsey Heagy 5e5c7ba0fb docs for regmesh, cellGrad--> cellDiff, faceDiv--> faceDiff for regmesh 2016-03-01 17:31:37 -08:00
Lindsey 6e0a54b319 Merge pull request #255 from simpeg/em/rx
Em/rx
2016-02-27 16:08:16 -08:00
Lindsey Heagy 5c8fba4242 changing btwn e,j and h,b depends on which formulation we are going between and is now in the fields object 2016-02-27 15:44:07 -08:00
D Fournier 6c33455d15 update Directive for sparse norm 2016-02-25 08:56:18 -08:00
D Fournier 7000699e38 Merge branch 'feat/sparse-regularization' of https://github.com/simpeg/simpeg into feat/sparse-regularization 2016-02-24 21:00:02 -08:00
D Fournier 63bf8b9e4d Add linear survey 2016-02-24 20:59:51 -08:00
Lindsey Heagy e3af1fd94e convert indActive to a bool if an integer list is provided 2016-02-24 20:28:09 -08:00
Lindsey Heagy 4e871a43a9 prototype of defining regularization mesh within Regularization.py for constructing operators for regularization that are not true differential operators 2016-02-24 18:03:42 -08:00
D Fournier 020332aec5 DCIP Changes 2016-02-24 15:25:56 -08:00
Lindsey Heagy ac008e7253 Merge branch 'em/dev' into em/rx
# Conflicts:
#	SimPEG/EM/FDEM/SurveyFDEM.py
2016-02-22 11:11:10 -08:00
Lindsey Heagy 52cc92f699 Merge branch 'dev' into em/dev
# Conflicts:
#	SimPEG/EM/FDEM/FDEM.py
2016-02-22 11:07:08 -08:00
Lindsey 8bd4eedb83 Merge pull request #256 from simpeg/ref/rx-eval
rx.projectFields --> rx.eval
2016-02-22 11:03:46 -08:00
Lindsey Heagy bcda60815e - rx.projectFields --> rx.eval
- rx.projectFieldsDeriv --> rx.evalDeriv
2016-02-21 15:31:02 -08:00
Lindsey Heagy f37235973b adjoint debugging 2016-02-21 11:33:15 -08:00
Lindsey Heagy feff936c92 cleanup of tests and debugging derivs 2016-02-21 11:02:29 -08:00
Lindsey Heagy 6aa9b533ba include mu in testing, cleanup and debugging in dipole sources 2016-02-21 10:36:46 -08:00
Lindsey Heagy 4df932ccfc notation cleanup 2016-02-21 10:35:27 -08:00
Lindsey Heagy 3e673d34f1 - each of e,b,h,j from every formulation. Currently, b from j is first order
- removed CCV primary and secondary (dangerous the way it was previously done)
- NOTE: Source derive may not be properly taken care of yet
2016-02-20 17:05:43 -08:00
Lindsey Heagy f1527f994b e,b,h,j from j formulation 2016-02-20 14:30:55 -08:00
Lindsey Heagy 0646a930ab e,b,h,j from b formulation 2016-02-20 13:27:51 -08:00
Lindsey Heagy 0edbc9f6ca docs for fields_e 2016-02-20 11:13:09 -08:00
Lindsey Heagy ce49249664 e,b,h,j with deriv and adjoint from e formulation 2016-02-20 11:05:25 -08:00
Lindsey Heagy 4c3c2c361c - merge em/dev
- start of j data from e
2016-02-20 10:13:37 -08:00
Lindsey 40d39d751a Merge pull request #244 from simpeg/em/FDEMfieldsDerivs
Em/fdem fields derivs
2016-02-20 09:11:49 -08:00
Lindsey Heagy b5f4d8e999 typo in Regularization.py 2016-02-19 17:43:50 -08:00
Lindsey Heagy 649525fa88 keep track of _v with notation 2016-02-19 17:31:43 -08:00
Lindsey 922bdf93e1 Merge pull request #246 from simpeg/ref/MappingNotation
Naming conventions in Maps (re #231)
2016-02-19 17:25:11 -08:00
D Fournier cd352dc5f7 Merge branch 'dcip/dev' of https://github.com/simpeg/simpeg into dcip/dev 2016-02-19 16:42:13 -08:00
D Fournier a7c35abd56 Major re-write for the IO and pseudo-section function.
Will need to adapt the example.
2016-02-19 16:41:59 -08:00
Lindsey Heagy e4a3e0a16d break out the Pac, Pafx, ... and make part of base regularization 2016-02-19 16:23:26 -08:00
Lindsey Heagy a5be262171 add future warnings for new map names to ensure backwards compatibility (for a time) 2016-02-17 14:32:49 -08:00
Rowan Cockett 16239aa414 Merge branch 'dev' of https://github.com/simpeg/simpeg into dcip/dev
# Conflicts:
#	SimPEG/Examples/__init__.py
2016-02-16 22:14:22 -08:00
Rowan Cockett 1c2fecf3a2 Add the IRLS Directive. 2016-02-16 22:07:33 -08:00
Rowan Cockett 9bf4a6228d Remove the update_IRLS and move to PR #254. 2016-02-16 22:06:17 -08:00
Rowan Cockett 226a28f611 Remove regularization and diff op changes, and deal with these in a separate PR #254. 2016-02-16 22:01:50 -08:00
Rowan Cockett c10777a245 Addition of unitCellGrad. Possibly rename to cellGradStencil? 2016-02-16 22:00:12 -08:00
Rowan Cockett 05a85018de Create a Simple and a SparseRegularization class.
The SparseRegularization class allows implementation of p-q norms.
2016-02-16 21:59:08 -08:00
Rowan Cockett 4c547d22c6 Move the optimization code into PR #253. 2016-02-16 21:55:21 -08:00
Rowan Cockett 8aa23c31de Allow moving off bounds in projected gradient.
The current implementation does not allow you to move off the
bounds (lower/upper) once you have gotten on them, this allows you
to move off of the bound.

Please note that more testing should be done to ensure that this does
not introduce oscillations into the optimization routine.
2016-02-16 21:53:31 -08:00
Rowan Cockett fb1973cfe4 Merge pull request #211 from simpeg/mt/dev
Merge MT into dev
2016-02-16 17:14:49 -08:00
Lindsey Heagy 4067106956 fixed merge conflict in examples __init__.py 2016-02-16 16:14:41 -08:00
Lindsey 980a382613 Merge pull request #252 from simpeg/em/dev
Em/dev
2016-02-16 16:09:07 -08:00
Rowan Cockett e464fc0dfd Reduce number of frequencies in forward problem MT example. 2016-02-16 14:55:17 -08:00
GudniRos 015b940130 Ran Example/__init__.py 2016-02-16 13:26:58 -08:00
Rowan Cockett 6ccfa71dd7 Merge branch 'dcip/dev' of https://github.com/simpeg/simpeg into dcip/dev 2016-02-16 13:01:48 -08:00
Rowan Cockett 1d06b768e2 Remove second derivatives in simple regularization 2016-02-16 13:01:32 -08:00
D Fournier cb9e820eb3 Merge branch 'dcip/dev' of https://github.com/simpeg/simpeg into dcip/dev 2016-02-16 12:36:22 -08:00
D Fournier d6664155c6 Start changing the IO to use Survey class 2016-02-16 12:35:36 -08:00
Rowan Cockett e4c30705ff Clean up whitespace in optimization. 2016-02-16 09:47:07 -08:00
Rowan Cockett 059850f282 Clean examples and remove duplicate. 2016-02-16 09:41:24 -08:00
Thibaut Astic a9c9ce6bc8 remove ipywidget 2016-02-15 19:50:04 -08:00
Thibaut Astic 6286e48830 Sphere Electrostatic example. code cleaned, commented and updated. 2016-02-15 13:13:44 -08:00
Rowan Cockett ea6ec4cb55 Integration in sources and documentation. 2016-02-15 10:56:09 -08:00
Lindsey Heagy 20f7f9be1d updated map names in TDEM testing 2016-02-14 21:23:38 -08:00
Lindsey 44359d4306 Merge pull request #245 from simpeg/em/patch-rxprojectfieldsnotation
use f to denote fields in the project fields and project fields deriv
2016-02-14 15:43:46 -08:00
Lindsey Heagy 2c4055aec1 Naming conventions in Maps (re #231)
- FullMap --> SurjectFull
- Vertical1DMap --> SurjectVertical1D
- Map2Dto3D --> Surject2Dto3D
- ActiveCells --> InjectActiveCells
- ActiveCellsTopo --> InjectActiveCellsTopo
2016-02-14 15:43:32 -08:00
Lindsey Heagy 3f2396ad33 use f to denote fields in the project fields and project fields deriv 2016-02-14 15:10:27 -08:00
Lindsey Heagy 8b152f3890 adjoint of fields deriv now returns a tuple (so you don't call derivs wrt _u, _m independently 2016-02-14 12:28:25 -08:00
Lindsey Heagy 64d89cfb6c - simplified sensitivity calculation for FDEM : only look at fields once (pass it two vectors)
- moved common elements from fields object into base fields object
2016-02-14 11:56:39 -08:00
Thibaut Astic 4cf5d49524 Ignoring non functioning examples 2016-02-12 15:48:48 -08:00
Thibaut Astic 88ef74ac38 MT_1D_analytic example 2016-02-12 15:40:48 -08:00
seogi_macbook c1bd8edf77 return DCdata class? 2016-02-11 15:29:16 -08:00
seogi_macbook d9c94b9793 Move stuff to DCIPUtils.py 2016-02-11 14:10:44 -08:00
seogi_macbook 3a506b9051 Fix DC examples ... 2016-02-11 08:54:44 -08:00
seogi_macbook fa6bcd3ffa Minor changes 2016-02-11 00:10:25 -08:00
seogi_macbook 47895ef270 consistent file name 2016-02-10 23:58:48 -08:00
seogi_macbook 429d8b1191 Add EM_FDEM_SusEffects example 2016-02-10 23:45:19 -08:00
seogi_macbook 774d612c18 Merge branch 'master' of https://github.com/simpeg/simpeg into Examples
Conflicts:
	SimPEG/Examples/__init__.py
2016-02-10 23:38:51 -08:00
GudniRos 186708f8de Fixed an error with u refactoring 2016-02-10 07:24:49 -08:00
GudniRos c8c034cc2d Changed default input of Jvec for f to u 2016-02-10 07:06:57 -08:00
seogi_macbook 60e18eef01 Working on reading DCIP 3D 2016-02-09 16:11:25 -08:00
Lindsey 8ba9815137 Merge pull request #241 from simpeg/dev
Dev
2016-02-09 15:39:16 -08:00
Lindsey 463b9b6164 Merge pull request #240 from simpeg/em/dev
Em/dev
2016-02-09 08:04:45 -08:00
GudniRos 97336129de Checkout a updated file from Seogi. 2016-02-08 22:25:42 -08:00
GudniRos cdf7c0edc1 Changed the name string. 2016-02-08 22:22:39 -08:00
Lindsey Heagy 92c83c88d4 Merge branch 'em/dev' of https://github.com/simpeg/simpeg into em/dev 2016-02-08 14:01:14 -08:00
Lindsey Heagy 5da9235eb4 light code cleanup 2016-02-08 12:58:04 -08:00
Lindsey e8712a9f4a Merge pull request #238 from simpeg/em/docs
Em/docs
2016-02-08 09:27:06 -08:00
Lindsey Heagy 00774176f3 cleanup of math 2016-02-08 08:55:02 -08:00
Lindsey Heagy f9359b7f08 a couple typo fixes 2016-02-07 13:07:40 -08:00
Lindsey Heagy 81c13b12e3 cleanup of docs, docs for survey 2016-02-07 13:04:13 -08:00
Lindsey Heagy cb9a70bacc docs for source 2016-02-07 12:53:57 -08:00
Lindsey Heagy e7b69dccfd FDEM Fields object docs 2016-02-07 11:31:00 -08:00
Lindsey Heagy e4fc128383 organizing toctree in EM docs 2016-02-06 15:06:23 -08:00
Lindsey Heagy a80eac7dc3 documentation for FDEM.py 2016-02-06 15:05:15 -08:00
Lindsey 994cba529b Merge pull request #227 from simpeg/dev
Dev
2016-02-05 17:55:13 -08:00
Rowan Cockett 7a6d0c9fdd Updates to SimPEG.DCIP 2016-02-05 15:09:52 -08:00
Rowan Cockett bdfabe620a Add the DC examples 2016-02-05 14:01:56 -08:00
Rowan Cockett 9b67956630 Use the linear problem and survey class 2016-02-05 14:01:20 -08:00
Rowan Cockett ac8f26be3e Update DC example. 2016-02-05 14:00:01 -08:00
Rowan Cockett 2e78e09bd0 Merge branch 'Dom_Dev' of https://github.com/simpeg/simpeg into dcip/dev 2016-02-05 13:51:53 -08:00
Lindsey 72a5009d9d Merge pull request #229 from simpeg/test/examples
add test to ensure examples are up to date
2016-02-05 11:13:59 -08:00
Lindsey 5515f7dadd Merge pull request #232 from simpeg/patch/Zero_in_sdiag
use Zero in sdiag instead of returing h to avoid confusion
2016-02-05 09:14:46 -08:00
GudniRos 3de8fb5f15 Fixed a spelling error 2016-02-04 23:53:36 -08:00
GudniRos 5705fabc5a Fixed comments from Lindsey and Rowan 2016-02-04 22:38:19 -08:00
Lindsey Heagy 73edef5eb7 the forward for all fields and fluxes can be computed from any formulation (todo: derive) 2016-02-04 19:34:16 -08:00
Lindsey Heagy 8a7e72f3e8 Merge branch 'em/dev' into em/rx
# Conflicts:
#	SimPEG/EM/FDEM/FDEM.py
#	SimPEG/Mesh/TensorMesh.py
2016-02-04 19:01:43 -08:00
Lindsey Heagy 2fb8de708a use Zero in sdiag instead of returing h to avoid confusion 2016-02-04 18:49:42 -08:00
Rowan Cockett 8262ee94bc Initial commit of DCIP. 2016-02-04 17:03:42 -08:00
sgkang d49a16d7e9 Merge pull request #8 from simpeg/IP
IP branch
2016-02-04 11:37:10 -08:00
seogi_macbook 1f1522da01 Minor correction for notebooks 2016-02-04 11:36:27 -08:00
seogi_macbook 0ad24f175b Merge branch 'master' of https://github.com/simpeg/simpegdc into IP 2016-02-04 11:24:39 -08:00
sgkang 7f14c32124 Merge pull request #7 from simpeg/Dom/BaseDC
Dom/base dc
2016-02-04 11:22:50 -08:00
seogi_macbook dc6009f9c8 add pymatsolver to travis 2016-02-04 11:12:12 -08:00
D Fournier e2f30ffbb6 Remove unnecessary files for pull request 2016-02-04 11:11:14 -08:00
D Fournier 34acd4876b Merge branch 'master' into Dom_dev 2016-02-04 11:06:53 -08:00
D Fournier ac7ba39732 Add example in preparation for branching off 2016-02-04 11:05:56 -08:00
Rowan Cockett 269269daf7 Merge pull request #6 from simpeg/Dom_dev
Examples and IP
2016-02-04 09:17:40 -08:00
Rowan Cockett 9b65fa80c9 getIndicesBlock typo. 2016-02-04 09:16:14 -08:00
Rowan Cockett 2a84f1556e Merge in @sgkang's work on IP. 2016-02-04 09:16:01 -08:00
Lindsey Heagy 5b78d69c6d use set diff for testing if all examples have been included 2016-02-04 09:11:23 -08:00
GudniRos b8bd011662 Added a 3D forward example. Missing plots. 2016-02-04 02:28:22 -08:00
GudniRos 345e39ed43 Updated doc strings, moved functions around and cleaned unused text. 2016-02-04 00:23:07 -08:00
Lindsey Heagy b81b5af461 use abspath for travis 2016-02-03 20:23:31 -08:00
Lindsey Heagy 433457f649 docs and import for DC_PseudoSection_Simulation.rst 2016-02-03 20:12:55 -08:00
D Fournier 3eeb5dbd3c Remove dependency from Utils. Replace by internal function. 2016-02-03 20:03:05 -08:00
Lindsey Heagy 32c936c4e3 add test to ensure examples are up to date 2016-02-03 19:55:42 -08:00
D Fournier df78f7b33a Branch off master
Add DC_Pseudo_Section example.
2016-02-03 14:35:03 -08:00
GudniRos 01bf46c8bf Updated example 2016-02-03 14:21:41 -08:00
GudniRos 664589f856 Example for 1D forward and inversion of MT 2016-02-03 14:21:11 -08:00
Lindsey 05ce38013e Merge pull request #223 from simpeg/em/dev
Em/dev
2016-02-02 14:35:22 -08:00
Lindsey 7c2d803dfe Merge pull request #225 from simpeg/patch/docsbadges
make travis badge look at master for docs
2016-02-02 09:54:43 -08:00
Lindsey abc464ab46 Merge pull request #224 from simpeg/patch/docsbadges
make travis badge look at master for docs
2016-02-02 08:13:35 -08:00
Lindsey Heagy 2adc7d4eb9 make travis badge look at master for docs 2016-02-01 22:31:12 -08:00
Lindsey Heagy 92b5435149 Merge branch 'dev' into em/dev 2016-02-01 22:12:22 -08:00
D Fournier 78584ae49d Create pseudo-section simulation in Notebook.
Sub-functions added to BaseDC. Required for the simulation
2016-02-01 21:03:58 -08:00
D Fournier b16b1b7526 Add ModelBuilder sphere model.
Add example for DC pseudo section -> Requires a pull request in SimpegDC for dependancies.
2016-02-01 21:02:11 -08:00
Lindsey 28a8a2ea80 Merge pull request #217 from simpeg/em/inversioncleanup
Em/inversioncleanup
2016-02-01 19:23:39 -08:00
D Fournier 04d977f861 Implement and test Directive for sparse norm... need clean up. 2016-01-31 15:31:20 -08:00
D Fournier 254fd1c029 Improved sparse regularization.
Issue with spyder debugger since last merge with dev...
2016-01-31 10:50:06 -08:00
D Fournier 2e3a6ddd96 Merge branch 'dev' into Dom_Dev 2016-01-31 10:33:44 -08:00
GudniRos 8340214d73 Merge branch 'mt/dev' of https://github.com/simpeg/simpeg into mt/dev 2016-01-30 14:18:54 -08:00
GudniRos 451cd46801 Added a clean to the Solver. 2016-01-30 14:11:38 -08:00
D Fournier b4c4841976 Merge 2016-01-29 13:47:13 -08:00
Rowan Cockett ef201be832 Merge branch 'dev' of https://github.com/simpeg/simpeg into mt/dev
Conflicts:
	SimPEG/Utils/meshutils.py
	docs/index.rst
	tests/mesh/test_MeshIO.py
2016-01-29 11:46:19 -08:00
D Fournier 54ec7187cb Add unitCellGrad to DiffOperators
Implement SparseRegularization and test on mag problem... works!
2016-01-29 00:50:59 -08:00
Lindsey Heagy 1457e51fc1 from SimPEG.EM import mu_0 2016-01-28 23:44:02 -08:00
Rowan Cockett 5dab7ac1a8 Merge pull request #216 from simpeg/bug/215
Closes #215
2016-01-28 23:32:54 -08:00
Lindsey Heagy 967dc83fa8 fixed merge conflict with em/dev 2016-01-28 23:14:03 -08:00
Rowan Cockett 3431fb46eb Merge branch 'dev' of https://github.com/simpeg/simpeg into bug/215 2016-01-28 23:07:34 -08:00
Rowan Cockett 0704c6dc25 Merge pull request #213 from simpeg/feat/treeMeshCounting
Tree Mesh Updates
2016-01-28 22:36:48 -08:00
Lindsey Heagy 37d37369d8 added example to docs 2016-01-28 22:36:39 -08:00
Rowan Cockett b013508270 Fixes #215 2016-01-28 22:33:04 -08:00
Rowan Cockett 20d5582c0f Merge branch 'master' of https://github.com/simpeg/simpeg into dev 2016-01-28 22:29:59 -08:00
Rowan Cockett caba2b6752 Merge pull request #191 from simpeg/ActiveCellReg
Meshless Identity Map, Regularization for Active Cell models
2016-01-28 22:28:08 -08:00
D Fournier 02d840a40e Merge branch 'master' into dom_Optimization_Dev 2016-01-28 18:37:23 -08:00
D Fournier 9f5b2e2dc1 Merge branch 'master' into dom_Optimization_Dev 2016-01-28 18:36:46 -08:00
D Fournier 85b55139e8 Implement simple regularization
Modified the Optimization.ProjectedGNCG to allow active cells back in.
Fix problem regarding the Directive.TargetMisfit --> Survey.Linear had wrong nD value
2016-01-28 18:36:34 -08:00
Rowan Cockett 43c49d5f15 Address mesh IO #212 2016-01-28 17:53:10 -08:00
Rowan Cockett 1bcb572c45 Remove ifmain from TreeMesh 2016-01-28 14:29:45 -08:00
Rowan Cockett 67d3cb4d9b Merge branch 'dev' of https://github.com/simpeg/simpeg into feat/treeMeshCounting
Conflicts:
	.travis.yml
	SimPEG/Utils/__init__.py
2016-01-28 14:26:21 -08:00
Rowan Cockett 860bd5638a Add VTK to the travis dependencies.
I am not adding this to the requirements.txt file.
2016-01-28 14:19:29 -08:00
Lindsey Heagy 4bcc9e0850 - name cleanup in Jvec and Jtvec (use u instead of f to be consistent with the rest of SimPEG)
- example 1D inversion for FDEM
2016-01-28 14:00:47 -08:00
Rowan Cockett 09161ff68e Hopefully get a better error message on travis. 2016-01-28 13:58:32 -08:00
Lindsey Heagy c24416ea12 use the std and eps from survey in definition of data misfit if defined (and demonstrate it with the TDEM example) 2016-01-28 13:20:48 -08:00
Lindsey Heagy f5333f35a2 use survey.createSyntheticData to make synthetic data 2016-01-28 13:07:48 -08:00
GudniRos 2702c3573b Merge branch 'mt/dev' of https://github.com/simpeg/simpeg into mt/dev 2016-01-28 13:04:47 -08:00
Lindsey Heagy d50232b385 give Zero a transpose 2016-01-28 13:04:13 -08:00
GudniRos b67bcfad31 Fix bug in test. 2016-01-28 13:04:13 -08:00
Rowan Cockett d7be0ada31 Update README.rst
Fix the branch that SimPEG travis is pointing
2016-01-28 12:52:21 -08:00
Rowan Cockett 7b94021f7e Add emails to travis failures. 2016-01-28 11:41:37 -08:00
Rowan Cockett e8a6a028c2 Merge pull request #208 from simpeg/docs
move examples right after getting started with SimPEG
2016-01-28 11:36:50 -08:00
Lindsey 06c82ba16d Merge pull request #209 from simpeg/examples
pass loc as a variable in mag dipole example
2016-01-27 09:03:25 -08:00
Lindsey Heagy a8539cc234 pass loc as a variable 2016-01-27 08:41:28 -08:00
GudniRos 7e45390611 Fixing a bug in Data class 2016-01-27 02:16:43 -08:00
GudniRos e276ca70d6 Added directive to save dpred after every iteration. 2016-01-27 01:01:50 -08:00
Lindsey Heagy 814bd00346 move examples right after getting started with SimPEG 2016-01-26 22:47:11 -08:00
GudniRos 096a72fdb4 Tipper derivatives and adjoint working. 2016-01-26 12:07:42 -08:00
GudniRos 78d710de57 Implemented tipper projection derivatives 2016-01-25 22:50:15 -08:00
GudniRos bd488a4f0b Removed rxPair from the source, which was causing a bug. 2016-01-25 22:23:29 -08:00
seogi_macbook d363a125b6 Merge branch 'master' of https://github.com/simpeg/simpeg 2016-01-25 15:17:34 -08:00
GudniRos f3bf17ebe5 Work on MT, fixing bugs 2016-01-25 12:29:03 -08:00
Lindsey 37ec0835c2 Merge pull request #206 from simpeg/examples
Mag Dipole Analytic Wholespace Example
2016-01-23 17:54:30 -08:00
Rowan Cockett 84400650fa Clean up init file in examples. 2016-01-23 16:37:11 -07:00
D Fournier 6fcd826673 Start branch for regularization
Add LinearSurvey
Add LinearProblem
2016-01-20 14:23:42 -08:00
Rowan Cockett 91e37c5fa7 Clean up init code, put inside run, remove mpl from TL import. 2016-01-20 12:52:51 -07:00
Lindsey Heagy 98f209d1f0 specify that example is FDEM 2016-01-20 08:04:01 -08:00
Lindsey Heagy 7107cd9d94 plot a harmonic mag dipole 2016-01-19 23:57:41 -08:00
Lindsey e254c04297 Merge pull request #205 from simpeg/example-typo-patch-1
Update and rename EM_FDEM_1D_Inversion.py to EM_TDEM_1D_Inversion.py
2016-01-19 21:12:47 -08:00
Lindsey Heagy bb3f9a6a87 make projGLoc a method not a property 2016-01-17 14:54:02 -08:00
Lindsey Heagy fac3f63fba Merge branch 'em/dev' into em/rx 2016-01-15 10:56:14 -08:00
Lindsey Heagy 8da4d78bde Merge branch 'master' into em/dev 2016-01-15 10:53:22 -08:00
Lindsey Heagy 0b971f4a50 updated examples init to also update docs 2016-01-15 10:46:31 -08:00
Lindsey 7a4aa4ddc3 Update and rename EM_FDEM_1D_Inversion.py to EM_TDEM_1D_Inversion.py
- this is a TDEM inversion (not FDEM)
2016-01-15 10:07:11 -08:00
Rowan Cockett 28b8a69d7b Merge pull request #203 from simpeg/em/dev
Em/dev
2016-01-14 21:21:07 -08:00
Lindsey 570dfb7aba Merge pull request #200 from simpeg/em/cleansolver
add Ainv.clean() to fdem fields, jvec, jtvec
2016-01-14 16:16:06 -08:00
Rowan Cockett c6e90230d4 Updates to the correct pointer for the flow module (docs) 2016-01-14 15:57:15 -08:00
Rowan Cockett b63434b89d Updates to the documentation. 2016-01-14 15:56:35 -08:00
Rowan Cockett 558e8879fe SimPEG.MT Mergify.
Merge branch 'move2Simpeg' of https://github.com/simpeg/simpegmt into mt/dev

Conflicts:
	.gitignore
	.travis.yml
	LICENSE
	docs/conf.py
	docs/index.rst
	requirements.txt
	setup.py
2016-01-14 15:36:58 -08:00
Rowan Cockett e15913cf84 Import all code utils into the utils namespace. 2016-01-14 15:12:34 -08:00
Rowan Cockett 01b1122fcf Add default interpolation location (CC). 2016-01-14 15:12:09 -08:00
Lindsey Heagy 1700f4f9c0 add Ainv.clean() to fdem fields, jvec, jtvec 2016-01-14 14:00:55 -08:00
GudniRos d77b393d42 Fixed tests to. TotalField formulation not working. 2016-01-14 13:34:08 -08:00
GudniRos b9e1d794f6 Changed the name space to correspond with FDEM. 2016-01-14 13:25:16 -08:00
seogi_macbook 32f3ef301a Modifications for general waveform 2016-01-12 18:52:39 -08:00
D Fournier 2dfacdc904 Appended functions to BaseDC 2016-01-12 17:46:58 -08:00
GudniRos 2cf3d5d195 Working on the namespace, renamed problems. 2016-01-12 17:16:35 -08:00
GudniRos 02afcabd7d Updated code to use SimPEG.EM instead of simpegEM module. 2016-01-12 16:51:10 -08:00
Rowan Cockett 17348e14e4 Merge pull request #198 from simpeg/bug/solver
Solver Bugs
2016-01-10 19:20:57 -08:00
Rowan Cockett cdf0ebf8d0 Merge pull request #197 from simpeg/dev
Dev
2016-01-10 18:47:52 -08:00
Rowan Cockett dedabcc15f Allow solver kwargs to go to the class directly. 2016-01-10 18:36:57 -08:00
Rowan Cockett ff0c81b96e Merge pull request #196 from simpeg/feat/docs
Feat/docs
2016-01-10 18:33:54 -08:00
Rowan Cockett 2c5b19b7a0 Updates to the documentation. 2016-01-10 17:21:01 -08:00
Rowan Cockett 8a61259cab Remove out of date GCE folder. 2016-01-10 15:17:13 -08:00
Rowan Cockett f482f9d877 Rearrange tests in order of speed for travis. 2016-01-10 15:16:46 -08:00
Rowan Cockett 1ba96ba8d0 Merge pull request #194 from simpeg/dev
Example, Pip, Zero, Identity, Faster Builds
2016-01-10 14:02:01 -08:00
Rowan Cockett 985d5b6469 Bump version: 0.1.7 → 0.1.8 (+7 squashed commits)
Squashed commits:
[ac5bb36] Bump version: 0.1.8 → 0.1.9
[8acd6b2] ImportException --> ImportError
[ac410a8] matplotlib.pyplot has errors on import, put these in the functions
that rely on them directly.
[f128a20] Bump version: 0.1.6 → 0.1.7
[5866bea] Remove IPython utils.

These are out of date, and have problems on Linux (without a proper
visual backend).
[a519e56] Bump version: 0.1.5 → 0.1.6
[f45aa83] Bump version: 0.1.4 → 0.1.5
2016-01-10 13:38:06 -08:00
Rowan Cockett 8da717521c Update scripts for pip 2016-01-10 13:01:00 -08:00
GudniRos 2dceea25ec Merge branch 'FDEMrefactor' 2015-12-22 16:10:28 -08:00
GudniRos d332d3068a Merge branch 'master' into FDEMrefactor
Conflicts:
	simpegMT/SurveyMT.py
2015-12-22 16:09:14 -08:00
Lindsey 5d38ea5e11 removed knownSrcType 2015-12-22 15:11:07 -08:00
Gudni Karl Rosenkjaer 27edc7742f Merge pull request #6 from simpeg/Travis
Travis
2015-12-22 13:12:53 -08:00
Lindsey Heagy 5b9dae2930 changed name of utility testing functions that we don't want travis to try and run automatically 2015-12-21 15:20:08 -08:00
Lindsey Heagy f82efee096 try running travis on new framework 2015-12-21 14:08:02 -08:00
D Fournier 9d861267e1 Generalize the DC2D HTML movie maker.
Create example for 2 sphere problem
2015-12-21 08:44:07 -08:00
GudniRos 66156481da Fixed an error in resampleByFreq 2015-12-18 14:31:22 -08:00
GudniRos 4342450360 Updated test_MeshIO to remove the temp files after using them. 2015-12-17 23:02:52 -08:00
GudniRos 77f476e248 Added a resampling function to datautils. 2015-12-16 23:48:37 -08:00
GudniRos 79f7ca7a1e Adden dpred to be written in the saveDict directive 2015-12-15 19:35:18 -08:00
D Fournier fc3893c72f Improved gradient plot and sections. 2015-12-15 11:59:44 -08:00
GudniRos e42727610a Implemented IO test for octree mesh. 2015-12-14 19:08:35 -08:00
GudniRos 84eb69f626 UBC ocTree read and write working. 2015-12-14 01:46:01 -08:00
GudniRos 69d109524e Working on reordering of UBC models. 2015-12-12 13:52:26 -08:00
D Fournier 2a76852e33 Implement Gradient array with 2D plotting
Test the potential as a function Tx distance from gradient grid
2015-12-11 18:16:52 -08:00
D Fournier 2aa523f0ad Implement iterative solver BiCGStab + Jacobi Preconditionner (success!!) 2015-12-11 11:32:03 -08:00
D Fournier 3d52778274 Finalize "2click" forward + inversion demo 2015-12-10 15:27:50 -08:00
Lindsey Heagy 22a6310a59 breaking up tests, also pass in u to df_dm 2015-12-10 08:51:06 -08:00
GudniRos ba2ac74740 Fixed code error 2015-12-09 15:53:41 -08:00
GudniRos 4b7f7c3c14 Fixed a spelling error 2015-12-09 15:46:57 -08:00
GudniRos d6585dcfcd Add Saving Directive 2015-12-09 15:43:51 -08:00
GudniRos e678affe41 Changed ave[F/E]2CC to be a csr not a css, which doesn't support indexing. 2015-12-09 15:33:05 -08:00
GudniRos 1a40e35c26 Fixed import bugs. 2015-12-09 14:40:32 -08:00
GudniRos f2c7cfab78 Added support sources to take TreeMesh. 2015-12-09 12:51:20 -08:00
Lindsey Heagy 9e69455d6e b from h and h from b 2015-12-08 23:35:06 -08:00
Lindsey Heagy b620c4286b smaller test mesh 2015-12-08 21:48:01 -08:00
Lindsey Heagy adda7a43dc E from J and J from E, and a test (need to choose better parameters) 2015-12-08 19:14:28 -08:00
Lindsey 884d27b541 start of getting any field from any formulation 2015-12-08 18:11:01 -08:00
D Fournier b3ceccf303 Finish script to extract 2D model from 3D mesh and write DCIP files
Compare SimPEG vs DCIP2D vs DCIP3D on Mt Isa synthetic model
Invert Mt Isa synthetic 2D line. Dipole-Dipole sucks... need another setup/
2015-12-08 17:31:19 -08:00
D Fournier 20585bad09 Advance the 2D to 3D interpolation.
Test SimPEG vs DCIP2D and DCIP3D
2015-12-07 16:44:15 -08:00
D Fournier 65d221ee36 On the fly forward modeling and pseudo section for 3D conductivity model 2015-12-05 18:57:56 -08:00
Rowan Cockett 8b53fd5965 Merge pull request #189 from simpeg/generalize-mappair
Generalize mapPair
2015-12-04 15:44:00 -08:00
Rowan Cockett c298ebe8d8 Remove the Meshless Identity Map.
- This is now default functionality in the IdentityMap.
2015-12-04 15:42:08 -08:00
Rowan Cockett 3972178069 Merge branch 'feat/treeMeshCounting' of https://github.com/simpeg/simpeg into feat/treeMeshCounting 2015-12-04 15:22:11 -08:00
seogi_macbook 1c39fcf680 Merge branch 'IP' of https://github.com/simpeg/simpegdc into IP
Conflicts:
	simpegDCIP/BaseDC.py
2015-12-02 23:13:20 -08:00
seogi_macbook 3215730d23 minor change 2015-12-02 23:12:36 -08:00
GudniRos 25ad1488f5 Added a function to read UBC octree mesh. Updated __init__ to import the new functions. 2015-12-02 19:20:21 -08:00
D Fournier 2fbcc076f9 DC FWR 3D demo started 2015-12-02 18:42:30 -08:00
GudniRos a8551f3e04 Added function to write a UBC octree mesh for TreeMesh object. 2015-12-02 16:07:33 -08:00
GudniRos 589cd655af Updated vtk write classes. 2015-12-02 16:07:33 -08:00
Rowan Cockett 7da637e883 documentation on Cell.nodes 2015-11-30 18:05:02 -08:00
Rowan Cockett a7ab0dc1e2 Unit tests for getitem on tree mesh 2015-11-30 18:00:16 -08:00
Rowan Cockett e30a7bcafc documentation updates 2015-11-30 17:52:38 -08:00
Rowan Cockett c4d34c4e0d Initial counting of nodes.
- Some of the nodes in the cell may be hanging.
2015-11-30 17:46:57 -08:00
Lindsey Heagy cfc921b667 cleaned out transform, inverse and deriv (all are inherited from IdentityMap) 2015-11-28 13:12:44 -08:00
Lindsey Heagy 83cb5ce46a - Meshlesses Identity Map (takes nP instead of a mesh)
- Tikhonov regularization if active cells are used (don't take derivs across interfaces between active cells and not)
- testing improvements: test 1D, 2D, 3D on a random tensor mesh , also test that for a constant mref, phi_m(ref) = 0
2015-11-28 12:55:24 -08:00
Brendan Smithyman 528253a8cb Generalize mapPair 2015-11-26 19:18:04 -05:00
seogi_macbook 898215222a play with fwd 2015-11-26 15:06:22 -08:00
D Fournier 058de2fd96 Animations added 2015-11-26 13:17:09 -08:00
D Fournier 44febb35b8 Merge branch 'IP' of https://github.com/simpeg/simpegdc into Dom_dev 2015-11-26 13:16:24 -08:00
GudniRos 4a8bc16634 Fix a bug in reshapeing in adjoint projFieldsDeriv 2015-11-25 16:22:06 -08:00
GudniRos 4de169c591 Removed Ipython.Debugger import and redused the amount of 3D testing. 2015-11-25 14:49:29 -08:00
GudniRos 4079f28e00 Moved reshaping from Jtvec to the respective derivative. Makes 1D/3D compadibility easier. 2015-11-22 14:02:24 -08:00
Lindsey Heagy 58efd8710f use 1 for fixing null space instead of volume 2015-11-19 13:37:18 -08:00
GudniRos ad20c73f18 Added support of Complex recarray for fromRecArray function 2015-11-16 01:53:26 -08:00
D Fournier fa20309bc9 Animation added, need to figure out how to add the streamplot for current 2015-11-15 15:17:03 -08:00
D Fournier 592d27ecc5 Complete plot with current and charge density. Need to fix the animation 2015-11-15 13:53:46 -08:00
D Fournier 6a744bab30 Work in progress, testing access rights 2015-11-13 13:56:05 -08:00
GudniRos 3b88366681 Add a scale flag in MT1Danalytic to scale the solution to be 1 at the top. 2015-11-13 13:35:19 -08:00
D Fournier 015099e72e Create import functions for UBCDC2D model and mesh.
Start driver function for forward model data from example.
2015-11-13 12:47:53 -08:00
seogi_macbook fc0a413b3c blah 2015-11-10 14:30:07 -08:00
GudniRos d7234cea9e Fixed dimension bugs in code. 2015-11-04 23:57:11 -08:00
GudniRos 9f69a33512 Added derivative tests for all the components of Jvec. 2015-11-03 12:12:45 -08:00
GudniRos fc8f3dd956 All derivatives for 1D and 3D MT are working. 2015-11-03 12:08:28 -08:00
GudniRos 3a51be6500 Corrected the notebook for MT3D derivative tests 2015-11-02 17:29:22 -08:00
GudniRos 0e81faf217 Field projection derivatives working 2015-11-02 17:26:52 -08:00
GudniRos 960cb0a3e5 Added a Derivative test notebook 2015-11-02 11:23:06 -08:00
GudniRos 42bc4404ba projection with sdiag for all the elements. Not sure if the is correct, but archiving the work 2015-11-01 13:05:24 -08:00
GudniRos 9d6a1dcac6 Reorignized to have u = [u_px,u_py].
Everything runs but tests are not passing.
2015-10-26 11:22:46 -07:00
GudniRos 7d913ef178 Derivative check of Jvec and wJv === vJtw are not passing. 2015-10-21 14:15:08 -07:00
GudniRos a963514f7e 3D derivatives are working and tested. 2015-10-20 10:36:36 -07:00
GudniRos c36dce943e Working on 3D derivatives.
rx.projectFieldsDeriv partly works, the adjoint doesn't. Not tested.
2015-10-15 14:52:49 -07:00
GudniRos 0e45d3674a Added derivative support for the 3D problem. 2015-10-15 08:09:31 -07:00
GudniRos 1654c1c8b5 Implementing 3D derivatives 2015-10-14 11:07:49 -07:00
seogi_macbook dea7eba5e0 work on IP stuff 2015-09-15 15:40:26 -07:00
GudniRos 5eccffffb5 Added tipper support 2015-09-08 17:11:12 -07:00
GudniRos b26412e7a9 Made changes to data utils 2015-08-13 12:26:16 -07:00
Gudni Karl 362638cc39 Fixed number of data error in the function 2015-08-11 11:22:02 -07:00
GudniRos 295eeb6a25 Updated DataMT while working 1D inversions. 2015-08-05 10:44:45 -07:00
GudniTeraClust ba1a85e269 Reran the MT3DforData1Dinv.py script 2015-07-12 16:14:11 -07:00
GudniRos 50ffc734c5 Update the forward modeling script 2015-07-12 14:55:49 -07:00
GudniRos 3990459c7c Updated notebooks and minor bug fixes 2015-07-12 14:35:46 -07:00
GudniTeraClust 452cd7e1da Merge branch 'FDEMrefactor' of https://github.com/simpeg/simpegmt into FDEMrefactor
Adding data file
2015-07-07 22:59:02 -07:00
GudniTeraClust 57fcf53542 Adding seogi model Data 2015-07-07 22:57:01 -07:00
Lindsey Heagy c72e3f5a80 Merge branch 'FDEMrefactor' of https://github.com/simpeg/simpegmt into FDEMrefactor 2015-07-07 21:16:47 -05:00
Lindsey Heagy 2dfce560f7 added myself to travis emails 2015-07-07 14:17:28 -05:00
GudniRos 30a1f10b29 Minor changes to run script 2015-07-07 11:34:05 -07:00
GudniRos 7703f8fa89 Adding changed data files 2015-07-07 11:28:01 -07:00
GudniRos 6ac63f12c6 Added the seogi model 2015-07-07 11:13:03 -07:00
GudniRos 855cf60ca0 Updated the import of osr package 2015-07-07 11:10:56 -07:00
GudniRos 1ab91fc2f4 Fixing imports for the run script 2015-07-07 11:06:29 -07:00
GudniRos 7e746870a9 Change a notebook to a script to run remotely. 2015-07-07 10:47:39 -07:00
GudniRos 5aefbb3a4c Fixed an import error of pymatsolver for travis runs 2015-07-07 10:35:27 -07:00
GudniRos 2b37f27602 Fix depenencies in notebooks and got tests to work. 2015-07-07 09:24:53 -07:00
GudniRos c78d5beef8 Updated notebooks and added plotDataTypes used for plotting MTdata 2015-07-06 09:54:21 -07:00
GudniRos 33d76346d1 Add notebooks for scipy2015 2015-07-03 16:47:05 -07:00
GudniRos 08cbcd6ac2 Fixing travis build 2015-07-02 16:12:26 -07:00
GudniRos b153053119 Working on get travis to work 2015-07-02 15:30:24 -07:00
GudniRos 40925a49cc Updated travis 2015-07-02 15:08:53 -07:00
GudniRos 26efae1f4a Fixing .travis.yml file to get testing to work 2015-07-02 14:17:40 -07:00
GudniRos ed72fba063 Added EDI files read support.
Fixed all srcMT to take 2 inputs.
2015-07-02 14:00:37 -07:00
GudniRos 205ee000a2 Changed travis setup file to include import of simpegem. 2015-06-30 08:46:18 -07:00
GudniRos 4d3351e99c Inversion problem working.
Fixed 1D problem to correct the phase quadrants.
2015-06-30 08:41:03 -07:00
GudniRos 81371e54ee Adding a MT1D inversion test notebook 2015-06-26 09:20:19 -07:00
GudniRos 4a39602ca4 Jvec adjoint test is working for MT1D primary/secondary formulation. 2015-06-25 10:36:10 -07:00
GudniRos d233e40a95 Jvec adjoint test not working, but all other derivatives adjoint tests are working. 2015-06-24 19:55:10 -07:00
GudniRos e3a2ec6c8d JTvec is working but not converging. 2015-06-24 12:33:08 -07:00
GudniRos f2a8cf0a62 Jvec working for MT1D, Jtvec getting close 2015-06-24 11:33:14 -07:00
GudniRos 2cbfe2d6b9 Working Jvec for the MT problem - not currently working. Dimensional mismatch with matrices. 2015-06-23 08:31:44 -07:00
GudniRos 60b6c24e19 Derivative test MT1D is now working and passing with 2 order convergence. 2015-06-19 12:47:31 -07:00
GudniRos 8ed4d41b2d Added a note book with MT1D derivative testing 2015-06-19 09:58:03 -07:00
GudniRos be0d269af1 Updated 1D_ps problem. Working on testing derivatives, only to 1st order at the commit 2015-06-19 09:54:53 -07:00
GudniRos 422911a95f Fixed 1D test and current code to work, where the src in the 1D problem is partly implemented 2015-06-11 16:26:11 -07:00
GudniRos 21d788edf4 Updated MT codes to use new changes from FDEM code. 3D code is working 2015-06-11 10:03:39 -07:00
GudniRos c4229b4906 Refactoring the MT code to relect on the FDEM parent.
The test work for FDEM branch feat/sourceRefactor commit 9eede4e840
2015-06-03 11:12:55 -07:00
seogi_macbook e0d9c27d87 Result of SimPEG hackathon
- Incorporate field class on DC
- Add IP forward modelling and inversion
- Modify notebooks
- change folder name form simpegDC to simpegDCIP
2015-06-03 08:29:05 -07:00
seogi_macbook 820bf85930 Working notebooks 2015-05-15 14:08:41 -07:00
Rowan Cockett 1455901474 Merge pull request #4 from simpeg/Tx2Src
Tx2 src
2015-05-15 13:07:25 -07:00
Rowan Cockett bcc3394079 Merge branch 'master' of https://github.com/simpeg/simpegDC into Tx2Src
Conflicts:
	simpegDC/BaseDC.py
	simpegDC/Examples/Verification.py
	simpegDC/Examples/WennerArray.py
2015-05-15 13:06:05 -07:00
Rowan Cockett 599847126c updates to source and rx conventions 2015-05-15 13:02:59 -07:00
Rowan Cockett fdd3a43d18 Update LICENSE 2015-05-15 12:48:47 -07:00
seogi_macbook 4b630df3ca Three mesh 2015-05-15 12:40:30 -07:00
Rowan Cockett 59c2216ec0 Merge pull request #2 from simpeg/SrcChanges
remove SrcType, put rx list first in inputs for src
2015-05-15 12:28:52 -07:00
seogi_macbook 5ea1aa34b9 ThreeMeshEx 2015-05-14 21:00:58 -07:00
seogi 7f0d8e4920 DC example: three mesh 2015-05-13 15:08:23 -07:00
Lindsey Heagy 3b427d8a85 remove SrcType, put rx list first in inputs for src 2015-05-10 16:54:55 -07:00
Lindsey 64574369c3 Merge pull request #1 from simpeg/Tx2Src
changed tx -> src
2015-05-10 16:35:25 -07:00
GudniRos 10f098c0b5 Updated codes, fixed bug in dataMT and moved notebooks to a folder. 2015-05-08 21:42:50 -07:00
GudniRos 22febe331b Working on ProblemMT_e_ps, not tested yet. 2015-05-07 19:22:28 -07:00
GudniRos 03383cf092 Adding missed changes 2015-05-07 16:26:58 -07:00
GudniRos 6eafbdca80 Adding fixes to code. 2015-05-07 16:26:35 -07:00
Gudni Karl Rosenkjaer 6746af4c3c Merge pull request #4 from simpeg/removeKnownSrc
removed knownSrcType
2015-05-05 14:53:45 -07:00
Lindsey 88556af40c removed knownSrcType 2015-05-04 10:49:52 -07:00
GudniRos 6eabd68a1d Updated to src implementation of SimPEG. 2015-05-01 13:01:13 -07:00
Lindsey c8b9611fca changed tx -> src 2015-04-17 17:17:03 -07:00
Gudni Karl 25799f3680 Optimized conversion codes 2015-04-07 19:06:01 -07:00
GudniRos 69966eae60 Added time string printing 2015-04-06 12:33:29 -07:00
GudniRos 028714b27d Added time string printing 2015-04-06 11:08:11 -07:00
GudniRos 3f338ddb43 Added time string printing 2015-04-06 10:59:40 -07:00
GudniRos 25acc67c43 Added time string printing 2015-04-06 10:42:46 -07:00
GudniRos d7c062c1c4 Fixed MTdata.toRecArray() 2015-04-06 07:22:37 -07:00
GudniRos 8123dff07a added a print statement in projectFields 2015-04-05 15:44:50 -07:00
GudniRos 6b3f9b9478 Fix import bug of sys 2015-04-03 10:44:56 -07:00
Gudni Karl d7aa612a23 Merge branch 'master' of https://github.com/simpeg/simpegmt 2015-04-02 16:45:04 -07:00
Gudni Karl fba5e75355 Added print statements to fields 2015-04-02 16:43:34 -07:00
Rowan Cockett b83421a27a update the coverage to cover simpegMT 2015-03-03 12:27:59 -08:00
Rowan Cockett 9049215811 add apparent resistivity tests 2015-03-03 11:29:10 -08:00
Gudni Karl Rosenkjaer 63ef5ef380 Adding notebooks on the MT1D problem 2015-03-02 21:08:32 -08:00
Gudni Karl Rosenkjaer 52618bac35 Fixed bugs. Added notebooks with halfspace and layer examples.
Code is working (returning results with in couple of % for a 1D analytic solution) but test need to be "automated".
2015-03-02 14:58:53 -08:00
Rowan Cockett 1ed4d5bc8d update miniconda 2015-02-24 17:19:17 -05:00
Gudni Karl fbf4370a78 Fixed bugs 2015-02-19 19:13:05 -08:00
Gudni Karl 1549ced52d Fixed a bug in homo1DModelSource 2015-02-19 18:27:09 -08:00
Gudni Karl f25681ce80 Edit in Sources/backgroundModelSources.py such that the
souce is only on the outer shell of the model.

Fixed bug is problem and survey classes.
2015-02-19 18:24:34 -08:00
Gudni Karl Rosenkjaer 36cde4fe4f Updated the example script. 2015-02-19 12:13:44 -08:00
Gudni Karl 6561376b51 Fixed bugs and got MTrx.projectFields to work. 2015-02-17 17:27:59 -08:00
Gudni Karl Rosenkjaer 9b650041d1 Working on MT problem and survey. Fixed bugs and completed example 2015-02-17 00:09:24 -08:00
Gudni Karl Rosenkjaer fb717b5f31 Updating MT classes,
Working on a example script to forward model impedance data
2015-02-16 15:35:40 -08:00
Gudni Karl Rosenkjaer 9aa94c95b1 Updating Survey and Problem MT, work in progress. Code not tested. 2015-02-15 23:14:04 -08:00
Rowan Cockett 852a7295ef Update .travis.yml 2015-02-13 14:58:58 -08:00
Gudni Karl a8dc7ddd25 Added Sources/backgroundModel 2015-02-12 19:40:06 -08:00
Gudni Karl 8aa823ba5d Fixing up ProblemMT, SurveyMT and adding Sources folder 2015-02-12 19:39:26 -08:00
Gudni Karl 0d1073367c Merge branch 'conglomerateOldEMCode' of https://github.com/simpeg/simpegmt 2015-02-12 19:05:36 -08:00
Rowan Cockett adfaf1b12a updates to travis script 2015-02-12 14:00:18 -08:00
Rowan Cockett 217d5fa79e renamed and conglomerated the three classes into one. 2015-02-12 13:58:32 -08:00
Rowan Cockett 05a64110fa travis fixes? 2015-02-12 11:56:06 -08:00
Rowan Cockett d507a330bd Merge pull request #3 from simpeg/develop
Develop
2015-02-12 11:49:21 -08:00
Rowan Cockett 9485c4c549 Delete __init__.pyc 2015-02-12 11:48:47 -08:00
Rowan Cockett c421d3bf5d Delete MT1Dsolutions.pyc 2015-02-12 11:48:38 -08:00
Rowan Cockett d3baf03c47 Delete MT1Danalytic.pyc 2015-02-12 11:48:22 -08:00
Rowan Cockett 5b5f83c58e Delete Base.pyc 2015-02-12 11:48:04 -08:00
Rowan Cockett 0e9a07c018 Delete __init__.pyc 2015-02-12 11:47:45 -08:00
Rowan Cockett 8a8ccebe3a Merge branch 'master' of https://github.com/simpeg/simpegMT into develop
Conflicts:
	simpegMT/Base.pyc
	simpegMT/Utils/MT1Danalytic.pyc
	simpegMT/Utils/MT1Dsolutions.pyc
	simpegMT/Utils/__init__.pyc
	simpegMT/__init__.pyc
2015-02-12 11:47:09 -08:00
Rowan Cockett 48ada2d63c Merge pull request #2 from simpeg/moveAnalytics
Move analytics
2015-02-12 11:40:30 -08:00
Rowan Cockett bae79ecb25 delete analytics folder. 2015-02-12 11:40:13 -08:00
Rowan Cockett 1aab6aaee5 move analytics to utils. 2015-02-12 11:39:13 -08:00
Rowan Cockett 7f817c96ad Merge pull request #1 from simpeg/delete-pyc
Delete pyc files
2015-02-12 11:37:09 -08:00
Rowan Cockett d188408b88 remove the rest of the pyc files. 2015-02-12 11:34:47 -08:00
Gudni Karl Rosenkjaer 4955b45c1f Added a MT 3D layer test notebook 2015-02-12 11:32:08 -08:00
Rowan Cockett 46d4e1bc01 Delete __init__.pyc 2015-02-12 11:31:34 -08:00
Gudni Karl Rosenkjaer 291fbb9ecb Added a new 1D layer test notebook 2015-02-04 00:02:42 -08:00
SEOGI KANG 90f98a6fd6 Modify averaging for current density 2015-01-29 10:45:49 -08:00
SEOGI KANG 8e14db7dba Modify Gudni's notebook:
- use SolverLU in simpeg
- visualize fields

Add gitignore
2015-01-29 10:35:39 -08:00
GudniRos 47e7132f26 Wrote 1D codes, both analytic and FV solutions. \n Made test notebooks for 1D and worked on the 3D notebook 2015-01-29 08:28:50 -08:00
seogi 59ffc57da3 figures.. 2014-11-24 09:41:24 -08:00
seogi 3f8ec7b07e modify figures 2014-11-24 09:37:14 -08:00
seogi c32347c726 Modify figures 2014-11-24 09:30:49 -08:00
seogi 9d120d7037 Figures for simpegPaper 2014-11-24 09:29:16 -08:00
SEOGI KANG 6f9a3e6598 Changing figures for simpegPaper 2014-11-24 09:04:30 -08:00
seogi 90957676b4 1D DC examples 2014-09-22 16:56:44 -07:00
rowanc1 f60a415b59 update the inverse notebook 2014-09-16 15:09:34 -07:00
rowanc1 b55e960e0d Updates to docs 2014-07-12 18:28:17 -05:00
rowanc1 adc2360a11 Analytic testing and showing online. 2014-07-12 18:23:58 -05:00
SEOGI KANG 77906e2d57 Verification plot 2014-07-12 14:26:01 -07:00
SEOGI KANG 8e616dc4c8 Documentations for DC resistivity survey 2014-07-12 14:15:51 -07:00
SEOGI KANG 5886b4b62a Inverse Ex 2014-07-12 11:06:03 -07:00
rowanc1 aa1a864ded Merge branch 'master' of https://github.com/simpeg/simpegdc 2014-07-12 12:59:08 -05:00
rowanc1 f23eb17d78 break out WennerArray into a few pieces 2014-07-12 12:57:18 -05:00
SEOGI KANG 4b2800ccef Verification for DC 2014-07-12 10:36:33 -07:00
rowanc1 1af495b910 remove static shift 2014-07-12 12:21:52 -05:00
rowanc1 f3bd31b258 added current to the dipole transmitter 2014-07-12 11:52:25 -05:00
rowanc1 4dcd831b22 make rhs negative and divide by volume 2014-07-12 11:51:19 -05:00
rowanc1 bbe2a8563c change innerproducts to massMatrices 2014-07-12 11:43:45 -05:00
rowanc1 1eae7a6807 add coverage to readme 2014-07-03 13:45:53 -07:00
rowanc1 10a39bc10c Updates to adjoint and derivative tests 2014-07-03 13:39:51 -07:00
rowanc1 58a1101448 Major updates. 2014-07-03 13:25:16 -07:00
rowanc1 828960c29f Changed EM --> MT 2014-05-13 12:04:41 -07:00
rowanc1 b91bc5fec4 added notebook with script 2014-05-13 12:04:15 -07:00
rowanc1 e8b27c409d Update Readme 2014-05-13 09:26:23 -07:00
rowanc1 d22e9eeb93 Initial Commit. 2014-05-13 09:25:25 -07:00
rowanc1 38e336c2f0 update travis 2014-02-21 10:48:52 -08:00
rowanc1 b3fef245c8 update travis 2014-02-21 10:45:41 -08:00
rowanc1 62abd1e5c7 Setup.py 2014-02-05 13:54:39 -08:00
rowanc1 caa2b5dac5 Fix Testing stuff. 2014-02-05 13:23:47 -08:00
rowanc1 98c8d1483a python path troubles in travis.. 2014-01-24 11:51:36 -07:00
rowanc1 45b4faf885 update travis again! 2014-01-24 11:33:12 -07:00
rowanc1 daf0aac544 update travis 2014-01-24 11:26:35 -07:00
rowanc1 06a2f55294 Update travis 2014-01-24 11:21:06 -07:00
rowanc1 631a416f89 Fixed Tests. 2014-01-24 11:15:03 -07:00
rowanc1 e504f3dc2f Merge branch 'DCproblem' of https://github.com/simpeg/simpeg 2014-01-24 10:58:57 -07:00
Rowan Cockett 827349d09d Initial commit 2014-01-24 09:25:47 -08:00
194 changed files with 19043 additions and 4316 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
[bumpversion]
current_version = 0.1.4
current_version = 0.1.10
files = setup.py SimPEG/__init__.py docs/conf.py
+8 -4
View File
@@ -16,12 +16,14 @@ addons:
env:
- TEST_DIR="tests/mesh tests/base tests/utils"
- TEST_DIR=tests/examples
- TEST_DIR=tests/em/fdem/forward
- TEST_DIR=tests/em/fdem/inverse/derivs
- TEST_DIR=tests/em/fdem/inverse/adjoint
- TEST_DIR=tests/em/tdem
- TEST_DIR=tests/dcip
- TEST_DIR=tests/flow
- TEST_DIR=tests/mt
- TEST_DIR=tests/examples
- TEST_DIR=tests/em/fdem/inverse/adjoint
- TEST_DIR=tests/em/fdem/forward
# Setup anaconda
before_install:
@@ -33,7 +35,7 @@ before_install:
# Install packages
install:
- conda install --yes pip python=$TRAVIS_PYTHON_VERSION numpy scipy matplotlib cython ipython nose
- conda install --yes pip python=$TRAVIS_PYTHON_VERSION numpy scipy matplotlib cython ipython nose vtk
- pip install nose-cov python-coveralls
- git clone https://github.com/rowanc1/pymatsolver.git
@@ -54,3 +56,5 @@ notifications:
email:
- rowanc1@gmail.com
- lindseyheagy@gmail.com
- gkrosen@gmail.com
- sgkang09@gmail.com
+7 -3
View File
@@ -1,9 +1,13 @@
- Luz Angelica Caudillo-Mata, (`@lacmajedrez <https://github.com/lacmajedrez/>`_)
- Rowan Cockett, (`@rowanc1 <https://github.com/rowanc1/>`_)
- Eldad Haber, (`@ehaber99 <https://github.com/ehaber99/>`_)
- Lindsey Heagy, (`@lheagy <https://github.com/lheagy/>`_)
- Seogi Kang, (`@sgkang <https://github.com/sgkang/>`_)
- Dave Marchant, (`@dwfmarchant <https://github.com/dwfmarchant/>`_)
- Brendan Smithyman, (`@bsmithyman <https://github.com/bsmithyman/>`_)
- Gudni Rosenkjaer, (`@grosenkj <https://github.com/grosenkj/>`_)
- Dom Fournier, (`@fourndo <https://github.com/fourndo/>`_)
- Dave Marchant, (`@dwfmarchant <https://github.com/dwfmarchant/>`_)
- Lars Ruthotto, (`@lruthotto <https://github.com/lruthotto/>`_)
- Mike Wathen, (`@mrwathen <https://github.com/mrwathen/>`_)
- Luz Angelica Caudillo-Mata, (`@lacmajedrez <https://github.com/lacmajedrez/>`_)
- Eldad Haber, (`@ehaber99 <https://github.com/ehaber99/>`_)
- Doug Oldenburg, (`@dougoldenburg <https://github.com/dougoldenburg/>`_)
- Adam Pidlisecky, (`@aPid1 <https://github.com/aPid1/>`_)
+2 -3
View File
@@ -1,14 +1,13 @@
Citing SimPEG
=============
-------------
There is a paper about SimPEG!
There is a `paper about SimPEG <http://dx.doi.org/10.1016/j.cageo.2015.09.015>`_, if you use this code, please help our scientific visibility by citing our work!
Cockett, R., Kang, S., Heagy, L. J., Pidlisecky, A., & Oldenburg, D. W. (2015). SimPEG: An open source framework for simulation and gradient based parameter estimation in geophysical applications. Computers & Geosciences.
BibTex:
-------
.. code::
-470
View File
@@ -1,470 +0,0 @@
#!/usr/bin/python
"""
Input and output functions.
"""
import os as _os
import errno as _errno
import sys as _sys
import numpy as _np
from petsc4py import PETSc as _PETSc
import fileinput as _fl
def vecToArray(obj):
""" Converts a PETSc vector to a numpy array, available on *all* MPI nodes.
Args:
obj (petsc4py.PETSc.Vec): input vector.
Returns:
numpy.array :
"""
# scatter vector 'obj' to all processes
comm = obj.getComm()
scatter, obj0 = _PETSc.Scatter.toAll(obj)
scatter.scatter(obj, obj0, False, _PETSc.Scatter.Mode.FORWARD)
return _np.asarray(obj0)
# deallocate
comm.barrier()
scatter.destroy()
obj0.destroy()
def vecToArray0(obj):
""" Converts a PETSc vector to a numpy array available on MPI node 0.
Args:
obj (petsc4py.PETSc.Vec): input vector.
Returns:
numpy.array :
"""
# scatter vector 'obj' to process 0
comm = obj.getComm()
rank = comm.getRank()
scatter, obj0 = _PETSc.Scatter.toZero(obj)
scatter.scatter(obj, obj0, False, _PETSc.Scatter.Mode.FORWARD)
if rank == 0: return _np.asarray(obj0)
# deallocate
comm.barrier()
scatter.destroy()
obj0.destroy()
def arrayToVec(vecArray):
""" Converts a (global) array to a PETSc vector over :attr:`petsc4py.PETSc.COMM_WORLD`.
Args:
vecArray (array or numpy.array): input vector.
Returns:
petsc4py.PETSc.Vec() :
"""
vec = _PETSc.Vec().create(comm=_PETSc.COMM_WORLD)
vec.setSizes(len(vecArray))
vec.setUp()
(Istart,Iend) = vec.getOwnershipRange()
return vec.createWithArray(vecArray[Istart:Iend],
comm=_PETSc.COMM_WORLD)
vec.destroy()
def arrayToMat(matArray):
""" Converts a (global) 2D array to a PETSc matrix over :attr:`petsc4py.PETSc.COMM_WORLD`.
Args:
matArray (array or numpy.array): input square array.
:rtype: petsc4py.PETSc.Mat()
.. important::
Requires `SciPy <http://www.scipy.org>`_.
"""
try:
import scipy.sparse as sparse
except:
print '\nERROR: loading matrices from txt files requires Scipy!'
return
matSparse =matArray
mat = _PETSc.Mat().createAIJ(size=matSparse.shape,comm=_PETSc.COMM_WORLD)
(Istart,Iend) = mat.getOwnershipRange()
ai = matSparse.indptr[Istart:Iend+1] - matSparse.indptr[Istart]
aj = matSparse.indices[matSparse.indptr[Istart]:matSparse.indptr[Iend]]
av = matSparse.data[matSparse.indptr[Istart]:matSparse.indptr[Iend]]
mat.setValuesCSR(ai,aj,av)
mat.assemble()
return mat
mat.destroy()
def matToSparse(mat):
""" Converts a PETSc matrix to a (global) sparse matrix.
Args:
mat (petsc4py.PETSc.Mat): input PETSc matrix.
:rtype: scipy.sparse.csr_matrix
.. important::
Requires `SciPy <http://www.scipy.org>`_.
"""
import scipy.sparse as sparse
data = mat.getValuesCSR()
(Istart,Iend) = mat.getOwnershipRange()
columns = mat.getSize()[0]
sparseSubMat = sparse.csr_matrix(data[::-1],shape=(Iend-Istart,columns))
comm = _PETSc.COMM_WORLD
sparseSubMat = comm.tompi4py().allgather(sparseSubMat)
return sparse.vstack(sparseSubMat)
def adjToH(adj,d=[0],amp=[0.]):
""" Creates a 1 particle PETSc-type Hamiltonian matrix from a PETSc adjacency matrix.
Args:
adj (petsc4py.PETSc.Mat): input PETSc-type adjacency matrix.
d (array of ints): an array containing *integers* indicating the nodes
where diagonal defects are to be placed (e.g. ``d=[0,1,4]``).
amp (array of floats): an array containing *floats* indicating the diagonal defect
amplitudes corresponding to each element in ``d`` (e.g. ``amp=[0.5,-1,4.2]``).
Returns:
: 1 particle Hamiltonian matrix
:rtype: petsc4py.PETSc.Mat()
Warning:
* The size of ``a`` and ``d`` must be identical
>>> amp = [0.5,-1.,4.2]
>>> len(d) == len(amp)
True
* Elements of ``d`` can range from :math:`[0,N-1]` where the adjacency matrix is :math:`N\\times N`.
"""
(Istart,Iend) = adj.getOwnershipRange()
diagSum = []
for i in range(Istart,Iend):
diagSum.append(_np.sum(adj.getRow(i)[-1]))
for j,val in enumerate(d):
if i==val: diagSum[i-Istart] += amp[j]
mat = _PETSc.Mat().create(comm=_PETSc.COMM_WORLD)
mat.setSizes(adj.getSize())
mat.setUp()
for i in range(Istart,Iend):
mat.setValue(i,i,diagSum[i-Istart])
mat.assemble()
mat.axpy(-1,adj)
return mat
mat.destroy()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#---------------------- Vec I/O functions ---------------------------
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def exportVec(vec,filename,filetype):
""" Export a PETSc vector to a file.
Args:
vec (petsc4py.PETSc.Vec): input vector.
filename (str): path to desired output file.
filetype (str): the filetype of the exported vector.
* ``'txt'`` - a column vector in text format.
* ``'bin'`` - a PETSc binary vector.
"""
if _os.path.isabs(filename):
outDir = _os.path.dirname(filename)
else:
outDir = './'+_os.path.dirname(filename)
# create output directory if it doesn't exist
try:
_os.mkdir(outDir)
except OSError as exception:
if exception.errno != _errno.EEXIST:
raise
if filetype == 'txt':
# scatter prob to process 0
comm = vec.getComm()
rank = comm.getRank()
scatter, vec0 = _PETSc.Scatter.toZero(vec)
scatter.scatter(vec, vec0, False, _PETSc.Scatter.Mode.FORWARD)
# use process 0 to write to text file
if rank == 0:
array0 = _np.asarray(vec0)
with open(filename,'w') as f:
for i in range(len(array0)):
f.write('{0: .12e}\n'.format(array0[i]))
# deallocate
comm.barrier()
scatter.destroy()
vec0.destroy()
elif filetype == 'bin':
binSave = _PETSc.Viewer().createBinary(filename, 'w')
binSave(vec)
binSave.destroy()
vec.comm.barrier()
def loadVec(filename,filetype):
""" Import a PETSc vector from a file.
Args:
filename (str): path to input file.
filetype (str): the filetype.
* ``'txt'`` - a column vector in text format.
* ``'bin'`` - a PETSc binary vector.
"""
if filetype == 'txt':
try:
vecArray = _np.loadtxt(filename,dtype=_PETSc.ScalarType)
return arrayToVec(vecArray)
except:
print "\nERROR: input state space file " + filename\
+ " does not exist or is in an incorrect format"
_sys.exit()
elif filetype == 'bin':
binLoad = _PETSc.Viewer().createBinary(filename, 'r')
try:
return _PETSc.Vec().load(binLoad)
except:
print "\nERROR: input state space file " + filename\
+ " does not exist or is in an incorrect format"
_sys.exit()
binLoad.destroy()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#---------------------- Mat I/O functions ---------------------------
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def exportMat(mat,filename,filetype,mattype=None):
""" Export a PETSc matrix to a file.
Args:
mat (petsc4py.PETSc.Mat): input matrix.
filename (str): path to desired output file.
filetype (str): the filetype of the exported vector.
* ``'txt'`` - a 2D matrix array in text format.
* ``'bin'`` - a PETSc binary matrix.
mattype (str): (``None``,``'adj'``) - if set to ``adj``, only
integers ``0`` and ``1`` are written. Note
that this only applied in ``txt`` mode.
"""
rank = _PETSc.Comm.Get_rank(_PETSc.COMM_WORLD)
if _os.path.isabs(filename):
outDir = _os.path.dirname(filename)
else:
outDir = './'+_os.path.dirname(filename)
# create output directory if it doesn't exist
try:
_os.mkdir(outDir)
except OSError as exception:
if exception.errno != _errno.EEXIST:
raise
if filetype == 'txt':
txtSave = _PETSc.Viewer().createASCII(filename, 'w',
format=_PETSc.Viewer.Format.ASCII_DENSE, comm=_PETSc.COMM_WORLD)
txtSave(mat)
txtSave.destroy()
if rank == 0:
for line in _fl.FileInput(filename,inplace=1):
if line[2] != 't':
if mattype == 'adj':
line = line.replace(" i","j")
line = line.replace(" -","-")
line = line.replace("+-","-")
line = line.replace("0000e+01+0.00000e+00j","")
line = line.replace(".00000e+00+0.00000e+00j","")
line = line.replace(".","")
line = line.replace(" -","\t-")
line = line.replace(" ","\t")
line = line.replace(" ","")
line = line.replace("\t"," ")
print line,
else:
line = line.replace(" i","j")
line = line.replace(" -","-")
line = line.replace("+-","-")
print line,
elif filetype == 'bin':
binSave = _PETSc.Viewer().createBinary(filename, 'w', comm=_PETSc.COMM_WORLD)
binSave(mat)
binSave.destroy()
mat.comm.barrier()
def loadMat(filename,filetype,delimiter=None):
""" Import a PETSc matrix from a file.
Args:
filename (str): path to input file.
filetype (str): the filetype.
* ``'txt'`` - a 2D matrix array in text format.
* ``'bin'`` - a PETSc matrix vector.
delimiter (str): this is passed to `numpy.genfromtxt\
<http://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html>`_
in the case of strange delimiters in an imported ``txt`` file.
"""
if filetype == 'txt':
try:
try:
if delimiter is None:
matArray = _np.genfromtxt(filename,dtype=_PETSc.ScalarType)
else:
matArray = _np.genfromtxt(filename,dtype=_PETSc.ScalarType,delimiter=delimiter)
except:
filefix = []
for line in _fl.FileInput(filename,inplace=0):
if line[2] != 't':
line = line.replace(" i","j")
line = line.replace(" -","-")
line = line.replace("+-","-")
filefix.append(line)
matArray = _np.genfromtxt(filefix,dtype=_PETSc.ScalarType)
return arrayToMat(matArray)
except:
print "\nERROR: input state space file " + filename\
+ " does not exist or is in an incorrect format"
_sys.exit()
elif filetype == 'bin':
binLoad = _PETSc.Viewer().createBinary(filename, 'r')
try:
return _PETSc.Mat().load(binLoad)
except:
print "\nERROR: input state space file " + filename\
+ " does not exist or is in an incorrect format"
_sys.exit()
binLoad.destroy()
def exportVecToMat(vec,filename,filetype):
""" Export a :math:`N^2` element PETSc vector as a :math:`N\\times N` matrix.
This is useful when wanting to view the full statespace of a 2 particle
quantum walk.
Args:
vec (petsc4py.PETSc.Vec): input :math:`N^2` element vector.
filename (str): path to desired output file.
filetype (str): the filetype of the exported vector.
* ``'txt'`` - an :math:`N\\times N` 2D matrix array in text format.
* ``'bin'`` - an :math:`N\\times N` PETSc binary matrix.
"""
rank = _PETSc.Comm.Get_rank(_PETSc.COMM_WORLD)
if _os.path.isabs(filename):
outDir = _os.path.dirname(filename)
else:
outDir = './'+_os.path.dirname(filename)
# create output directory if it doesn't exist
try:
_os.mkdir(outDir)
except OSError as exception:
if exception.errno != _errno.EEXIST:
raise
vecArray = vecToArray(vec)
matArray = vecArray.reshape([_np.sqrt(vecArray.size),_np.sqrt(vecArray.size)])
if filetype == 'txt':
#if rank == 0: _np.savetxt(filename,matArray)
txtSave = _PETSc.Viewer().createASCII(filename, 'w',
format=_PETSc.Viewer.Format.ASCII_DENSE, comm=_PETSc.COMM_WORLD)
txtSave(arrayToMat(matArray))
txtSave.destroy()
if rank == 0:
for line in _fl.FileInput(filename,inplace=1):
if line[2] != 't':
line = line.replace(" i","j")
line = line.replace(" -","-")
line = line.replace("+-","-")
print line,
elif filetype == 'bin':
binSave = _PETSc.Viewer().createBinary(filename, 'w', comm=_PETSc.COMM_WORLD)
binSave(arrayToMat(matArray))
binSave.destroy()
vec.comm.barrier()
def loadMatToVec(filename,filetype):
""" Load a :math:`N\\times N` matrix as a :math:`N^2` element PETSc vector.
This is useful when wanting to import the full statespace of a 2 particle
quantum walk to use for propagation.
Args:
filename (str): path to the input file.
filetype (str): the filetype
* ``'txt'`` - an :math:`N\\times N` 2D matrix array in text format.
* ``'bin'`` - **Not yet implemented! Please use a txt \
format for this type of import**.
"""
if filetype == 'txt':
try:
try:
matArray = _np.loadtxt(filename,dtype=_PETSc.ScalarType)
except:
filefix = []
for line in _fl.FileInput(filename,inplace=0):
if line[2] != 't':
line = line.replace(" i","j")
line = line.replace(" -","-")
line = line.replace("+-","-")
filefix.append(line)
matArray = _np.loadtxt(filefix,dtype=_PETSc.ScalarType)
vecArray = matArray.reshape(matArray.shape[0]**2)
return arrayToVec(vecArray)
except:
print "\nERROR: input state space file " + filename\
+ " does not exist or is in an incorrect format"
_sys.exit()
elif filetype == 'bin':
print '\nERROR: only works for txt storage!'
_sys.exit()
File diff suppressed because one or more lines are too long
-11
View File
@@ -1,11 +0,0 @@
# Check project status
gcutil getproject --project=<ProjectName> --cache_flag_values
# Start an instance
gcutil addinstance <instanceName>
# Log in
gcutil ssh <instanceName>
# Shut down
gcutil deleteinstance <instanceName>
-145
View File
@@ -1,145 +0,0 @@
#! /bin/bash
locale-gen en_US en_US.UTF-8 hu_HU hu_HU.UTF-8 > output.t
dpkg-reconfigure locales >> output.t
sudo apt-get update >> output.t
echo " "
echo " "
echo " ============================================"
echo " | Installing packages form package manager |"
echo " ============================================"
echo " "
echo " "
sudo apt-get -y install aptitude >> output.t
packages=(gcc gfortran git libopenmpi-dev python-pip python-dev git flex bison cmake vim cython ipython python-scipy python-numpy python-nose python-pip python-matplotlib python-vtk python-h5py libmumps-ptscotch-4.10.0 libmumps-ptscotch-dev libblas-dev liblapack-dev )
for item in ${packages[*]}
do
printf " %-30s\n" $item
done
for item in ${packages[*]}
do
tput cuu1
done
for item in ${packages[*]}
do
sudo aptitude -y install $item >> output.t
printf " %-30s %-4s\n" $item done
done
echo " "
echo " "
echo " ====================================="
echo " | Installing extra Python libraries |"
echo " ====================================="
echo " "
echo " "
pipPackages=(mpi4py pymumps)
for item in ${pipPackages[*]}
do
printf " %-30s\n" $item
done
for item in ${pipPackages[*]}
do
tput cuu1
done
for item in ${pipPackages[*]}
do
sudo pip install $item >> output.t
printf " %-30s %-4s\n" $item done
done
Upgrade=(scipy numpy ipython)
for item in ${Upgrade[*]}
do
printf " %-8s%-7s\n" $item upgrade
done
for item in ${Upgrade[*]}
do
tput cuu1
done
for item in ${Upgrade[*]}
do
sudo pip install $item --upgrade >> output.t
printf " %-8s%-7s %-4s\n" $item upgrade done
done
echo " "
echo " "
echo " ====================="
echo " | Installing SimPEG |"
echo " ====================="
echo " "
echo " "
cd ~
git clone https://github.com/simpeg/simpeg.git >> output.t
cd simpeg/SimPEG/
python setup.py >> output.t
cd ~
mkdir petsc
cd petsc
echo " "
echo " "
echo " ===================="
echo " | Installing PETSc |"
echo " ===================="
echo " "
echo " "
wget http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/petsc-3.4.3.tar.gz
tar -zxf petsc-3.4.3.tar.gz
cd petsc-3.4.3
./configure --with-debugging=no --dowload-mpich=yes --download-blacs=yes --download-f-blas-lapack=yes --download-scalapack=yes --download-mumps=yes --download-ml=yes --download-spooles=yes --download-hypre=yes --dowload-trilinos=yes --download-metis=yes --download-parmetis=yes --download-umfpack=yes --download-ptscotch=yes --download-superlu=yes --download-superlu_dist=yes --download-essl=yes --download-eucild=yes --download-spai=yes --download-mpi4py=yes --download-petsc4py=yes --download-scientificpython=yes
echo "export PETSC_DIR=/home/${USER}/petsc/petsc-3.4.3" >> ~/.bashrc
echo "export PETSC_ARCH=arch-linux2-c-opt" >> ~/.bashrc
export PETSC_DIR=/home/${USER}/petsc/petsc-3.4.3
export PETSC_ARCH=arch-linux2-c-opt
. ~/.bashrc
make PETSC_DIR=/home/${USER}/petsc/petsc-3.4.3 PETSC_ARCH=arch-linux2-c-opt all
make PETSC_DIR=/home/${USER}/petsc/petsc-3.4.3 PETSC_ARCH=arch-linux2-c-opt test
cd ~/petsc
echo " "
echo " "
echo " ======================="
echo " | Installing PETSc4PY |"
echo " ======================="
echo " "
echo " "
git clone https://bitbucket.org/petsc/petsc4py.git
cd petsc4py/
python setup.py build >> output.t
python setup.py install --prefix=~/petsc >> output.t
echo "export PYTHONPATH=~/petsc/lib/python2.7/site-packages:/home/$USER/simpeg:${PYTHONPATH}" >> ~/.bashrc
cd ~
source ~/.bashrc
-22
View File
@@ -1,22 +0,0 @@
#! /bin/bash
sudo aptitude -y update
sudo aptitude -y upgrade
sudo aptitude -y install gcc gfortran git libopenmpi-dev python-pip python-dev
sudo aptitude -y install ipython python-scipy python-numpy python-nose python-pip python-matplotlib
sudo aptitude -y install libmumps-ptscotch-4.10.0 libmumps-ptscotch-dev
sudo aptitude -y install libblas-dev liblapack-dev
sudo pip install mpi4py
sudo pip install pymumps
sudo pip install scipy --upgrade
sudo pip install numpy --upgrade
sudo pip install ipython --upgrade
git clone https://github.com/simpeg/simpeg.git
cd simpeg/SimPEG/
python setup.py
cd ~
echo export PYTHONPATH=/home/$USER/simpeg/ >> .bashrc
source .bashrc
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013-2015 SimPEG Developers
Copyright (c) 2013-2016 SimPEG Developers
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
-36
View File
@@ -1,36 +0,0 @@
- Electromagnetics (`simpegEM <http://simpegem.rtfd.org/>`_)
.. image:: https://travis-ci.org/simpeg/simpegem.svg?branch=master
:target: https://travis-ci.org/simpeg/simpegem
:alt: Master Branch
.. image:: https://coveralls.io/repos/simpeg/simpegem/badge.png?branch=master
:target: https://coveralls.io/r/simpeg/simpegem?branch=master
- Potential Fields (`simpegPF <http://simpegpf.rtfd.org/>`_)
.. image:: https://travis-ci.org/simpeg/simpegpf.svg?branch=master
:target: https://travis-ci.org/simpeg/simpegpf
:alt: Master Branch
.. image:: https://coveralls.io/repos/simpeg/simpegpf/badge.png?branch=master
:target: https://coveralls.io/r/simpeg/simpegpf?branch=master
- Ground Water Flow (`simpegFLOW <http://simpegflow.rtfd.org/>`_)
.. image:: https://travis-ci.org/simpeg/simpegflow.svg?branch=master
:target: https://travis-ci.org/simpeg/simpegflow
:alt: Master Branch
.. image:: https://coveralls.io/repos/simpeg/simpegflow/badge.png?branch=master
:target: https://coveralls.io/r/simpeg/simpegflow?branch=master
- Direct Current Resistivity (`simpegDC <http://simpeg-dc.rtfd.org/>`_)
.. image:: https://travis-ci.org/simpeg/simpegdc.svg?branch=master
:target: https://travis-ci.org/simpeg/simpegdc
:alt: Master Branch
.. image:: https://coveralls.io/repos/simpeg/simpegdc/badge.png?branch=master
:target: https://coveralls.io/r/simpeg/simpegdc?branch=master
- Electromagnetics 1D (`simpegEM1D <http://simpegem1d.rtfd.org/>`_)
.. image:: https://travis-ci.org/simpeg/simpegEM1D.svg?branch=master
:target: https://travis-ci.org/simpeg/simpegEM1D
:alt: Master Branch
.. image:: https://coveralls.io/repos/simpeg/simpegEM1D/badge.png?branch=master
:target: https://coveralls.io/r/simpeg/simpegEM1D?branch=master
- Magnetotellurics (`simpegMT <http://simpegmt.rtfd.org/>`_)
.. image:: https://travis-ci.org/simpeg/simpegmt.svg?branch=master
:target: https://travis-ci.org/simpeg/simpegmt
:alt: Master Branch
.. image:: https://coveralls.io/repos/simpeg/simpegmt/badge.png?branch=master
:target: https://coveralls.io/r/simpeg/simpegmt?branch=master
+5 -1
View File
@@ -17,7 +17,7 @@ SimPEG
:target: https://github.com/simpeg/simpeg/blob/master/LICENSE
:alt: BSD 3 clause license.
.. image:: https://img.shields.io/travis/simpeg/simpeg.svg
.. image:: https://api.travis-ci.org/simpeg/simpeg.svg?branch=master
:target: https://travis-ci.org/simpeg/simpeg
:alt: Travis CI build status
@@ -25,6 +25,10 @@ SimPEG
:target: https://coveralls.io/r/simpeg/simpeg?branch=master
:alt: Coverage status
.. image:: http://img.shields.io/badge/GITTER-JOIN_CHAT-brightgreen.svg?style=flat-square
:alt: gitter chat room at https://gitter.im/simpeg/simpeg
:target: https://gitter.im/simpeg/simpeg
Simulation and Parameter Estimation in Geophysics - A python package for simulation and gradient based parameter estimation in the context of geophysical applications.
The vision is to create a package for finite volume simulation with applications to geophysical imaging and subsurface flow. To enable the understanding of the many different components, this package has the following features:
+292
View File
@@ -0,0 +1,292 @@
from SimPEG import *
class FieldsDC_CC(Problem.Fields):
knownFields = {'phi_sol':'CC'}
aliasFields = {
'phi' : ['phi_sol','CC','_phi'],
'e' : ['phi_sol','F','_e'],
'j' : ['phi_sol','F','_j']
}
def __init__(self,mesh,survey,**kwargs):
super(FieldsDC_CC, self).__init__(mesh, survey, **kwargs)
def startup(self):
self._cellGrad = self.survey.prob.mesh.cellGrad
self._Mfinv = self.survey.prob.mesh.getFaceInnerProduct(invMat=True)
def _phi(self, phi_sol, srcList):
phi = phi_sol
# for i, src in enumerate(srcList):
# phi_p = src.phi_p(self.survey.prob)
# if phi_p is not None:
# phi[:,i] += phi_p
return phi
def _e(self, phi_sol, srcList):
e = -self._cellGrad*phi_sol
# for i, src in enumerate(srcList):
# e_p = src.e_p(self.survey.prob)
# if e_p is not None:
# e[:,i] += e_p
return e
def _j(self, phi_sol, srcList):
j = -self._Mfinv*self.survey.prob.Msig*self._cellGrad*phi_sol
# for i, src in enumerate(srcList):
# j_p = src.j_p(self.survey.prob)
# if j_p is not None:
# j[:,i] += j_p
return j
class SrcDipole(Survey.BaseSrc):
"""A dipole source, locA and locB are moved to the closest cell-centers"""
current = 1
loc = None
# _rhsDict = None
def __init__(self, rxList, locA, locB, **kwargs):
self.loc = (locA, locB)
super(SrcDipole, self).__init__(rxList, **kwargs)
def eval(self, prob):
# Recompute rhs
# if getattr(self, '_rhsDict', None) is None:
# self._rhsDict = {}
# if mesh not in self._rhsDict:
pts = [self.loc[0], self.loc[1]]
inds = Utils.closestPoints(prob.mesh, pts)
q = np.zeros(prob.mesh.nC)
q[inds] = - self.current * ( np.r_[1., -1.] / prob.mesh.vol[inds] )
# self._rhsDict[mesh] = q
# return self._rhsDict[mesh]
return q
class RxDipole(Survey.BaseRx):
"""A dipole source, locA and locB are moved to the closest cell-centers"""
def __init__(self, locsM, locsN, **kwargs):
locs = (locsM, locsN)
assert locsM.shape == locsN.shape, 'locs must be the same shape.'
super(RxDipole, self).__init__(locs, 'dipole', storeProjections=False, **kwargs)
@property
def nD(self):
"""Number of data in the receiver."""
return self.locs[0].shape[0]
def getP(self, mesh):
P0 = mesh.getInterpolationMat(self.locs[0], self.projGLoc)
P1 = mesh.getInterpolationMat(self.locs[1], self.projGLoc)
return P0 - P1
class SurveyDC(Survey.BaseSurvey):
"""
**SurveyDC**
Geophysical DC resistivity data.
"""
uncert = None
def __init__(self, srcList, **kwargs):
self.srcList = srcList
Survey.BaseSurvey.__init__(self, **kwargs)
# self._rhsDict = {}
self._Ps = {}
def eval(self, u):
"""
Predicted data.
.. math::
d_\\text{pred} = Pu(m)
"""
P = self.getP(self.prob.mesh)
return P*mkvc(u[self.srcList, 'phi_sol'])
def getP(self, mesh):
if mesh in self._Ps:
return self._Ps[mesh]
P_src = [sp.vstack([rx.getP(mesh) for rx in src.rxList]) for src in self.srcList]
self._Ps[mesh] = sp.block_diag(P_src)
return self._Ps[mesh]
class ProblemDC_CC(Problem.BaseProblem):
"""
**ProblemDC**
Geophysical DC resistivity problem.
"""
surveyPair = SurveyDC
Solver = Solver
fieldsPair = FieldsDC_CC
Ainv = None
def __init__(self, mesh, **kwargs):
Problem.BaseProblem.__init__(self, mesh)
self.mesh.setCellGradBC('neumann')
Utils.setKwargs(self, **kwargs)
deleteTheseOnModelUpdate = ['_A', '_Msig', '_dMdsig']
@property
def Msig(self):
if getattr(self, '_Msig', None) is None:
sigma = self.curModel.transform
Av = self.mesh.aveF2CC
self._Msig = Utils.sdiag(1/(self.mesh.dim * Av.T * (1/sigma)))
return self._Msig
@property
def dMdsig(self):
if getattr(self, '_dMdsig', None) is None:
sigma = self.curModel.transform
Av = self.mesh.aveF2CC
dMdprop = self.mesh.dim * Utils.sdiag(self.Msig.diagonal()**2) * Av.T * Utils.sdiag(1./sigma**2)
self._dMdsig = lambda Gu: Utils.sdiag(Gu) * dMdprop
return self._dMdsig
@property
def A(self):
"""
Makes the matrix A(m) for the DC resistivity problem.
:param numpy.array m: model
:rtype: scipy.csc_matrix
:return: A(m)
.. math::
c(m,u) = A(m)u - q = G\\text{sdiag}(M(mT(m)))Du - q = 0
Where M() is the mass matrix and mT is the model transform.
"""
if getattr(self, '_A', None) is None:
D = self.mesh.faceDiv
G = self.mesh.cellGrad
self._A = D*self.Msig*G
# Remove the null space from the matrix.
self._A[0,0] /= self.mesh.vol[0]
self._A = self._A.tocsc()
return self._A
def getRHS(self):
# if self.mesh not in self._rhsDict:
RHS = np.array([src.eval(self) for src in self.survey.srcList]).T
# self._rhsDict[mesh] = RHS
# return self._rhsDict[mesh]
return RHS
def fields(self, m):
F = self.fieldsPair(self.mesh, self.survey)
self.curModel = m
A = self.A
self.Ainv = self.Solver(A, **self.solverOpts)
RHS = self.getRHS()
Phi = self.Ainv * RHS
Srcs = self.survey.srcList
F[Srcs, 'phi_sol'] = Phi
return F
def Jvec(self, m, v, f=None):
"""
:param numpy.array m: model
:param numpy.array v: vector to multiply
:param Fields f: fields
:rtype: numpy.array
:return: Jv
.. math::
c(m,u) = A(m)u - q = G\\text{sdiag}(M(mT(m)))Du - q = 0
\\nabla_u (A(m)u - q) = A(m)
\\nabla_m (A(m)u - q) = G\\text{sdiag}(Du)\\nabla_m(M(mT(m)))
Where M() is the mass matrix and mT is the model transform.
.. math::
J = - P \left( \\nabla_u c(m, u) \\right)^{-1} \\nabla_m c(m, u)
J(v) = - P ( A(m)^{-1} ( G\\text{sdiag}(Du)\\nabla_m(M(mT(m))) v ) )
"""
# Set current model; clear dependent property $\mathbf{A(m)}$
self.curModel = m
sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$
if f is None:
# Run forward simulation if $u$ not provided
f = self.fields(self.curModel)
u = f[self.survey.srcList, 'phi_sol']
D = self.mesh.faceDiv
G = self.mesh.cellGrad
# Derivative of model transform, $\deriv{\sigma}{\m}$
dsigdm_x_v = self.curModel.transformDeriv * v
# Take derivative of $C(m,u)$ w.r.t. $m$
dCdm_x_v = np.empty_like(u)
# loop over fields for each source
for i in range(self.survey.nSrc):
# Derivative of inner product, $\left(\mathbf{M}_{1/\sigma}^f\right)^{-1}$
dAdsig = D * self.dMdsig( G * u[:,i] )
dCdm_x_v[:, i] = dAdsig * dsigdm_x_v
# Take derivative of $C(m,u)$ w.r.t. $u$
dA_du = self.A
# Solve for $\deriv{u}{m}$
# dCdu_inv = self.Solver(dCdu, **self.solverOpts)
if self.Ainv is None:
self.Ainv = self.Solver(dA_du, **self.solverOpts)
P = self.survey.getP(self.mesh)
Jv = - P * mkvc( self.Ainv * dCdm_x_v )
return Jv
def Jtvec(self, m, v, f=None):
self.curModel = m
sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$
if f is None:
# Run forward simulation if $f$ not provided
f = self.fields(self.curModel)
u = f[self.survey.srcList, 'phi_sol']
shp = u.shape
P = self.survey.getP(self.mesh)
PT_x_v = (P.T*v).reshape(shp, order='F')
D = self.mesh.faceDiv
G = self.mesh.cellGrad
dA_du = self.A
mT_dm = self.mapping.deriv(m)
# We probably always need this due to the linesearch .. (?)
self.Ainv = self.Solver(dA_du.T, **self.solverOpts)
# if self.Ainv is None:
# self.Ainv = self.Solver(dCdu, **self.solverOpts)
w = self.Ainv * PT_x_v
Jtv = 0
for i, ui in enumerate(u.T): # loop over each column
Jtv += self.dMdsig( G * ui ).T * ( D.T * w[:,i] )
Jtv = - mT_dm.T * ( Jtv )
return Jtv
+182
View File
@@ -0,0 +1,182 @@
from SimPEG import *
from BaseDC import SurveyDC, FieldsDC_CC
class SurveyIP(SurveyDC):
"""
**SurveyDC**
Geophysical DC resistivity data.
"""
def __init__(self, srcList, **kwargs):
self.srcList = srcList
Survey.BaseSurvey.__init__(self, **kwargs)
self._Ps = {}
def dpred(self, m, f=None):
"""
Predicted data.
.. math::
d_\\text{pred} = Pf(m)
"""
return self.prob.forward(m)
class ProblemIP(Problem.BaseProblem):
"""
**ProblemIP**
Geophysical IP resistivity problem.
"""
surveyPair = SurveyDC
Solver = Solver
sigma = None
Ainv = None
u = None
def __init__(self, mesh, **kwargs):
Problem.BaseProblem.__init__(self, mesh)
self.mesh.setCellGradBC('neumann')
Utils.setKwargs(self, **kwargs)
# deleteTheseOnModelUpdate = ['_A', '_Msig', '_dMdsig']
@property
def Msig(self):
if getattr(self, '_Msig', None) is None:
# sigma = self.curModel.transform
sigma = self.sigma
Av = self.mesh.aveF2CC
self._Msig = Utils.sdiag(1/(self.mesh.dim * Av.T * (1/sigma)))
return self._Msig
@property
def dMdsig(self):
if getattr(self, '_dMdsig', None) is None:
# sigma = self.curModel.transform
sigma = self.sigma
Av = self.mesh.aveF2CC
dMdprop = self.mesh.dim * Utils.sdiag(self.Msig.diagonal()**2) * Av.T * Utils.sdiag(1./sigma**2)
self._dMdsig = lambda Gu: Utils.sdiag(Gu) * dMdprop
return self._dMdsig
@property
def A(self):
"""
Makes the matrix A(m) for the DC resistivity problem.
:param numpy.array m: model
:rtype: scipy.csc_matrix
:return: A(m)
.. math::
c(m,u) = A(m)u - q = G\\text{sdiag}(M(mT(m)))Du - q = 0
Where M() is the mass matrix and mT is the model transform.
"""
if getattr(self, '_A', None) is None:
D = self.mesh.faceDiv
G = self.mesh.cellGrad
self._A = D*self.Msig*G
# Remove the null space from the matrix.
self._A[-1,-1] /= self.mesh.vol[-1]
self._A = self._A.tocsc()
return self._A
def getRHS(self):
# if self.mesh not in self._rhsDict:
RHS = np.array([src.eval(self) for src in self.survey.srcList]).T
# self._rhsDict[mesh] = RHS
# return self._rhsDict[mesh]
return RHS
def fields(self, m):
if self.u is None:
A = self.A
if self.Ainv == None:
self.Ainv = self.Solver(A, **self.solverOpts)
Q = self.getRHS()
self.u = self.Ainv * Q
return self.u
def forward(self, m, u=None):
# Set current model; clear dependent property $\mathbf{A(m)}$
self.curModel = m
# sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$
sigma = self.sigma
if self.u is None:
# Run forward simulation if $u$ not provided
u = self.fields(sigma)
shp = (self.mesh.nC, self.survey.nSrc)
u = self.u.reshape(shp, order='F')
D = self.mesh.faceDiv
G = self.mesh.cellGrad
# Derivative of model transform, $\deriv{\sigma}{\m}$
# dsigdm_x_v = self.curModel.transformDeriv * v
dsigdm_x_v = Utils.sdiag(sigma) * self.curModel.transformDeriv * m
# Take derivative of $C(m,u)$ w.r.t. $m$
dCdm_x_v = np.empty_like(u)
# loop over fields for each source
for i in range(self.survey.nSrc):
# Derivative of inner product, $\left(\mathbf{M}_{1/\sigma}^f\right)^{-1}$
dAdsig = D * self.dMdsig( G * u[:,i] )
dCdm_x_v[:, i] = dAdsig * dsigdm_x_v
# Take derivative of $C(m,u)$ w.r.t. $u$
if self.Ainv == None:
self.Ainv = self.Solver(A, **self.solverOpts)
# dCdu = self.A
# Solve for $\deriv{u}{m}$
# dCdu_inv = self.Solver(dCdu, **self.solverOpts)
P = self.survey.getP(self.mesh)
J_x_v = - P * mkvc( self.Ainv * dCdm_x_v )
return -J_x_v
def Jvec(self, m, v, f=None):
return self.forward(v)
def Jtvec(self, m, v, f=None):
self.curModel = m
# sigma = self.curModel.transform # $\sigma = \mathcal{M}(\m)$
sigma = self.sigma
if self.u is None:
u = self.fields(sigma)
else:
u = self.u
shp = (self.mesh.nC, self.survey.nSrc)
u = u.reshape(shp, order='F')
P = self.survey.getP(self.mesh)
PT_x_v = (P.T*v).reshape(shp, order='F')
D = self.mesh.faceDiv
G = self.mesh.cellGrad
A = self.A
mT_dm = Utils.sdiag(sigma)*self.mapping.deriv(m)
# mT_dm = self.mapping.deriv(m)
# dCdu = A.T
# Ainv = self.Solver(dCdu, **self.solverOpts)
# if self.Ainv == None:
self.Ainv = self.Solver(A.T, **self.solverOpts)
w = self.Ainv * PT_x_v
Jtv = 0
for i, ui in enumerate(u.T): # loop over each column
Jtv += self.dMdsig( G * ui ).T * ( D.T * w[:,i] )
Jtv = - mT_dm.T * ( Jtv )
return -Jtv
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
import numpy as np
def WennerSrcList(nElecs, aSpacing, in2D=False, plotIt=False):
import SimPEG.DCIP as DC
elocs = np.arange(0,aSpacing*nElecs,aSpacing)
elocs -= (nElecs*aSpacing - aSpacing)/2
space = 1
WENNER = np.zeros((0,),dtype=int)
for ii in range(nElecs):
for jj in range(nElecs):
test = np.r_[jj,jj+space,jj+space*2,jj+space*3]
if np.any(test >= nElecs):
break
WENNER = np.r_[WENNER, test]
space += 1
WENNER = WENNER.reshape((-1,4))
if plotIt:
for i, s in enumerate('rbkg'):
plt.plot(elocs[WENNER[:,i]],s+'.')
plt.show()
# Create sources and receivers
i = 0
if in2D:
getLoc = lambda ii, abmn: np.r_[elocs[WENNER[ii,abmn]],0]
else:
getLoc = lambda ii, abmn: np.r_[elocs[WENNER[ii,abmn]],0, 0]
srcList = []
for i in range(WENNER.shape[0]):
rx = DC.RxDipole(getLoc(i,1),getLoc(i,2))
src = DC.SrcDipole([rx], getLoc(i,0),getLoc(i,3))
srcList += [src]
return srcList
+4
View File
@@ -0,0 +1,4 @@
from BaseDC import *
from BaseIP import *
from DCIPUtils import *
import Utils
+32 -42
View File
@@ -22,11 +22,11 @@ class BaseDataMisfit(object):
Utils.setKwargs(self,**kwargs)
@Utils.timeIt
def eval(self, m, u=None):
"""eval(m, u=None)
def eval(self, m, f=None):
"""eval(m, f=None)
:param numpy.array m: geophysical model
:param numpy.array u: fields
:param Fields f: fields
:rtype: float
:return: data misfit
@@ -34,11 +34,11 @@ class BaseDataMisfit(object):
raise NotImplementedError('This method should be overwritten.')
@Utils.timeIt
def evalDeriv(self, m, u=None):
"""evalDeriv(m, u=None)
def evalDeriv(self, m, f=None):
"""evalDeriv(m, f=None)
:param numpy.array m: geophysical model
:param numpy.array u: fields
:param Fields f: fields
:rtype: numpy.array
:return: data misfit derivative
@@ -47,32 +47,18 @@ class BaseDataMisfit(object):
@Utils.timeIt
def eval2Deriv(self, m, v, u=None):
"""eval2Deriv(m, v, u=None)
def eval2Deriv(self, m, v, f=None):
"""eval2Deriv(m, v, f=None)
:param numpy.array m: geophysical model
:param numpy.array v: vector to multiply
:param numpy.array u: fields
:param Fields f: fields
:rtype: numpy.array
:return: data misfit derivative
"""
raise NotImplementedError('This method should be overwritten.')
# TODO: implement target misfit as a property, or possibly as an inversion directive.
# def target(self, forward):
# """target(forward)
# Target for data misfit. By default this is the number of data,
# which satisfies the Discrepancy Principle.
# :rtype: float
# :return: data misfit target
# """
# prob, survey = self.splitForward(forward)
# return survey.nD
class l2_DataMisfit(BaseDataMisfit):
@@ -103,10 +89,18 @@ class l2_DataMisfit(BaseDataMisfit):
"""
if getattr(self, '_Wd', None) is None:
print 'SimPEG.l2_DataMisfit is creating default weightings for Wd.'
survey = self.survey
eps = np.linalg.norm(Utils.mkvc(survey.dobs),2)*1e-5
self._Wd = Utils.sdiag(1/(abs(survey.dobs)*survey.std+eps))
if getattr(survey,'std', None) is None:
print 'SimPEG.DataMisfit.l2_DataMisfit assigning default std of 5%'
survey.std = 0.05
if getattr(survey, 'eps', None) is None:
print 'SimPEG.DataMisfit.l2_DataMisfit assigning default eps of 1e-5 * ||dobs||'
survey.eps = np.linalg.norm(Utils.mkvc(survey.dobs),2)*1e-5
self._Wd = Utils.sdiag(1/(abs(survey.dobs)*survey.std+survey.eps))
return self._Wd
@Wd.setter
@@ -114,24 +108,20 @@ class l2_DataMisfit(BaseDataMisfit):
self._Wd = value
@Utils.timeIt
def eval(self, m, u=None):
"eval(m, u=None)"
prob = self.prob
survey = self.survey
R = self.Wd * survey.residual(m, u=u)
def eval(self, m, f=None):
"eval(m, f=None)"
if f is None: f = self.prob.fields(m)
R = self.Wd * self.survey.residual(m, f)
return 0.5*np.vdot(R, R)
@Utils.timeIt
def evalDeriv(self, m, u=None):
"evalDeriv(m, u=None)"
prob = self.prob
survey = self.survey
if u is None: u = prob.fields(m)
return prob.Jtvec(m, self.Wd * (self.Wd * survey.residual(m, u=u)), u=u)
def evalDeriv(self, m, f=None):
"evalDeriv(m, f=None)"
if f is None: f = self.prob.fields(m)
return self.prob.Jtvec(m, self.Wd * (self.Wd * self.survey.residual(m, f=f)), f=f)
@Utils.timeIt
def eval2Deriv(self, m, v, u=None):
"eval2Deriv(m, v, u=None)"
prob = self.prob
if u is None: u = prob.fields(m)
return prob.Jtvec_approx(m, self.Wd * (self.Wd * prob.Jvec_approx(m, v, u=u)), u=u)
def eval2Deriv(self, m, v, f=None):
"eval2Deriv(m, v, f=None)"
if f is None: f = self.prob.fields(m)
return self.prob.Jtvec_approx(m, self.Wd * (self.Wd * self.prob.Jvec_approx(m, v, f=f)), f=f)
+159 -3
View File
@@ -123,10 +123,10 @@ class BetaEstimate_ByEig(InversionDirective):
if self.debug: print 'Calculating the beta0 parameter.'
m = self.invProb.curModel
u = self.invProb.getFields(m, store=True, deleteWarmstart=False)
f = self.invProb.getFields(m, store=True, deleteWarmstart=False)
x0 = np.random.rand(*m.shape)
t = x0.dot(self.dmisfit.eval2Deriv(m,x0,u=u))
t = x0.dot(self.dmisfit.eval2Deriv(m,x0,f=f))
b = x0.dot(self.reg.eval2Deriv(m, v=x0))
self.beta0 = self.beta0_ratio*(t/b)
@@ -146,10 +146,15 @@ class BetaSchedule(InversionDirective):
class TargetMisfit(InversionDirective):
chifact = 1.
phi_d_star = None
@property
def target(self):
if getattr(self, '_target', None) is None:
self._target = self.survey.nD*0.5
if self.phi_d_star is None:
self.phi_d_star = 0.5 * self.survey.nD
self._target = self.chifact * self.phi_d_star # the factor of 0.5 is because we do phid = 0.5*|| dpred - dobs||^2
return self._target
@target.setter
def target(self, val):
@@ -206,7 +211,36 @@ class SaveOutputEveryIteration(_SaveEveryIteration):
f.write(' %3d %1.4e %1.4e %1.4e %1.4e\n'%(self.opt.iter, self.invProb.beta, self.invProb.phi_d, self.invProb.phi_m, self.opt.f))
f.close()
class SaveOutputDictEveryIteration(_SaveEveryIteration):
"""SaveOutputDictEveryIteration"""
def initialize(self):
print "SimPEG.SaveOutputDictEveryIteration will save your inversion progress as dictionary: '###-%s.npz'"%self.fileName
def endIter(self):
# Save the data.
ms = self.reg.Ws * ( self.reg.mapping * (self.invProb.curModel - self.reg.mref) )
phi_ms = 0.5*ms.dot(ms)
if self.reg.mrefInSmooth == True:
mref = self.reg.mref
else:
mref = 0
mx = self.reg.Wx * ( self.reg.mapping * (self.invProb.curModel - mref) )
phi_mx = 0.5 * mx.dot(mx)
if self.prob.mesh.dim >= 2:
my = self.reg.Wy * ( self.reg.mapping * (self.invProb.curModel - mref) )
phi_my = 0.5 * my.dot(my)
else:
phi_my = 'NaN'
if self.prob.mesh.dim==3:
mz = self.reg.Wz * ( self.reg.mapping * (self.invProb.curModel - mref) )
phi_mz = 0.5 * mz.dot(mz)
else:
phi_mz = 'NaN'
# Save the file as a npz
np.savez('{:03d}-{:s}'.format(self.opt.iter,self.fileName), iter=self.opt.iter, beta=self.invProb.beta, phi_d=self.invProb.phi_d, phi_m=self.invProb.phi_m, phi_ms=phi_ms, phi_mx=phi_mx, phi_my=phi_my, phi_mz=phi_mz,f=self.opt.f, m=self.invProb.curModel,dpred=self.invProb.dpred)
# class UpdateReferenceModel(Parameter):
@@ -220,3 +254,125 @@ class SaveOutputEveryIteration(_SaveEveryIteration):
# mref = self.mref0
# self.m_prev = self.invProb.m_current
# return mref
class Update_IRLS(InversionDirective):
eps_min = None
factor = None
gamma = None
phi_m_last = None
phi_d_last = None
def initialize(self):
# Scale the regularization for changes in norm
if getattr(self, 'phi_m_last', None) is not None:
self.reg.curModel = self.invProb.curModel
self.reg.gamma = 1.
phim_new = self.reg.eval(self.invProb.curModel)
self.gamma = self.phi_m_last / phim_new
self.reg.curModel = self.invProb.curModel
self.reg.gamma = self.gamma
if getattr(self, 'phi_d_last', None) is None:
self.phi_d_last = self.invProb.phi_d
def endIter(self):
# Cool the threshold parameter if required
if getattr(self, 'factor', None) is not None:
eps = self.reg.eps / self.factor
if getattr(self, 'eps_min', None) is not None:
self.reg.eps = np.max([self.eps_min,eps])
else:
self.reg.eps = eps
# Get phi_m at the end of current iteration
self.phi_m_last = self.invProb.phi_m_last
# Update the model used for the IRLS weights
self.reg.curModel = self.invProb.curModel
# Temporarely set gamma to 1. to get raw phi_m
self.reg.gamma = 1.
# Compute new model objective function value
phim_new = self.reg.eval(self.invProb.curModel)
# Update gamma to scale the regularization between IRLS iterations
self.reg.gamma = self.phi_m_last / phim_new
# Set the weighting matrix to None so that it is recomputed next time
# it is called in the inversion
self.reg._W = None
class Update_lin_PreCond(InversionDirective):
"""
Create a Jacobi preconditioner for the linear problem
"""
onlyOnStart=False
def initialize(self):
if getattr(self.opt, 'approxHinv', None) is None:
# Update the pre-conditioner
diagA = np.sum(self.prob.G**2.,axis=0) + self.invProb.beta*(self.reg.W.T*self.reg.W).diagonal() #* (self.reg.mapping * np.ones(self.reg.curModel.size))**2.
PC = Utils.sdiag((self.prob.mapping.deriv(None).T *diagA)**-1.)
self.opt.approxHinv = PC
def endIter(self):
# Cool the threshold parameter
if self.onlyOnStart==True:
return
if getattr(self.opt, 'approxHinv', None) is not None:
# Update the pre-conditioner
diagA = np.sum(self.prob.G**2.,axis=0) + self.invProb.beta*(self.reg.W.T*self.reg.W).diagonal() #* (self.reg.mapping * np.ones(self.reg.curModel.size))**2.
PC = Utils.sdiag((self.prob.mapping.deriv(None).T *diagA)**-1.)
self.opt.approxHinv = PC
class Update_Wj(InversionDirective):
"""
Create approx-sensitivity base weighting using the probing method
"""
k = None # Number of probing cycles
itr = None # Iteration number to update Wj, or always update if None
def endIter(self):
if self.itr is None or self.itr == self.opt.iter:
m = self.invProb.curModel
if self.k is None:
self.k = int(self.survey.nD/10)
def JtJv(v):
Jv = self.prob.Jvec(m, v)
return self.prob.Jtvec(m,Jv)
JtJdiag = Utils.diagEst(JtJv,len(m),k=self.k)
JtJdiag = JtJdiag / max(JtJdiag)
self.reg.wght = JtJdiag
class Scale_Beta(InversionDirective):
"""
Instead of a linear cooling schedule, beta is allowed to change based
on the ratio between the target misfit and the current data misfit. The
update is done only if the misfit is outside some threshold bounds.
"""
tol = 0.05
def endIter(self):
# Check if misfit is within the tolerance, otherwise adjust beta
val = self.invProb.phi_d / (self.survey.nD*0.5)
if np.abs(1.-val) > self.tol:
self.invProb.beta = self.invProb.beta * self.survey.nD*0.5 / self.invProb.phi_d
+118
View File
@@ -0,0 +1,118 @@
import numpy as np
from scipy.constants import mu_0, pi
from scipy import special
def DCAnalyticHalf(txloc, rxlocs, sigma, earth_type="wholespace"):
"""
Analytic solution for electric potential from a postive pole
:param array txloc: a xyz location of A (+) electrode (np.r_[xa, ya, za])
:param list rxlocs: xyz locations of M (+) and N (-) electrodes [M, N]
e.g.
rxlocs = [M, N]
M: xyz locations of M (+) electrode (np.c_[xmlocs, ymlocs, zmlocs])
N: xyz locations of N (-) electrode (np.c_[xnlocs, ynlocs, znlocs])
:param float or complex sigma: values of conductivity
:param string earth_type: values of conductivity ("wholsespace" or "halfspace")
"""
M = rxlocs[0]
N = rxlocs[1]
rM = np.sqrt( (M[:,0]-txloc[0])**2 + (M[:,1]-txloc[1])**2 + (M[:,2]-txloc[1])**2 )
rN = np.sqrt( (N[:,0]-txloc[0])**2 + (N[:,1]-txloc[1])**2 + (N[:,2]-txloc[1])**2 )
phiM = 1./(4*np.pi*rM*sigma)
phiN = 1./(4*np.pi*rN*sigma)
phi = phiM - phiN
if earth_type == "halfspace":
phi *= 2
return phi
deg2rad = lambda deg: deg/180.*np.pi
rad2deg = lambda rad: rad*180./np.pi
def DCAnalyticSphere(txloc, rxloc, xc, radius, sigma, sigma1, \
field_type = "secondary", order=12, halfspace=False):
# def DCSpherePointCurrent(txloc, rxloc, xc, radius, rho, rho1, \
# field_type = "secondary", order=12):
"""
Parameters:
:param array txloc: A (+) current electrode location (x,y,z)
:param array xc: x center of depressed sphere
:param array rxloc: M(+) electrode locations / (Nx3 array, # of electrodes)
:param float radius: radius (float): radius of the sphere (m)
:param float rho: resistivity of the background (ohm-m)
:param float rho1: resistivity of the sphere
:param string field_type: : "secondary", "total", "primary"
(default="secondary")
"secondary": secondary potential only due to sphere
"primary": primary potential from the point source
"total": "secondary"+"primary"
:param float order: maximum order of Legendre polynomial (default=12)
Written by Seogi Kang (skang@eos.ubc.ca)
Ph.D. Candidate of University of British Columbia, Canada
"""
Pleg = []
# Compute Legendre Polynomial
for i in range(order):
Pleg.append(special.legendre(i, monic=0))
rho = 1./sigma
rho1 = 1./sigma1
# Center of the sphere should be aligned in txloc in y-direction
yc = txloc[1]
xyz = np.c_[rxloc[:,0]-xc, rxloc[:,1]-yc, rxloc[:,2]]
r = np.sqrt( (xyz**2).sum(axis=1) )
x0 = abs(txloc[0]-xc)
costheta = xyz[:,0]/r * (txloc[0]-xc)/x0
phi = np.zeros_like(r)
R = (r**2+x0**2.-2.*r*x0*costheta)**0.5
# primary potential in a whole space
prim = rho*1./(4*np.pi*R)
if field_type =="primary":
return prim
sphind = r < radius
out = np.zeros_like(r)
for n in range(order):
An, Bn = AnBnfun(n, radius, x0, rho, rho1)
dumout = An*r[~sphind]**(-n-1.)*Pleg[n](costheta[~sphind])
out[~sphind] += dumout
dumin = Bn*r[sphind]**(n)*Pleg[n](costheta[sphind])
out[sphind] += dumin
out[~sphind] += prim[~sphind]
if halfspace:
scale = 2
else:
scale = 1
if field_type == "secondary":
return scale*(out-prim)
elif field_type == "total":
return scale*out
def AnBnfun(n, radius, x0, rho, rho1, I=1.):
const = I*rho/(4*np.pi)
bunmo = n*rho + (n+1)*rho1
An = const * radius**(2*n+1) / x0 ** (n+1.) * n * \
(rho1-rho) / bunmo
Bn = const * 1. / x0 ** (n+1.) * (2*n+1) * (rho1) / bunmo
return An, Bn
+2 -2
View File
@@ -2,7 +2,6 @@ from __future__ import division
import numpy as np
from scipy.constants import mu_0, pi
from scipy.special import erf
import matplotlib.pyplot as plt
from SimPEG import Utils
@@ -59,8 +58,9 @@ def MagneticDipoleWholeSpace(XYZ, srcLoc, sig, f, moment=1., orientation='X', mu
from SimPEG import EM
import matplotlib.pyplot as plt
from scipy.constants import mu_0
freqs = np.logspace(-2,5,100)
Bx, By, Bz = EM.Analytics.FDEM.AnalyticMagDipoleWholeSpace([0,100,0], [0,0,0], 1e-2, freqs, m=1, orientation='Z')
Bx, By, Bz = EM.Analytics.FDEM.MagneticDipoleWholeSpace([0,100,0], [0,0,0], 1e-2, freqs, moment=1, orientation='Z')
plt.loglog(freqs, np.abs(Bz.real)/mu_0, 'b')
plt.loglog(freqs, np.abs(Bz.imag)/mu_0, 'r')
plt.legend(('real','imag'))
+1
View File
@@ -1,3 +1,4 @@
from TDEM import hzAnalyticDipoleT
from FDEM import hzAnalyticDipoleF
from FDEMcasing import *
from DC import DCAnalyticHalf, DCAnalyticSphere
+66 -21
View File
@@ -1,15 +1,16 @@
from SimPEG import Survey, Problem, Utils, Models, Maps, PropMaps, np, sp, Solver as SimpegSolver
from scipy.constants import mu_0
class EMPropMap(Maps.PropMap):
"""
"""
Property Map for EM Problems. The electrical conductivity (\\(\\sigma\\)) is the default inversion property, and the default value of the magnetic permeability is that of free space (\\(\\mu = 4\\pi\\times 10^{-7} \\) H/m)
"""
sigma = Maps.Property("Electrical Conductivity", defaultInvProp = True, propertyLink=('rho',Maps.ReciprocalMap))
mu = Maps.Property("Inverse Magnetic Permeability", defaultVal = mu_0, propertyLink=('mui',Maps.ReciprocalMap))
rho = Maps.Property("Electrical Resistivity", propertyLink=('sigma', Maps.ReciprocalMap))
rho = Maps.Property("Electrical Resistivity", propertyLink=('sigma', Maps.ReciprocalMap))
mui = Maps.Property("Inverse Magnetic Permeability", defaultVal = 1./mu_0, propertyLink=('mu', Maps.ReciprocalMap))
@@ -21,7 +22,7 @@ class BaseEMProblem(Problem.BaseProblem):
surveyPair = Survey.BaseSurvey
dataPair = Survey.Data
PropMap = EMPropMap
Solver = SimpegSolver
@@ -51,7 +52,7 @@ class BaseEMProblem(Problem.BaseProblem):
if self.mapping.muMap is not None or self.mapping.muiMap is not None:
toDelete += ['_MeMu', '_MeMuI','_MfMui','_MfMuiI']
return toDelete
@property
def Me(self):
"""
@@ -61,6 +62,15 @@ class BaseEMProblem(Problem.BaseProblem):
self._Me = self.mesh.getEdgeInnerProduct()
return self._Me
@property
def MeI(self):
"""
Edge inner product matrix
"""
if getattr(self, '_MeI', None) is None:
self._MeI = self.mesh.getEdgeInnerProduct(invMat=True)
return self._MeI
@property
def Mf(self):
"""
@@ -70,8 +80,22 @@ class BaseEMProblem(Problem.BaseProblem):
self._Mf = self.mesh.getFaceInnerProduct()
return self._Mf
@property
def MfI(self):
"""
Face inner product matrix
"""
if getattr(self, '_MfI', None) is None:
self._MfI = self.mesh.getFaceInnerProduct(invMat=True)
return self._MfI
# ----- Magnetic Permeability ----- #
@property
def Vol(self):
if getattr(self, '_Vol', None) is None:
self._Vol = Utils.sdiag(self.mesh.vol)
return self._Vol
# ----- Magnetic Permeability ----- #
@property
def MfMui(self):
"""
@@ -109,7 +133,7 @@ class BaseEMProblem(Problem.BaseProblem):
return self._MeMuI
# ----- Electrical Conductivity ----- #
# ----- Electrical Conductivity ----- #
#TODO: hardcoded to sigma as the model
@property
def MeSigma(self):
@@ -120,18 +144,17 @@ class BaseEMProblem(Problem.BaseProblem):
self._MeSigma = self.mesh.getEdgeInnerProduct(self.curModel.sigma)
return self._MeSigma
# TODO: This should take a vector
# TODO: This should take a vector
def MeSigmaDeriv(self, u):
"""
Derivative of MeSigma with respect to the model
"""
"""
return self.mesh.getEdgeInnerProductDeriv(self.curModel.sigma)(u) * self.curModel.sigmaDeriv
@property
def MeSigmaI(self):
"""
Inverse of the edge inner product matrix for \\(\\sigma\\).
Inverse of the edge inner product matrix for \\(\\sigma\\).
"""
if getattr(self, '_MeSigmaI', None) is None:
self._MeSigmaI = self.mesh.getEdgeInnerProduct(self.curModel.sigma, invMat=True)
@@ -140,16 +163,13 @@ class BaseEMProblem(Problem.BaseProblem):
# TODO: This should take a vector
def MeSigmaIDeriv(self, u):
"""
Derivative of :code:`MeSigma` with respect to the model
"""
Derivative of :code:`MeSigma` with respect to the model
"""
# TODO: only works for diagonal tensors. getEdgeInnerProductDeriv, invMat=True should be implemented in SimPEG
dMeSigmaI_dI = -self.MeSigmaI**2
dMe_dsig = self.mesh.getEdgeInnerProductDeriv(self.curModel.sigma)(u)
dsig_dm = self.curModel.sigmaDeriv
return dMeSigmaI_dI * ( dMe_dsig * ( dsig_dm))
# return self.mesh.getEdgeInnerProductDeriv(self.curModel.sigma, invMat=True)(u)
return dMeSigmaI_dI * ( dMe_dsig * self.curModel.sigmaDeriv )
@property
def MfRho(self):
@@ -163,10 +183,9 @@ class BaseEMProblem(Problem.BaseProblem):
# TODO: This should take a vector
def MfRhoDeriv(self,u):
"""
Derivative of :code:`MfRho` with respect to the model.
Derivative of :code:`MfRho` with respect to the model.
"""
return self.mesh.getFaceInnerProductDeriv(self.curModel.rho)(u) * (-Utils.sdiag(self.curModel.rho**2) * self.curModel.sigmaDeriv)
# self.curModel.rhoDeriv
return self.mesh.getFaceInnerProductDeriv(self.curModel.rho)(u) * self.curModel.rhoDeriv
@property
def MfRhoI(self):
@@ -181,6 +200,32 @@ class BaseEMProblem(Problem.BaseProblem):
# TODO: This should take a vector
def MfRhoIDeriv(self,u):
"""
Derivative of :code:`MfRhoI` with respect to the model.
Derivative of :code:`MfRhoI` with respect to the model.
"""
return self.mesh.getFaceInnerProductDeriv(self.curModel.rho, invMat=True)(u) * self.curModel.rhoDeriv
dMfRhoI_dI = -self.MfRhoI**2
dMf_drho = self.mesh.getFaceInnerProductDeriv(self.curModel.rho)(u)
return dMfRhoI_dI * ( dMf_drho * self.curModel.rhoDeriv )
class BaseEMSurvey(Survey.BaseSurvey):
def __init__(self, srcList, **kwargs):
# Sort these by frequency
self.srcList = srcList
Survey.BaseSurvey.__init__(self, **kwargs)
def eval(self, f):
"""
Project fields to receiver locations
:param Fields u: fields object
:rtype: numpy.ndarray
:return: data
"""
data = Survey.Data(self)
for src in self.srcList:
for rx in src.rxList:
data[src, rx] = rx.eval(src, self.mesh, f)
return data
def evalDeriv(self, f):
raise Exception('Use Receivers to project fields deriv.')
-570
View File
@@ -1,570 +0,0 @@
from SimPEG import Problem, Utils, np, sp, Solver as SimpegSolver
from scipy.constants import mu_0
from SurveyFDEM import Survey as SurveyFDEM
from FieldsFDEM import Fields, Fields_e, Fields_b, Fields_h, Fields_j
from SimPEG.EM.Base import BaseEMProblem
from SimPEG.EM.Utils import omega
class BaseFDEMProblem(BaseEMProblem):
"""
We start by looking at Maxwell's equations in the electric
field \\\(\\\mathbf{e}\\\) and the magnetic flux
density \\\(\\\mathbf{b}\\\)
.. math ::
\mathbf{C} \mathbf{e} + i \omega \mathbf{b} = \mathbf{s_m} \\\\
{\mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{M_{\sigma}^e} \mathbf{e} = \mathbf{M^e} \mathbf{s_e}}
if using the E-B formulation (:code:`Problem_e`
or :code:`Problem_b`) or the magnetic field
\\\(\\\mathbf{h}\\\) and current density \\\(\\\mathbf{j}\\\)
.. math ::
\mathbf{C}^T \mathbf{M_{\\rho}^f} \mathbf{j} + i \omega \mathbf{M_{\mu}^e} \mathbf{h} = \mathbf{M^e} \mathbf{s_m} \\\\
\mathbf{C} \mathbf{h} - \mathbf{j} = \mathbf{s_e}
if using the H-J formulation (:code:`Problem_j` or :code:`Problem_h`).
The problem performs the elimination so that we are solving the system for \\\(\\\mathbf{e},\\\mathbf{b},\\\mathbf{j} \\\) or \\\(\\\mathbf{h}\\\)
"""
surveyPair = SurveyFDEM
fieldsPair = Fields
def fields(self, m=None):
"""
Solve the forward problem for the fields.
"""
self.curModel = m
F = self.fieldsPair(self.mesh, self.survey)
for freq in self.survey.freqs:
A = self.getA(freq)
rhs = self.getRHS(freq)
Ainv = self.Solver(A, **self.solverOpts)
sol = Ainv * rhs
Srcs = self.survey.getSrcByFreq(freq)
ftype = self._fieldType + 'Solution'
F[Srcs, ftype] = sol
return F
def Jvec(self, m, v, f=None):
"""
Sensitivity times a vector
"""
if f is None:
f = self.fields(m)
self.curModel = m
Jv = self.dataPair(self.survey)
for freq in self.survey.freqs:
A = self.getA(freq) #
Ainv = self.Solver(A, **self.solverOpts)
for src in self.survey.getSrcByFreq(freq):
ftype = self._fieldType + 'Solution'
u_src = f[src, ftype]
dA_dm = self.getADeriv_m(freq, u_src, v)
dRHS_dm = self.getRHSDeriv_m(freq, src, v)
du_dm = Ainv * ( - dA_dm + dRHS_dm )
for rx in src.rxList:
df_duFun = getattr(f, '_%sDeriv_u'%rx.projField, None)
df_dudu_dm = df_duFun(src, du_dm, adjoint=False)
df_dmFun = getattr(f, '_%sDeriv_m'%rx.projField, None)
df_dm = df_dmFun(src, v, adjoint=False)
Df_Dm = np.array(df_dudu_dm + df_dm,dtype=complex)
P = lambda v: rx.projectFieldsDeriv(src, self.mesh, f, v) # wrt u, also have wrt m
Jv[src, rx] = P(Df_Dm)
return Utils.mkvc(Jv)
def Jtvec(self, m, v, f=None):
"""
Sensitivity transpose times a vector
"""
if f is None:
f = self.fields(m)
self.curModel = m
# Ensure v is a data object.
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
Jtv = np.zeros(m.size)
for freq in self.survey.freqs:
AT = self.getA(freq).T
ATinv = self.Solver(AT, **self.solverOpts)
for src in self.survey.getSrcByFreq(freq):
ftype = self._fieldType + 'Solution'
u_src = f[src, ftype]
for rx in src.rxList:
PTv = rx.projectFieldsDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt u, need possibility wrt m
df_duTFun = getattr(f, '_%sDeriv_u'%rx.projField, None)
df_duT = df_duTFun(src, PTv, adjoint=True)
ATinvdf_duT = ATinv * df_duT
dA_dmT = self.getADeriv_m(freq, u_src, ATinvdf_duT, adjoint=True)
dRHS_dmT = self.getRHSDeriv_m(freq,src, ATinvdf_duT, adjoint=True)
du_dmT = -dA_dmT + dRHS_dmT
df_dmFun = getattr(f, '_%sDeriv_m'%rx.projField, None)
dfT_dm = df_dmFun(src, PTv, adjoint=True)
du_dmT += dfT_dm
real_or_imag = rx.projComp
if real_or_imag is 'real':
Jtv += np.array(du_dmT,dtype=complex).real
elif real_or_imag is 'imag':
Jtv += - np.array(du_dmT,dtype=complex).real
else:
raise Exception('Must be real or imag')
return Jtv
def getSourceTerm(self, freq):
"""
Evaluates the sources for a given frequency and puts them in matrix form
:param float freq: Frequency
:rtype: numpy.ndarray (nE or nF, nSrc)
:return: S_m, S_e
"""
Srcs = self.survey.getSrcByFreq(freq)
if self._eqLocs is 'FE':
S_m = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex)
S_e = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex)
elif self._eqLocs is 'EF':
S_m = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex)
S_e = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex)
for i, src in enumerate(Srcs):
smi, sei = src.eval(self)
S_m[:,i] = S_m[:,i] + smi
S_e[:,i] = S_e[:,i] + sei
return S_m, S_e
##########################################################################################
################################ E-B Formulation #########################################
##########################################################################################
class Problem_e(BaseFDEMProblem):
"""
By eliminating the magnetic flux density using
.. math ::
\mathbf{b} = \\frac{1}{i \omega}\\left(-\mathbf{C} \mathbf{e} + \mathbf{s_m}\\right)
we can write Maxwell's equations as a second order system in \\\(\\\mathbf{e}\\\) only:
.. math ::
\\left(\mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} \mathbf{C}+ i \omega \mathbf{M^e_{\sigma}} \\right)\mathbf{e} = \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f}\mathbf{s_m} -i\omega\mathbf{M^e}\mathbf{s_e}
which we solve for \\\(\\\mathbf{e}\\\).
"""
_fieldType = 'e'
_eqLocs = 'FE'
fieldsPair = Fields_e
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
.. math ::
\mathbf{A} = \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} \mathbf{C} + i \omega \mathbf{M^e_{\sigma}}
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MfMui = self.MfMui
MeSigma = self.MeSigma
C = self.mesh.edgeCurl
return C.T*MfMui*C + 1j*omega(freq)*MeSigma
def getADeriv_m(self, freq, u, v, adjoint=False):
dsig_dm = self.curModel.sigmaDeriv
dMe_dsig = self.MeSigmaDeriv(u)
if adjoint:
return 1j * omega(freq) * ( dMe_dsig.T * v )
return 1j * omega(freq) * ( dMe_dsig * v )
def getRHS(self, freq):
"""
.. math ::
\mathbf{RHS} = \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f}\mathbf{s_m} -i\omega\mathbf{M_e}\mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray (nE, nSrc)
:return: RHS
"""
S_m, S_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MfMui = self.MfMui
RHS = C.T * (MfMui * S_m) -1j * omega(freq) * S_e
return RHS
def getRHSDeriv_m(self, freq, src, v, adjoint=False):
C = self.mesh.edgeCurl
MfMui = self.MfMui
S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint)
if adjoint:
dRHS = MfMui * (C * v)
return S_mDeriv(dRHS) - 1j * omega(freq) * S_eDeriv(v)
else:
return C.T * (MfMui * S_mDeriv(v)) -1j * omega(freq) * S_eDeriv(v)
class Problem_b(BaseFDEMProblem):
"""
We eliminate \\\(\\\mathbf{e}\\\) using
.. math ::
\mathbf{e} = \mathbf{M^e_{\sigma}}^{-1} \\left(\mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{s_e}\\right)
and solve for \\\(\\\mathbf{b}\\\) using:
.. math ::
\\left(\mathbf{C} \mathbf{M^e_{\sigma}}^{-1} \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} + i \omega \\right)\mathbf{b} = \mathbf{s_m} + \mathbf{M^e_{\sigma}}^{-1}\mathbf{M^e}\mathbf{s_e}
.. note ::
The inverse problem will not work with full anisotropy
"""
_fieldType = 'b'
_eqLocs = 'FE'
fieldsPair = Fields_b
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
.. math ::
\mathbf{A} = \mathbf{C} \mathbf{M^e_{\sigma}}^{-1} \mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} + i \omega
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MfMui = self.MfMui
MeSigmaI = self.MeSigmaI
C = self.mesh.edgeCurl
iomega = 1j * omega(freq) * sp.eye(self.mesh.nF)
A = C * (MeSigmaI * (C.T * MfMui)) + iomega
if self._makeASymmetric is True:
return MfMui.T*A
return A
def getADeriv_m(self, freq, u, v, adjoint=False):
MfMui = self.MfMui
C = self.mesh.edgeCurl
MeSigmaIDeriv = self.MeSigmaIDeriv
vec = C.T * (MfMui * u)
MeSigmaIDeriv = MeSigmaIDeriv(vec)
if adjoint:
if self._makeASymmetric is True:
v = MfMui * v
return MeSigmaIDeriv.T * (C.T * v)
if self._makeASymmetric is True:
return MfMui.T * ( C * ( MeSigmaIDeriv * v ) )
return C * ( MeSigmaIDeriv * v )
def getRHS(self, freq):
"""
.. math ::
\mathbf{RHS} = \mathbf{s_m} + \mathbf{M^e_{\sigma}}^{-1}\mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray (nE, nSrc)
:return: RHS
"""
S_m, S_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MeSigmaI = self.MeSigmaI
RHS = S_m + C * ( MeSigmaI * S_e )
if self._makeASymmetric is True:
MfMui = self.MfMui
return MfMui.T * RHS
return RHS
def getRHSDeriv_m(self, freq, src, v, adjoint=False):
C = self.mesh.edgeCurl
S_m, S_e = src.eval(self)
MfMui = self.MfMui
if self._makeASymmetric and adjoint:
v = self.MfMui * v
MeSigmaIDeriv = self.MeSigmaIDeriv(S_e)
S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint)
if not adjoint:
RHSderiv = C * (MeSigmaIDeriv * v)
SrcDeriv = S_mDeriv(v) + C * (self.MeSigmaI * S_eDeriv(v))
elif adjoint:
RHSderiv = MeSigmaIDeriv.T * (C.T * v)
SrcDeriv = S_mDeriv(v) + self.MeSigmaI.T * (C.T * S_eDeriv(v))
if self._makeASymmetric is True and not adjoint:
return MfMui.T * (SrcDeriv + RHSderiv)
return RHSderiv + SrcDeriv
##########################################################################################
################################ H-J Formulation #########################################
##########################################################################################
class Problem_j(BaseFDEMProblem):
"""
We eliminate \\\(\\\mathbf{h}\\\) using
.. math ::
\mathbf{h} = \\frac{1}{i \omega} \mathbf{M_{\mu}^e}^{-1} \\left(-\mathbf{C}^T \mathbf{M_{\\rho}^f} \mathbf{j} + \mathbf{M^e} \mathbf{s_m} \\right)
and solve for \\\(\\\mathbf{j}\\\) using
.. math ::
\\left(\mathbf{C} \mathbf{M_{\mu}^e}^{-1} \mathbf{C}^T \mathbf{M_{\\rho}^f} + i \omega\\right)\mathbf{j} = \mathbf{C} \mathbf{M_{\mu}^e}^{-1} \mathbf{M^e} \mathbf{s_m} -i\omega\mathbf{s_e}
.. note::
This implementation does not yet work with full anisotropy!!
"""
_fieldType = 'j'
_eqLocs = 'EF'
fieldsPair = Fields_j
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
.. math ::
\\mathbf{A} = \\mathbf{C} \\mathbf{M^e_{mu^{-1}}} \\mathbf{C}^T \\mathbf{M^f_{\\sigma^{-1}}} + i\\omega
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MeMuI = self.MeMuI
MfRho = self.MfRho
C = self.mesh.edgeCurl
iomega = 1j * omega(freq) * sp.eye(self.mesh.nF)
A = C * MeMuI * C.T * MfRho + iomega
if self._makeASymmetric is True:
return MfRho.T*A
return A
def getADeriv_m(self, freq, u, v, adjoint=False):
"""
In this case, we assume that electrical conductivity, \\\(\\\sigma\\\) is the physical property of interest (i.e. \\\(\\\sigma\\\) = model.transform). Then we want
.. math ::
\\frac{\mathbf{A(\sigma)} \mathbf{v}}{d \\mathbf{m}} &= \\mathbf{C} \\mathbf{M^e_{mu^{-1}}} \\mathbf{C^T} \\frac{d \\mathbf{M^f_{\\sigma^{-1}}}}{d \\mathbf{m}}
&= \\mathbf{C} \\mathbf{M^e_{mu}^{-1}} \\mathbf{C^T} \\frac{d \\mathbf{M^f_{\\sigma^{-1}}}}{d \\mathbf{\\sigma^{-1}}} \\frac{d \\mathbf{\\sigma^{-1}}}{d \\mathbf{\\sigma}} \\frac{d \\mathbf{\\sigma}}{d \\mathbf{m}}
"""
MeMuI = self.MeMuI
MfRho = self.MfRho
C = self.mesh.edgeCurl
MfRhoDeriv_m = self.MfRhoDeriv(u)
if adjoint:
if self._makeASymmetric is True:
v = MfRho * v
return MfRhoDeriv_m.T * (C * (MeMuI.T * (C.T * v)))
if self._makeASymmetric is True:
return MfRho.T * (C * ( MeMuI * (C.T * (MfRhoDeriv_m * v) )))
return C * (MeMuI * (C.T * (MfRhoDeriv_m * v)))
def getRHS(self, freq):
"""
.. math ::
\mathbf{RHS} = \mathbf{C} \mathbf{M_{\mu}^e}^{-1}\mathbf{s_m} -i\omega \mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray (nE, nSrc)
:return: RHS
"""
S_m, S_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MeMuI = self.MeMuI
RHS = C * (MeMuI * S_m) - 1j * omega(freq) * S_e
if self._makeASymmetric is True:
MfRho = self.MfRho
return MfRho.T*RHS
return RHS
def getRHSDeriv_m(self, freq, src, v, adjoint=False):
C = self.mesh.edgeCurl
MeMuI = self.MeMuI
S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint)
if adjoint:
if self._makeASymmetric:
MfRho = self.MfRho
v = MfRho*v
return S_mDeriv(MeMuI.T * (C.T * v)) - 1j * omega(freq) * S_eDeriv(v)
else:
RHSDeriv = C * (MeMuI * S_mDeriv(v)) - 1j * omega(freq) * S_eDeriv(v)
if self._makeASymmetric:
MfRho = self.MfRho
return MfRho.T * RHSDeriv
return RHSDeriv
class Problem_h(BaseFDEMProblem):
"""
We eliminate \\\(\\\mathbf{j}\\\) using
.. math ::
\mathbf{j} = \mathbf{C} \mathbf{h} - \mathbf{s_e}
and solve for \\\(\\\mathbf{h}\\\) using
.. math ::
\\left(\mathbf{C}^T \mathbf{M_{\\rho}^f} \mathbf{C} + i \omega \mathbf{M_{\mu}^e}\\right) \mathbf{h} = \mathbf{M^e} \mathbf{s_m} + \mathbf{C}^T \mathbf{M_{\\rho}^f} \mathbf{s_e}
"""
_fieldType = 'h'
_eqLocs = 'EF'
fieldsPair = Fields_h
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
.. math ::
\mathbf{A} = \mathbf{C}^T \mathbf{M_{\\rho}^f} \mathbf{C} + i \omega \mathbf{M_{\mu}^e}
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MeMu = self.MeMu
MfRho = self.MfRho
C = self.mesh.edgeCurl
return C.T * (MfRho * C) + 1j*omega(freq)*MeMu
def getADeriv_m(self, freq, u, v, adjoint=False):
MeMu = self.MeMu
C = self.mesh.edgeCurl
MfRhoDeriv_m = self.MfRhoDeriv(C*u)
if adjoint:
return MfRhoDeriv_m.T * (C * v)
return C.T * (MfRhoDeriv_m * v)
def getRHS(self, freq):
"""
.. math ::
\mathbf{RHS} = \mathbf{M^e} \mathbf{s_m} + \mathbf{C}^T \mathbf{M_{\\rho}^f} \mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray (nE, nSrc)
:return: RHS
"""
S_m, S_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MfRho = self.MfRho
RHS = S_m + C.T * ( MfRho * S_e )
return RHS
def getRHSDeriv_m(self, freq, src, v, adjoint=False):
_, S_e = src.eval(self)
C = self.mesh.edgeCurl
MfRho = self.MfRho
MfRhoDeriv = self.MfRhoDeriv(S_e)
if not adjoint:
RHSDeriv = C.T * (MfRhoDeriv * v)
elif adjoint:
RHSDeriv = MfRhoDeriv.T * (C * v)
S_mDeriv, S_eDeriv = src.evalDeriv(self, adjoint)
return RHSDeriv + S_mDeriv(v) + C.T * (MfRho * S_eDeriv(v))
+1017 -129
View File
File diff suppressed because it is too large Load Diff
+689
View File
@@ -0,0 +1,689 @@
from SimPEG import Problem, Utils, np, sp, Solver as SimpegSolver
from scipy.constants import mu_0
from SurveyFDEM import Survey as SurveyFDEM
from FieldsFDEM import Fields, Fields3D_e, Fields3D_b, Fields3D_h, Fields3D_j
from SimPEG.EM.Base import BaseEMProblem
from SimPEG.EM.Utils import omega
class BaseFDEMProblem(BaseEMProblem):
"""
We start by looking at Maxwell's equations in the electric
field \\\(\\\mathbf{e}\\\) and the magnetic flux
density \\\(\\\mathbf{b}\\\)
.. math ::
\mathbf{C} \mathbf{e} + i \omega \mathbf{b} = \mathbf{s_m} \\\\
{\mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{M_{\sigma}^e} \mathbf{e} = \mathbf{s_e}}
if using the E-B formulation (:code:`Problem3D_e`
or :code:`Problem3D_b`). Note that in this case, :math:`\mathbf{s_e}` is an integrated quantity.
If we write Maxwell's equations in terms of
\\\(\\\mathbf{h}\\\) and current density \\\(\\\mathbf{j}\\\)
.. math ::
\mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{j} + i \omega \mathbf{M_{\mu}^e} \mathbf{h} = \mathbf{s_m} \\\\
\mathbf{C} \mathbf{h} - \mathbf{j} = \mathbf{s_e}
if using the H-J formulation (:code:`Problem3D_j` or :code:`Problem3D_h`). Note that here, :math:`\mathbf{s_m}` is an integrated quantity.
The problem performs the elimination so that we are solving the system for \\\(\\\mathbf{e},\\\mathbf{b},\\\mathbf{j} \\\) or \\\(\\\mathbf{h}\\\)
"""
surveyPair = SurveyFDEM
fieldsPair = Fields
def fields(self, m):
"""
Solve the forward problem for the fields.
:param numpy.array m: inversion model (nP,)
:rtype numpy.array:
:return f: forward solution
"""
self.curModel = m
f = self.fieldsPair(self.mesh, self.survey)
for freq in self.survey.freqs:
A = self.getA(freq)
rhs = self.getRHS(freq)
Ainv = self.Solver(A, **self.solverOpts)
u = Ainv * rhs
Srcs = self.survey.getSrcByFreq(freq)
f[Srcs, self._solutionType] = u
Ainv.clean()
return f
def Jvec(self, m, v, f=None):
"""
Sensitivity times a vector.
:param numpy.array m: inversion model (nP,)
:param numpy.array v: vector which we take sensitivity product with (nP,)
:param SimPEG.EM.FDEM.Fields u: fields object
:rtype numpy.array:
:return: Jv (ndata,)
"""
if f is None:
f = self.fields(m)
self.curModel = m
# Jv = self.dataPair(self.survey)
Jv = []
for freq in self.survey.freqs:
A = self.getA(freq)
Ainv = self.Solver(A, **self.solverOpts) # create the concept of Ainv (actually a solve)
for src in self.survey.getSrcByFreq(freq):
u_src = f[src, self._solutionType]
dA_dm_v = self.getADeriv(freq, u_src, v)
dRHS_dm_v = self.getRHSDeriv(freq, src, v)
du_dm_v = Ainv * ( - dA_dm_v + dRHS_dm_v )
for rx in src.rxList:
df_dmFun = getattr(f, '_{0}Deriv'.format(rx.projField), None)
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
Jv.append(rx.evalDeriv(src, self.mesh, f, df_dm_v))
Ainv.clean()
return np.hstack(Jv)
def Jtvec(self, m, v, f=None):
"""
Sensitivity transpose times a vector
:param numpy.array m: inversion model (nP,)
:param numpy.array v: vector which we take adjoint product with (nP,)
:param SimPEG.EM.FDEM.Fields u: fields object
:rtype numpy.array:
:return: Jv (ndata,)
"""
if f is None:
f = self.fields(m)
self.curModel = m
# Ensure v is a data object.
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
Jtv = np.zeros(m.size)
for freq in self.survey.freqs:
AT = self.getA(freq).T
ATinv = self.Solver(AT, **self.solverOpts)
for src in self.survey.getSrcByFreq(freq):
u_src = f[src, self._solutionType]
for rx in src.rxList:
PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m
df_duTFun = getattr(f, '_{0}Deriv'.format(rx.projField), None)
df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True)
ATinvdf_duT = ATinv * df_duT
dA_dmT = self.getADeriv(freq, u_src, ATinvdf_duT, adjoint=True)
dRHS_dmT = self.getRHSDeriv(freq, src, ATinvdf_duT, adjoint=True)
du_dmT = -dA_dmT + dRHS_dmT
df_dmT = df_dmT + du_dmT
# TODO: this should be taken care of by the reciever?
if rx.component is 'real':
Jtv += np.array(df_dmT, dtype=complex).real
elif rx.component is 'imag':
Jtv += - np.array(df_dmT, dtype=complex).real
else:
raise Exception('Must be real or imag')
ATinv.clean()
return Utils.mkvc(Jtv)
def getSourceTerm(self, freq):
"""
Evaluates the sources for a given frequency and puts them in matrix form
:param float freq: Frequency
:rtype: (numpy.ndarray, numpy.ndarray)
:return: s_m, s_e (nE or nF, nSrc)
"""
Srcs = self.survey.getSrcByFreq(freq)
if self._formulation is 'EB':
s_m = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex)
s_e = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex)
elif self._formulation is 'HJ':
s_m = np.zeros((self.mesh.nE,len(Srcs)), dtype=complex)
s_e = np.zeros((self.mesh.nF,len(Srcs)), dtype=complex)
for i, src in enumerate(Srcs):
smi, sei = src.eval(self)
s_m[:,i] = s_m[:,i] + smi
s_e[:,i] = s_e[:,i] + sei
return s_m, s_e
##########################################################################################
################################ E-B Formulation #########################################
##########################################################################################
class Problem3D_e(BaseFDEMProblem):
"""
By eliminating the magnetic flux density using
.. math ::
\mathbf{b} = \\frac{1}{i \omega}\\left(-\mathbf{C} \mathbf{e} + \mathbf{s_m}\\right)
we can write Maxwell's equations as a second order system in \\\(\\\mathbf{e}\\\) only:
.. math ::
\\left(\mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{C}+ i \omega \mathbf{M^e_{\sigma}} \\right)\mathbf{e} = \mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f}\mathbf{s_m} -i\omega\mathbf{M^e}\mathbf{s_e}
which we solve for :math:`\mathbf{e}`.
:param SimPEG.Mesh mesh: mesh
"""
_solutionType = 'eSolution'
_formulation = 'EB'
fieldsPair = Fields3D_e
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
System matrix
.. math ::
\mathbf{A} = \mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{C} + i \omega \mathbf{M^e_{\sigma}}
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MfMui = self.MfMui
MeSigma = self.MeSigma
C = self.mesh.edgeCurl
return C.T*MfMui*C + 1j*omega(freq)*MeSigma
def getADeriv(self, freq, u, v, adjoint=False):
"""
Product of the derivative of our system matrix with respect to the model and a vector
.. math ::
\\frac{\mathbf{A}(\mathbf{m}) \mathbf{v}}{d \mathbf{m}} = i \omega \\frac{d \mathbf{M^e_{\sigma}}\mathbf{v} }{d\mathbf{m}}
:param float freq: frequency
:param numpy.ndarray u: solution vector (nE,)
:param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: derivative of the system matrix times a vector (nP,) or adjoint (nD,)
"""
dsig_dm = self.curModel.sigmaDeriv
dMe_dsig = self.MeSigmaDeriv(u)
if adjoint:
return 1j * omega(freq) * ( dMe_dsig.T * v )
return 1j * omega(freq) * ( dMe_dsig * v )
def getRHS(self, freq):
"""
Right hand side for the system
.. math ::
\mathbf{RHS} = \mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f}\mathbf{s_m} -i\omega\mathbf{M_e}\mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray
:return: RHS (nE, nSrc)
"""
s_m, s_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MfMui = self.MfMui
return C.T * (MfMui * s_m) -1j * omega(freq) * s_e
def getRHSDeriv(self, freq, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
:param float freq: frequency
:param SimPEG.EM.FDEM.Src src: FDEM source
:param numpy.ndarray v: vector to take product with
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: product of rhs deriv with a vector
"""
C = self.mesh.edgeCurl
MfMui = self.MfMui
s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint)
if adjoint:
dRHS = MfMui * (C * v)
return s_mDeriv(dRHS) - 1j * omega(freq) * s_eDeriv(v)
else:
return C.T * (MfMui * s_mDeriv(v)) -1j * omega(freq) * s_eDeriv(v)
class Problem3D_b(BaseFDEMProblem):
"""
We eliminate :math:`\mathbf{e}` using
.. math ::
\mathbf{e} = \mathbf{M^e_{\sigma}}^{-1} \\left(\mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{s_e}\\right)
and solve for :math:`\mathbf{b}` using:
.. math ::
\\left(\mathbf{C} \mathbf{M^e_{\sigma}}^{-1} \mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} + i \omega \\right)\mathbf{b} = \mathbf{s_m} + \mathbf{M^e_{\sigma}}^{-1}\mathbf{M^e}\mathbf{s_e}
.. note ::
The inverse problem will not work with full anisotropy
:param SimPEG.Mesh mesh: mesh
"""
_solutionType = 'bSolution'
_formulation = 'EB'
fieldsPair = Fields3D_b
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
System matrix
.. math ::
\mathbf{A} = \mathbf{C} \mathbf{M^e_{\sigma}}^{-1} \mathbf{C}^{\\top} \mathbf{M_{\mu^{-1}}^f} + i \omega
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MfMui = self.MfMui
MeSigmaI = self.MeSigmaI
C = self.mesh.edgeCurl
iomega = 1j * omega(freq) * sp.eye(self.mesh.nF)
A = C * (MeSigmaI * (C.T * MfMui)) + iomega
if self._makeASymmetric is True:
return MfMui.T*A
return A
def getADeriv(self, freq, u, v, adjoint=False):
"""
Product of the derivative of our system matrix with respect to the model and a vector
.. math ::
\\frac{\mathbf{A}(\mathbf{m}) \mathbf{v}}{d \mathbf{m}} = \mathbf{C} \\frac{\mathbf{M^e_{\sigma}} \mathbf{v}}{d\mathbf{m}}
:param float freq: frequency
:param numpy.ndarray u: solution vector (nF,)
:param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: derivative of the system matrix times a vector (nP,) or adjoint (nD,)
"""
MfMui = self.MfMui
C = self.mesh.edgeCurl
MeSigmaIDeriv = self.MeSigmaIDeriv
vec = C.T * (MfMui * u)
MeSigmaIDeriv = MeSigmaIDeriv(vec)
if adjoint:
if self._makeASymmetric is True:
v = MfMui * v
return MeSigmaIDeriv.T * (C.T * v)
if self._makeASymmetric is True:
return MfMui.T * ( C * ( MeSigmaIDeriv * v ) )
return C * ( MeSigmaIDeriv * v )
def getRHS(self, freq):
"""
Right hand side for the system
.. math ::
\mathbf{RHS} = \mathbf{s_m} + \mathbf{M^e_{\sigma}}^{-1}\mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray
:return: RHS (nE, nSrc)
"""
s_m, s_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MeSigmaI = self.MeSigmaI
RHS = s_m + C * ( MeSigmaI * s_e )
if self._makeASymmetric is True:
MfMui = self.MfMui
return MfMui.T * RHS
return RHS
def getRHSDeriv(self, freq, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
:param float freq: frequency
:param SimPEG.EM.FDEM.Src src: FDEM source
:param numpy.ndarray v: vector to take product with
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: product of rhs deriv with a vector
"""
C = self.mesh.edgeCurl
s_m, s_e = src.eval(self)
MfMui = self.MfMui
if self._makeASymmetric and adjoint:
v = self.MfMui * v
MeSigmaIDeriv = self.MeSigmaIDeriv(s_e)
s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint)
if not adjoint:
RHSderiv = C * (MeSigmaIDeriv * v)
SrcDeriv = s_mDeriv(v) + C * (self.MeSigmaI * s_eDeriv(v))
elif adjoint:
RHSderiv = MeSigmaIDeriv.T * (C.T * v)
SrcDeriv = s_mDeriv(v) + self.MeSigmaI.T * (C.T * s_eDeriv(v))
if self._makeASymmetric is True and not adjoint:
return MfMui.T * (SrcDeriv + RHSderiv)
return RHSderiv + SrcDeriv
##########################################################################################
################################ H-J Formulation #########################################
##########################################################################################
class Problem3D_j(BaseFDEMProblem):
"""
We eliminate \\\(\\\mathbf{h}\\\) using
.. math ::
\mathbf{h} = \\frac{1}{i \omega} \mathbf{M_{\mu}^e}^{-1} \\left(-\mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{j} + \mathbf{M^e} \mathbf{s_m} \\right)
and solve for \\\(\\\mathbf{j}\\\) using
.. math ::
\\left(\mathbf{C} \mathbf{M_{\mu}^e}^{-1} \mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} + i \omega\\right)\mathbf{j} = \mathbf{C} \mathbf{M_{\mu}^e}^{-1} \mathbf{M^e} \mathbf{s_m} -i\omega\mathbf{s_e}
.. note::
This implementation does not yet work with full anisotropy!!
:param SimPEG.Mesh mesh: mesh
"""
_solutionType = 'jSolution'
_formulation = 'HJ'
fieldsPair = Fields3D_j
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
System matrix
.. math ::
\\mathbf{A} = \\mathbf{C} \\mathbf{M^e_{\\mu^{-1}}} \\mathbf{C}^{\\top} \\mathbf{M^f_{\\sigma^{-1}}} + i\\omega
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MeMuI = self.MeMuI
MfRho = self.MfRho
C = self.mesh.edgeCurl
iomega = 1j * omega(freq) * sp.eye(self.mesh.nF)
A = C * MeMuI * C.T * MfRho + iomega
if self._makeASymmetric is True:
return MfRho.T*A
return A
def getADeriv(self, freq, u, v, adjoint=False):
"""
Product of the derivative of our system matrix with respect to the model and a vector
In this case, we assume that electrical conductivity, :math:`\sigma` is the physical property of interest (i.e. :math:`\sigma` = model.transform). Then we want
.. math ::
\\frac{\mathbf{A(\sigma)} \mathbf{v}}{d \mathbf{m}} = \mathbf{C} \mathbf{M^e_{mu^{-1}}} \mathbf{C^{\\top}} \\frac{d \mathbf{M^f_{\sigma^{-1}}}\mathbf{v} }{d \mathbf{m}}
:param float freq: frequency
:param numpy.ndarray u: solution vector (nF,)
:param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: derivative of the system matrix times a vector (nP,) or adjoint (nD,)
"""
MeMuI = self.MeMuI
MfRho = self.MfRho
C = self.mesh.edgeCurl
MfRhoDeriv = self.MfRhoDeriv(u)
if adjoint:
if self._makeASymmetric is True:
v = MfRho * v
return MfRhoDeriv.T * (C * (MeMuI.T * (C.T * v)))
if self._makeASymmetric is True:
return MfRho.T * (C * ( MeMuI * (C.T * (MfRhoDeriv * v) )))
return C * (MeMuI * (C.T * (MfRhoDeriv * v)))
def getRHS(self, freq):
"""
Right hand side for the system
.. math ::
\mathbf{RHS} = \mathbf{C} \mathbf{M_{\mu}^e}^{-1}\mathbf{s_m} -i\omega \mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray (nE, nSrc)
:return: RHS
"""
s_m, s_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MeMuI = self.MeMuI
RHS = C * (MeMuI * s_m) - 1j * omega(freq) * s_e
if self._makeASymmetric is True:
MfRho = self.MfRho
return MfRho.T*RHS
return RHS
def getRHSDeriv(self, freq, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
:param float freq: frequency
:param SimPEG.EM.FDEM.Src src: FDEM source
:param numpy.ndarray v: vector to take product with
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: product of rhs deriv with a vector
"""
C = self.mesh.edgeCurl
MeMuI = self.MeMuI
s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint)
if adjoint:
if self._makeASymmetric:
MfRho = self.MfRho
v = MfRho*v
return s_mDeriv(MeMuI.T * (C.T * v)) - 1j * omega(freq) * s_eDeriv(v)
else:
RHSDeriv = C * (MeMuI * s_mDeriv(v)) - 1j * omega(freq) * s_eDeriv(v)
if self._makeASymmetric:
MfRho = self.MfRho
return MfRho.T * RHSDeriv
return RHSDeriv
class Problem3D_h(BaseFDEMProblem):
"""
We eliminate \\\(\\\mathbf{j}\\\) using
.. math ::
\mathbf{j} = \mathbf{C} \mathbf{h} - \mathbf{s_e}
and solve for \\\(\\\mathbf{h}\\\) using
.. math ::
\\left(\mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{C} + i \omega \mathbf{M_{\mu}^e}\\right) \mathbf{h} = \mathbf{M^e} \mathbf{s_m} + \mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{s_e}
:param SimPEG.Mesh mesh: mesh
"""
_solutionType = 'hSolution'
_formulation = 'HJ'
fieldsPair = Fields3D_h
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
def getA(self, freq):
"""
System matrix
.. math::
\mathbf{A} = \mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{C} + i \omega \mathbf{M_{\mu}^e}
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MeMu = self.MeMu
MfRho = self.MfRho
C = self.mesh.edgeCurl
return C.T * (MfRho * C) + 1j*omega(freq)*MeMu
def getADeriv(self, freq, u, v, adjoint=False):
"""
Product of the derivative of our system matrix with respect to the model and a vector
.. math::
\\frac{\mathbf{A}(\mathbf{m}) \mathbf{v}}{d \mathbf{m}} = \mathbf{C}^{\\top}\\frac{d \mathbf{M^f_{\\rho}}\mathbf{v} }{d\mathbf{m}}
:param float freq: frequency
:param numpy.ndarray u: solution vector (nE,)
:param numpy.ndarray v: vector to take prodct with (nP,) or (nD,) for adjoint
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: derivative of the system matrix times a vector (nP,) or adjoint (nD,)
"""
MeMu = self.MeMu
C = self.mesh.edgeCurl
MfRhoDeriv = self.MfRhoDeriv(C*u)
if adjoint:
return MfRhoDeriv.T * (C * v)
return C.T * (MfRhoDeriv * v)
def getRHS(self, freq):
"""
Right hand side for the system
.. math ::
\mathbf{RHS} = \mathbf{M^e} \mathbf{s_m} + \mathbf{C}^{\\top} \mathbf{M_{\\rho}^f} \mathbf{s_e}
:param float freq: Frequency
:rtype: numpy.ndarray
:return: RHS (nE, nSrc)
"""
s_m, s_e = self.getSourceTerm(freq)
C = self.mesh.edgeCurl
MfRho = self.MfRho
return s_m + C.T * ( MfRho * s_e )
def getRHSDeriv(self, freq, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
:param float freq: frequency
:param SimPEG.EM.FDEM.Src src: FDEM source
:param numpy.ndarray v: vector to take product with
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: product of rhs deriv with a vector
"""
_, s_e = src.eval(self)
C = self.mesh.edgeCurl
MfRho = self.MfRho
MfRhoDeriv = self.MfRhoDeriv(s_e)
if not adjoint:
RHSDeriv = C.T * (MfRhoDeriv * v)
elif adjoint:
RHSDeriv = MfRhoDeriv.T * (C * v)
s_mDeriv, s_eDeriv = src.evalDeriv(self, adjoint=adjoint)
return RHSDeriv + s_mDeriv(v) + C.T * (MfRho * s_eDeriv(v))
+126
View File
@@ -0,0 +1,126 @@
import SimPEG
from SimPEG import sp
class BaseRx(SimPEG.Survey.BaseRx):
"""
Frequency domain receiver base class
:param numpy.ndarray locs: receiver locations (ie. :code:`np.r_[x,y,z]`)
:param string orientation: receiver orientation 'x', 'y' or 'z'
:param string component: real or imaginary component 'real' or 'imag'
"""
def __init__(self, locs, orientation=None, component=None):
assert(orientation in ['x','y','z']), "Orientation %s not known. Orientation must be in 'x', 'y', 'z'. Arbitrary orientations have not yet been implemented."%orientation
assert(component in ['real', 'imag']), "'component' must be 'real' or 'imag', not %s"%component
self.projComp = orientation
self.component = component
SimPEG.Survey.BaseRx.__init__(self, locs, rxType=None) #TODO: remove rxType from baseRx
def projGLoc(self, u):
"""Grid Location projection (e.g. Ex Fy ...)"""
return u._GLoc(self.projField) + self.projComp
def eval(self, src, mesh, f):
"""
Project fields to recievers to get data.
:param Source src: FDEM source
:param Mesh mesh: mesh used
:param Fields f: fields object
:rtype: numpy.ndarray
:return: fields projected to recievers
"""
P = self.getP(mesh, self.projGLoc(f))
f_part_complex = f[src, self.projField]
f_part = getattr(f_part_complex, self.component) # get the real or imag component
return P*f_part
def evalDeriv(self, src, mesh, f, v, adjoint=False):
"""
Derivative of projected fields with respect to the inversion model times a vector.
:param Source src: FDEM source
:param Mesh mesh: mesh used
:param Fields f: fields object
:param numpy.ndarray v: vector to multiply
:rtype: numpy.ndarray
:return: fields projected to recievers
"""
P = self.getP(mesh, self.projGLoc(f))
if not adjoint:
Pv_complex = P * v
Pv = getattr(Pv_complex, self.component)
elif adjoint:
Pv_real = P.T * v
if self.component == 'imag':
Pv = 1j*Pv_real
elif self.component == 'real':
Pv = Pv_real.astype(complex)
else:
raise NotImplementedError('must be real or imag')
return Pv
class Point_e(BaseRx):
"""
Electric field FDEM receiver
:param numpy.ndarray locs: receiver locations (ie. :code:`np.r_[x,y,z]`)
:param string orientation: receiver orientation 'x', 'y' or 'z'
:param string component: real or imaginary component 'real' or 'imag'
"""
def __init__(self, locs, orientation=None, component=None):
self.projField = 'e'
super(Point_e, self).__init__(locs, orientation, component)
class Point_b(BaseRx):
"""
Magnetic flux FDEM receiver
:param numpy.ndarray locs: receiver locations (ie. :code:`np.r_[x,y,z]`)
:param string orientation: receiver orientation 'x', 'y' or 'z'
:param string component: real or imaginary component 'real' or 'imag'
"""
def __init__(self, locs, orientation=None, component=None):
self.projField = 'b'
super(Point_b, self).__init__(locs, orientation, component)
class Point_h(BaseRx):
"""
Magnetic field FDEM receiver
:param numpy.ndarray locs: receiver locations (ie. :code:`np.r_[x,y,z]`)
:param string orientation: receiver orientation 'x', 'y' or 'z'
:param string component: real or imaginary component 'real' or 'imag'
"""
def __init__(self, locs, orientation=None, component=None):
self.projField = 'h'
super(Point_h, self).__init__(locs, orientation, component)
class Point_j(BaseRx):
"""
Current density FDEM receiver
:param numpy.ndarray locs: receiver locations (ie. :code:`np.r_[x,y,z]`)
:param string orientation: receiver orientation 'x', 'y' or 'z'
:param string component: real or imaginary component 'real' or 'imag'
"""
def __init__(self, locs, orientation=None, component=None):
self.projField = 'j'
super(Point_j, self).__init__(locs, orientation, component)
+589 -89
View File
@@ -2,134 +2,366 @@ from SimPEG import Survey, Problem, Utils, np, sp
from scipy.constants import mu_0
from SimPEG.EM.Utils import *
from SimPEG.Utils import Zero
# from SurveyFDEM import Rx
class BaseSrc(Survey.BaseSrc):
"""
Base source class for FDEM Survey
"""
freq = None
# rxPair = Rx
integrate = True
integrate = False
_ePrimary = None
_bPrimary = None
_hPrimary = None
_jPrimary = None
def __init__(self, rxList, **kwargs):
Survey.BaseSrc.__init__(self, rxList, **kwargs)
def eval(self, prob):
S_m = self.S_m(prob)
S_e = self.S_e(prob)
return S_m, S_e
"""
- :math:`s_m` : magnetic source term
- :math:`s_e` : electric source term
def evalDeriv(self, prob, v, adjoint=False):
return lambda v: self.S_mDeriv(prob,v,adjoint), lambda v: self.S_eDeriv(prob,v,adjoint)
:param Problem prob: FDEM Problem
:rtype: (numpy.ndarray, numpy.ndarray)
:return: tuple with magnetic source term and electric source term
"""
s_m = self.s_m(prob)
s_e = self.s_e(prob)
return s_m, s_e
def evalDeriv(self, prob, v=None, adjoint=False):
"""
Derivatives of the source terms with respect to the inversion model
- :code:`s_mDeriv` : derivative of the magnetic source term
- :code:`s_eDeriv` : derivative of the electric source term
:param Problem prob: FDEM Problem
:param numpy.ndarray v: vector to take product with
:param bool adjoint: adjoint?
:rtype: (numpy.ndarray, numpy.ndarray)
:return: tuple with magnetic source term and electric source term derivatives times a vector
"""
if v is not None:
return self.s_mDeriv(prob, v, adjoint), self.s_eDeriv(prob, v, adjoint)
else:
return lambda v: self.s_mDeriv(prob, v, adjoint), lambda v: self.s_eDeriv(prob, v, adjoint)
def bPrimary(self, prob):
"""
Primary magnetic flux density
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: primary magnetic flux density
"""
if self._bPrimary is None:
return Zero()
return self._bPrimary
def bPrimaryDeriv(self, prob, v, adjoint=False):
"""
Derivative of the primary magnetic flux density
:param Problem prob: FDEM Problem
:param numpy.ndarray v: vector
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: primary magnetic flux density
"""
return Zero()
def hPrimary(self, prob):
"""
Primary magnetic field
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
if self._hPrimary is None:
return Zero()
return self._hPrimary
def hPrimaryDeriv(self, prob, v, adjoint=False):
"""
Derivative of the primary magnetic field
:param Problem prob: FDEM Problem
:param numpy.ndarray v: vector
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: primary magnetic flux density
"""
return Zero()
def ePrimary(self, prob):
"""
Primary electric field
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: primary electric field
"""
if self._ePrimary is None:
return Zero()
return self._ePrimary
def ePrimaryDeriv(self, prob, v, adjoint=False):
"""
Derivative of the primary electric field
:param Problem prob: FDEM Problem
:param numpy.ndarray v: vector
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: primary magnetic flux density
"""
return Zero()
def jPrimary(self, prob):
"""
Primary current density
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: primary current density
"""
if self._jPrimary is None:
return Zero()
return self._jPrimary
def jPrimaryDeriv(self, prob, v, adjoint=False):
"""
Derivative of the primary current density
:param Problem prob: FDEM Problem
:param numpy.ndarray v: vector
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: primary magnetic flux density
"""
return Zero()
def S_m(self, prob):
def s_m(self, prob):
"""
Magnetic source term
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: magnetic source term on mesh
"""
return Zero()
def S_e(self, prob):
def s_e(self, prob):
"""
Electric source term
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: electric source term on mesh
"""
return Zero()
def S_mDeriv(self, prob, v, adjoint = False):
def s_mDeriv(self, prob, v, adjoint = False):
"""
Derivative of magnetic source term with respect to the inversion model
:param Problem prob: FDEM Problem
:param numpy.ndarray v: vector to take product with
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: product of magnetic source term derivative with a vector
"""
return Zero()
def S_eDeriv(self, prob, v, adjoint = False):
def s_eDeriv(self, prob, v, adjoint = False):
"""
Derivative of electric source term with respect to the inversion model
:param Problem prob: FDEM Problem
:param numpy.ndarray v: vector to take product with
:param bool adjoint: adjoint?
:rtype: numpy.ndarray
:return: product of electric source term derivative with a vector
"""
return Zero()
class RawVec_e(BaseSrc):
"""
RawVec electric source. It is defined by the user provided vector S_e
RawVec electric source. It is defined by the user provided vector s_e
:param numpy.array S_e: electric source term
:param float freq: frequency
:param rxList: receiver list
:param list rxList: receiver list
:param float freq: frequency
:param numpy.array s_e: electric source term
:param bool integrate: Integrate the source term (multiply by Me) [False]
"""
def __init__(self, rxList, freq, S_e): #, ePrimary=None, bPrimary=None, hPrimary=None, jPrimary=None):
self._S_e = np.array(S_e,dtype=complex)
def __init__(self, rxList, freq, s_e, **kwargs):
self._s_e = np.array(s_e, dtype=complex)
self.freq = float(freq)
BaseSrc.__init__(self, rxList)
def S_e(self, prob):
return self._S_e
BaseSrc.__init__(self, rxList, **kwargs)
def s_e(self, prob):
"""
Electric source term
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: electric source term on mesh
"""
if prob._formulation is 'EB' and self.integrate is True:
return prob.Me * self._s_e
return self._s_e
class RawVec_m(BaseSrc):
"""
RawVec magnetic source. It is defined by the user provided vector S_m
RawVec magnetic source. It is defined by the user provided vector s_m
:param numpy.array S_m: magnetic source term
:param float freq: frequency
:param rxList: receiver list
:param float freq: frequency
:param rxList: receiver list
:param numpy.array s_m: magnetic source term
:param bool integrate: Integrate the source term (multiply by Me) [False]
"""
def __init__(self, rxList, freq, S_m, integrate = True): #ePrimary=Zero(), bPrimary=Zero(), hPrimary=Zero(), jPrimary=Zero()):
self._S_m = np.array(S_m,dtype=complex)
def __init__(self, rxList, freq, s_m, **kwargs): #ePrimary=Zero(), bPrimary=Zero(), hPrimary=Zero(), jPrimary=Zero()):
self._s_m = np.array(s_m, dtype=complex)
self.freq = float(freq)
self.integrate = integrate
BaseSrc.__init__(self, rxList)
BaseSrc.__init__(self, rxList, **kwargs)
def S_m(self, prob):
return self._S_m
def s_m(self, prob):
"""
Magnetic source term
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: magnetic source term on mesh
"""
if prob._formulation is 'HJ' and self.integrate is True:
return prob.Me * self._s_m
return self._s_m
class RawVec(BaseSrc):
"""
RawVec source. It is defined by the user provided vectors S_m, S_e
RawVec source. It is defined by the user provided vectors s_m, s_e
:param numpy.array S_m: magnetic source term
:param numpy.array S_e: electric source term
:param float freq: frequency
:param rxList: receiver list
:param rxList: receiver list
:param float freq: frequency
:param numpy.array s_m: magnetic source term
:param numpy.array s_e: electric source term
:param bool integrate: Integrate the source term (multiply by Me) [False]
"""
def __init__(self, rxList, freq, S_m, S_e, integrate = True):
self._S_m = np.array(S_m,dtype=complex)
self._S_e = np.array(S_e,dtype=complex)
def __init__(self, rxList, freq, s_m, s_e, **kwargs):
self._s_m = np.array(s_m, dtype=complex)
self._s_e = np.array(s_e, dtype=complex)
self.freq = float(freq)
self.integrate = integrate
BaseSrc.__init__(self, rxList)
BaseSrc.__init__(self, rxList, **kwargs)
def S_m(self, prob):
if prob._eqLocs is 'EF' and self.integrate is True:
return prob.Me * self._S_m
return self._S_m
def s_m(self, prob):
"""
Magnetic source term
def S_e(self, prob):
if prob._eqLocs is 'FE' and self.integrate is True:
return prob.Me * self._S_e
return self._S_e
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: magnetic source term on mesh
"""
if prob._formulation is 'HJ' and self.integrate is True:
return prob.Me * self._s_m
return self._s_m
def s_e(self, prob):
"""
Electric source term
:param Problem prob: FDEM Problem
:rtype: numpy.ndarray
:return: electric source term on mesh
"""
if prob._formulation is 'EB' and self.integrate is True:
return prob.Me * self._s_e
return self._s_e
class MagDipole(BaseSrc):
"""
Point magnetic dipole source calculated by taking the curl of a magnetic
vector potential. By taking the discrete curl, we ensure that the magnetic
flux density is divergence free (no magnetic monopoles!).
#TODO: right now, orientation doesn't actually do anything! The methods in SrcUtils should take care of that
def __init__(self, rxList, freq, loc, orientation='Z', moment=1., mu = mu_0):
This approach uses a primary-secondary in frequency. Here we show the
derivation for E-B formulation noting that similar steps are followed for
the H-J formulation.
.. math::
\mathbf{C} \mathbf{e} + i \omega \mathbf{b} = \mathbf{s_m} \\\\
{\mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} \mathbf{b} - \mathbf{M_{\sigma}^e} \mathbf{e} = \mathbf{s_e}}
We split up the fields and :math:`\mu^{-1}` into primary (:math:`\mathbf{P}`) and secondary (:math:`\mathbf{S}`) components
- :math:`\mathbf{e} = \mathbf{e^P} + \mathbf{e^S}`
- :math:`\mathbf{b} = \mathbf{b^P} + \mathbf{b^S}`
- :math:`\\boldsymbol{\mu}^{\mathbf{-1}} = \\boldsymbol{\mu}^{\mathbf{-1}^\mathbf{P}} + \\boldsymbol{\mu}^{\mathbf{-1}^\mathbf{S}}`
and define a zero-frequency primary problem, noting that the source is
generated by a divergence free electric current
.. math::
\mathbf{C} \mathbf{e^P} = \mathbf{s_m^P} = 0 \\\\
{\mathbf{C}^T \mathbf{{M_{\mu^{-1}}^f}^P} \mathbf{b^P} - \mathbf{M_{\sigma}^e} \mathbf{e^P} = \mathbf{M^e} \mathbf{s_e^P}}
Since :math:`\mathbf{e^P}` is curl-free, divergence-free, we assume that there is no constant field background, the :math:`\mathbf{e^P} = 0`, so our primary problem is
.. math::
\mathbf{e^P} = 0 \\\\
{\mathbf{C}^T \mathbf{{M_{\mu^{-1}}^f}^P} \mathbf{b^P} = \mathbf{s_e^P}}
Our secondary problem is then
.. math::
\mathbf{C} \mathbf{e^S} + i \omega \mathbf{b^S} = - i \omega \mathbf{b^P} \\\\
{\mathbf{C}^T \mathbf{M_{\mu^{-1}}^f} \mathbf{b^S} - \mathbf{M_{\sigma}^e} \mathbf{e^S} = -\mathbf{C}^T \mathbf{{M_{\mu^{-1}}^f}^S} \mathbf{b^P}}
:param list rxList: receiver list
:param float freq: frequency
:param numpy.ndarray loc: source location (ie: :code:`np.r_[xloc,yloc,zloc]`)
:param string orientation: 'X', 'Y', 'Z'
:param float moment: magnetic dipole moment
:param float mu: background magnetic permeability
"""
def __init__(self, rxList, freq, loc, orientation='Z', moment=1., mu=mu_0, **kwargs):
self.freq = float(freq)
self.loc = loc
self.orientation = orientation
assert orientation in ['X','Y','Z'], "Orientation (right now) doesn't actually do anything! The methods in SrcUtils should take care of this..."
self.moment = moment
self.mu = mu
self.integrate = False
BaseSrc.__init__(self, rxList)
def bPrimary(self, prob):
eqLocs = prob._eqLocs
"""
The primary magnetic flux density from a magnetic vector potential
if eqLocs is 'FE':
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
formulation = prob._formulation
if formulation is 'EB':
gridX = prob.mesh.gridEx
gridY = prob.mesh.gridEy
gridZ = prob.mesh.gridEz
C = prob.mesh.edgeCurl
elif eqLocs is 'EF':
elif formulation is 'HJ':
gridX = prob.mesh.gridFx
gridY = prob.mesh.gridFy
gridZ = prob.mesh.gridFz
@@ -152,26 +384,51 @@ class MagDipole(BaseSrc):
return C*a
def hPrimary(self, prob):
"""
The primary magnetic field from a magnetic vector potential
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
b = self.bPrimary(prob)
return h_from_b(prob,b)
return 1./self.mu * b
def s_m(self, prob):
"""
The magnetic source term
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
def S_m(self, prob):
b_p = self.bPrimary(prob)
if prob._formulation is 'HJ':
b_p = prob.Me * b_p
return -1j*omega(self.freq)*b_p
def S_e(self, prob):
def s_e(self, prob):
"""
The electric source term
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
if all(np.r_[self.mu] == np.r_[prob.curModel.mu]):
return Zero()
else:
eqLocs = prob._eqLocs
formulation = prob._formulation
if eqLocs is 'FE':
if formulation is 'EB':
mui_s = prob.curModel.mui - 1./self.mu
MMui_s = prob.mesh.getFaceInnerProduct(mui_s)
C = prob.mesh.edgeCurl
elif eqLocs is 'EF':
elif formulation is 'HJ':
mu_s = prob.curModel.mu - self.mu
MMui_s = prob.mesh.getEdgeInnerProduct(mu_s,invMat=True)
MMui_s = prob.mesh.getEdgeInnerProduct(mu_s, invMat=True)
C = prob.mesh.edgeCurl.T
return -C.T * (MMui_s * self.bPrimary(prob))
@@ -179,26 +436,48 @@ class MagDipole(BaseSrc):
class MagDipole_Bfield(BaseSrc):
#TODO: right now, orientation doesn't actually do anything! The methods in SrcUtils should take care of that
#TODO: neither does moment
"""
Point magnetic dipole source calculated with the analytic solution for the
fields from a magnetic dipole. No discrete curl is taken, so the magnetic
flux density may not be strictly divergence free.
This approach uses a primary-secondary in frequency in the same fashion as the MagDipole.
:param list rxList: receiver list
:param float freq: frequency
:param numpy.ndarray loc: source location (ie: :code:`np.r_[xloc,yloc,zloc]`)
:param string orientation: 'X', 'Y', 'Z'
:param float moment: magnetic dipole moment
:param float mu: background magnetic permeability
"""
def __init__(self, rxList, freq, loc, orientation='Z', moment=1., mu = mu_0):
self.freq = float(freq)
self.loc = loc
assert orientation in ['X','Y','Z'], "Orientation (right now) doesn't actually do anything! The methods in SrcUtils should take care of this..."
self.orientation = orientation
self.moment = moment
self.mu = mu
BaseSrc.__init__(self, rxList)
def bPrimary(self, prob):
eqLocs = prob._eqLocs
"""
The primary magnetic flux density from the analytic solution for magnetic fields from a dipole
if eqLocs is 'FE':
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
formulation = prob._formulation
if formulation is 'EB':
gridX = prob.mesh.gridFx
gridY = prob.mesh.gridFy
gridZ = prob.mesh.gridFz
C = prob.mesh.edgeCurl
elif eqLocs is 'EF':
elif formulation is 'HJ':
gridX = prob.mesh.gridEx
gridY = prob.mesh.gridEy
gridZ = prob.mesh.gridEz
@@ -221,37 +500,74 @@ class MagDipole_Bfield(BaseSrc):
return b
def hPrimary(self, prob):
b = self.bPrimary(prob)
return h_from_b(prob, b)
"""
The primary magnetic field from a magnetic vector potential
def S_m(self, prob):
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
b = self.bPrimary(prob)
return 1/self.mu * b
def s_m(self, prob):
"""
The magnetic source term
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
b = self.bPrimary(prob)
if prob._formulation is 'HJ':
b = prob.Me * b
return -1j*omega(self.freq)*b
def S_e(self, prob):
def s_e(self, prob):
"""
The electric source term
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
if all(np.r_[self.mu] == np.r_[prob.curModel.mu]):
return Zero()
else:
eqLocs = prob._eqLocs
formulation = prob._formulation
if eqLocs is 'FE':
if formulation is 'EB':
mui_s = prob.curModel.mui - 1./self.mu
MMui_s = prob.mesh.getFaceInnerProduct(mui_s)
C = prob.mesh.edgeCurl
elif eqLocs is 'EF':
elif formulation is 'HJ':
mu_s = prob.curModel.mu - self.mu
MMui_s = prob.mesh.getEdgeInnerProduct(mu_s,invMat=True)
MMui_s = prob.mesh.getEdgeInnerProduct(mu_s, invMat=True)
C = prob.mesh.edgeCurl.T
return -C.T * (MMui_s * self.bPrimary(prob))
class CircularLoop(BaseSrc):
"""
Circular loop magnetic source calculated by taking the curl of a magnetic
vector potential. By taking the discrete curl, we ensure that the magnetic
flux density is divergence free (no magnetic monopoles!).
#TODO: right now, orientation doesn't actually do anything! The methods in SrcUtils should take care of that
def __init__(self, rxList, freq, loc, orientation='Z', radius = 1., mu=mu_0):
This approach uses a primary-secondary in frequency in the same fashion as the MagDipole.
:param list rxList: receiver list
:param float freq: frequency
:param numpy.ndarray loc: source location (ie: :code:`np.r_[xloc,yloc,zloc]`)
:param string orientation: 'X', 'Y', 'Z'
:param float moment: magnetic dipole moment
:param float mu: background magnetic permeability
"""
def __init__(self, rxList, freq, loc, orientation='Z', radius=1., mu=mu_0):
self.freq = float(freq)
self.orientation = orientation
assert orientation in ['X','Y','Z'], "Orientation (right now) doesn't actually do anything! The methods in SrcUtils should take care of this..."
self.radius = radius
self.mu = mu
self.loc = loc
@@ -259,15 +575,22 @@ class CircularLoop(BaseSrc):
BaseSrc.__init__(self, rxList)
def bPrimary(self, prob):
eqLocs = prob._eqLocs
"""
The primary magnetic flux density from a magnetic vector potential
if eqLocs is 'FE':
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
formulation = prob._formulation
if formulation is 'EB':
gridX = prob.mesh.gridEx
gridY = prob.mesh.gridEy
gridZ = prob.mesh.gridEz
C = prob.mesh.edgeCurl
elif eqLocs is 'EF':
elif formulation is 'HJ':
gridX = prob.mesh.gridFx
gridY = prob.mesh.gridFy
gridZ = prob.mesh.gridFz
@@ -277,10 +600,10 @@ class CircularLoop(BaseSrc):
if not prob.mesh.isSymmetric:
# TODO ?
raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!')
a = MagneticDipoleVectorPotential(self.loc, gridY, 'y', moment=self.radius, mu=self.mu)
a = MagneticLoopVectorPotential(self.loc, gridY, 'y', moment=self.radius, mu=self.mu)
else:
srcfct = MagneticDipoleVectorPotential
srcfct = MagneticLoopVectorPotential
ax = srcfct(self.loc, gridX, 'x', self.radius, mu=self.mu)
ay = srcfct(self.loc, gridY, 'y', self.radius, mu=self.mu)
az = srcfct(self.loc, gridZ, 'z', self.radius, mu=self.mu)
@@ -289,28 +612,205 @@ class CircularLoop(BaseSrc):
return C*a
def hPrimary(self, prob):
"""
The primary magnetic field from a magnetic vector potential
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
b = self.bPrimary(prob)
return 1./self.mu*b
def S_m(self, prob):
def s_m(self, prob):
"""
The magnetic source term
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
b = self.bPrimary(prob)
if prob._formulation is 'HJ':
b = prob.Me * b
return -1j*omega(self.freq)*b
def S_e(self, prob):
def s_e(self, prob):
"""
The electric source term
:param Problem prob: FDEM problem
:rtype: numpy.ndarray
:return: primary magnetic field
"""
if all(np.r_[self.mu] == np.r_[prob.curModel.mu]):
return Zero()
else:
eqLocs = prob._eqLocs
formulation = prob._formulation
if eqLocs is 'FE':
if formulation is 'EB':
mui_s = prob.curModel.mui - 1./self.mu
MMui_s = prob.mesh.getFaceInnerProduct(mui_s)
C = prob.mesh.edgeCurl
elif eqLocs is 'EF':
elif formulation is 'HJ':
mu_s = prob.curModel.mu - self.mu
MMui_s = prob.mesh.getEdgeInnerProduct(mu_s,invMat=True)
MMui_s = prob.mesh.getEdgeInnerProduct(mu_s, invMat=True)
C = prob.mesh.edgeCurl.T
return -C.T * (MMui_s * self.bPrimary(prob))
class PrimSecSigma(BaseSrc):
def __init__(self, rxList, freq, sigBack, ePrimary, **kwargs):
self.sigBack = sigBack
BaseSrc.__init__(self, rxList, freq=freq, _ePrimary=ePrimary, **kwargs)
def s_e(self, prob):
return (prob.MeSigma - prob.mesh.getEdgeInnerProduct(self.sigBack)) * self.ePrimary(prob)
def s_eDeriv(self, prob, v, adjoint=False):
if adjoint:
return prob.MeSigmaDeriv(self.ePrimary(prob)).T * v
return prob.MeSigmaDeriv(self.ePrimary(prob)) * v
class PrimSecMappedSigma(BaseSrc):
"""
Primary-Secondary Source in which a mapping is provided to put the current model
onto the primary mesh. This is solved on every model update.
There are a lot of layers to the derivatives here!
**Required**
:param list rxList: Receiver List
:param float freq: frequency
:param ProblemFDEM primaryProblem: FDEM primary problem
:param SurveyFDEM primarySurvey: FDEM primary survey
**Optional**
:param Mapping map2meshSecondary: mapping current model to act as primary model on the secondary mesh
"""
def __init__(self, rxList, freq, primaryProblem, primarySurvey, map2meshSecondary = None ,**kwargs):
self.primaryProblem = primaryProblem
self.primarySurvey = primarySurvey
if self.primaryProblem.ispaired is False:
self.primaryProblem.pair(self.primarySurvey)
self.map2meshSecondary = map2meshSecondary
BaseSrc.__init__(self, rxList, freq=freq, **kwargs)
def _ProjPrimary(self, prob):
# if getattr(self, '__ProjPrimary', None) is None:
return self.primaryProblem.mesh.getInterpolationMatCartMesh(prob.mesh, locType='F', locTypeTo='E')
# return self.__ProjPrimary
def _primaryFields(self, prob, fieldType=None):
# TODO: cache and check if prob.curModel has changed
fields = self.primaryProblem.fields(prob.curModel.sigmaModel)
if fieldType is not None:
return fields[:,fieldType]
return fields
def _primaryFieldsDeriv(self, prob, v, adjoint=False, f=None):
if adjoint:
raise NotImplementedError
# TODO: this should not be hard-coded for j
# jp = self._primaryFields(prob)[:,'j']
# TODO: pull apart Jvec so that don't have to copy paste this code in
# A = self.primaryProblem.getA(self.freq)
# Ainv = self.primaryProblem.Solver(A, **self.primaryProblem.solverOpts) # create the concept of Ainv (actually a solve)
if f is None:
f = self._primaryFields(prob.curModel.sigmaModel)
freq = self.freq
A = self.primaryProblem.getA(freq)
Ainv = self.primaryProblem.Solver(A, **self.primaryProblem.solverOpts) # create the concept of Ainv (actually a solve)
src = self.primarySurvey.srcList[0]
# for src in self.survey.getSrcByFreq(freq):
u_src = Utils.mkvc(f[src, self.primaryProblem._solutionType])
dA_dm_v = self.primaryProblem.getADeriv(freq, u_src, v)
dRHS_dm_v = self.primaryProblem.getRHSDeriv(freq, src, v)
du_dm_v = Ainv * ( - dA_dm_v + dRHS_dm_v )
df_dmFun = getattr(f, '_{0}Deriv'.format('j'), None)
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
# Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v)
Ainv.clean()
return df_dm_v
# return self.primaryProblem.Jvec(prob.curModel, v, f=f)
def ePrimary(self, prob, f=None):
if f is None:
f = self._primaryFields(prob)
ep = self._ProjPrimary(prob) * (
self.primaryProblem.MfI * (
self.primaryProblem.MfRho * f[:,'j'])
)
return Utils.mkvc(ep)
def ePrimaryDeriv(self, prob, v, adjoint=False, f=None):
if adjoint is True:
raise NotImplementedError
if f is None:
f = self._primaryFields(prob)
epDeriv = self._ProjPrimary(prob) * (
self.primaryProblem.MfI * (
(self.primaryProblem.MfRhoDeriv(f[:,'j']) * v)
+
(self.primaryProblem.MfRho * self._primaryFieldsDeriv(prob, v, f=f))
)
)
return Utils.mkvc(epDeriv)
def s_e(self, prob):
sigmaPrimary = self.map2meshSecondary * prob.curModel.sigmaModel
return Utils.mkvc((prob.MeSigma - prob.mesh.getEdgeInnerProduct(sigmaPrimary)) * self.ePrimary(prob))
def s_eDeriv(self, prob, v, adjoint=False):
if adjoint:
raise NotImplementedError
return prob.MeSigmaDeriv(self.ePrimary(prob)).T * v
sigmaPrimary = self.map2meshSecondary * prob.curModel.sigmaModel
sigmaPrimaryDeriv = self.map2meshSecondary.deriv(prob.curModel.sigmaModel)
f = self._primaryFields(prob)
ePrimary = self.ePrimary(prob,f=f)
return (prob.MeSigmaDeriv(ePrimary) * v
- prob.mesh.getEdgeInnerProductDeriv(sigmaPrimary)(ePrimary) * sigmaPrimaryDeriv * v
+ (prob.MeSigma - prob.mesh.getEdgeInnerProduct(sigmaPrimary)) * self.ePrimaryDeriv(prob, v, None, f=f)
)
+16 -102
View File
@@ -1,109 +1,26 @@
import SimPEG
from SimPEG.EM.Utils import *
from SimPEG.EM.Base import BaseEMSurvey
from scipy.constants import mu_0
from SimPEG.Utils import Zero, Identity
import SrcFDEM as Src
import RxFDEM as Rx
from SimPEG import sp
####################################################
# Receivers
####################################################
class Rx(SimPEG.Survey.BaseRx):
knownRxTypes = {
'exr':['e', 'Ex', 'real'],
'eyr':['e', 'Ey', 'real'],
'ezr':['e', 'Ez', 'real'],
'exi':['e', 'Ex', 'imag'],
'eyi':['e', 'Ey', 'imag'],
'ezi':['e', 'Ez', 'imag'],
'bxr':['b', 'Fx', 'real'],
'byr':['b', 'Fy', 'real'],
'bzr':['b', 'Fz', 'real'],
'bxi':['b', 'Fx', 'imag'],
'byi':['b', 'Fy', 'imag'],
'bzi':['b', 'Fz', 'imag'],
'jxr':['j', 'Fx', 'real'],
'jyr':['j', 'Fy', 'real'],
'jzr':['j', 'Fz', 'real'],
'jxi':['j', 'Fx', 'imag'],
'jyi':['j', 'Fy', 'imag'],
'jzi':['j', 'Fz', 'imag'],
'hxr':['h', 'Ex', 'real'],
'hyr':['h', 'Ey', 'real'],
'hzr':['h', 'Ez', 'real'],
'hxi':['h', 'Ex', 'imag'],
'hyi':['h', 'Ey', 'imag'],
'hzi':['h', 'Ez', 'imag'],
}
radius = None
def __init__(self, locs, rxType):
SimPEG.Survey.BaseRx.__init__(self, locs, rxType)
@property
def projField(self):
"""Field Type projection (e.g. e b ...)"""
return self.knownRxTypes[self.rxType][0]
@property
def projGLoc(self):
"""Grid Location projection (e.g. Ex Fy ...)"""
return self.knownRxTypes[self.rxType][1]
@property
def projComp(self):
"""Component projection (real/imag)"""
return self.knownRxTypes[self.rxType][2]
def projectFields(self, src, mesh, u):
P = self.getP(mesh)
u_part_complex = u[src, self.projField]
# get the real or imag component
real_or_imag = self.projComp
u_part = getattr(u_part_complex, real_or_imag)
return P*u_part
def projectFieldsDeriv(self, src, mesh, u, v, adjoint=False):
P = self.getP(mesh)
if not adjoint:
Pv_complex = P * v
real_or_imag = self.projComp
Pv = getattr(Pv_complex, real_or_imag)
elif adjoint:
Pv_real = P.T * v
real_or_imag = self.projComp
if real_or_imag == 'imag':
Pv = 1j*Pv_real
elif real_or_imag == 'real':
Pv = Pv_real.astype(complex)
else:
raise NotImplementedError('must be real or imag')
return Pv
####################################################
# Survey
####################################################
class Survey(SimPEG.Survey.BaseSurvey):
class Survey(BaseEMSurvey):
"""
docstring for SurveyFDEM
Frequency domain electromagnetic survey
:param list srcList: list of FDEM sources used in the survey
"""
srcPair = Src.BaseSrc
rxPair = Rx.BaseRx
def __init__(self, srcList, **kwargs):
# Sort these by frequency
self.srcList = srcList
SimPEG.Survey.BaseSurvey.__init__(self, **kwargs)
BaseEMSurvey.__init__(self, srcList, **kwargs)
_freqDict = {}
for src in srcList:
@@ -126,6 +43,7 @@ class Survey(SimPEG.Survey.BaseSurvey):
@property
def nSrcByFreq(self):
"""Number of sources at each frequency"""
if getattr(self, '_nSrcByFreq', None) is None:
self._nSrcByFreq = {}
for freq in self.freqs:
@@ -133,16 +51,12 @@ class Survey(SimPEG.Survey.BaseSurvey):
return self._nSrcByFreq
def getSrcByFreq(self, freq):
"""Returns the sources associated with a specific frequency."""
"""
Returns the sources associated with a specific frequency.
:param float freq: frequency for which we look up sources
:rtype: dictionary
:return: sources at the sepcified frequency
"""
assert freq in self._freqDict, "The requested frequency is not in this survey."
return self._freqDict[freq]
def projectFields(self, u):
data = SimPEG.Survey.Data(self)
for src in self.srcList:
for rx in src.rxList:
data[src, rx] = rx.projectFields(src, self.mesh, u)
return data
def projectFieldsDeriv(self, u):
raise Exception('Use Sources to project fields deriv.')
+5 -3
View File
@@ -1,3 +1,5 @@
from SurveyFDEM import Rx, Src, Survey
from FDEM import BaseFDEMProblem, Problem_e, Problem_b, Problem_j, Problem_h
from FieldsFDEM import *
from SurveyFDEM import Survey
import SrcFDEM as Src
import RxFDEM as Rx
from ProblemFDEM import Problem3D_e, Problem3D_b, Problem3D_j, Problem3D_h
from FieldsFDEM import Fields3D_e, Fields3D_b, Fields3D_j, Fields3D_h
+160
View File
@@ -0,0 +1,160 @@
import numpy as np
def getxBCyBC_CC(mesh, alpha, beta, gamma):
# def getxBCyBC(mesh, alpha, beta, gamma):
"""
This is a subfunction generating mixed-boundary condition:
.. math::
\nabla \cdot \vec{j} = -\nabla \cdot \vec{j}_s = q
\rho \vec{j} = -\nabla \phi \phi
\alpha \phi + \beta \frac{\partial \phi}{\partial r} = \gamma \ at \ r = \partial \Omega
xBC = f_1(\alpha, \beta, \gamma)
yBC = f(\alpha, \beta, \gamma)
Computes xBC and yBC for cell-centered discretizations
"""
if mesh.dim == 1: #1D
if (len(alpha) != 2 or len(beta) != 2 or len(gamma) != 2):
raise Exception("Lenght of list, alpha should be 2")
fCCxm,fCCxp = mesh.cellBoundaryInd
nBC = fCCxm.sum()+fCCxp.sum()
h_xm, h_xp = mesh.gridCC[fCCxm], mesh.gridCC[fCCxp]
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
# h_xm, h_xp = mesh.gridCC[fCCxm], mesh.gridCC[fCCxp]
h_xm, h_xp = mesh.hx[0], mesh.hx[-1]
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
xBC_xm = 0.5*a_xm
xBC_xp = 0.5*a_xp/b_xp
yBC_xm = 0.5*(1.-b_xm)
yBC_xp = 0.5*(1.-1./b_xp)
xBC = np.r_[xBC_xm, xBC_xp]
yBC = np.r_[yBC_xm, yBC_xp]
elif mesh.dim == 2: #2D
if (len(alpha) != 4 or len(beta) != 4 or len(gamma) != 4):
raise Exception("Lenght of list, alpha should be 4")
fxm,fxp,fym,fyp = mesh.faceBoundaryInd
nBC = fxm.sum()+fxp.sum()+fxm.sum()+fxp.sum()
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
alpha_ym, beta_ym, gamma_ym = alpha[2], beta[2], gamma[2]
alpha_yp, beta_yp, gamma_yp = alpha[3], beta[3], gamma[3]
# h_xm, h_xp = mesh.gridCC[fCCxm,0], mesh.gridCC[fCCxp,0]
# h_ym, h_yp = mesh.gridCC[fCCym,1], mesh.gridCC[fCCyp,1]
h_xm, h_xp = mesh.hx[0]*np.ones_like(alpha_xm), mesh.hx[-1]*np.ones_like(alpha_xp)
h_ym, h_yp = mesh.hy[0]*np.ones_like(alpha_ym), mesh.hy[-1]*np.ones_like(alpha_yp)
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
a_ym = gamma_ym/(0.5*alpha_ym-beta_ym/h_ym)
b_ym = (0.5*alpha_ym+beta_ym/h_ym)/(0.5*alpha_ym-beta_ym/h_ym)
a_yp = gamma_yp/(0.5*alpha_yp-beta_yp/h_yp)
b_yp = (0.5*alpha_yp+beta_yp/h_yp)/(0.5*alpha_yp-beta_yp/h_yp)
xBC_xm = 0.5*a_xm
xBC_xp = 0.5*a_xp/b_xp
yBC_xm = 0.5*(1.-b_xm)
yBC_xp = 0.5*(1.-1./b_xp)
xBC_ym = 0.5*a_ym
xBC_yp = 0.5*a_yp/b_yp
yBC_ym = 0.5*(1.-b_ym)
yBC_yp = 0.5*(1.-1./b_yp)
sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm], np.arange(mesh.nFx)[fxp]])
sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym], np.arange(mesh.nFy)[fyp]])
xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx]
xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy]
yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx]
yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy]
xBC = np.r_[xBC_x, xBC_y]
yBC = np.r_[yBC_x, yBC_y]
elif mesh.dim == 3: #3D
if (len(alpha) != 6 or len(beta) != 6 or len(gamma) != 6):
raise Exception("Lenght of list, alpha should be 6")
# fCCxm,fCCxp,fCCym,fCCyp,fCCzm,fCCzp = mesh.cellBoundaryInd
fxm,fxp,fym,fyp,fzm,fzp = mesh.faceBoundaryInd
nBC = fxm.sum()+fxp.sum()+fxm.sum()+fxp.sum()
alpha_xm, beta_xm, gamma_xm = alpha[0], beta[0], gamma[0]
alpha_xp, beta_xp, gamma_xp = alpha[1], beta[1], gamma[1]
alpha_ym, beta_ym, gamma_ym = alpha[2], beta[2], gamma[2]
alpha_yp, beta_yp, gamma_yp = alpha[3], beta[3], gamma[3]
alpha_zm, beta_zm, gamma_zm = alpha[4], beta[4], gamma[4]
alpha_zp, beta_zp, gamma_zp = alpha[5], beta[5], gamma[5]
# h_xm, h_xp = mesh.gridCC[fCCxm,0], mesh.gridCC[fCCxp,0]
# h_ym, h_yp = mesh.gridCC[fCCym,1], mesh.gridCC[fCCyp,1]
# h_zm, h_zp = mesh.gridCC[fCCzm,2], mesh.gridCC[fCCzp,2]
h_xm, h_xp = mesh.hx[0]*np.ones_like(alpha_xm), mesh.hx[-1]*np.ones_like(alpha_xp)
h_ym, h_yp = mesh.hy[0]*np.ones_like(alpha_ym), mesh.hy[-1]*np.ones_like(alpha_yp)
h_zm, h_zp = mesh.hz[0]*np.ones_like(alpha_zm), mesh.hz[-1]*np.ones_like(alpha_zp)
a_xm = gamma_xm/(0.5*alpha_xm-beta_xm/h_xm)
b_xm = (0.5*alpha_xm+beta_xm/h_xm)/(0.5*alpha_xm-beta_xm/h_xm)
a_xp = gamma_xp/(0.5*alpha_xp-beta_xp/h_xp)
b_xp = (0.5*alpha_xp+beta_xp/h_xp)/(0.5*alpha_xp-beta_xp/h_xp)
a_ym = gamma_ym/(0.5*alpha_ym-beta_ym/h_ym)
b_ym = (0.5*alpha_ym+beta_ym/h_ym)/(0.5*alpha_ym-beta_ym/h_ym)
a_yp = gamma_yp/(0.5*alpha_yp-beta_yp/h_yp)
b_yp = (0.5*alpha_yp+beta_yp/h_yp)/(0.5*alpha_yp-beta_yp/h_yp)
a_zm = gamma_zm/(0.5*alpha_zm-beta_zm/h_zm)
b_zm = (0.5*alpha_zm+beta_zm/h_zm)/(0.5*alpha_zm-beta_zm/h_zm)
a_zp = gamma_zp/(0.5*alpha_zp-beta_zp/h_zp)
b_zp = (0.5*alpha_zp+beta_zp/h_zp)/(0.5*alpha_zp-beta_zp/h_zp)
xBC_xm = 0.5*a_xm
xBC_xp = 0.5*a_xp/b_xp
yBC_xm = 0.5*(1.-b_xm)
yBC_xp = 0.5*(1.-1./b_xp)
xBC_ym = 0.5*a_ym
xBC_yp = 0.5*a_yp/b_yp
yBC_ym = 0.5*(1.-b_ym)
yBC_yp = 0.5*(1.-1./b_yp)
xBC_zm = 0.5*a_zm
xBC_zp = 0.5*a_zp/b_zp
yBC_zm = 0.5*(1.-b_zm)
yBC_zp = 0.5*(1.-1./b_zp)
sortindsfx = np.argsort(np.r_[np.arange(mesh.nFx)[fxm], np.arange(mesh.nFx)[fxp]])
sortindsfy = np.argsort(np.r_[np.arange(mesh.nFy)[fym], np.arange(mesh.nFy)[fyp]])
sortindsfz = np.argsort(np.r_[np.arange(mesh.nFz)[fzm], np.arange(mesh.nFz)[fzp]])
xBC_x = np.r_[xBC_xm, xBC_xp][sortindsfx]
xBC_y = np.r_[xBC_ym, xBC_yp][sortindsfy]
xBC_z = np.r_[xBC_zm, xBC_zp][sortindsfz]
yBC_x = np.r_[yBC_xm, yBC_xp][sortindsfx]
yBC_y = np.r_[yBC_ym, yBC_yp][sortindsfy]
yBC_z = np.r_[yBC_zm, yBC_zp][sortindsfz]
xBC = np.r_[xBC_x, xBC_y, xBC_z]
yBC = np.r_[yBC_x, yBC_y, yBC_z]
return xBC, yBC
+148
View File
@@ -0,0 +1,148 @@
import SimPEG
from SimPEG.Utils import Identity, Zero
import numpy as np
from scipy.constants import epsilon_0
class Fields(SimPEG.Problem.Fields):
knownFields = {}
dtype = float
def _phiDeriv(self, src, du_dm_v, v, adjoint=False):
if getattr(self, '_phiDeriv_u', None) is None or getattr(self, '_phiDeriv_m', None) is None:
raise NotImplementedError ('Getting phiDerivs from %s is not implemented' %self.knownFields.keys()[0])
if adjoint:
return self._phiDeriv_u(src, v, adjoint=adjoint), self._phiDeriv_m(src, v, adjoint=adjoint)
return np.array(self._phiDeriv_u(src, du_dm_v, adjoint) + self._phiDeriv_m(src, v, adjoint), dtype = float)
def _eDeriv(self, src, du_dm_v, v, adjoint=False):
if getattr(self, '_eDeriv_u', None) is None or getattr(self, '_eDeriv_m', None) is None:
raise NotImplementedError ('Getting eDerivs from %s is not implemented' %self.knownFields.keys()[0])
if adjoint:
return self._eDeriv_u(src, v, adjoint), self._eDeriv_m(src, v, adjoint)
return np.array(self._eDeriv_u(src, du_dm_v, adjoint) + self._eDeriv_m(src, v, adjoint), dtype = float)
def _jDeriv(self, src, du_dm_v, v, adjoint=False):
if getattr(self, '_jDeriv_u', None) is None or getattr(self, '_jDeriv_m', None) is None:
raise NotImplementedError ('Getting jDerivs from %s is not implemented' %self.knownFields.keys()[0])
if adjoint:
return self._jDeriv_u(src, v, adjoint), self._jDeriv_m(src, v, adjoint)
return np.array(self._jDeriv_u(src, du_dm_v, adjoint) + self._jDeriv_m(src, v, adjoint), dtype = float)
class Fields_CC(Fields):
knownFields = {'phiSolution':'CC'}
aliasFields = {
'phi': ['phiSolution','CC','_phi'],
'j' : ['phiSolution','F','_j'],
'e' : ['phiSolution','F','_e'],
'charge' : ['phiSolution','CC','_charge'],
}
# primary - secondary
# CC variables
def __init__(self, mesh, survey, **kwargs):
Fields.__init__(self, mesh, survey, **kwargs)
mesh.setCellGradBC("neumann")
cellGrad = mesh.cellGrad
def startup(self):
self.prob = self.survey.prob
def _GLoc(self, fieldType):
if fieldType == 'phi':
return 'CC'
elif fieldType == 'e' or fieldType == 'j':
return 'F'
else:
raise Exception('Field type must be phi, e, j')
def _phi(self, phiSolution, srcList):
return phiSolution
def _phiDeriv_u(self, src, v, adjoint = False):
return Identity()*v
def _phiDeriv_m(self, src, v, adjoint = False):
return Zero()
def _j(self, phiSolution, srcList):
"""
.. math::
\mathbf{j} = \mathbf{M}^{f \ -1}_{\rho} \mathbf{G} \phi
"""
return self.prob.MfRhoI*self.prob.Grad*phiSolution
def _e(self, phiSolution, srcList):
"""
In HJ formulation e is not well-defined!!
.. math::
\vec{e} = -\nabla \phi
"""
return -self.mesh.cellGrad*phiSolution
def _charge(self, phiSolution, srcList):
"""
.. math::
\int \nabla \codt \vec{e} = \int \frac{\rho_v }{\epsillon_0}
"""
return epsilon_0*self.prob.Vol*(self.mesh.faceDiv*self._e(phiSolution, srcList))
class Fields_N(Fields):
knownFields = {'phiSolution':'N'}
aliasFields = {
'phi': ['phiSolution','N','_phi'],
'j' : ['phiSolution','E','_j'],
'e' : ['phiSolution','E','_e'],
'charge' : ['phiSolution','N','_charge'],
}
# primary - secondary
# N variables
def __init__(self, mesh, survey, **kwargs):
Fields.__init__(self, mesh, survey, **kwargs)
def startup(self):
self.prob = self.survey.prob
def _GLoc(self, fieldType):
if fieldType == 'phi':
return 'N'
elif fieldType == 'e' or fieldType == 'j':
return 'E'
else:
raise Exception('Field type must be phi, e, j')
def _phi(self, phiSolution, srcList):
return phiSolution
def _phiDeriv_u(self, src, v, adjoint = False):
return Identity()*v
def _phiDeriv_m(self, src, v, adjoint = False):
return Zero()
def _j(self, phiSolution, srcList):
"""
In EB formulation j is not well-defined!!
.. math::
\mathbf{j} = - \mathbf{M}^{e}_{\sigma} \mathbf{G} \phi
"""
return self.prob.MeSigma * self._e(phiSolution, srcList)
def _e(self, phiSolution, srcList):
"""
In HJ formulation e is not well-defined!!
.. math::
\vec{e} = -\nabla \phi
"""
return -self.mesh.nodalGrad * phiSolution
def _charge(self, phiSolution, srcList):
"""
.. math::
\int \nabla \codt \vec{e} = \int \frac{\rho_v }{\epsillon_0}
"""
return - epsilon_0*(self.mesh.nodalGrad.T*self.mesh.getEdgeInnerProduct()*self._e(phiSolution, srcList))
+146
View File
@@ -0,0 +1,146 @@
import SimPEG
from SimPEG.Utils import Identity, Zero
import numpy as np
class Fields_ky(SimPEG.Problem.TimeFields):
"""
Fancy Field Storage for a 2.5D code.
u[:,'phi', kyInd] = phi
print u[src0,'phi']
Only one field type is stored for
each problem, the rest are computed. The fields obejct acts like an array and is indexed by
.. code-block:: python
f = problem.fields(m)
e = f[srcList,'e']
j = f[srcList,'j']
If accessing all sources for a given field, use the :code:`:`
.. code-block:: python
f = problem.fields(m)
phi = f[:,'phi']
e = f[:,'e']
b = f[:,'b']
The array returned will be size (nE or nF, nSrcs :math:`\\times` nFrequencies)
"""
knownFields = {}
dtype = float
def _phiDeriv(self,kyInd, src, du_dm_v, v, adjoint=False):
if getattr(self, '_phiDeriv_u', None) is None or getattr(self, '_phiDeriv_m', None) is None:
raise NotImplementedError ('Getting phiDerivs from %s is not implemented' %self.knownFields.keys()[0])
if adjoint:
return self._phiDeriv_u(kyInd, src, v, adjoint=adjoint), self._phiDeriv_m(kyInd, src, v, adjoint=adjoint)
return np.array(self._phiDeriv_u(kyInd, src, du_dm_v, adjoint) + self._phiDeriv_m(kyInd, src, v, adjoint), dtype = float)
def _eDeriv(self,kyInd, src, du_dm_v, v, adjoint=False):
if getattr(self, '_eDeriv_u', None) is None or getattr(self, '_eDeriv_m', None) is None:
raise NotImplementedError ('Getting eDerivs from %s is not implemented' %self.knownFields.keys()[0])
if adjoint:
return self._eDeriv_u(kyInd, src, v, adjoint), self._eDeriv_m(kyInd, src, v, adjoint)
return np.array(self._eDeriv_u(kyInd, src, du_dm_v, adjoint) + self._eDeriv_m(kyInd, src, v, adjoint), dtype = float)
def _jDeriv(self,kyInd, src, du_dm_v, v, adjoint=False):
if getattr(self, '_jDeriv_u', None) is None or getattr(self, '_jDeriv_m', None) is None:
raise NotImplementedError ('Getting jDerivs from %s is not implemented' %self.knownFields.keys()[0])
if adjoint:
return self._jDeriv_u(kyInd, src, v, adjoint), self._jDeriv_m(kyInd, src, v, adjoint)
return np.array(self._jDeriv_u(kyInd, src, du_dm_v, adjoint) + self._jDeriv_m(kyInd, src, v, adjoint), dtype = float)
# def _eDeriv(self, tInd, src, dun_dm_v, v, adjoint=False):
# if adjoint is True:
# return self._eDeriv_u(tInd, src, v, adjoint), self._eDeriv_m(tInd, src, v, adjoint)
# return self._eDeriv_u(tInd, src, dun_dm_v) + self._eDeriv_m(tInd, src, v)
# def _bDeriv(self, tInd, src, dun_dm_v, v, adjoint=False):
# if adjoint is True:
# return self._bDeriv_u(tInd, src, v, adjoint), self._bDeriv_m(tInd, src, v, adjoint)
# return self._bDeriv_u(tInd, src, dun_dm_v) + self._bDeriv_m(tInd, src, v)
class Fields_ky_CC(Fields_ky):
knownFields = {'phiSolution':'CC'}
aliasFields = {
'phi': ['phiSolution','CC','_phi'],
'j' : ['phiSolution','F','_j'],
'e' : ['phiSolution','F','_e'],
}
# primary - secondary
# CC variables
def __init__(self, mesh, survey, **kwargs):
Fields_ky.__init__(self, mesh, survey, **kwargs)
def startup(self):
self.prob = self.survey.prob
def _GLoc(self, fieldType):
if fieldType == 'phi':
return 'CC'
elif fieldType == 'e' or fieldType == 'j':
return 'F'
else:
raise Exception('Field type must be phi, e, j')
def _phi(self, phiSolution, src, kyInd):
return phiSolution
def _phiDeriv_u(self, kyInd, src, v, adjoint = False):
return Identity()*v
def _phiDeriv_m(self, kyInd, src, v, adjoint = False):
return Zero()
def _j(self, phiSolution, srcList):
raise NotImplementedError
def _e(self, phiSolution, srcList):
raise NotImplementedError
class Fields_ky_N(Fields_ky):
knownFields = {'phiSolution':'N'}
aliasFields = {
'phi': ['phiSolution','N','_phi'],
'j' : ['phiSolution','E','_j'],
'e' : ['phiSolution','E','_e'],
}
# primary - secondary
# CC variables
def __init__(self, mesh, survey, **kwargs):
Fields_ky.__init__(self, mesh, survey, **kwargs)
def startup(self):
self.prob = self.survey.prob
def _GLoc(self, fieldType):
if fieldType == 'phi':
return 'N'
elif fieldType == 'e' or fieldType == 'j':
return 'E'
else:
raise Exception('Field type must be phi, e, j')
def _phi(self, phiSolution, src, kyInd):
return phiSolution
def _phiDeriv_u(self, kyInd, src, v, adjoint = False):
return Identity()*v
def _phiDeriv_m(self, kyInd, src, v, adjoint = False):
return Zero()
def _j(self, phiSolution, srcList):
raise NotImplementedError
def _e(self, phiSolution, srcList):
raise NotImplementedError
+296
View File
@@ -0,0 +1,296 @@
from SimPEG import Problem, Utils
from SimPEG.EM.Base import BaseEMProblem
from SurveyDC import Survey
from FieldsDC import Fields, Fields_CC, Fields_N
from SimPEG.Utils import sdiag
import numpy as np
from SimPEG.Utils import Zero
from BoundaryUtils import getxBCyBC_CC
class BaseDCProblem(BaseEMProblem):
surveyPair = Survey
fieldsPair = Fields
Ainv = None
def fields(self, m):
self.curModel = m
if not self.Ainv == None:
self.Ainv.clean()
f = self.fieldsPair(self.mesh, self.survey)
A = self.getA()
self.Ainv = self.Solver(A, **self.solverOpts)
RHS = self.getRHS()
u = self.Ainv * RHS
Srcs = self.survey.srcList
f[Srcs, self._solutionType] = u
return f
def Jvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
Jv = self.dataPair(self.survey) #same size as the data
A = self.getA()
for src in self.survey.srcList:
u_src = f[src, self._solutionType] # solution vector
dA_dm_v = self.getADeriv(u_src, v)
dRHS_dm_v = self.getRHSDeriv(src, v)
du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v )
for rx in src.rxList:
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v)
return Utils.mkvc(Jv)
def Jtvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
# Ensure v is a data object.
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
Jtv = np.zeros(m.size)
AT = self.getA()
for src in self.survey.srcList:
u_src = f[src, self._solutionType]
for rx in src.rxList:
PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True)
ATinvdf_duT = self.Ainv * df_duT
dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True)
dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True)
du_dmT = -dA_dmT + dRHS_dmT
Jtv += (df_dmT + du_dmT).astype(float)
return Utils.mkvc(Jtv)
def getSourceTerm(self):
"""
takes concept of source and turns it into a matrix
"""
"""
Evaluates the sources, and puts them in matrix form
:rtype: (numpy.ndarray, numpy.ndarray)
:return: q (nC or nN, nSrc)
"""
Srcs = self.survey.srcList
if self._formulation is 'EB':
n = self.mesh.nN
# return NotImplementedError
elif self._formulation is 'HJ':
n = self.mesh.nC
q = np.zeros((n, len(Srcs)))
for i, src in enumerate(Srcs):
q[:,i] = src.eval(self)
return q
class Problem3D_CC(BaseDCProblem):
_solutionType = 'phiSolution'
_formulation = 'HJ' # CC potentials means J is on faces
fieldsPair = Fields_CC
def __init__(self, mesh, **kwargs):
BaseDCProblem.__init__(self, mesh, **kwargs)
self.setBC()
def getA(self):
"""
Make the A matrix for the cell centered DC resistivity problem
A = D MfRhoI G
"""
D = self.Div
G = self.Grad
MfRhoI = self.MfRhoI
A = D * MfRhoI * G
# I think we should deprecate this for DC problem.
# if self._makeASymmetric is True:
# return V.T * A
return A
def getADeriv(self, u, v, adjoint= False):
D = self.Div
G = self.Grad
MfRhoIDeriv = self.MfRhoIDeriv
if adjoint:
return(MfRhoIDeriv( G * u ).T) * ( D.T * v)
return D * (MfRhoIDeriv( G * u ) * v)
def getRHS(self):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm()
return RHS
def getRHSDeriv(self, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
# return qDeriv
return Zero()
def setBC(self):
if self.mesh.dim==3:
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
gBFzm = self.mesh.gridFz[fzm,:]
gBFzp = self.mesh.gridFz[fzp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
beta_zm, beta_zp = temp_zm, temp_zp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
elif self.mesh.dim==2:
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
V = self.Vol
self.Div = V * self.mesh.faceDiv
P_BC, B = self.mesh.getBCProjWF_simple()
M = B*self.mesh.aveCC2F
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
class Problem3D_N(BaseDCProblem):
_solutionType = 'phiSolution'
_formulation = 'EB' # N potentials means B is on faces
fieldsPair = Fields_N
def __init__(self, mesh, **kwargs):
BaseDCProblem.__init__(self, mesh, **kwargs)
def getA(self):
"""
Make the A matrix for the cell centered DC resistivity problem
A = G.T MeSigma G
"""
MeSigma = self.MeSigma
Grad = self.mesh.nodalGrad
A = Grad.T * MeSigma * Grad
# Handling Null space of A
A[0,0] = A[0,0] + 1.
return A
def getADeriv(self, u, v, adjoint=False):
"""
Product of the derivative of our system matrix with respect to the model and a vector
"""
MeSigma = self.MeSigma
Grad = self.mesh.nodalGrad
if not adjoint:
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v)
elif adjoint:
return self.MeSigmaDeriv(Grad*u).T * (Grad*v)
def getRHS(self):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm()
return RHS
def getRHSDeriv(self, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
# return qDeriv
return Zero()
+349
View File
@@ -0,0 +1,349 @@
from SimPEG import Problem, Utils
from SimPEG.EM.Base import BaseEMProblem
from SurveyDC import Survey, Survey_ky
from FieldsDC_2D import Fields_ky, Fields_ky_CC, Fields_ky_N
from SimPEG.Utils import sdiag
import numpy as np
from SimPEG.Utils import Zero
from BoundaryUtils import getxBCyBC_CC
class BaseDCProblem_2D(BaseEMProblem):
surveyPair = Survey_ky
fieldsPair = Fields_ky
nky = 15
kys = np.logspace(-4, 1, nky)
Ainv = [None for i in range(nky)]
nT = nky # Only for using TimeFields
def fields(self, m):
self.curModel = m
if not self.Ainv[0] == None:
for i in range(self.nky):
self.Ainv[i].clean()
f = self.fieldsPair(self.mesh, self.survey)
Srcs = self.survey.srcList
for iky in range(self.nky):
ky = self.kys[iky]
A = self.getA(ky)
self.Ainv[iky] = self.Solver(A, **self.solverOpts)
RHS = self.getRHS(ky)
u = self.Ainv[iky] * RHS
f[Srcs, self._solutionType, iky] = u
return f
def Jvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
Jv = self.dataPair(self.survey) #same size as the data
Jv0 = self.dataPair(self.survey)
# Assume y=0.
# This needs some thoughts to implement in general when src is dipole
dky = np.diff(self.kys)
dky = np.r_[dky[0], dky]
y = 0.
#TODO: this loop is pretty slow .. (Parellize)
for iky in range(self.nky):
ky = self.kys[iky]
A = self.getA(ky)
for src in self.survey.srcList:
u_src = f[src, self._solutionType, iky] # solution vector
dA_dm_v = self.getADeriv(ky, u_src, v)
dRHS_dm_v = self.getRHSDeriv(ky, src, v)
du_dm_v = self.Ainv[iky] * ( - dA_dm_v + dRHS_dm_v )
for rx in src.rxList:
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_dm_v = df_dmFun(iky, src, du_dm_v, v, adjoint=False)
# Trapezoidal intergration
Jv1_temp = 1./np.pi*rx.evalDeriv(ky, src, self.mesh, f, df_dm_v)
if iky==0:
#First assigment
Jv[src, rx] = Jv1_temp*dky[iky]*np.cos(ky*y)
else:
Jv[src, rx] += Jv1_temp*dky[iky] /2.*np.cos(ky*y)
Jv[src, rx] += Jv0[src, rx]*dky[iky]/2.*np.cos(ky*y)
Jv0[src, rx] = Jv1_temp.copy()
return Utils.mkvc(Jv)
def Jtvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
# Ensure v is a data object.
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
Jtv = np.zeros(m.size, dtype=float)
# Assume y=0.
# This needs some thoughts to implement in general when src is dipole
dky = np.diff(self.kys)
dky = np.r_[dky[0], dky]
y = 0.
for src in self.survey.srcList:
for rx in src.rxList:
Jtv_temp1 = np.zeros(m.size, dtype=float)
Jtv_temp0 = np.zeros(m.size, dtype=float)
#TODO: this loop is pretty slow .. (Parellize)
for iky in range(self.nky):
u_src = f[src, self._solutionType, iky]
ky = self.kys[iky]
AT = self.getA(ky)
PTv = rx.evalDeriv(ky, src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_duT, df_dmT = df_duTFun(iky, src, None, PTv, adjoint=True)
ATinvdf_duT = self.Ainv[iky] * df_duT
dA_dmT = self.getADeriv(ky, u_src, ATinvdf_duT, adjoint=True)
dRHS_dmT = self.getRHSDeriv(ky, src, ATinvdf_duT, adjoint=True)
du_dmT = -dA_dmT + dRHS_dmT
Jtv_temp1 = 1./np.pi*(df_dmT + du_dmT).astype(float)
# Trapezoidal intergration
if iky==0:
#First assigment
Jtv += Jtv_temp1*dky[iky]*np.cos(ky*y)
else:
Jtv += Jtv_temp1*dky[iky]/2.*np.cos(ky*y)
Jtv += Jtv_temp0*dky[iky]/2.*np.cos(ky*y)
Jtv_temp0 = Jtv_temp1.copy()
return Utils.mkvc(Jtv)
def getSourceTerm(self, ky):
"""
takes concept of source and turns it into a matrix
"""
"""
Evaluates the sources, and puts them in matrix form
:rtype: (numpy.ndarray, numpy.ndarray)
:return: q (nC or nN, nSrc)
"""
Srcs = self.survey.srcList
if self._formulation is 'EB':
n = self.mesh.nN
# return NotImplementedError
elif self._formulation is 'HJ':
n = self.mesh.nC
q = np.zeros((n, len(Srcs)))
for i, src in enumerate(Srcs):
q[:,i] = src.eval(self)
return q
class Problem2D_CC(BaseDCProblem_2D):
_solutionType = 'phiSolution'
_formulation = 'HJ' # CC potentials means J is on faces
fieldsPair = Fields_ky_CC
def __init__(self, mesh, **kwargs):
BaseDCProblem_2D.__init__(self, mesh, **kwargs)
self.setBC()
def getA(self, ky):
"""
Make the A matrix for the cell centered DC resistivity problem
A = D MfRhoI G
"""
D = self.Div
G = self.Grad
vol = self.mesh.vol
MfRhoI = self.MfRhoI
# Get resistivity rho
rho = self.curModel.rho
A = D * MfRhoI * G + Utils.sdiag(ky**2*vol/rho)
return A
def getADeriv(self, ky, u, v, adjoint= False):
D = self.Div
G = self.Grad
vol = self.mesh.vol
MfRhoIDeriv = self.MfRhoIDeriv
rho = self.curModel.rho
if adjoint:
return(MfRhoIDeriv( G * u ).T) * ( D.T * v) + ky**2*Utils.sdiag(u.flatten()*vol*(-1./rho**2))*v
return D * ((MfRhoIDeriv( G * u )) * v) + ky**2*Utils.sdiag(u.flatten()*vol*(-1./rho**2))*v
def getRHS(self, ky):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm(ky)
return RHS
def getRHSDeriv(self, ky, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, ky, adjoint=adjoint)
# return qDeriv
return Zero()
def setBC(self):
if self.mesh.dim==3:
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
gBFzm = self.mesh.gridFz[fzm,:]
gBFzp = self.mesh.gridFz[fzp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
beta_zm, beta_zp = temp_zm, temp_zp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
elif self.mesh.dim==2:
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
V = self.Vol
self.Div = V * self.mesh.faceDiv
P_BC, B = self.mesh.getBCProjWF_simple()
M = B*self.mesh.aveCC2F
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
class Problem2D_N(BaseDCProblem_2D):
_solutionType = 'phiSolution'
_formulation = 'EB' # CC potentials means J is on faces
fieldsPair = Fields_ky_N
def __init__(self, mesh, **kwargs):
BaseDCProblem_2D.__init__(self, mesh, **kwargs)
# self.setBC()
@property
def MnSigma(self):
"""
Node inner product matrix for \\(\\sigma\\). Used in the E-B formulation
"""
# TODO: only works isotropic sigma
sigma = self.curModel.sigma
vol = self.mesh.vol
MnSigma = Utils.sdiag(self.mesh.aveN2CC.T*(Utils.sdiag(vol)*sigma))
return MnSigma
def MnSigmaDeriv(self, u):
"""
Derivative of MnSigma with respect to the model
"""
sigma = self.curModel.sigma
sigmaderiv = self.curModel.sigmaDeriv
vol = self.mesh.vol
return Utils.sdiag(u)*self.mesh.aveN2CC.T*Utils.sdiag(vol) * self.curModel.sigmaDeriv
def getA(self, ky):
"""
Make the A matrix for the cell centered DC resistivity problem
A = D MfRhoI G
"""
MeSigma = self.MeSigma
MnSigma = self.MnSigma
Grad = self.mesh.nodalGrad
# Get conductivity sigma
sigma = self.curModel.sigma
A = Grad.T * MeSigma * Grad + ky**2*MnSigma
# Handling Null space of A
A[0,0] = A[0,0] + 1.
return A
def getADeriv(self, ky, u, v, adjoint= False):
MeSigma = self.MeSigma
Grad = self.mesh.nodalGrad
sigma = self.curModel.sigma
vol = self.mesh.vol
if adjoint:
return self.MeSigmaDeriv(Grad*u).T * (Grad*v) + ky**2*self.MnSigmaDeriv(u).T*v
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v) + ky**2*self.MnSigmaDeriv(u)*v
def getRHS(self, ky):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm(ky)
return RHS
def getRHSDeriv(self, ky, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, ky, adjoint=adjoint)
# return qDeriv
return Zero()
+136
View File
@@ -0,0 +1,136 @@
import SimPEG
import numpy as np
from SimPEG.Utils import Zero, closestPoints
class BaseRx(SimPEG.Survey.BaseRx):
locs = None
rxType = None
knownRxTypes = {
'phi':['phi',None],
'ex':['e','x'],
'ey':['e','y'],
'ez':['e','z'],
'jx':['j','x'],
'jy':['j','y'],
'jz':['j','z'],
}
def __init__(self, locs, rxType, **kwargs):
SimPEG.Survey.BaseRx.__init__(self, locs, rxType, **kwargs)
@property
def projField(self):
"""Field Type projection (e.g. e b ...)"""
return self.knownRxTypes[self.rxType][0]
def projGLoc(self, f):
"""Grid Location projection (e.g. Ex Fy ...)"""
comp = self.knownRxTypes[self.rxType][1]
if comp is not None:
return f._GLoc(self.rxType) + comp
return f._GLoc(self.rxType)
def eval(self, src, mesh, f):
P = self.getP(mesh, self.projGLoc(f))
return P*f[src, self.projField]
def evalDeriv(self, src, mesh, f, v, adjoint=False):
P = self.getP(mesh, self.projGLoc(f))
if not adjoint:
return P*v
elif adjoint:
return P.T*v
# DC.Rx.Pole(locs)
class Pole(BaseRx):
def __init__(self, locs, rxType = 'phi', **kwargs):
BaseRx.__init__(self, locs, rxType)
# DC.Rx.Dipole(locsM, locsN)
class Dipole(BaseRx):
def __init__(self, locsM, locsN, rxType = 'phi', **kwargs):
assert locsM.shape == locsN.shape, 'locsM and locsN need to be the same size'
locs = [locsM, locsN]
# We may not need this ...
BaseRx.__init__(self, locs, rxType)
@property
def nD(self):
"""Number of data in the receiver."""
return self.locs[0].shape[0]
# Not sure why ...
# return int(self.locs[0].size / 2)
def getP(self, mesh, Gloc):
if mesh in self._Ps:
return self._Ps[mesh]
P0 = mesh.getInterpolationMat(self.locs[0], Gloc)
P1 = mesh.getInterpolationMat(self.locs[1], Gloc)
P = P0 - P1
if self.storeProjections:
self._Ps[mesh] = P
return P
class Dipole_ky(BaseRx):
def __init__(self, locsM, locsN, rxType = 'phi', **kwargs):
assert locsM.shape == locsN.shape, 'locsM and locsN need to be the same size'
locs = [locsM, locsN]
# We may not need this ...
BaseRx.__init__(self, locs, rxType)
@property
def nD(self):
"""Number of data in the receiver."""
return self.locs[0].shape[0]
# Not sure why ...
# return int(self.locs[0].size / 2)
def getP(self, mesh, Gloc):
if mesh in self._Ps:
return self._Ps[mesh]
P0 = mesh.getInterpolationMat(self.locs[0], Gloc)
P1 = mesh.getInterpolationMat(self.locs[1], Gloc)
P = P0 - P1
if self.storeProjections:
self._Ps[mesh] = P
return P
def eval(self, kys, src, mesh, f):
P = self.getP(mesh, self.projGLoc(f))
Pf = P*f[src, self.projField,:]
return self.IntTrapezoidal(kys, Pf, y=0.)
def evalDeriv(self, ky, src, mesh, f, v, adjoint=False):
P = self.getP(mesh, self.projGLoc(f))
if not adjoint:
return P*v
elif adjoint:
return P.T*v
def IntTrapezoidal(self, kys, Pf, y=0.):
phi = np.zeros(Pf.shape[0])
nky = kys.size
dky = np.diff(kys)
dky = np.r_[dky[0], dky]
phi0 = 1./np.pi*Pf[:,0]
for iky in range(nky):
phi1 = 1./np.pi*Pf[:,iky]
phi += phi1*dky[iky]/2.*np.cos(kys[iky]*y)
phi += phi0*dky[iky]/2.*np.cos(kys[iky]*y)
phi0 = phi1.copy()
return phi
+86
View File
@@ -0,0 +1,86 @@
import SimPEG
# from SimPEG.EM.Base import BaseEMSurvey
from SimPEG.Utils import Zero, closestPoints, mkvc
import numpy as np
class BaseSrc(SimPEG.Survey.BaseSrc):
current = 1.0
loc = None
def __init__(self, rxList, **kwargs):
SimPEG.Survey.BaseSrc.__init__(self, rxList, **kwargs)
def eval(self, prob):
raise NotImplementedError
def evalDeriv(self, prob):
return Zero()
class Dipole(BaseSrc):
def __init__(self, rxList, locA, locB, **kwargs):
assert locA.shape == locB.shape, 'Shape of locA and locB should be the same'
self.loc = [locA, locB]
BaseSrc.__init__(self, rxList, **kwargs)
def eval(self, prob):
if prob._formulation == 'HJ':
inds = closestPoints(prob.mesh, self.loc, gridLoc='CC')
q = np.zeros(prob.mesh.nC)
q[inds] = self.current * np.r_[1., -1.]
elif prob._formulation == 'EB':
qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense()
qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense()
q = self.current * mkvc(qa+qb)
return q
class Pole(BaseSrc):
def __init__(self, rxList, loc, **kwargs):
BaseSrc.__init__(self, rxList, loc=loc, **kwargs)
def eval(self, prob):
if prob._formulation == 'HJ':
inds = closestPoints(prob.mesh, self.loc)
q = np.zeros(prob.mesh.nC)
q[inds] = self.current * np.r_[1.]
elif prob._formulation == 'EB':
q = prob.mesh.getInterpolationMat(self.loc, locType='N').todense()
q = self.current * mkvc(q)
return q
# class Dipole_ky(BaseSrc):
# def __init__(self, rxList, locA, locB, **kwargs):
# assert locA.shape == locB.shape, 'Shape of locA and locB should be the same'
# self.loc = [locA[[0,2]], locB[[0,2]]]
# BaseSrc.__init__(self, rxList, **kwargs)
# def eval(self, prob):
# if prob._formulation == 'HJ':
# inds = closestPoints(prob.mesh, self.loc, gridLoc='CC')
# q = np.zeros(prob.mesh.nC)
# q[inds] = self.current * np.r_[1., -1.]
# elif prob._formulation == 'EB':
# qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense()
# qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense()
# q = self.current * mkvc(qa+qb)
# return q
# class Pole_ky(BaseSrc):
# def __init__(self, rxList, loc, **kwargs):
# BaseSrc.__init__(self, rxList, loc=loc, **kwargs)
# def eval(self, prob):
# if prob._formulation == 'HJ':
# inds = closestPoints(prob.mesh, self.loc[[0,2]])
# q = np.zeros(prob.mesh.nC)
# q[inds] = self.current * np.r_[1.]
# elif prob._formulation == 'EB':
# q = prob.mesh.getInterpolationMat(self.loc[[0,2]], locType='N').todense()
# q = self.current * mkvc(q)
# return q
+38
View File
@@ -0,0 +1,38 @@
import SimPEG
from SimPEG.EM.Base import BaseEMSurvey
from SimPEG import sp, Survey
from SimPEG.Utils import Zero, Identity
from RxDC import BaseRx
from SrcDC import BaseSrc
class Survey(BaseEMSurvey):
rxPair = BaseRx
srcPair = BaseSrc
def __init__(self, srcList, **kwargs):
self.srcList = srcList
BaseEMSurvey.__init__(self, srcList, **kwargs)
class Survey_ky(BaseEMSurvey):
rxPair = BaseRx
srcPair = BaseSrc
def __init__(self, srcList, **kwargs):
self.srcList = srcList
BaseEMSurvey.__init__(self, srcList, **kwargs)
def eval(self, f):
"""
Project fields to receiver locations
:param Fields u: fields object
:rtype: numpy.ndarray
:return: data
"""
data = SimPEG.Survey.Data(self)
kys = self.prob.kys
for src in self.srcList:
for rx in src.rxList:
data[src, rx] = rx.eval(kys, src, self.mesh, f)
return data
+38
View File
@@ -0,0 +1,38 @@
import numpy as np
def WennerSrcList(nElecs, aSpacing, in2D=False, plotIt=False):
import SimPEG.EM.Static.DC as DC
elocs = np.arange(0,aSpacing*nElecs,aSpacing)
elocs -= (nElecs*aSpacing - aSpacing)/2
space = 1
WENNER = np.zeros((0,),dtype=int)
for ii in range(nElecs):
for jj in range(nElecs):
test = np.r_[jj,jj+space,jj+space*2,jj+space*3]
if np.any(test >= nElecs):
break
WENNER = np.r_[WENNER, test]
space += 1
WENNER = WENNER.reshape((-1,4))
if plotIt:
for i, s in enumerate('rbkg'):
plt.plot(elocs[WENNER[:,i]],s+'.')
plt.show()
# Create sources and receivers
i = 0
if in2D:
getLoc = lambda ii, abmn: np.r_[elocs[WENNER[ii,abmn]],0]
else:
getLoc = lambda ii, abmn: np.r_[elocs[WENNER[ii,abmn]],0, 0]
srcList = []
for i in range(WENNER.shape[0]):
rx = DC.Rx.Dipole(getLoc(i,1).reshape([1,-1]),getLoc(i,2).reshape([1,-1]))
src = DC.Src.Dipole([rx], getLoc(i,0),getLoc(i,3))
srcList += [src]
return srcList
+8
View File
@@ -0,0 +1,8 @@
from ProblemDC import Problem3D_CC, Problem3D_N
from ProblemDC_2D import Problem2D_CC, Problem2D_N
from SurveyDC import Survey, Survey_ky
import SrcDC as Src #Pole
import RxDC as Rx
from FieldsDC import Fields_CC
from BoundaryUtils import getxBCyBC_CC
import Utils
+372
View File
@@ -0,0 +1,372 @@
from SimPEG import Problem, Utils, Maps, Mesh
from SimPEG.EM.Base import BaseEMProblem
from SimPEG.EM.Static.DC.FieldsDC import Fields, Fields_CC, Fields_N
from SimPEG.Utils import sdiag
import numpy as np
from SimPEG.Utils import Zero
from SimPEG.EM.Static.DC import getxBCyBC_CC
from SurveyIP import Survey
class IPPropMap(Maps.PropMap):
"""
Property Map for IP Problems. The electrical chargeability,
(\\(\\eta\\)) is the default inversion property
"""
eta = Maps.Property("Electrical Chargeability", defaultInvProp = True)
class BaseIPProblem(BaseEMProblem):
surveyPair = Survey
fieldsPair = Fields
PropMap = IPPropMap
Ainv = None
sigma = None
rho = None
f = None
Ainv = None
def fields(self, m):
self.curModel = m
if self.f is None:
self.f = self.fieldsPair(self.mesh, self.survey)
if self.Ainv == None:
A = self.getA()
self.Ainv = self.Solver(A, **self.solverOpts)
RHS = self.getRHS()
u = self.Ainv * RHS
Srcs = self.survey.srcList
self.f[Srcs, self._solutionType] = u
return self.f
def Jvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
Jv = self.dataPair(self.survey) #same size as the data
A = self.getA()
for src in self.survey.srcList:
u_src = f[src, self._solutionType] # solution vector
dA_dm_v = self.getADeriv(u_src, v)
dRHS_dm_v = self.getRHSDeriv(src, v)
du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v )
for rx in src.rxList:
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v)
# Conductivity (d u / d log sigma)
if self._formulation is 'EB':
return -Utils.mkvc(Jv)
# Conductivity (d u / d log rho)
if self._formulation is 'HJ':
return Utils.mkvc(Jv)
def Jtvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
# Ensure v is a data object.
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
Jtv = np.zeros(m.size)
AT = self.getA()
for src in self.survey.srcList:
u_src = f[src, self._solutionType]
for rx in src.rxList:
PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True)
ATinvdf_duT = self.Ainv * df_duT
dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True)
dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True)
du_dmT = -dA_dmT + dRHS_dmT
Jtv += (df_dmT + du_dmT).astype(float)
# Conductivity ((d u / d log sigma).T)
if self._formulation is 'EB':
return -Utils.mkvc(Jtv)
# Conductivity ((d u / d log rho).T)
if self._formulation is 'HJ':
return Utils.mkvc(Jtv)
def getSourceTerm(self):
"""
takes concept of source and turns it into a matrix
"""
"""
Evaluates the sources, and puts them in matrix form
:rtype: (numpy.ndarray, numpy.ndarray)
:return: q (nC or nN, nSrc)
"""
Srcs = self.survey.srcList
if self._formulation is 'EB':
n = self.mesh.nN
# return NotImplementedError
elif self._formulation is 'HJ':
n = self.mesh.nC
q = np.zeros((n, len(Srcs)))
for i, src in enumerate(Srcs):
q[:,i] = src.eval(self)
return q
@property
def deleteTheseOnModelUpdate(self):
toDelete = []
return toDelete
# assume log rho or log cond
@property
def MeSigma(self):
"""
Edge inner product matrix for \\(\\sigma\\). Used in the E-B formulation
"""
if getattr(self, '_MeSigma', None) is None:
self._MeSigma = self.mesh.getEdgeInnerProduct(self.sigma)
return self._MeSigma
@property
def MfRhoI(self):
"""
Inverse of :code:`MfRho`
"""
if getattr(self, '_MfRhoI', None) is None:
self._MfRhoI = self.mesh.getFaceInnerProduct(self.rho, invMat=True)
return self._MfRhoI
def MfRhoIDeriv(self,u):
"""
Derivative of :code:`MfRhoI` with respect to the model.
"""
dMfRhoI_dI = -self.MfRhoI**2
dMf_drho = self.mesh.getFaceInnerProductDeriv(self.rho)(u)
drho_dlogrho = Utils.sdiag(self.rho)*self.curModel.etaDeriv
return dMfRhoI_dI * ( dMf_drho * ( drho_dlogrho))
# TODO: This should take a vector
def MeSigmaDeriv(self, u):
"""
Derivative of MeSigma with respect to the model
"""
dsigma_dlogsigma = Utils.sdiag(self.sigma)*self.curModel.etaDeriv
return self.mesh.getEdgeInnerProductDeriv(self.sigma)(u) * dsigma_dlogsigma
class Problem3D_CC(BaseIPProblem):
_solutionType = 'phiSolution'
_formulation = 'HJ' # CC potentials means J is on faces
fieldsPair = Fields_CC
def __init__(self, mesh, **kwargs):
BaseIPProblem.__init__(self, mesh, **kwargs)
self.setBC()
def getA(self):
"""
Make the A matrix for the cell centered DC resistivity problem
A = D MfRhoI G
"""
D = self.Div
G = self.Grad
MfRhoI = self.MfRhoI
A = D * MfRhoI * G
# I think we should deprecate this for DC problem.
# if self._makeASymmetric is True:
# return V.T * A
return A
def getADeriv(self, u, v, adjoint= False):
D = self.Div
G = self.Grad
MfRhoIDeriv = self.MfRhoIDeriv
if adjoint:
# if self._makeASymmetric is True:
# v = V * v
return(MfRhoIDeriv( G * u ).T) * ( D.T * v)
# I think we should deprecate this for DC problem.
# if self._makeASymmetric is True:
# return V.T * ( D * ( MfRhoIDeriv( D.T * ( V * u ) ) * v ) )
return D * (MfRhoIDeriv( G * u ) * v)
def getRHS(self):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm()
# I think we should deprecate this for DC problem.
# if self._makeASymmetric is True:
# return self.Vol.T * RHS
return RHS
def getRHSDeriv(self, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
# return qDeriv
return Zero()
def setBC(self):
if self.mesh.dim==3:
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
gBFzm = self.mesh.gridFz[fzm,:]
gBFzp = self.mesh.gridFz[fzp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
beta_zm, beta_zp = temp_zm, temp_zp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
elif self.mesh.dim==2:
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
V = self.Vol
self.Div = V * self.mesh.faceDiv
P_BC, B = self.mesh.getBCProjWF_simple()
M = B*self.mesh.aveCC2F
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
class Problem3D_N(BaseIPProblem):
_solutionType = 'phiSolution'
_formulation = 'EB' # N potentials means B is on faces
fieldsPair = Fields_N
def __init__(self, mesh, **kwargs):
BaseIPProblem.__init__(self, mesh, **kwargs)
def getA(self):
"""
Make the A matrix for the cell centered DC resistivity problem
A = G.T MeSigma G
"""
MeSigma = self.MeSigma
Grad = self.mesh.nodalGrad
A = Grad.T * MeSigma * Grad
# Handling Null space of A
A[0,0] = A[0,0] + 1.
return A
def getADeriv(self, u, v, adjoint=False):
"""
Product of the derivative of our system matrix with respect to the model and a vector
"""
MeSigma = self.MeSigma
Grad = self.mesh.nodalGrad
if not adjoint:
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v)
elif adjoint:
return self.MeSigmaDeriv(Grad*u).T * (Grad*v)
def getRHS(self):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm()
return RHS
def getRHSDeriv(self, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
# return qDeriv
return Zero()
if __name__ == '__main__':
cs = 12.5
hx = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
hy = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
hz = [(cs,7, -1.3),(cs,20)]
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
sigma = np.ones(mesh.nC)
prob = BaseIPProblem(mesh, sigma=sigma)
+23
View File
@@ -0,0 +1,23 @@
import SimPEG
from SimPEG.EM.Base import BaseEMSurvey
from SimPEG import sp, Survey
from SimPEG.Utils import Zero, Identity
from SimPEG.EM.Static.DC.SrcDC import BaseSrc
from SimPEG.EM.Static.DC.RxDC import BaseRx
class Survey(BaseEMSurvey):
rxPair = BaseRx
srcPair = BaseSrc
def __init__(self, srcList, **kwargs):
self.srcList = srcList
BaseEMSurvey.__init__(self, srcList, **kwargs)
def dpred(self, m, f=None):
"""
Predicted data.
.. math::
d_\\text{pred} = Pf(m)
"""
return self.prob.Jvec(m, m, f=f)
+2
View File
@@ -0,0 +1,2 @@
from ProblemIP import Problem3D_CC, Problem3D_N
from SurveyIP import Survey
+445
View File
@@ -0,0 +1,445 @@
from SimPEG import Problem, Utils, Maps, Mesh
from SimPEG.EM.Base import BaseEMProblem
from SimPEG.EM.Static.DC.FieldsDC import Fields, Fields_CC, Fields_N
from SimPEG.Utils import sdiag
import numpy as np
from SimPEG.Utils import Zero
from SimPEG.EM.Static.DC import getxBCyBC_CC
from SurveySIP import Survey, Data
class ColeColePropMap(Maps.PropMap):
"""
Property Map for EM Problems. The electrical conductivity (\\(\\sigma\\)) is the default inversion property, and the default value of the magnetic permeability is that of free space (\\(\\mu = 4\\pi\\times 10^{-7} \\) H/m)
"""
eta = Maps.Property("Electrical Conductivity", defaultInvProp=True)
tau = Maps.Property("Electrical Conductivity", defaultVal=0.1, propertyLink=('taui', Maps.ReciprocalMap))
taui = Maps.Property("Electrical Conductivity", defaultVal=1., propertyLink=('tau', Maps.ReciprocalMap))
c = Maps.Property("Electrical Conductivity", defaultVal=1.)
class BaseSIPProblem(BaseEMProblem):
surveyPair = Survey
fieldsPair = Fields
dataPair = Data
PropMap = ColeColePropMap
Ainv = None
sigma = None
rho = None
f = None
Ainv = None
def DebyeTime(self, t):
peta = self.curModel.eta*np.exp(-self.curModel.taui*t)
return peta
def EtaDeriv(self, t, v, adjoint=False):
v = np.array(v, dtype=float)
if adjoint:
return self.curModel.etaDeriv.T * (np.exp(-self.curModel.taui*t)*v)
else:
return np.exp(-self.curModel.taui*t) * (self.curModel.etaDeriv*v)
def TauiDeriv(self, t, v, adjoint=False):
v = np.array(v, dtype=float)
if adjoint:
return -self.curModel.tauiDeriv.T * (self.curModel.eta*t*np.exp(-self.curModel.taui*t)*v)
else:
return -self.curModel.eta*t*np.exp(-self.curModel.taui*t) * (self.curModel.tauiDeriv*v)
def fields(self, m):
self.curModel = m
if self.f is None:
self.f = self.fieldsPair(self.mesh, self.survey)
if self.Ainv == None:
A = self.getA()
self.Ainv = self.Solver(A, **self.solverOpts)
RHS = self.getRHS()
u = self.Ainv * RHS
Srcs = self.survey.srcList
self.f[Srcs, self._solutionType] = u
return self.f
def forward(self, m, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
Jv = self.dataPair(self.survey) #same size as the data
# A = self.getA()
JvAll = []
for tind in range(len(self.survey.times)):
#Pseudo-chareability
t = self.survey.times[tind]
v = self.DebyeTime(t)
for src in self.survey.srcList:
u_src = f[src, self._solutionType] # solution vector
dA_dm_v = self.getADeriv(u_src, v)
dRHS_dm_v = self.getRHSDeriv(src, v)
du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v )
for rx in src.rxList:
timeindex = rx.getTimeP(self.survey.times)
if timeindex[tind]:
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False)
Jv[src, rx, t] = rx.evalDeriv(src, self.mesh, f, df_dm_v)
# Conductivity (d u / d log sigma)
if self._formulation is 'EB':
return -Utils.mkvc(Jv)
# Resistivity (d u / d log rho)
if self._formulation is 'HJ':
return Utils.mkvc(Jv)
def Jvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
Jv = self.dataPair(self.survey) #same size as the data
# A = self.getA()
JvAll = []
#Assume only eta and tau (eta first then tau)
# v = [2*Mx1]
v = v.reshape((int(v.size/2), 2), order='F')
for tind in range(len(self.survey.times)):
t = self.survey.times[tind]
v0 = self.EtaDeriv(t, v[:,0])
v1 = self.TauiDeriv(t, v[:,1])
for src in self.survey.srcList:
u_src = f[src, self._solutionType] # solution vector
dA_dm_v0 = self.getADeriv(u_src, v0)
dRHS_dm_v0 = self.getRHSDeriv(src, v0)
du_dm_v0 = self.Ainv * ( - dA_dm_v0 + dRHS_dm_v0 )
dA_dm_v1 = self.getADeriv(u_src, v1)
dRHS_dm_v1 = self.getRHSDeriv(src, v1)
du_dm_v1 = self.Ainv * ( - dA_dm_v1 + dRHS_dm_v1 )
for rx in src.rxList:
timeindex = rx.getTimeP(self.survey.times)
if timeindex[tind]:
df_dmFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_dm_v0 = df_dmFun(src, du_dm_v0, v0, adjoint=False)
df_dm_v1 = df_dmFun(src, du_dm_v1, v1, adjoint=False)
Jv[src, rx, t] = rx.evalDeriv(src, self.mesh, f, df_dm_v0)
Jv[src, rx, t] += rx.evalDeriv(src, self.mesh, f, df_dm_v1)
# Conductivity (d u / d log sigma)
if self._formulation is 'EB':
return -Jv.tovec()
# Resistivity (d u / d log rho)
if self._formulation is 'HJ':
return Jv.tovec()
def Jtvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
self.curModel = m
# Ensure v is a data object.
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
Jtv= np.zeros(m.size)
for tind in range(len(self.survey.times)):
t = self.survey.times[tind]
for src in self.survey.srcList:
u_src = f[src, self._solutionType]
for rx in src.rxList:
timeindex = rx.getTimeP(self.survey.times)
if timeindex[tind]:
PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx, t], adjoint=True) # wrt f, need possibility wrt m
df_duTFun = getattr(f, '_%sDeriv'%rx.projField, None)
df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True)
ATinvdf_duT = self.Ainv * df_duT
dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True)
dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True)
du_dmT = -dA_dmT + dRHS_dmT
Jtv += np.r_[self.EtaDeriv(self.survey.times[tind], du_dmT, adjoint=True), self.TauiDeriv(self.survey.times[tind], du_dmT, adjoint=True)]
# Conductivity ((d u / d log sigma).T)
if self._formulation is 'EB':
return -Jtv
# Conductivity ((d u / d log rho).T)
if self._formulation is 'HJ':
return Jtv
def getSourceTerm(self):
"""
takes concept of source and turns it into a matrix
"""
"""
Evaluates the sources, and puts them in matrix form
:rtype: (numpy.ndarray, numpy.ndarray)
:return: q (nC or nN, nSrc)
"""
Srcs = self.survey.srcList
if self._formulation is 'EB':
n = self.mesh.nN
# return NotImplementedError
elif self._formulation is 'HJ':
n = self.mesh.nC
q = np.zeros((n, len(Srcs)))
for i, src in enumerate(Srcs):
q[:,i] = src.eval(self)
return q
@property
def deleteTheseOnModelUpdate(self):
toDelete = []
return toDelete
# assume log rho or log cond
@property
def MeSigma(self):
"""
Edge inner product matrix for \\(\\sigma\\). Used in the E-B formulation
"""
if getattr(self, '_MeSigma', None) is None:
self._MeSigma = self.mesh.getEdgeInnerProduct(self.sigma)
return self._MeSigma
@property
def MfRhoI(self):
"""
Inverse of :code:`MfRho`
"""
if getattr(self, '_MfRhoI', None) is None:
self._MfRhoI = self.mesh.getFaceInnerProduct(self.rho, invMat=True)
return self._MfRhoI
def MfRhoIDeriv(self,u):
"""
Derivative of :code:`MfRhoI` with respect to the model.
"""
dMfRhoI_dI = -self.MfRhoI**2
dMf_drho = self.mesh.getFaceInnerProductDeriv(self.rho)(u)
drho_dlogrho = Utils.sdiag(self.rho)
return dMfRhoI_dI * ( dMf_drho * ( drho_dlogrho))
# TODO: This should take a vector
def MeSigmaDeriv(self, u):
"""
Derivative of MeSigma with respect to the model
"""
dsigma_dlogsigma = Utils.sdiag(self.sigma)
return self.mesh.getEdgeInnerProductDeriv(self.sigma)(u) * dsigma_dlogsigma
class Problem3D_CC(BaseSIPProblem):
_solutionType = 'phiSolution'
_formulation = 'HJ' # CC potentials means J is on faces
fieldsPair = Fields_CC
def __init__(self, mesh, **kwargs):
BaseSIPProblem.__init__(self, mesh, **kwargs)
self.setBC()
def getA(self):
"""
Make the A matrix for the cell centered DC resistivity problem
A = D MfRhoI G
"""
D = self.Div
G = self.Grad
# TODO: this won't work for full anisotropy
MfRhoI = self.MfRhoI
A = D * MfRhoI * G
# I think we should deprecate this for DC problem.
# if self._makeASymmetric is True:
# return V.T * A
return A
def getADeriv(self, u, v, adjoint= False):
D = self.Div
G = self.Grad
MfRhoIDeriv = self.MfRhoIDeriv
if adjoint:
# if self._makeASymmetric is True:
# v = V * v
return(MfRhoIDeriv( G * u ).T) * ( D.T * v)
# I think we should deprecate this for DC problem.
# if self._makeASymmetric is True:
# return V.T * ( D * ( MfRhoIDeriv( D.T * ( V * u ) ) * v ) )
return D * (MfRhoIDeriv( G * u ) * v)
def getRHS(self):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm()
# I think we should deprecate this for DC problem.
# if self._makeASymmetric is True:
# return self.Vol.T * RHS
return RHS
def getRHSDeriv(self, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
# return qDeriv
return Zero()
def setBC(self):
if self.mesh.dim==3:
fxm,fxp,fym,fyp,fzm,fzp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
gBFzm = self.mesh.gridFz[fzm,:]
gBFzp = self.mesh.gridFz[fzp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
temp_zm, temp_zp = np.ones_like(gBFzm[:,2]), np.ones_like(gBFzp[:,2])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
alpha_zm, alpha_zp = temp_zm*0., temp_zp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
beta_zm, beta_zp = temp_zm, temp_zp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
gamma_zm, gamma_zp = temp_zm*0., temp_zp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp, alpha_zm, alpha_zp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp, beta_zm, beta_zp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp, gamma_zm, gamma_zp]
elif self.mesh.dim==2:
fxm,fxp,fym,fyp = self.mesh.faceBoundaryInd
gBFxm = self.mesh.gridFx[fxm,:]
gBFxp = self.mesh.gridFx[fxp,:]
gBFym = self.mesh.gridFy[fym,:]
gBFyp = self.mesh.gridFy[fyp,:]
# Setup Mixed B.C (alpha, beta, gamma)
temp_xm, temp_xp = np.ones_like(gBFxm[:,0]), np.ones_like(gBFxp[:,0])
temp_ym, temp_yp = np.ones_like(gBFym[:,1]), np.ones_like(gBFyp[:,1])
alpha_xm, alpha_xp = temp_xm*0., temp_xp*0.
alpha_ym, alpha_yp = temp_ym*0., temp_yp*0.
beta_xm, beta_xp = temp_xm, temp_xp
beta_ym, beta_yp = temp_ym, temp_yp
gamma_xm, gamma_xp = temp_xm*0., temp_xp*0.
gamma_ym, gamma_yp = temp_ym*0., temp_yp*0.
alpha = [alpha_xm, alpha_xp, alpha_ym, alpha_yp]
beta = [beta_xm, beta_xp, beta_ym, beta_yp]
gamma = [gamma_xm, gamma_xp, gamma_ym, gamma_yp]
x_BC, y_BC = getxBCyBC_CC(self.mesh, alpha, beta, gamma)
V = self.Vol
self.Div = V * self.mesh.faceDiv
P_BC, B = self.mesh.getBCProjWF_simple()
M = B*self.mesh.aveCC2F
self.Grad = self.Div.T - P_BC*Utils.sdiag(y_BC)*M
class Problem3D_N(BaseSIPProblem):
_solutionType = 'phiSolution'
_formulation = 'EB' # N potentials means B is on faces
fieldsPair = Fields_N
def __init__(self, mesh, **kwargs):
BaseSIPProblem.__init__(self, mesh, **kwargs)
def getA(self):
"""
Make the A matrix for the cell centered DC resistivity problem
A = G.T MeSigma G
"""
# TODO: this won't work for full anisotropy
MeSigma = self.MeSigma
Grad = self.mesh.nodalGrad
A = Grad.T * MeSigma * Grad
# Handling Null space of A
A[0,0] = A[0,0] + 1.
return A
def getADeriv(self, u, v, adjoint=False):
"""
Product of the derivative of our system matrix with respect to the model and a vector
"""
MeSigma = self.MeSigma
Grad = self.mesh.nodalGrad
if not adjoint:
return Grad.T*(self.MeSigmaDeriv(Grad*u)*v)
elif adjoint:
return self.MeSigmaDeriv(Grad*u).T * (Grad*v)
def getRHS(self):
"""
RHS for the DC problem
q
"""
RHS = self.getSourceTerm()
return RHS
def getRHSDeriv(self, src, v, adjoint=False):
"""
Derivative of the right hand side with respect to the model
"""
# TODO: add qDeriv for RHS depending on m
# qDeriv = src.evalDeriv(self, adjoint=adjoint)
# return qDeriv
return Zero()
if __name__ == '__main__':
cs = 12.5
hx = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
hy = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
hz = [(cs,7, -1.3),(cs,20)]
mesh = Mesh.TensorMesh([hx, hy, hz],x0="CCN")
sigma = np.ones(mesh.nC)
prob = BaseSIPProblem(mesh, sigma=sigma)
+204
View File
@@ -0,0 +1,204 @@
from SimPEG import Utils, Maps, Mesh, sp, np
from SimPEG.Regularization import BaseRegularization, Simple
class MultiRegularization(Simple):
"""
**MultiRegularization Class**
This is used to regularize the model space
having multiple models [m1, m2, m3, ...] ::
reg = Regularization(mesh)
"""
nModels = None # Number of models
ratios = None # Ratio for different models
crossgrad = False # Use cross gradient or not
betacross = 1.
wx = []
wy = []
wz = []
def __init__(self, mesh, mapping=None, indActive=None, **kwargs):
BaseRegularization.__init__(self, mesh, mapping=mapping, indActive=indActive, **kwargs)
if self.nModels == None:
raise Exception("Put nModels as a initial input!")
if self.ratios == None:
self.ratios = [1. for imodel in range(self.nModels)]
@property
def Wsmall(self):
"""Regularization matrix Wsmall"""
if getattr(self,'_Wsmall', None) is None:
vecs = []
for imodel in range(self.nModels):
vecs.append((self.regmesh.vol*self.alpha_s*self.wght*self.ratios[imodel])**0.5)
self._Wsmall = Utils.sdiag(np.hstack(vecs))
return self._Wsmall
@property
def Wx(self):
"""Regularization matrix Wx"""
if getattr(self, '_Wx', None) is None:
mats = []
for imodel in range(self.nModels):
self.wx.append(Utils.sdiag((self.regmesh.aveCC2Fx * self.regmesh.vol*self.alpha_x*self.ratios[imodel]*(self.regmesh.aveCC2Fx*self.wght))**0.5))
mats.append(self.wx[imodel]*self.regmesh.cellDiffxStencil)
self._Wx = sp.block_diag(mats)
return self._Wx
@property
def Wy(self):
"""Regularization matrix Wy"""
if getattr(self, '_Wy', None) is None:
mats = []
for imodel in range(self.nModels):
self.wy.append(Utils.sdiag((self.regmesh.aveCC2Fy * self.regmesh.vol*self.alpha_y*self.ratios[imodel]*(self.regmesh.aveCC2Fy*self.wght))**0.5))
mats.append(self.wy[imodel]*self.regmesh.cellDiffyStencil)
self._Wy = sp.block_diag(mats)
return self._Wy
@property
def Wz(self):
"""Regularization matrix Wz"""
if getattr(self, '_Wz', None) is None:
mats = []
for imodel in range(self.nModels):
self.wz.append(Utils.sdiag((self.regmesh.aveCC2Fz * self.regmesh.vol*self.alpha_z*self.ratios[imodel]*(self.regmesh.aveCC2Fz*self.wght))**0.5))
mats.append(self.wz[imodel]*self.regmesh.cellDiffzStencil)
self._Wz = sp.block_diag(mats)
return self._Wz
@property
def Wsmooth(self):
"""Full smoothness regularization matrix W"""
if getattr(self, '_Wsmooth', None) is None:
wlist = (self.Wx,)
if self.regmesh.dim > 1:
wlist += (self.Wy,)
if self.regmesh.dim > 2:
wlist += (self.Wz,)
self._Wsmooth = sp.vstack(wlist)
return self._Wsmooth
@property
def W(self):
"""Full regularization matrix W"""
if getattr(self, '_W', None) is None:
wlist = (self.Wsmall, self.Wsmooth)
self._W = sp.vstack(wlist)
return self._W
@Utils.timeIt
def eval(self, m):
return self._evalSmall(m) + self._evalSmooth(m)
@Utils.timeIt
def _evalSmall(self, m):
r = self.Wsmall * ( self.mapping * (m - self.mref) )
return 0.5 * r.dot(r)
@Utils.timeIt
def _evalSmooth(self, m):
if self.mrefInSmooth == True:
r = self.Wsmooth * ( self.mapping * (m - self.mref) )
elif self.mrefInSmooth == False:
r = self.Wsmooth * ( self.mapping * m)
return 0.5 * r.dot(r)
def cross(a,b):
ax, ay, az = a[0], a[1], a[2]
bx, by, bz = b[0], b[1], b[2]
cx = ay*bz - az*by
cy = az*bx - ax*bz
cz = ax*by - ay*bx
return [cx, cy, cz]
# TODO: Implement Cross Gradients..
@Utils.timeIt
def _evalCross(self, m):
if self.crossgrad == False:
return 0.
elif self.crossgrad == True:
M = (self.mapping * m).reshape((self.regmesh.nC, self.nModels), order="F")
ax = self.regmesh.aveFx2CC*self.regmesh.wx[0]*M[:,0]
ay = self.regmesh.aveFy2CC*self.regmesh.wy[0]*M[:,0]
az = self.regmesh.aveFz2CC*self.regmesh.wz[0]*M[:,0]
bx = self.regmesh.aveFx2CC*self.regmesh.wx[1]*M[:,1]
by = self.regmesh.aveFy2CC*self.regmesh.wy[1]*M[:,1]
bz = self.regmesh.aveFz2CC*self.regmesh.wz[1]*M[:,1]
#ab
out_ab = cross([ax, ay, az], [bx, by, bz])
r = np.r_[out_ab[0], out_ab[1], out_ab[2]]*np.sqrt(self.betacross)
if self.nModels == 3:
cx = self.regmesh.aveFx2CC*self.regmesh.wx[1]*M[:,1]
cy = self.regmesh.aveFy2CC*self.regmesh.wy[1]*M[:,1]
cz = self.regmesh.aveFz2CC*self.regmesh.wz[1]*M[:,1]
#ac
out_ac = cross([ax, ay, az], [cx, cy, cz])
#bc
out_bc = cross([bx, by, bz], [cx, cy, cz])
r = np.r_[r, np.hstack(out_ac)*np.sqrt(self.betacross), np.hstack(out_bc)*np.sqrt(self.betacross)]
return 0.5 * r.dot(r)
@Utils.timeIt
def evalDeriv(self, m):
"""
The regularization is:
.. math::
R(m) = \\frac{1}{2}\mathbf{(m-m_\\text{ref})^\\top W^\\top W(m-m_\\text{ref})}
So the derivative is straight forward:
.. math::
R(m) = \mathbf{W^\\top W (m-m_\\text{ref})}
"""
deriv = self._evalSmallDeriv(m) + self._evalSmoothDeriv(m)
if self.crossgrad==True:
deriv += self._evalCrossDeriv(m)
return deriv
@Utils.timeIt
def _evalCrossDeriv(self,m):
r = self.Wsmall * ( self.mapping * (m - self.mref) )
return r.T * ( self.Wsmall * self.mapping.deriv(m - self.mref) )
@Utils.timeIt
def eval2Deriv(self, m, v=None):
"""
Second derivative
:param numpy.array m: geophysical model
:param numpy.array v: vector to multiply
:rtype: scipy.sparse.csr_matrix or numpy.ndarray
:return: WtW or WtW*v
The regularization is:
.. math::
R(m) = \\frac{1}{2}\mathbf{(m-m_\\text{ref})^\\top W^\\top W(m-m_\\text{ref})}
So the second derivative is straight forward:
.. math::
R(m) = \mathbf{W^\\top W}
"""
mD = self.mapping.deriv(m - self.mref)
if v is None:
return mD.T * self.W.T * self.W * mD
return mD.T * ( self.W.T * ( self.W * ( mD * v) ) )
+88
View File
@@ -0,0 +1,88 @@
import SimPEG
import numpy as np
from SimPEG.Utils import Zero, closestPoints
class BaseRx(SimPEG.Survey.BaseTimeRx):
locs = None
rxType = None
knownRxTypes = {
'phi':['phi',None],
'ex':['e','x'],
'ey':['e','y'],
'ez':['e','z'],
'jx':['j','x'],
'jy':['j','y'],
'jz':['j','z'],
}
def __init__(self, locs, times, rxType, **kwargs):
SimPEG.Survey.BaseTimeRx.__init__(self, locs, times, rxType, **kwargs)
@property
def projField(self):
"""Field Type projection (e.g. e b ...)"""
return self.knownRxTypes[self.rxType][0]
def projGLoc(self, f):
"""Grid Location projection (e.g. Ex Fy ...)"""
comp = self.knownRxTypes[self.rxType][1]
if comp is not None:
return f._GLoc(self.rxType) + comp
return f._GLoc(self.rxType)
def getTimeP(self, timesall):
"""
Returns the time projection matrix.
.. note::
This is not stored in memory, but is created on demand.
"""
time_inds = np.in1d(timesall, self.times)
return time_inds
def evalDeriv(self, src, mesh, f, v, adjoint=False):
P = self.getP(mesh, self.projGLoc(f))
if not adjoint:
return P*v
elif adjoint:
return P.T*v
# DC.Rx.Dipole(locs)
class Dipole(BaseRx):
def __init__(self, locsM, locsN, times, rxType = 'phi', **kwargs):
assert locsM.shape == locsN.shape, 'locsM and locsN need to be the same size'
locs = [locsM, locsN]
# We may not need this ...
BaseRx.__init__(self, locs, times, rxType)
@property
def nD(self):
"""Number of data in the receiver."""
# return self.locs[0].shape[0] * len(self.times)
return self.locs[0].shape[0]
@property
def nRx(self):
"""Number of data in the receiver."""
return self.locs[0].shape[0]
# Not sure why ...
# return int(self.locs[0].size / 2)
def getP(self, mesh, Gloc):
if mesh in self._Ps:
return self._Ps[mesh]
P0 = mesh.getInterpolationMat(self.locs[0], Gloc)
P1 = mesh.getInterpolationMat(self.locs[1], Gloc)
P = P0 - P1
if self.storeProjections:
self._Ps[mesh] = P
return P
+64
View File
@@ -0,0 +1,64 @@
import SimPEG
# from SimPEG.EM.Base import BaseEMSurvey
from SimPEG.Utils import Zero, closestPoints, mkvc
import numpy as np
class BaseSrc(SimPEG.Survey.BaseSrc):
current = 1.0
loc = None
def __init__(self, rxList, **kwargs):
SimPEG.Survey.BaseSrc.__init__(self, rxList, **kwargs)
def eval(self, prob):
raise NotImplementedError
def evalDeriv(self, prob):
return Zero()
@property
def nD(self):
"""Number of data"""
return self.vnD.sum()
@property
def vnD(self):
"""Vector number of data"""
return np.array([rx.nD*len(rx.times) for rx in self.rxList])
class Dipole(BaseSrc):
def __init__(self, rxList, locA, locB, **kwargs):
assert locA.shape == locB.shape, 'Shape of locA and locB should be the same'
self.loc = [locA, locB]
BaseSrc.__init__(self, rxList, **kwargs)
def eval(self, prob):
if prob._formulation == 'HJ':
inds = closestPoints(prob.mesh, self.loc, gridLoc='CC')
q = np.zeros(prob.mesh.nC)
q[inds] = self.current * np.r_[1., -1.]
elif prob._formulation == 'EB':
qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense()
qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense()
q = self.current * mkvc(qa+qb)
return q
class Pole(BaseSrc):
def __init__(self, rxList, loc, **kwargs):
BaseSrc.__init__(self, rxList, loc=loc, **kwargs)
def eval(self, prob):
if prob._formulation == 'HJ':
inds = closestPoints(prob.mesh, self.loc)
q = np.zeros(prob.mesh.nC)
q[inds] = self.current * np.r_[1.]
elif prob._formulation == 'EB':
q = prob.mesh.getInterpolationMat(self.loc, locType='N').todense()
q = self.current * mkvc(q)
return q
+102
View File
@@ -0,0 +1,102 @@
import SimPEG
from SimPEG.EM.Base import BaseEMSurvey
from SimPEG import np, sp, Survey, Utils
from SimPEG.Utils import Zero, Identity
from SimPEG.EM.Static.SIP.SrcSIP import BaseSrc
from SimPEG.EM.Static.SIP.RxSIP import BaseRx
import uuid
class Survey(BaseEMSurvey):
rxPair = BaseRx
srcPair = BaseSrc
times = None
def __init__(self, srcList, **kwargs):
self.srcList = srcList
BaseEMSurvey.__init__(self, srcList, **kwargs)
self.getUniqueTimes()
def getUniqueTimes(self):
time_rx = []
for src in self.srcList:
for rx in src.rxList:
time_rx.append(rx.times)
self.times = np.unique(np.hstack(time_rx))
def dpred(self, m, f=None):
"""
Predicted data.
.. math::
d_\\text{pred} = Pf(m)
"""
return self.prob.forward(m, f=f)
class Data(SimPEG.Survey.Data):
"""Fancy data storage by Src and Rx"""
def __init__(self, survey, v=None):
self.uid = str(uuid.uuid4())
self.survey = survey
self._dataDict = {}
for src in self.survey.srcList:
self._dataDict[src] = {}
for rx in src.rxList:
self._dataDict[src][rx] = {}
if v is not None:
self.fromvec(v)
def _ensureCorrectKey(self, key):
if type(key) is tuple:
if len(key) is not 3:
raise KeyError('Key must be [Src, Rx, tInd]')
if key[0] not in self.survey.srcList:
raise KeyError('Src Key must be a source in the survey.')
if key[1] not in key[0].rxList:
raise KeyError('Rx Key must be a receiver for the source.')
return key
elif isinstance(key, self.survey.srcPair):
if key not in self.survey.srcList:
raise KeyError('Key must be a source in the survey.')
return key, None, None
else:
raise KeyError('Key must be [Src] or [Src,Rx] or [Src, Rx, tInd]')
def __setitem__(self, key, value):
src, rx, t = self._ensureCorrectKey(key)
assert rx is not None, 'set data using [Src, Rx]'
assert isinstance(value, np.ndarray), 'value must by ndarray'
assert value.size == rx.nD, "value must have the same number of data as the source."
self._dataDict[src][rx][t] = Utils.mkvc(value)
def __getitem__(self, key):
src, rx, t = self._ensureCorrectKey(key)
if rx is not None:
if rx not in self._dataDict[src]:
raise Exception('Data for receiver has not yet been set.')
return self._dataDict[src][rx][t]
return np.concatenate([self[src,rx, t] for rx in src.rxList])
def tovec(self):
val = []
for src in self.survey.srcList:
for rx in src.rxList:
for t in rx.times:
val.append(self[src, rx, t])
return np.concatenate(val)
def fromvec(self, v):
v = Utils.mkvc(v)
assert v.size == self.survey.nD, 'v must have the correct number of data.'
indBot, indTop = 0, 0
for src in self.survey.srcList:
for rx in src.rxList:
for t in rx.times:
indTop += rx.nRx
self[src, rx, t] = v[indBot:indTop]
indBot += rx.nRx
+5
View File
@@ -0,0 +1,5 @@
from ProblemSIP import Problem3D_CC, Problem3D_N
from SurveySIP import Survey, Data
import SrcSIP as Src #Pole
import RxSIP as Rx
from Regularization import MultiRegularization
+317
View File
@@ -0,0 +1,317 @@
from SimPEG import np
from SimPEG.EM.Static import DC, IP
def plot_pseudoSection(DCsurvey, axs, stype='dpdp', dtype="appc", clim=None):
"""
Read list of 2D tx-rx location and plot a speudo-section of apparent
resistivity.
Assumes flat topo for now...
Input:
:param d2D, z0
:switch stype -> Either 'pdp' (pole-dipole) | 'dpdp' (dipole-dipole)
:switch dtype=-> Either 'appr' (app. res) | 'appc' (app. con) | 'volt' (potential)
Output:
:figure scatter plot overlayed on image
Edited Feb 17th, 2016
@author: dominiquef
"""
from SimPEG import np
from scipy.interpolate import griddata
import pylab as plt
# Set depth to 0 for now
z0 = 0.
# Pre-allocate
midx = []
midz = []
rho = []
LEG = []
count = 0 # Counter for data
for ii in range(DCsurvey.nSrc):
Tx = DCsurvey.srcList[ii].loc
Rx = DCsurvey.srcList[ii].rxList[0].locs
nD = DCsurvey.srcList[ii].rxList[0].nD
data = DCsurvey.dobs[count:count+nD]
count += nD
# Get distances between each poles A-B-M-N
if stype == 'pdp':
MA = np.abs(Tx[0] - Rx[0][:,0])
NA = np.abs(Tx[0] - Rx[1][:,0])
MN = np.abs(Rx[1][:,0] - Rx[0][:,0])
# Create mid-point location
Cmid = Tx[0]
Pmid = (Rx[0][:,0] + Rx[1][:,0])/2
if DCsurvey.mesh.dim == 2:
zsrc = Tx[1]
elif DCsurvey.mesh.dim ==3:
zsrc = Tx[2]
elif stype == 'dpdp':
MA = np.abs(Tx[0][0] - Rx[0][:,0])
MB = np.abs(Tx[1][0] - Rx[0][:,0])
NA = np.abs(Tx[0][0] - Rx[1][:,0])
NB = np.abs(Tx[1][0] - Rx[1][:,0])
# Create mid-point location
Cmid = (Tx[0][0] + Tx[1][0])/2
Pmid = (Rx[0][:,0] + Rx[1][:,0])/2
if DCsurvey.mesh.dim == 2:
zsrc = (Tx[0][1] + Tx[1][1])/2
elif DCsurvey.mesh.dim ==3:
zsrc = (Tx[0][2] + Tx[1][2])/2
# Change output for dtype
if dtype == 'volt':
rho = np.hstack([rho,data])
else:
# Compute pant leg of apparent rho
if stype == 'pdp':
leg = data * 2*np.pi * MA * ( MA + MN ) / MN
elif stype == 'dpdp':
leg = data * 2*np.pi / ( 1/MA - 1/MB + 1/NB - 1/NA )
LEG.append(1./(2*np.pi) *( 1/MA - 1/MB + 1/NB - 1/NA ))
else:
print """dtype must be 'pdp'(pole-dipole) | 'dpdp' (dipole-dipole) """
break
if dtype == 'appc':
leg = np.log10(abs(1./leg))
rho = np.hstack([rho,leg])
elif dtype == 'appr':
leg = np.log10(abs(leg))
rho = np.hstack([rho,leg])
else:
print """dtype must be 'appr' | 'appc' | 'volt' """
break
midx = np.hstack([midx, ( Cmid + Pmid )/2 ])
if DCsurvey.mesh.dim==3:
midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + zsrc ])
elif DCsurvey.mesh.dim==2:
midz = np.hstack([midz, -np.abs(Cmid-Pmid)/2 + zsrc ])
ax = axs
# Grid points
grid_x, grid_z = np.mgrid[np.min(midx):np.max(midx), np.min(midz):np.max(midz)]
grid_rho = griddata(np.c_[midx,midz], rho.T, (grid_x, grid_z), method='linear')
if clim == None:
vmin, vmax = rho.min(), rho.max()
else:
vmin, vmax = clim[0], clim[1]
grid_rho = np.ma.masked_where(np.isnan(grid_rho), grid_rho)
ph = plt.pcolormesh(grid_x[:,0],grid_z[0,:],grid_rho.T, clim=(vmin, vmax), vmin=vmin, vmax=vmax)
cbar = plt.colorbar(format="$10^{%.1f}$",fraction=0.04,orientation="horizontal")
cmin,cmax = cbar.get_clim()
ticks = np.linspace(cmin,cmax,3)
cbar.set_ticks(ticks)
cbar.ax.tick_params(labelsize=10)
if dtype == 'appc':
cbar.set_label("App.Cond",size=12)
elif dtype == 'appr':
cbar.set_label("App.Res.",size=12)
elif dtype == 'volt':
cbar.set_label("Potential (V)",size=12)
# Plot apparent resistivity
ax.scatter(midx,midz,s=10,c=rho.T, vmin =vmin, vmax = vmax, clim=(vmin, vmax))
#ax.set_xticklabels([])
#ax.set_yticklabels([])
plt.gca().set_aspect('equal', adjustable='box')
return ph, LEG
def gen_DCIPsurvey(endl, mesh, stype, a, b, n):
"""
Load in endpoints and survey specifications to generate Tx, Rx location
stations.
Assumes flat topo for now...
Input:
:param endl -> input endpoints [x1, y1, z1, x2, y2, z2]
:object mesh -> SimPEG mesh object
:switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient'
: param a, n -> pole seperation, number of rx dipoles per tx
Output:
:param Tx, Rx -> List objects for each tx location
Lines: P1x, P1y, P1z, P2x, P2y, P2z
Created on Wed December 9th, 2015
@author: dominiquef
!! Require clean up to deal with DCsurvey
"""
from SimPEG import np
def xy_2_r(x1,x2,y1,y2):
r = np.sqrt( np.sum((x2 - x1)**2 + (y2 - y1)**2) )
return r
## Evenly distribute electrodes and put on surface
# Mesure survey length and direction
dl_len = xy_2_r(endl[0,0],endl[1,0],endl[0,1],endl[1,1])
dl_x = ( endl[1,0] - endl[0,0] ) / dl_len
dl_y = ( endl[1,1] - endl[0,1] ) / dl_len
nstn = np.floor( dl_len / a )
# Compute discrete pole location along line
stn_x = endl[0,0] + np.array(range(int(nstn)))*dl_x*a
stn_y = endl[0,1] + np.array(range(int(nstn)))*dl_y*a
if mesh.dim==2:
ztop = mesh.vectorNy[-1]
# Create line of P1 locations
M = np.c_[stn_x, np.ones(nstn).T*ztop]
# Create line of P2 locations
N = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop]
elif mesh.dim==3:
ztop = mesh.vectorNz[-1]
# Create line of P1 locations
M = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop]
# Create line of P2 locations
N = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop]
## Build list of Tx-Rx locations depending on survey type
# Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn]
# Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B]
SrcList = []
if stype != 'gradient':
for ii in range(0, int(nstn)-1):
if stype == 'dpdp':
tx = np.c_[M[ii,:],N[ii,:]]
elif stype == 'pdp':
tx = np.c_[M[ii,:],M[ii,:]]
# Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]])
# Current elctrode seperation
AB = xy_2_r(tx[0,1],endl[1,0],tx[1,1],endl[1,1])
# Number of receivers to fit
nstn = np.min([np.floor( (AB - b) / a ) , n])
# Check if there is enough space, else break the loop
if nstn <= 0:
continue
# Compute discrete pole location along line
stn_x = N[ii,0] + dl_x*b + np.array(range(int(nstn)))*dl_x*a
stn_y = N[ii,1] + dl_y*b + np.array(range(int(nstn)))*dl_y*a
# Create receiver poles
if mesh.dim==3:
# Create line of P1 locations
P1 = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop]
# Create line of P2 locations
P2 = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop]
rxClass = DC.Rx.Dipole(P1, P2)
elif mesh.dim==2:
# Create line of P1 locations
P1 = np.c_[stn_x, np.ones(nstn).T*ztop]
# Create line of P2 locations
P2 = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop]
rxClass = DC.Rx.Dipole_ky(P1, P2)
if stype == 'dpdp':
srcClass = DC.Src.Dipole([rxClass], M[ii,:],N[ii,:])
elif stype == 'pdp':
srcClass = DC.Src.Pole([rxClass], M[ii,:])
SrcList.append(srcClass)
elif stype == 'gradient':
# Gradient survey only requires Tx at end of line and creates a square
# grid of receivers at in the middle at a pre-set minimum distance
# Get the edge limit of survey area
min_x = endl[0,0] + dl_x * b
min_y = endl[0,1] + dl_y * b
max_x = endl[1,0] - dl_x * b
max_y = endl[1,1] - dl_y * b
box_l = np.sqrt( (min_x - max_x)**2 + (min_y - max_y)**2 )
box_w = box_l/2.
nstn = np.floor( box_l / a )
# Compute discrete pole location along line
stn_x = min_x + np.array(range(int(nstn)))*dl_x*a
stn_y = min_y + np.array(range(int(nstn)))*dl_y*a
# Define number of cross lines
nlin = int(np.floor( box_w / a ))
lind = range(-nlin,nlin+1)
ngrad = nstn * len(lind)
rx = np.zeros([ngrad,6])
for ii in range( len(lind) ):
# Move line in perpendicular direction by dipole spacing
lxx = stn_x - lind[ii]*a*dl_y
lyy = stn_y + lind[ii]*a*dl_x
M = np.c_[ lxx, lyy , np.ones(nstn).T*ztop]
N = np.c_[ lxx+a*dl_x, lyy+a*dl_y, np.ones(nstn).T*ztop]
rx[(ii*nstn):((ii+1)*nstn),:] = np.c_[M,N]
if mesh.dim==3:
rxClass = DC.Rx.Dipole(rx[:,:3], rx[:,3:])
elif mesh.dim==2:
M = M[:,[0,2]]
N = N[:,[0,2]]
rxClass = DC.Rx.Dipole_ky(rx[:,[0,2]], rx[:,[3,5]])
srcClass = DC.Src.Dipole([rxClass], M[0,:], N[-1,:])
SrcList.append(srcClass)
else:
print """stype must be either 'pdp', 'dpdp' or 'gradient'. """
return SrcList
+1
View File
@@ -0,0 +1 @@
from StaticUtils import *
+3
View File
@@ -0,0 +1,3 @@
import DC
import IP
import SIP
+21 -12
View File
@@ -27,16 +27,25 @@ class FieldsTDEM(Problem.TimeFields):
else:
e = np.zeros((nE,nSrc)) # if nSrc == 1 else (nE, nSrc))
u = np.concatenate((u, b, e))
return Utils.mkvc(u,nSrc)
class BaseTDEMProblem(BaseTimeProblem, BaseEMProblem):
"""docstring for ProblemTDEM1D"""
"""docstring for BaseTDEMProblem"""
def __init__(self, mesh, mapping=None, **kwargs):
BaseTimeProblem.__init__(self, mesh, mapping=mapping, **kwargs)
_FieldsForward_pair = FieldsTDEM #: used for the forward calculation only
waveformType = "STEPOFF"
current = None
def currentwaveform(self, wave):
self._timeSteps = np.diff(wave[:,0])
self.current = wave[:,1]
self.waveformType = "GENERAL"
def fields(self, m):
if self.verbose: print '%s\nCalculating fields(m)\n%s'%('*'*50,'*'*50)
self.curModel = m
@@ -99,11 +108,11 @@ class BaseTDEMProblem(BaseTimeProblem, BaseEMProblem):
Ainv.clean()
return F
def Jvec(self, m, v, u=None):
def Jvec(self, m, v, f=None):
"""
:param numpy.array m: Conductivity model
:param numpy.ndarray v: vector (model object)
:param simpegEM.TDEM.FieldsTDEM u: Fields resulting from m
:param simpegEM.TDEM.FieldsTDEM f: Fields resulting from m
:rtype: numpy.ndarray
:return: w (data object)
@@ -116,15 +125,15 @@ class BaseTDEMProblem(BaseTimeProblem, BaseEMProblem):
"""
if self.verbose: print '%s\nCalculating J(v)\n%s'%('*'*50,'*'*50)
self.curModel = m
if u is None:
u = self.fields(m)
p = self.Gvec(m, v, u)
if f is None:
f = self.fields(m)
p = self.Gvec(m, v, f)
y = self.solveAh(m, p)
Jv = self.survey.projectFieldsDeriv(u, v=y)
Jv = self.survey.evalDeriv(f, v=y)
if self.verbose: print '%s\nDone calculating J(v)\n%s'%('*'*50,'*'*50)
return - mkvc(Jv)
def Jtvec(self, m, v, u=None):
def Jtvec(self, m, v, f=None):
"""
:param numpy.array m: Conductivity model
:param numpy.ndarray,SimPEG.Survey.Data v: vector (data object)
@@ -141,15 +150,15 @@ class BaseTDEMProblem(BaseTimeProblem, BaseEMProblem):
"""
if self.verbose: print '%s\nCalculating J^T(v)\n%s'%('*'*50,'*'*50)
self.curModel = m
if u is None:
u = self.fields(m)
if f is None:
f = self.fields(m)
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
p = self.survey.projectFieldsDeriv(u, v=v, adjoint=True)
p = self.survey.evalDeriv(f, v=v, adjoint=True)
y = self.solveAht(m, p)
w = self.Gtvec(m, y, u)
w = self.Gtvec(m, y, f)
if self.verbose: print '%s\nDone calculating J^T(v)\n%s'%('*'*50,'*'*50)
return - mkvc(w)
+51 -14
View File
@@ -51,12 +51,12 @@ class RxTDEM(Survey.BaseTimeRx):
else:
return timeMesh.getInterpolationMat(self.times, self.projTLoc)
def projectFields(self, src, mesh, timeMesh, u):
def eval(self, src, mesh, timeMesh, u):
P = self.getP(mesh, timeMesh)
u_part = Utils.mkvc(u[src, self.projField, :])
return P*u_part
def projectFieldsDeriv(self, src, mesh, timeMesh, u, v, adjoint=False):
def evalDeriv(self, src, mesh, timeMesh, u, v, adjoint=False):
P = self.getP(mesh, timeMesh)
if not adjoint:
@@ -79,12 +79,32 @@ class SrcTDEM(Survey.BaseSrc):
class SrcTDEM_VMD_MVP(SrcTDEM):
def __init__(self,rxList,loc):
def __init__(self,rxList,loc,waveformType="STEPOFF"):
self.loc = loc
self.waveformType = waveformType
SrcTDEM.__init__(self,rxList)
def getInitialFields(self, mesh):
"""Vertical magnetic dipole, magnetic vector potential"""
if self.waveformType == "STEPOFF":
print ">> Step waveform: Non-zero initial condition"
if mesh._meshType is 'CYL':
if mesh.isSymmetric:
MVP = MagneticDipoleVectorPotential(self.loc, mesh, 'Ey')
else:
raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!')
elif mesh._meshType is 'TENSOR':
MVP = MagneticDipoleVectorPotential(self.loc, mesh, ['Ex','Ey','Ez'])
else:
raise Exception('Unknown mesh for VMD')
return {"b": mesh.edgeCurl*MVP}
elif self.waveformType == "GENERAL":
print ">> General waveform: Zero initial condition"
return {"b": np.zeros(mesh.nF)}
else:
raise NotImplementedError("Only use STEPOFF or GENERAL")
def getMeS(self, mesh, MfMui):
if mesh._meshType is 'CYL':
if mesh.isSymmetric:
MVP = MagneticDipoleVectorPotential(self.loc, mesh, 'Ey')
@@ -94,19 +114,37 @@ class SrcTDEM_VMD_MVP(SrcTDEM):
MVP = MagneticDipoleVectorPotential(self.loc, mesh, ['Ex','Ey','Ez'])
else:
raise Exception('Unknown mesh for VMD')
return {"b": mesh.edgeCurl*MVP}
return mesh.edgeCurl.T*MfMui*mesh.edgeCurl*MVP
class SrcTDEM_CircularLoop_MVP(SrcTDEM):
def __init__(self,rxList,loc,radius):
def __init__(self,rxList,loc,radius,waveformType="STEPOFF"):
self.loc = loc
self.radius = radius
self.waveformType = waveformType
SrcTDEM.__init__(self,rxList)
def getInitialFields(self, mesh):
"""Circular Loop, magnetic vector potential"""
if self.waveformType == "STEPOFF":
print ">> Step waveform: Non-zero initial condition"
if mesh._meshType is 'CYL':
if mesh.isSymmetric:
MVP = MagneticLoopVectorPotential(self.loc, mesh, 'Ey', self.radius)
else:
raise NotImplementedError('Non-symmetric cyl mesh not implemented yet!')
elif mesh._meshType is 'TENSOR':
MVP = MagneticLoopVectorPotential(self.loc, mesh, ['Ex','Ey','Ez'], self.radius)
else:
raise Exception('Unknown mesh for CircularLoop')
return {"b": mesh.edgeCurl*MVP}
elif self.waveformType == "GENERAL":
print ">> General waveform: Zero initial condition"
return {"b": np.zeros(mesh.nF)}
else:
raise NotImplementedError("Only use STEPOFF or GENERAL")
def getMeS(self, mesh, MfMui):
if mesh._meshType is 'CYL':
if mesh.isSymmetric:
MVP = MagneticLoopVectorPotential(self.loc, mesh, 'Ey', self.radius)
@@ -116,8 +154,7 @@ class SrcTDEM_CircularLoop_MVP(SrcTDEM):
MVP = MagneticLoopVectorPotential(self.loc, mesh, ['Ex','Ey','Ez'], self.radius)
else:
raise Exception('Unknown mesh for CircularLoop')
return {"b": mesh.edgeCurl*MVP}
return mesh.edgeCurl.T*MfMui*mesh.edgeCurl*MVP
class SurveyTDEM(Survey.BaseSurvey):
@@ -131,27 +168,27 @@ class SurveyTDEM(Survey.BaseSurvey):
self.srcList = srcList
Survey.BaseSurvey.__init__(self, **kwargs)
def projectFields(self, u):
def eval(self, u):
data = Survey.Data(self)
for src in self.srcList:
for rx in src.rxList:
data[src, rx] = rx.projectFields(src, self.mesh, self.prob.timeMesh, u)
data[src, rx] = rx.eval(src, self.mesh, self.prob.timeMesh, u)
return data
def projectFieldsDeriv(self, u, v=None, adjoint=False):
def evalDeriv(self, u, v=None, adjoint=False):
assert v is not None, 'v to multiply must be provided.'
if not adjoint:
data = Survey.Data(self)
for src in self.srcList:
for rx in src.rxList:
data[src, rx] = rx.projectFieldsDeriv(src, self.mesh, self.prob.timeMesh, u, v)
data[src, rx] = rx.evalDeriv(src, self.mesh, self.prob.timeMesh, u, v)
return data
else:
f = FieldsTDEM(self.mesh, self)
for src in self.srcList:
for rx in src.rxList:
Ptv = rx.projectFieldsDeriv(src, self.mesh, self.prob.timeMesh, u, v, adjoint=True)
Ptv = rx.evalDeriv(src, self.mesh, self.prob.timeMesh, u, v, adjoint=True)
Ptv = Ptv.reshape((-1, self.prob.timeMesh.nN), order='F')
if rx.projField not in f: # first time we are projecting
f[src, rx.projField, :] = Ptv
-33
View File
@@ -13,37 +13,4 @@ def k(freq, sigma, mu=mu_0, eps=epsilon_0):
beta = w * np.sqrt( mu*eps/2 * ( np.sqrt(1. + (sigma / (eps*w))**2 ) - 1) )
return alp - 1j*beta
# Constitutive relations
def e_from_j(prob,j):
eqLocs = prob._eqLocs
if eqLocs is 'FE':
MSigmaI = prob.MeSigmaI
elif eqLocs is 'EF':
MSigmaI = prob.MfRho
return MSigmaI*j
def j_from_e(prob,e):
eqLocs = prob._eqLocs
if eqLocs is 'FE':
MSigma = prob.MeSigma
elif eqLocs is 'EF':
MSigma = prob.MfRhoI
return MSigma*e
def b_from_h(prob,h):
eqLocs = prob._eqLocs
if eqLocs is 'FE':
MMu = prob.MfMuiI
elif eqLocs is 'EF':
MMu = prob.MeMu
return MMu*h
def h_from_b(prob,b):
eqLocs = prob._eqLocs
if eqLocs is 'FE':
MMuI = prob.MfMui
elif eqLocs is 'EF':
MMuI = prob.MeMuI
return MMuI*b
+1 -4
View File
@@ -1,5 +1,2 @@
# import Sources
# import Ana
# import Solver
from EMUtils import omega, e_from_j, j_from_e, b_from_h, h_from_b
from EMUtils import omega, k
from AnalyticUtils import MagneticDipoleFields, MagneticDipoleVectorPotential, MagneticLoopVectorPotential
+79 -23
View File
@@ -4,63 +4,77 @@ from SimPEG import EM
import sys
from scipy.constants import mu_0
def getFDEMProblem(fdemType, comp, SrcList, freq, verbose=False):
cs = 5.
ncx, ncy, ncz = 6, 6, 6
npad = 3
FLR = 1e-20 # "zero", so if residual below this --> pass regardless of order
CONDUCTIVITY = 1e1
MU = mu_0
freq = 5e-1
def getFDEMProblem(fdemType, comp, SrcList, freq, useMu=False, verbose=False):
cs = 10.
ncx, ncy, ncz = 0, 0, 0
npad = 8
hx = [(cs,npad,-1.3), (cs,ncx), (cs,npad,1.3)]
hy = [(cs,npad,-1.3), (cs,ncy), (cs,npad,1.3)]
hz = [(cs,npad,-1.3), (cs,ncz), (cs,npad,1.3)]
mesh = Mesh.TensorMesh([hx,hy,hz],['C','C','C'])
mapping = Maps.ExpMap(mesh)
if useMu is True:
mapping = [('sigma', Maps.ExpMap(mesh)), ('mu', Maps.IdentityMap(mesh))]
else:
mapping = Maps.ExpMap(mesh)
x = np.array([np.linspace(-30,-15,3),np.linspace(15,30,3)]) #don't sample right by the source
XYZ = Utils.ndgrid(x,x,np.r_[0.])
Rx0 = EM.FDEM.Rx(XYZ, comp)
x = np.array([np.linspace(-5.*cs,-2.*cs,3),np.linspace(5.*cs,2.*cs,3)]) + cs/4. #don't sample right by the source, slightly off alignment from either staggered grid
XYZ = Utils.ndgrid(x,x,np.linspace(-2.*cs,2.*cs,5))
Rx0 = getattr(EM.FDEM.Rx, 'Point_' + comp[0])
if comp[2] == 'r':
real_or_imag = 'real'
elif comp[2] == 'i':
real_or_imag = 'imag'
rx0 = Rx0(XYZ, comp[1], 'imag')
Src = []
for SrcType in SrcList:
if SrcType is 'MagDipole':
Src.append(EM.FDEM.Src.MagDipole([Rx0], freq=freq, loc=np.r_[0.,0.,0.]))
Src.append(EM.FDEM.Src.MagDipole([rx0], freq=freq, loc=np.r_[0.,0.,0.]))
elif SrcType is 'MagDipole_Bfield':
Src.append(EM.FDEM.Src.MagDipole_Bfield([Rx0], freq=freq, loc=np.r_[0.,0.,0.]))
Src.append(EM.FDEM.Src.MagDipole_Bfield([rx0], freq=freq, loc=np.r_[0.,0.,0.]))
elif SrcType is 'CircularLoop':
Src.append(EM.FDEM.Src.CircularLoop([Rx0], freq=freq, loc=np.r_[0.,0.,0.]))
Src.append(EM.FDEM.Src.CircularLoop([rx0], freq=freq, loc=np.r_[0.,0.,0.]))
elif SrcType is 'RawVec':
if fdemType is 'e' or fdemType is 'b':
S_m = np.zeros(mesh.nF)
S_e = np.zeros(mesh.nE)
S_m[Utils.closestPoints(mesh,[0.,0.,0.],'Fz') + np.sum(mesh.vnF[:1])] = 1.
S_e[Utils.closestPoints(mesh,[0.,0.,0.],'Ez') + np.sum(mesh.vnE[:1])] = 1.
Src.append(EM.FDEM.Src.RawVec([Rx0], freq, S_m, S_e))
S_m[Utils.closestPoints(mesh,[0.,0.,0.],'Fz') + np.sum(mesh.vnF[:1])] = 1e-3
S_e[Utils.closestPoints(mesh,[0.,0.,0.],'Ez') + np.sum(mesh.vnE[:1])] = 1e-3
Src.append(EM.FDEM.Src.RawVec([rx0], freq, S_m, mesh.getEdgeInnerProduct()*S_e))
elif fdemType is 'h' or fdemType is 'j':
S_m = np.zeros(mesh.nE)
S_e = np.zeros(mesh.nF)
S_m[Utils.closestPoints(mesh,[0.,0.,0.],'Ez') + np.sum(mesh.vnE[:1])] = 1.
S_e[Utils.closestPoints(mesh,[0.,0.,0.],'Fz') + np.sum(mesh.vnF[:1])] = 1.
Src.append(EM.FDEM.Src.RawVec([Rx0], freq, S_m, S_e))
S_m[Utils.closestPoints(mesh,[0.,0.,0.],'Ez') + np.sum(mesh.vnE[:1])] = 1e-3
S_e[Utils.closestPoints(mesh,[0.,0.,0.],'Fz') + np.sum(mesh.vnF[:1])] = 1e-3
Src.append(EM.FDEM.Src.RawVec([rx0], freq, mesh.getEdgeInnerProduct()*S_m, S_e))
if verbose:
print ' Fetching %s problem' % (fdemType)
if fdemType == 'e':
survey = EM.FDEM.Survey(Src)
prb = EM.FDEM.Problem_e(mesh, mapping=mapping)
prb = EM.FDEM.Problem3D_e(mesh, mapping=mapping)
elif fdemType == 'b':
survey = EM.FDEM.Survey(Src)
prb = EM.FDEM.Problem_b(mesh, mapping=mapping)
prb = EM.FDEM.Problem3D_b(mesh, mapping=mapping)
elif fdemType == 'j':
survey = EM.FDEM.Survey(Src)
prb = EM.FDEM.Problem_j(mesh, mapping=mapping)
prb = EM.FDEM.Problem3D_j(mesh, mapping=mapping)
elif fdemType == 'h':
survey = EM.FDEM.Survey(Src)
prb = EM.FDEM.Problem_h(mesh, mapping=mapping)
prb = EM.FDEM.Problem3D_h(mesh, mapping=mapping)
else:
raise NotImplementedError()
@@ -70,6 +84,48 @@ def getFDEMProblem(fdemType, comp, SrcList, freq, verbose=False):
from pymatsolver import MumpsSolver
prb.Solver = MumpsSolver
except ImportError, e:
pass
prb.Solver = SolverLU
return prb
return prb
def crossCheckTest(SrcList, fdemType1, fdemType2, comp, addrandoms = False, useMu=False, TOL=1e-5, verbose=False):
l2norm = lambda r: np.sqrt(r.dot(r))
prb1 = getFDEMProblem(fdemType1, comp, SrcList, freq, useMu, verbose)
mesh = prb1.mesh
print 'Cross Checking Forward: %s, %s formulations - %s' % (fdemType1, fdemType2, comp)
logsig = np.log(np.ones(mesh.nC)*CONDUCTIVITY)
mu = np.ones(mesh.nC)*MU
if addrandoms is True:
logsig += np.random.randn(mesh.nC)*np.log(CONDUCTIVITY)*1e-1
mu += np.random.randn(mesh.nC)*MU*1e-1
if useMu is True:
m = np.r_[logsig, mu]
else:
m = logsig
survey1 = prb1.survey
d1 = survey1.dpred(m)
if verbose:
print ' Problem 1 solved'
prb2 = getFDEMProblem(fdemType2, comp, SrcList, freq, useMu, verbose)
survey2 = prb2.survey
d2 = survey2.dpred(m)
if verbose:
print ' Problem 2 solved'
r = d2-d1
l2r = l2norm(r)
tol = np.max([TOL*(10**int(np.log10(0.5* (l2norm(d1) + l2norm(d2)) ))),FLR])
print l2norm(d1), l2norm(d2), l2r , tol, l2r < tol
return l2r < tol
+2 -1
View File
@@ -1,6 +1,7 @@
# from EM import *
import TDEM
import FDEM
import Static
import Base
import Analytics
import Utils
from scipy.constants import mu_0, epsilon_0
+68
View File
@@ -0,0 +1,68 @@
from SimPEG import *
import SimPEG.DCIP as DC
def run(plotIt=False):
cs = 25.
hx = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
hy = [(cs,7, -1.3),(cs,21),(cs,7, 1.3)]
hz = [(cs,7, -1.3),(cs,20)]
mesh = Mesh.TensorMesh([hx, hy, hz], 'CCN')
sighalf = 1e-2
sigma = np.ones(mesh.nC)*sighalf
xtemp = np.linspace(-150, 150, 21)
ytemp = np.linspace(-150, 150, 21)
xyz_rxP = Utils.ndgrid(xtemp-10., ytemp, np.r_[0.])
xyz_rxN = Utils.ndgrid(xtemp+10., ytemp, np.r_[0.])
xyz_rxM = Utils.ndgrid(xtemp, ytemp, np.r_[0.])
# if plotIt:
# fig, ax = plt.subplots(1,1, figsize = (5,5))
# mesh.plotSlice(sigma, grid=True, ax = ax)
# ax.plot(xyz_rxP[:,0],xyz_rxP[:,1], 'w.')
# ax.plot(xyz_rxN[:,0],xyz_rxN[:,1], 'r.', ms = 3)
rx = DC.RxDipole(xyz_rxP, xyz_rxN)
src = DC.SrcDipole([rx], [-200, 0, -12.5], [+200, 0, -12.5])
survey = DC.SurveyDC([src])
problem = DC.ProblemDC_CC(mesh)
problem.pair(survey)
try:
from pymatsolver import MumpsSolver
problem.Solver = MumpsSolver
except Exception, e:
pass
data = survey.dpred(sigma)
def DChalf(srclocP, srclocN, rxloc, sigma, I=1.):
rp = (srclocP.reshape([1,-1])).repeat(rxloc.shape[0], axis = 0)
rn = (srclocN.reshape([1,-1])).repeat(rxloc.shape[0], axis = 0)
rP = np.sqrt(((rxloc-rp)**2).sum(axis=1))
rN = np.sqrt(((rxloc-rn)**2).sum(axis=1))
return I/(sigma*2.*np.pi)*(1/rP-1/rN)
data_anaP = DChalf(np.r_[-200, 0, 0.],np.r_[+200, 0, 0.], xyz_rxP, sighalf)
data_anaN = DChalf(np.r_[-200, 0, 0.],np.r_[+200, 0, 0.], xyz_rxN, sighalf)
data_ana = data_anaP-data_anaN
Data_ana = data_ana.reshape((21, 21), order = 'F')
Data = data.reshape((21, 21), order = 'F')
X = xyz_rxM[:,0].reshape((21, 21), order = 'F')
Y = xyz_rxM[:,1].reshape((21, 21), order = 'F')
if plotIt:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,2, figsize = (12, 5))
vmin = np.r_[data, data_ana].min()
vmax = np.r_[data, data_ana].max()
dat1 = ax[1].contourf(X, Y, Data, 60, vmin = vmin, vmax = vmax)
dat0 = ax[0].contourf(X, Y, Data_ana, 60, vmin = vmin, vmax = vmax)
cb0 = plt.colorbar(dat1, orientation = 'horizontal', ax = ax[0])
cb1 = plt.colorbar(dat1, orientation = 'horizontal', ax = ax[1])
ax[1].set_title('Analytic')
ax[0].set_title('Computed')
plt.show()
return np.linalg.norm(data-data_ana)/np.linalg.norm(data_ana)
if __name__ == '__main__':
print run(plotIt=True)
+208
View File
@@ -0,0 +1,208 @@
from SimPEG import Mesh, Utils, np, sp
import SimPEG.DCIP as DC
import time
def run(loc=None, sig=None, radi=None, param=None, surveyType='dipole-dipole', unitType='appConductivity', plotIt=True):
"""
DC Forward Simulation
=====================
Forward model two conductive spheres in a half-space and plot a
pseudo-section. Assumes an infinite line source and measures along the
center of the spheres.
INPUT:
loc = Location of spheres [[x1,y1,z1],[x2,y2,z2]]
radi = Radius of spheres [r1,r2]
param = Conductivity of background and two spheres [m0,m1,m2]
surveyType = survey type 'pole-dipole' or 'dipole-dipole'
unitType = Data type "appResistivity" | "appConductivity" | "volt"
Created by @fourndo
"""
assert surveyType in ['pole-dipole', 'dipole-dipole'], "Source type (surveyType) must be pdp or dpdp (pole dipole or dipole dipole)"
assert unitType in ['appResistivity', 'appConductivity', 'volt'], "Unit type (unitType) must be appResistivity or appConductivity or volt (potential)"
if loc is None:
loc = np.c_[[-50.,0.,-50.],[50.,0.,-50.]]
if sig is None:
sig = np.r_[1e-2,1e-1,1e-3]
if radi is None:
radi = np.r_[25.,25.]
if param is None:
param = np.r_[30.,30.,5]
# First we need to create a mesh and a model.
# This is our mesh
dx = 5.
hxind = [(dx,15,-1.3), (dx, 75), (dx,15,1.3)]
hyind = [(dx,15,-1.3), (dx, 10), (dx,15,1.3)]
hzind = [(dx,15,-1.3),(dx, 15)]
mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCN')
# Set background conductivity
model = np.ones(mesh.nC) * sig[0]
# First anomaly
ind = Utils.ModelBuilder.getIndicesSphere(loc[:,0],radi[0],mesh.gridCC)
model[ind] = sig[1]
# Second anomaly
ind = Utils.ModelBuilder.getIndicesSphere(loc[:,1],radi[1],mesh.gridCC)
model[ind] = sig[2]
# Get index of the center
indy = int(mesh.nCy/2)
# Plot the model for reference
# Define core mesh extent
xlim = 200
zlim = 100
# Then specify the end points of the survey. Let's keep it simple for now and survey above the anomalies, top of the mesh
ends = [(-175,0),(175,0)]
ends = np.c_[np.asarray(ends),np.ones(2).T*mesh.vectorNz[-1]]
# Snap the endpoints to the grid. Easier to create 2D section.
indx = Utils.closestPoints(mesh, ends )
locs = np.c_[mesh.gridCC[indx,0],mesh.gridCC[indx,1],np.ones(2).T*mesh.vectorNz[-1]]
# We will handle the geometry of the survey for you and create all the combination of tx-rx along line
# [Tx, Rx] = DC.gen_DCIPsurvey(locs, mesh, surveyType, param[0], param[1], param[2])
survey, Tx, Rx = DC.gen_DCIPsurvey(locs, mesh, surveyType, param[0], param[1], param[2])
# Define some global geometry
dl_len = np.sqrt( np.sum((locs[0,:] - locs[1,:])**2) )
dl_x = ( Tx[-1][0,1] - Tx[0][0,0] ) / dl_len
dl_y = ( Tx[-1][1,1] - Tx[0][1,0] ) / dl_len
#azm = np.arctan(dl_y/dl_x)
#Set boundary conditions
mesh.setCellGradBC('neumann')
# Define the linear system needed for the DC problem. We assume an infitite
# line source for simplicity.
Div = mesh.faceDiv
Grad = mesh.cellGrad
Msig = Utils.sdiag(1./(mesh.aveF2CC.T*(1./model)))
A = Div*Msig*Grad
# Change one corner to deal with nullspace
A[0,0] = 1
A = sp.csc_matrix(A)
# We will solve the system iteratively, so a pre-conditioner is helpful
# This is simply a Jacobi preconditioner (inverse of the main diagonal)
dA = A.diagonal()
P = sp.spdiags(1/dA,0,A.shape[0],A.shape[0])
# Now we can solve the system for all the transmitters
# We want to store the data
data = []
# There is probably a more elegant way to do this, but we can just for-loop through the transmitters
for ii in range(len(Tx)):
start_time = time.time() # Let's time the calculations
#print("Transmitter %i / %i\r" % (ii+1,len(Tx)))
# Select dipole locations for receiver
rxloc_M = np.asarray(Rx[ii][:,0:3])
rxloc_N = np.asarray(Rx[ii][:,3:])
# For usual cases 'dipole-dipole' or "gradient"
if surveyType == 'pole-dipole':
# Create an "inifinity" pole
tx = np.squeeze(Tx[ii][:,0:1])
tinf = tx + np.array([dl_x,dl_y,0])*dl_len*2
inds = Utils.closestPoints(mesh, np.c_[tx,tinf].T)
RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T*( [-1] / mesh.vol[inds] )
else:
inds = Utils.closestPoints(mesh, np.asarray(Tx[ii]).T )
RHS = mesh.getInterpolationMat(np.asarray(Tx[ii]).T, 'CC').T*( [-1,1] / mesh.vol[inds] )
# Iterative Solve
Ainvb = sp.linalg.bicgstab(P*A,P*RHS, tol=1e-5)
# We now have the potential everywhere
phi = Utils.mkvc(Ainvb[0])
# Solve for phi on pole locations
P1 = mesh.getInterpolationMat(rxloc_M, 'CC')
P2 = mesh.getInterpolationMat(rxloc_N, 'CC')
# Compute the potential difference
dtemp = (P1*phi - P2*phi)*np.pi
data.append( dtemp )
print '\rTransmitter {0} of {1} -> Time:{2} sec'.format(ii,len(Tx),time.time()- start_time),
print 'Transmitter {0} of {1}'.format(ii,len(Tx))
print 'Forward completed'
# Let's just convert the 3D format into 2D (distance along line) and plot
survey2D = DC.convertObs_DC3D_to_2D(survey, np.ones(survey.nSrc) , 'Xloc')
survey2D.dobs =np.hstack(data)
if plotIt:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(7,7))
ax = plt.subplot(2,1,1, aspect='equal')
# Plot the location of the spheres for reference
circle1=plt.Circle((loc[0,0], loc[2,0]), radi[0], color='w', fill=False, lw=3)
circle2=plt.Circle((loc[0,1], loc[2,1]), radi[1], color='k', fill=False, lw=3)
ax.add_artist(circle1)
ax.add_artist(circle2)
dat = mesh.plotSlice(np.log10(model), ax = ax, normal = 'Y',
ind = indy,grid=True, clim = np.log10([sig.min(),sig.max()]))
ax.set_title('3-D model')
plt.gca().set_aspect('equal', adjustable='box')
plt.scatter(Tx[0][0,:],Tx[0][2,:],s=40,c='g', marker='v')
plt.scatter(Rx[0][:,0::3],Rx[0][:,2::3],s=40,c='y')
plt.xlim([-xlim,xlim])
plt.ylim([-zlim,mesh.vectorNz[-1]+dx])
pos = ax.get_position()
ax.set_position([pos.x0 , pos.y0 + 0.025 , pos.width, pos.height])
pos = ax.get_position()
cbarax = fig.add_axes([pos.x0 , pos.y0 + 0.025 , pos.width, pos.height * 0.04]) ## the parameters are the specified position you set
cb = fig.colorbar(dat[0],cax=cbarax, orientation="horizontal",
ax = ax, ticks=np.linspace(np.log10(sig.min()),
np.log10(sig.max()), 3), format="$10^{%.1f}$")
cb.set_label("Conductivity (S/m)",size=12)
cb.ax.tick_params(labelsize=12)
# Second plot for the predicted apparent resistivity data
ax2 = plt.subplot(2,1,2, aspect='equal')
# Plot the location of the spheres for reference
circle1=plt.Circle((loc[0,0], loc[2,0]), radi[0], color='w', fill=False, lw=3)
circle2=plt.Circle((loc[0,1], loc[2,1]), radi[1], color='k', fill=False, lw=3)
ax2.add_artist(circle1)
ax2.add_artist(circle2)
# Add the speudo section
dat = DC.plot_pseudoSection(survey2D, ax2, surveyType=surveyType, unitType=unitType) # plt.scatter(Tx2d[0][:],Tx[0][2,:],s=40,c='g', marker='v')
# plt.scatter(Rx2d[0][:],Rx[0][:,2::3],s=40,c='y')
# plt.plot(np.r_[Tx2d[0][0],Rx2d[-1][-1,-1]],np.ones(2)*mesh.vectorNz[-1], color='k')
ax2.set_title('Apparent Conductivity data')
plt.ylim([-zlim,mesh.vectorNz[-1]+dx])
plt.show()
return fig, ax
if __name__ == '__main__':
run()
+43 -32
View File
@@ -1,7 +1,7 @@
from SimPEG import *
import SimPEG.EM as EM
from scipy.constants import mu_0
import matplotlib.pyplot as plt
from SimPEG.EM import mu_0
def run(plotIt=True):
"""
@@ -17,52 +17,61 @@ def run(plotIt=True):
hz = [(cs,npad,-1.3), (cs,ncz), (cs,npad,1.3)]
mesh = Mesh.CylMesh([hx,1,hz], '00C')
layerz = -100.
active = mesh.vectorCCz<0.
layer = (mesh.vectorCCz<0.) & (mesh.vectorCCz>=-100.)
actMap = Maps.ActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
mapping = Maps.ExpMap(mesh) * Maps.Vertical1DMap(mesh) * actMap
sig_half = 2e-3
layer = (mesh.vectorCCz<0.) & (mesh.vectorCCz>=layerz)
actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
sig_half = 2e-2
sig_air = 1e-8
sig_layer = 1e-3
sig_layer = 1e-2
sigma = np.ones(mesh.nCz)*sig_air
sigma[active] = sig_half
sigma[layer] = sig_layer
mtrue = np.log(sigma[active])
if plotIt:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1, figsize = (3, 6))
plt.semilogx(sigma[active], mesh.vectorCCz[active])
ax.set_ylim(-600, 0)
ax.set_xlim(1e-4, 1e-2)
ax.set_ylim(-500, 0)
ax.set_xlim(1e-3, 1e-1)
ax.set_xlabel('Conductivity (S/m)', fontsize = 14)
ax.set_ylabel('Depth (m)', fontsize = 14)
ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
rxOffset=1e-3
rx = EM.TDEM.RxTDEM(np.array([[rxOffset, 0., 30]]), np.logspace(-5,-3, 31), 'bz')
src = EM.TDEM.SrcTDEM_VMD_MVP([rx], np.array([0., 0., 80]))
survey = EM.TDEM.SurveyTDEM([src])
prb = EM.TDEM.ProblemTDEM_b(mesh, mapping=mapping)
rxOffset=10.
bzi = EM.FDEM.Rx.Point_b(np.array([[rxOffset, 0., 1e-3]]), orientation='z', component='imag')
freqs = np.logspace(1,3,10)
srcLoc = np.array([0., 0., 10.])
srcList = [EM.FDEM.Src.MagDipole([bzi],freq, srcLoc,orientation='Z') for freq in freqs]
survey = EM.FDEM.Survey(srcList)
prb = EM.FDEM.Problem3D_b(mesh, mapping=mapping)
try:
from pymatsolver import MumpsSolver
prb.Solver = MumpsSolver
except ImportError, e:
prb.Solver = SolverLU
prb.Solver = SolverLU
prb.timeSteps = [(1e-06, 20),(1e-05, 20), (0.0001, 20)]
prb.pair(survey)
dtrue = survey.dpred(mtrue)
survey.dtrue = dtrue
std = 0.05
noise = std*abs(survey.dtrue)*np.random.randn(*survey.dtrue.shape)
survey.dobs = survey.dtrue+noise
survey.std = survey.dobs*0 + std
survey.Wd = 1/(abs(survey.dobs)*std)
survey.makeSyntheticData(mtrue, std)
survey.std = std
survey.eps = np.linalg.norm(survey.dtrue)*1e-5
if plotIt:
fig, ax = plt.subplots(1,1, figsize = (10, 6))
ax.loglog(rx.times, dtrue, 'b.-')
ax.loglog(rx.times, survey.dobs, 'r.-')
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1, figsize = (6, 6))
ax.semilogx(freqs,survey.dtrue[:freqs.size], 'b.-')
ax.semilogx(freqs,survey.dobs[:freqs.size], 'r.-')
ax.legend(('Noisefree', '$d^{obs}$'), fontsize = 16)
ax.set_xlabel('Time (s)', fontsize = 14)
ax.set_ylabel('$B_z$ (T)', fontsize = 16)
@@ -72,14 +81,15 @@ def run(plotIt=True):
dmisfit = DataMisfit.l2_DataMisfit(survey)
regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
reg = Regularization.Tikhonov(regMesh)
opt = Optimization.InexactGaussNewton(maxIter = 5)
opt = Optimization.InexactGaussNewton(maxIter = 6)
invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
# Create an inversion object
beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2)
betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
inv = Inversion.BaseInversion(invProb, directiveList=[beta,betaest])
m0 = np.log(np.ones(mtrue.size)*sig_half)
reg.alpha_s = 1e-2
reg.alpha_s = 1e-3
reg.alpha_x = 1.
prb.counter = opt.counter = Utils.Counter()
opt.LSshorten = 0.5
@@ -88,15 +98,16 @@ def run(plotIt=True):
mopt = inv.run(m0)
if plotIt:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1, figsize = (3, 6))
plt.semilogx(sigma[active], mesh.vectorCCz[active])
plt.semilogx(np.exp(mopt), mesh.vectorCCz[active])
ax.set_ylim(-600, 0)
ax.set_xlim(1e-4, 1e-2)
ax.set_ylim(-500, 0)
ax.set_xlim(1e-3, 1e-1)
ax.set_xlabel('Conductivity (S/m)', fontsize = 14)
ax.set_ylabel('Depth (m)', fontsize = 14)
ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'])
plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'],loc='best')
plt.show()
@@ -0,0 +1,43 @@
from SimPEG import *
import SimPEG.EM as EM
def run(XYZ=None, loc=np.r_[0.,0.,0.], sig=1.0, freq=1.0, orientation='Z', plotIt=True):
"""
EM: Magnetic Dipole in a Whole-Space
====================================
Here we plot the magnetic flux density from a harmonic dipole in a wholespace.
"""
if XYZ is None:
x = np.arange(-100.5,100.5,step = 1.) #(avoid putting measurement points where source is located)
y = np.r_[0]
z = x
XYZ = Utils.ndgrid(x,y,z)
Bx, By, Bz = EM.Analytics.FDEM.MagneticDipoleWholeSpace(XYZ, loc, sig, freq, orientation=orientation)
absB = np.sqrt(Bx*Bx.conj()+By*By.conj()+Bz*Bz.conj()).real
if plotIt:
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
fig, ax = plt.subplots(1,1,figsize=(6,5))
bxplt = Bx.reshape(x.size,z.size)
bzplt = Bz.reshape(x.size,z.size)
pc = ax.pcolor(x,z,absB.reshape(x.size,z.size),norm=LogNorm())
ax.streamplot(x,z,bxplt.real,bzplt.real,color='k',density=1)
ax.set_xlim([x.min(),x.max()])
ax.set_ylim([z.min(),z.max()])
ax.set_xlabel('x')
ax.set_ylabel('z')
cb = plt.colorbar(pc,ax = ax)
cb.set_label('|B| (T)')
plt.show()
return fig, ax
if __name__ == '__main__':
run()
@@ -0,0 +1,275 @@
from SimPEG import *
from SimPEG.EM import FDEM, Analytics, mu_0
import time
try:
from pymatsolver import MumpsSolver
solver = MumpsSolver
except Exception:
solver = SolverLU
pass
def run(plotIt=True):
"""
EM: Schenkel and Morrison Casing Model
======================================
Here we create and run a FDEM forward simulation to calculate the vertical
current inside a steel-cased. The model is based on the Schenkel and
Morrison Casing Model, and the results are used in a 2016 SEG abstract by
Yang et al.
- Schenkel, C.J., and H.F. Morrison, 1990, Effects of well casing on potential field measurements using downhole current sources: Geophysical prospecting, 38, 663-686.
The model consists of:
- Air: Conductivity 1e-8 S/m, above z = 0
- Background: conductivity 1e-2 S/m, below z = 0
- Casing: conductivity 1e6 S/m
- 300m long
- radius of 0.1m
- thickness of 6e-3m
Inside the casing, we take the same conductivity as the background.
We are using an EM code to simulate DC, so we use frequency low enough
that the skin depth inside the casing is longer than the casing length (f
= 1e-6 Hz). The plot produced is of the current inside the casing.
These results are shown in the SEG abstract by Yang et al., 2016: 3D DC
resistivity modeling of steel casing for reservoir monitoring using
equivalent resistor network. The solver used to produce these results and
achieve the CPU time of ~30s is Mumps, which was installed using pymatsolver_
.. _pymatsolver: https://github.com/rowanc1/pymatsolver
This example is on figshare: https://dx.doi.org/10.6084/m9.figshare.3126961.v1
If you would use this example for a code comparison, or build upon it, a
citation would be much appreciated!
"""
if plotIt:
import matplotlib.pylab as plt
# ------------------ MODEL ------------------
sigmaair = 1e-8 # air
sigmaback = 1e-2 # background
sigmacasing = 1e6 # casing
sigmainside = sigmaback # inside the casing
casing_t = 0.006 # 1cm thickness
casing_l = 300 # length of the casing
casing_r = 0.1
casing_a = casing_r - casing_t/2. # inner radius
casing_b = casing_r + casing_t/2. # outer radius
casing_z = np.r_[-casing_l,0.]
# ------------------ SURVEY PARAMETERS ------------------
freqs = np.r_[1e-6] #[1e-1, 1, 5] # frequencies
dsz = -300 # down-hole z source location
src_loc = np.r_[0.,0.,dsz]
inf_loc = np.r_[0.,0.,1e4]
print 'Skin Depth: ', [(500./np.sqrt(sigmaback*_)) for _ in freqs]
# ------------------ MESH ------------------
# fine cells near well bore
csx1, csx2 = 2e-3, 60.
pfx1, pfx2 = 1.3, 1.3
ncx1 = np.ceil(casing_b/csx1+2)
# pad nicely to second cell size
npadx1 = np.floor(np.log(csx2/csx1) / np.log(pfx1))
hx1a,hx1b = Utils.meshTensor([(csx1,ncx1)]),Utils.meshTensor([(csx1,npadx1,pfx1)])
dx1 = sum(hx1a)+sum(hx1b)
dx1 = np.floor(dx1/csx2)
hx1b *= (dx1*csx2 - sum(hx1a))/sum(hx1b)
# second chunk of mesh
dx2 = 300. # uniform mesh out to here
ncx2 = np.ceil((dx2 - dx1)/csx2)
npadx2 = 45
hx2a, hx2b = Utils.meshTensor([(csx2,ncx2)]), Utils.meshTensor([(csx2,npadx2,pfx2)])
hx = np.hstack([hx1a,hx1b,hx2a,hx2b])
# z-direction
csz = 0.05
nza = 10
ncz, npadzu, npadzd = np.int(np.ceil(np.diff(casing_z)[0]/csz))+10, 68, 68 # cell size, number of core cells, number of padding cells in the x- direction
hz = Utils.meshTensor([(csz,npadzd,-1.3), (csz,ncz), (csz,npadzu,1.3)]) # vector of cell widths in the z-direction
# Mesh
mesh = Mesh.CylMesh([hx,1.,hz], [0.,0.,-np.sum(hz[:npadzu+ncz-nza])])
print 'Mesh Extent xmax: %f,: zmin: %f, zmax: %f'%(mesh.vectorCCx.max(), mesh.vectorCCz.min(), mesh.vectorCCz.max())
print 'Number of cells', mesh.nC
if plotIt is True:
fig, ax = plt.subplots(1, 1, figsize=(6, 4))
ax.set_title('Simulation Mesh')
mesh.plotGrid(ax=ax)
plt.show()
# Put the model on the mesh
sigWholespace = sigmaback*np.ones((mesh.nC))
sigBack = sigWholespace.copy()
sigBack[mesh.gridCC[:,2] > 0.] = sigmaair
sigCasing = sigBack.copy()
iCasingZ = (mesh.gridCC[:,2] <= casing_z[1]) & (mesh.gridCC[:,2] >= casing_z[0])
iCasingX = (mesh.gridCC[:,0] >= casing_a) & (mesh.gridCC[:,0] <= casing_b)
iCasing = iCasingX & iCasingZ
sigCasing[iCasing] = sigmacasing
if plotIt is True:
# plotting parameters
xlim = np.r_[0., 0.2]
zlim = np.r_[-350., 10.]
clim_sig = np.r_[-8,6]
# plot models
fig, ax = plt.subplots(1,1,figsize=(4,4))
f = plt.colorbar(mesh.plotImage(np.log10(sigCasing),ax=ax)[0], ax=ax)
ax.grid(which='both')
ax.set_title('Log_10 (Sigma)')
ax.set_xlim(xlim)
ax.set_ylim(zlim)
f.set_clim(clim_sig)
plt.show()
# -------------- Sources --------------------
# Define Custom Current Sources
# surface source
sg_x = np.zeros(mesh.vnF[0],dtype=complex)
sg_y = np.zeros(mesh.vnF[1],dtype=complex)
sg_z = np.zeros(mesh.vnF[2],dtype=complex)
nza = 2 # put the wire two cells above the surface
ncin = 2
# vertically directed wire
sgv_indx = (mesh.gridFz[:,0] > casing_a) & (mesh.gridFz[:,0] < casing_a + csx1) # hook it up to casing at the surface
sgv_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] >= -csz*2)
sgv_ind = sgv_indx & sgv_indz
sg_z[sgv_ind] = -1.
# horizontally directed wire
sgh_indx = (mesh.gridFx[:,0] > casing_a) & (mesh.gridFx[:,0] <= inf_loc[2])
sgh_indz = (mesh.gridFx[:,2] > csz*(nza-0.5)) & (mesh.gridFx[:,2] < csz*(nza+0.5))
sgh_ind = sgh_indx & sgh_indz
sg_x[sgh_ind] = -1.
sgv2_indx = (mesh.gridFz[:,0] >= mesh.gridFx[sgh_ind,0].max()) & (mesh.gridFz[:,0] <= inf_loc[2]*1.2) # hook it up to casing at the surface
sgv2_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] >= -csz*2)
sgv2_ind = sgv2_indx & sgv2_indz
sg_z[sgv2_ind] = 1.
# assemble the source
sg = np.hstack([sg_x,sg_y,sg_z])
sg_p = [FDEM.Src.RawVec_e([],_,sg/mesh.area) for _ in freqs]
# downhole source
dg_x = np.zeros(mesh.vnF[0],dtype=complex)
dg_y = np.zeros(mesh.vnF[1],dtype=complex)
dg_z = np.zeros(mesh.vnF[2],dtype=complex)
# vertically directed wire
dgv_indx = (mesh.gridFz[:,0] < csx1) # go through the center of the well
dgv_indz = (mesh.gridFz[:,2] <= +csz*nza) & (mesh.gridFz[:,2] > dsz + csz/2.)
dgv_ind = dgv_indx & dgv_indz
dg_z[dgv_ind] = -1.
# couple to the casing downhole
dgh_indx = mesh.gridFx[:,0] < casing_a + csx1
dgh_indz = (mesh.gridFx[:,2] < dsz + csz) & (mesh.gridFx[:,2] >= dsz)
dgh_ind = dgh_indx & dgh_indz
dg_x[dgh_ind] = 1.
# horizontal part at surface
dgh2_indx = mesh.gridFx[:,0] <= inf_loc[2]*1.2
dgh2_indz = sgh_indz.copy()
dgh2_ind = dgh2_indx & dgh2_indz
dg_x[dgh2_ind] = -1.
# vertical part at surface
dgv2_ind = sgv2_ind.copy()
dg_z[dgv2_ind] = 1.
# assemble the source
dg = np.hstack([dg_x,dg_y,dg_z])
dg_p = [FDEM.Src.RawVec_e([],_,dg/mesh.area) for _ in freqs]
# ------------ Problem and Survey ---------------
survey = FDEM.Survey(sg_p + dg_p)
mapping = [('sigma', Maps.IdentityMap(mesh))]
problem = FDEM.Problem3D_h(mesh, mapping=mapping)
problem.pair(survey)
# ------------- Solve ---------------------------
t0 = time.time()
fieldsCasing = problem.fields(sigCasing)
print 'Time to solve 2 sources', time.time() - t0
# Plot current
# current density
jn0 = fieldsCasing[dg_p,'j']
jn1 = fieldsCasing[sg_p,'j']
# current
in0 = [mesh.area*fieldsCasing[dg_p,'j'][:,i] for i in range(len(freqs))]
in1 = [mesh.area*fieldsCasing[sg_p,'j'][:,i] for i in range(len(freqs))]
in0 = np.vstack(in0).T
in1 = np.vstack(in1).T
# integrate to get z-current inside casing
inds_inx = (mesh.gridFz[:,0] >= casing_a) & (mesh.gridFz[:,0] <= casing_b)
inds_inz = (mesh.gridFz[:,2] >= dsz ) & (mesh.gridFz[:,2] <= 0)
inds_fz = inds_inx & inds_inz
indsx = [False]*mesh.nFx
inds = list(indsx) + list(inds_fz)
in0_in = in0[np.r_[inds]]
in1_in = in1[np.r_[inds]]
z_in = mesh.gridFz[inds_fz,2]
in0_in = in0_in.reshape([in0_in.shape[0]/3,3])
in1_in = in1_in.reshape([in1_in.shape[0]/3,3])
z_in = z_in.reshape([z_in.shape[0]/3,3])
I0 = in0_in.sum(1).real
I1 = in1_in.sum(1).real
z_in = z_in[:,0]
if plotIt is True:
fig, ax = plt.subplots(1,2,figsize=(12,4))
ax[0].plot(z_in,np.absolute(I0), z_in,np.absolute(I1))
ax[0].legend(['top casing', 'bottom casing'],loc='best')
ax[0].set_title('Magnitude of Vertical Current in Casing')
ax[1].semilogy(z_in,np.absolute(I0), z_in,np.absolute(I1))
ax[1].legend(['top casing', 'bottom casing'],loc='best')
ax[1].set_title('Magnitude of Vertical Current in Casing')
ax[1].set_ylim([1e-2, 1.])
plt.show()
if __name__ == '__main__':
run()
+106
View File
@@ -0,0 +1,106 @@
from SimPEG import *
import SimPEG.EM as EM
from SimPEG.EM import mu_0
def run(plotIt=True):
"""
EM: TDEM: 1D: Inversion
=======================
Here we will create and run a TDEM 1D inversion.
"""
cs, ncx, ncz, npad = 5., 25, 15, 15
hx = [(cs,ncx), (cs,npad,1.3)]
hz = [(cs,npad,-1.3), (cs,ncz), (cs,npad,1.3)]
mesh = Mesh.CylMesh([hx,1,hz], '00C')
active = mesh.vectorCCz<0.
layer = (mesh.vectorCCz<0.) & (mesh.vectorCCz>=-100.)
actMap = Maps.InjectActiveCells(mesh, active, np.log(1e-8), nC=mesh.nCz)
mapping = Maps.ExpMap(mesh) * Maps.SurjectVertical1D(mesh) * actMap
sig_half = 2e-3
sig_air = 1e-8
sig_layer = 1e-3
sigma = np.ones(mesh.nCz)*sig_air
sigma[active] = sig_half
sigma[layer] = sig_layer
mtrue = np.log(sigma[active])
if plotIt:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1, figsize = (3, 6))
plt.semilogx(sigma[active], mesh.vectorCCz[active])
ax.set_ylim(-600, 0)
ax.set_xlim(1e-4, 1e-2)
ax.set_xlabel('Conductivity (S/m)', fontsize = 14)
ax.set_ylabel('Depth (m)', fontsize = 14)
ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
rxOffset=1e-3
rx = EM.TDEM.RxTDEM(np.array([[rxOffset, 0., 30]]), np.logspace(-5,-3, 31), 'bz')
src = EM.TDEM.SrcTDEM_VMD_MVP([rx], np.array([0., 0., 80]))
survey = EM.TDEM.SurveyTDEM([src])
prb = EM.TDEM.ProblemTDEM_b(mesh, mapping=mapping)
prb.Solver = SolverLU
prb.timeSteps = [(1e-06, 20),(1e-05, 20), (0.0001, 20)]
prb.pair(survey)
# create observed data
std = 0.05
survey.dobs = survey.makeSyntheticData(mtrue,std)
survey.std = std
survey.eps = 1e-5*np.linalg.norm(survey.dobs)
if plotIt:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1, figsize = (10, 6))
ax.loglog(rx.times, survey.dtrue, 'b.-')
ax.loglog(rx.times, survey.dobs, 'r.-')
ax.legend(('Noisefree', '$d^{obs}$'), fontsize = 16)
ax.set_xlabel('Time (s)', fontsize = 14)
ax.set_ylabel('$B_z$ (T)', fontsize = 16)
ax.set_xlabel('Time (s)', fontsize = 14)
ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
dmisfit = DataMisfit.l2_DataMisfit(survey)
regMesh = Mesh.TensorMesh([mesh.hz[mapping.maps[-1].indActive]])
reg = Regularization.Tikhonov(regMesh)
opt = Optimization.InexactGaussNewton(maxIter = 5)
invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt)
# Create an inversion object
beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2)
betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0)
inv = Inversion.BaseInversion(invProb, directiveList=[beta,betaest])
m0 = np.log(np.ones(mtrue.size)*sig_half)
reg.alpha_s = 1e-2
reg.alpha_x = 1.
prb.counter = opt.counter = Utils.Counter()
opt.LSshorten = 0.5
opt.remember('xc')
mopt = inv.run(m0)
if plotIt:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1, figsize = (3, 6))
plt.semilogx(sigma[active], mesh.vectorCCz[active])
plt.semilogx(np.exp(mopt), mesh.vectorCCz[active])
ax.set_ylim(-600, 0)
ax.set_xlim(1e-4, 1e-2)
ax.set_xlabel('Conductivity (S/m)', fontsize = 14)
ax.set_ylabel('Depth (m)', fontsize = 14)
ax.grid(color='k', alpha=0.5, linestyle='dashed', linewidth=0.5)
plt.legend(['$\sigma_{true}$', '$\sigma_{pred}$'])
plt.show()
if __name__ == '__main__':
run()
@@ -1,6 +1,5 @@
from SimPEG import *
from SimPEG.FLOW import Richards
import matplotlib.pyplot as plt
def run(plotIt=True):
"""
@@ -61,6 +60,7 @@ def run(plotIt=True):
Hs_H120= getFields(120.,'head')
if not plotIt:return
import matplotlib.pyplot as plt
plt.figure(figsize=(13,5))
plt.subplot(121)
plt.plot(40-M.gridCC, Hs_M10[-1],'b-')
@@ -1,7 +1,4 @@
from SimPEG import Mesh, Utils, np, SolverLU
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.mlab import griddata
## 2D DC forward modeling example with Tensor and Curvilinear Meshes
@@ -39,6 +36,10 @@ def run(plotIt=True):
if not plotIt: return
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.mlab import griddata
#Step4: Making Figure
fig, axes = plt.subplots(1,2,figsize=(12*1.2,4*1.2))
label = ["(a)", "(b)"]
+132
View File
@@ -0,0 +1,132 @@
from SimPEG import *
def run(N=200, plotIt=True):
"""
Inversion: Linear Problem
=========================
Here we go over the basics of creating a linear problem and inversion.
"""
np.random.seed(1)
std_noise = 1e-2
mesh = Mesh.TensorMesh([N])
m0 = np.ones(mesh.nC) * 1e-4
nk = 10
jk = np.linspace(1.,nk,nk)
p = -2.
q = 1.
g = lambda k: np.exp(p*jk[k]*mesh.vectorCCx)*np.cos(np.pi*q*jk[k]*mesh.vectorCCx)
G = np.empty((nk, mesh.nC))
for i in range(nk):
G[i,:] = g(i)
mtrue = np.zeros(mesh.nC)
mtrue[mesh.vectorCCx > 0.3] = 1.
mtrue[mesh.vectorCCx > 0.45] = -0.5
mtrue[mesh.vectorCCx > 0.6] = 0
prob = Problem.LinearProblem(mesh, G)
survey = Survey.LinearSurvey()
survey.pair(prob)
survey.dobs = prob.fields(mtrue) + std_noise * np.random.randn(nk)
#survey.makeSyntheticData(mtrue, std=std_noise)
wd = np.ones(nk) * std_noise
#print survey.std[0]
#M = prob.mesh
# Distance weighting
wr = np.sum(prob.G**2.,axis=0)**0.5
wr = ( wr/np.max(wr) )
reg = Regularization.Simple(mesh)
reg.wght = wr
dmis = DataMisfit.l2_DataMisfit(survey)
dmis.Wd = 1./wd
opt = Optimization.ProjectedGNCG(maxIter=30,lower=-2.,upper=2., maxIterCG= 20, tolCG = 1e-4)
invProb = InvProblem.BaseInvProblem(dmis, reg, opt)
invProb.curModel = m0
beta = Directives.BetaSchedule(coolingFactor=2, coolingRate=1)
target = Directives.TargetMisfit()
betaest = Directives.BetaEstimate_ByEig()
inv = Inversion.BaseInversion(invProb, directiveList=[beta, betaest, target])
mrec = inv.run(m0)
ml2 = mrec
print "Final misfit:" + str(invProb.dmisfit.eval(mrec))
# Switch regularization to sparse
phim = invProb.phi_m_last
phid = invProb.phi_d
reg = Regularization.Sparse(mesh)
#==============================================================================
# fig, axes = plt.subplots(1,2,figsize=(12*1.2,4*1.2))
# dmdx = reg.mesh.cellDiffxStencil * mrec
# plt.plot(np.sort(dmdx))
#==============================================================================
#reg.recModel = mrec
reg.wght = np.ones(mesh.nC)
reg.mref = np.zeros(mesh.nC)
reg.eps_p = 5e-2
reg.eps_q = 1e-2
reg.norms = [0., 0., 2., 2.]
reg.wght = wr
opt = Optimization.ProjectedGNCG(maxIter=10 ,lower=-2.,upper=2., maxIterLS = 20, maxIterCG= 20, tolCG = 1e-3)
invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta = invProb.beta*2.)
beta = Directives.BetaSchedule(coolingFactor=1, coolingRate=1)
#betaest = Directives.BetaEstimate_ByEig()
target = Directives.TargetMisfit()
IRLS =Directives.Update_IRLS( phi_m_last = phim, phi_d_last = phid )
inv = Inversion.BaseInversion(invProb, directiveList=[beta,IRLS])
m0 = mrec
# Run inversion
mrec = inv.run(m0)
print "Final misfit:" + str(invProb.dmisfit.eval(mrec))
if plotIt:
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1,2,figsize=(12*1.2,4*1.2))
for i in range(prob.G.shape[0]):
axes[0].plot(prob.G[i,:])
axes[0].set_title('Columns of matrix G')
axes[1].plot(mesh.vectorCCx, mtrue, 'b-')
axes[1].plot(mesh.vectorCCx, ml2, 'r-')
#axes[1].legend(('True Model', 'Recovered Model'))
axes[1].set_ylim(-1.0,1.25)
axes[1].plot(mesh.vectorCCx, mrec, 'k-',lw = 2)
axes[1].legend(('True Model', 'Smooth l2-l2',
'Sparse lp:' + str(reg.norms[0]) + ', lqx:' + str(reg.norms[1]) ), fontsize = 12)
plt.show()
return prob, survey, mesh, mrec
if __name__ == '__main__':
run()
+2 -24
View File
@@ -10,28 +10,6 @@ def run(N=100, plotIt=True):
"""
class LinearSurvey(Survey.BaseSurvey):
def projectFields(self, u):
return u
class LinearProblem(Problem.BaseProblem):
surveyPair = LinearSurvey
def __init__(self, mesh, G, **kwargs):
Problem.BaseProblem.__init__(self, mesh, **kwargs)
self.G = G
def fields(self, m, u=None):
return self.G.dot(m)
def Jvec(self, m, v, u=None):
return self.G.dot(v)
def Jtvec(self, m, v, u=None):
return self.G.T.dot(v)
np.random.seed(1)
mesh = Mesh.TensorMesh([N])
@@ -53,8 +31,8 @@ def run(N=100, plotIt=True):
mtrue[mesh.vectorCCx > 0.45] = -0.5
mtrue[mesh.vectorCCx > 0.6] = 0
prob = LinearProblem(mesh, G)
survey = LinearSurvey()
prob = Problem.LinearProblem(mesh, G)
survey = Survey.LinearSurvey()
survey.pair(prob)
survey.makeSyntheticData(mtrue, std=0.01)
@@ -0,0 +1,129 @@
import SimPEG as simpeg
import numpy as np
import SimPEG.MT as MT
from scipy.constants import mu_0
import matplotlib.pyplot as plt
def run(plotIt=True):
"""
MT: 1D: Inversion
=======================
Forward model 1D MT data.
Setup and run a MT 1D inversion.
"""
## Setup the forward modeling
# Setting up 1D mesh and conductivity models to forward model data.
# Frequency
nFreq = 31
freqs = np.logspace(3,-3,nFreq)
# Set mesh parameters
ct = 20
air = simpeg.Utils.meshTensor([(ct,16,1.4)])
core = np.concatenate( ( np.kron(simpeg.Utils.meshTensor([(ct,10,-1.3)]),np.ones((5,))) , simpeg.Utils.meshTensor([(ct,5)]) ) )
bot = simpeg.Utils.meshTensor([(core[0],10,-1.4)])
x0 = -np.array([np.sum(np.concatenate((core,bot)))])
# Make the model
m1d = simpeg.Mesh.TensorMesh([np.concatenate((bot,core,air))], x0=x0)
# Setup model varibles
active = m1d.vectorCCx<0.
layer1 = (m1d.vectorCCx<-500.) & (m1d.vectorCCx>=-800.)
layer2 = (m1d.vectorCCx<-3500.) & (m1d.vectorCCx>=-5000.)
# Set the conductivity values
sig_half = 2e-3
sig_air = 1e-8
sig_layer1 = .2
sig_layer2 = .2
# Make the true model
sigma_true = np.ones(m1d.nCx)*sig_air
sigma_true[active] = sig_half
sigma_true[layer1] = sig_layer1
sigma_true[layer2] = sig_layer2
# Extract the model
m_true = np.log(sigma_true[active])
# Make the background model
sigma_0 = np.ones(m1d.nCx)*sig_air
sigma_0[active] = sig_half
m_0 = np.log(sigma_0[active])
# Set the mapping
actMap = simpeg.Maps.ActiveCells(m1d, active, np.log(1e-8), nC=m1d.nCx)
mappingExpAct = simpeg.Maps.ExpMap(m1d) * actMap
## Setup the layout of the survey, set the sources and the connected receivers
# Receivers
rxList = []
for rxType in ['z1dr','z1di']:
rxList.append(MT.Rx(simpeg.mkvc(np.array([0.0]),2).T,rxType))
# Source list
srcList =[]
for freq in freqs:
srcList.append(MT.SrcMT.polxy_1Dprimary(rxList,freq))
# Make the survey
survey = MT.Survey(srcList)
survey.mtrue = m_true
## Set the problem
problem = MT.Problem1D.eForm_psField(m1d,sigmaPrimary=sigma_0,mapping=mappingExpAct)
problem.pair(survey)
## Forward model data
# Project the data
survey.dtrue = survey.dpred(m_true)
survey.dobs = survey.dtrue + 0.025*abs(survey.dtrue)*np.random.randn(*survey.dtrue.shape)
if plotIt:
fig = MT.Utils.dataUtils.plotMT1DModelData(problem)
fig.suptitle('Target - smooth true')
# Assign uncertainties
std = 0.05 # 5% std
survey.std = np.abs(survey.dobs*std)
# Assign the data weight
Wd = 1./survey.std
## Setup the inversion proceedure
# Define a counter
C = simpeg.Utils.Counter()
# Set the optimization
opt = simpeg.Optimization.InexactGaussNewton(maxIter = 30)
opt.counter = C
opt.LSshorten = 0.5
opt.remember('xc')
# Data misfit
dmis = simpeg.DataMisfit.l2_DataMisfit(survey)
dmis.Wd = Wd
# Regularization - with a regularization mesh
regMesh = simpeg.Mesh.TensorMesh([m1d.hx[problem.mapping.sigmaMap.maps[-1].indActive]],m1d.x0)
reg = simpeg.Regularization.Tikhonov(regMesh)
reg.mrefInSmooth = True
reg.alpha_s = 1e-7
reg.alpha_x = 1.
# Inversion problem
invProb = simpeg.InvProblem.BaseInvProblem(dmis, reg, opt)
invProb.counter = C
# Beta cooling
beta = simpeg.Directives.BetaSchedule()
beta.coolingRate = 4
betaest = simpeg.Directives.BetaEstimate_ByEig(beta0_ratio=0.75)
targmis = simpeg.Directives.TargetMisfit()
targmis.target = survey.nD
saveModel = simpeg.Directives.SaveModelEveryIteration()
saveModel.fileName = 'Inversion_TargMisEqnD_smoothTrue'
# Create an inversion object
inv = simpeg.Inversion.BaseInversion(invProb, directiveList=[beta,betaest,targmis])
## Run the inversion
mopt = inv.run(m_0)
if plotIt:
fig = MT.Utils.dataUtils.plotMT1DModelData(problem,[mopt])
fig.suptitle('Target - smooth true')
plt.show()
if __name__ == '__main__':
run()
+64
View File
@@ -0,0 +1,64 @@
# Test script to use SimPEG.MT platform to forward model synthetic data.
# Import
import SimPEG as simpeg
from SimPEG import MT
import numpy as np
try:
from pymatsolver import MumpsSolver as Solver
except:
from SimPEG import Solver
def run(plotIt=True, nFreq=1):
"""
MT: 3D: Forward
=======================
Forward model 3D MT data.
"""
# Make a mesh
M = simpeg.Mesh.TensorMesh([[(100,5,-1.5),(100.,10),(100,5,1.5)],[(100,5,-1.5),(100.,10),(100,5,1.5)],[(100,5,1.6),(100.,10),(100,3,2)]], x0=['C','C',-3529.5360])
# Setup the model
conds = [1e-2,1]
sig = simpeg.Utils.ModelBuilder.defineBlock(M.gridCC,[-1000,-1000,-400],[1000,1000,-200],conds)
sig[M.gridCC[:,2]>0] = 1e-8
sig[M.gridCC[:,2]<-600] = 1e-1
sigBG = np.zeros(M.nC) + conds[0]
sigBG[M.gridCC[:,2]>0] = 1e-8
## Setup the the survey object
# Receiver locations
rx_x, rx_y = np.meshgrid(np.arange(-500,501,50),np.arange(-500,501,50))
rx_loc = np.hstack((simpeg.Utils.mkvc(rx_x,2),simpeg.Utils.mkvc(rx_y,2),np.zeros((np.prod(rx_x.shape),1))))
# Make a receiver list
rxList = []
for loc in rx_loc:
# NOTE: loc has to be a (1,3) np.ndarray otherwise errors accure
for rxType in ['zxxr','zxxi','zxyr','zxyi','zyxr','zyxi','zyyr','zyyi','tzxr','tzxi','tzyr','tzyi']:
rxList.append(MT.Rx(simpeg.mkvc(loc,2).T,rxType))
# Source list
srcList =[]
for freq in np.logspace(3,-3,nFreq):
srcList.append(MT.SrcMT.polxy_1Dprimary(rxList,freq))
# Survey MT
survey = MT.Survey(srcList)
## Setup the problem object
problem = MT.Problem3D.eForm_ps(M, sigmaPrimary=sigBG)
problem.pair(survey)
problem.Solver = Solver
# Calculate the data
fields = problem.fields(sig)
dataVec = survey.eval(fields)
# Make the data
mtData = MT.Data(survey,dataVec)
# Add plots
if plotIt:
pass
if __name__ == '__main__':
run()
+41
View File
@@ -0,0 +1,41 @@
from SimPEG import *
from SimPEG.Utils import surface2ind_topo
def run(plotIt=False, nx = 5, ny = 5):
"""
Here we show how to use :code:`Utils.surface2ind_topo` to identify cells below
a topographic surface.
"""
mesh = Mesh.TensorMesh([nx,ny], x0='CC') # 2D mesh
xtopo = np.linspace(mesh.gridN[:,0].min(), mesh.gridN[:,0].max())
topo = 0.4*np.sin(xtopo*5) # define a topographic surface
Topo = np.hstack([Utils.mkvc(xtopo,2),Utils.mkvc(topo,2)]) #make it an array
indcc = surface2ind_topo(mesh, Topo,'CC')
if plotIt:
from matplotlib.pylab import plt
from scipy.interpolate import interp1d
fig, ax = plt.subplots(1,1,figsize=(6,6))
mesh.plotGrid(ax=ax, nodes=True, centers=True)
ax.plot(xtopo,topo,'k',linewidth=1)
# ax.plot(mesh.vectorNx, interp1d(xtopo,topo)(mesh.vectorNx),'--k',linewidth=3)
ax.plot(mesh.vectorCCx, interp1d(xtopo,topo)(mesh.vectorCCx),'--k',linewidth=3)
aveN2CC = Utils.sdiag(mesh.aveN2CC.T.sum(1))*mesh.aveN2CC.T
a = aveN2CC * indcc
a[a > 0] = 1.
a[a < 0.25] = np.nan
a = a.reshape(mesh.vnN, order='F')
masked_array = np.ma.array(a, mask=np.isnan(a))
ax.pcolor(mesh.vectorNx,mesh.vectorNy,masked_array.T, cmap = plt.cm.gray,alpha=0.2)
plt.show()
if __name__ == '__main__':
run(plotIt=True)
+15 -5
View File
@@ -1,9 +1,15 @@
# Run this file to add imports.
##### AUTOIMPORTS #####
import DC_Analytic_Dipole
import DC_Forward_PseudoSection
import EM_FDEM_1D_Inversion
import EM_FDEM_Analytic_MagDipoleWholespace
import EM_Schenkel_Morrison_Casing
import EM_TDEM_1D_Inversion
import FLOW_Richards_1D_Celia1990
import Forward_BasicDirectCurrent
import Inversion_IRLS
import Inversion_Linear
import Mesh_Basic_PlotImage
import Mesh_Basic_Types
@@ -12,8 +18,11 @@ import Mesh_QuadTree_Creation
import Mesh_QuadTree_FaceDiv
import Mesh_QuadTree_HangingNodes
import Mesh_Tensor_Creation
import MT_1D_ForwardAndInversion
import MT_3D_Foward
import Utils_surface2ind_topo
__examples__ = ["EM_FDEM_1D_Inversion", "FLOW_Richards_1D_Celia1990", "Forward_BasicDirectCurrent", "Inversion_Linear", "Mesh_Basic_PlotImage", "Mesh_Basic_Types", "Mesh_Operators_CahnHilliard", "Mesh_QuadTree_Creation", "Mesh_QuadTree_FaceDiv", "Mesh_QuadTree_HangingNodes", "Mesh_Tensor_Creation"]
__examples__ = ["DC_Analytic_Dipole", "DC_Forward_PseudoSection", "EM_FDEM_1D_Inversion", "EM_FDEM_Analytic_MagDipoleWholespace", "EM_Schenkel_Morrison_Casing", "EM_TDEM_1D_Inversion", "FLOW_Richards_1D_Celia1990", "Forward_BasicDirectCurrent", "Inversion_IRLS", "Inversion_Linear", "Mesh_Basic_PlotImage", "Mesh_Basic_Types", "Mesh_Operators_CahnHilliard", "Mesh_QuadTree_Creation", "Mesh_QuadTree_FaceDiv", "Mesh_QuadTree_HangingNodes", "Mesh_Tensor_Creation", "MT_1D_ForwardAndInversion", "MT_3D_Foward", "Utils_surface2ind_topo"]
##### AUTOIMPORTS #####
@@ -28,16 +37,17 @@ if __name__ == '__main__':
from SimPEG import Examples
# Create the examples dir in the docs folder.
docExamplesDir = os.path.sep.join(os.path.realpath(__file__).split(os.path.sep)[:-3] + ['docs', 'examples'])
fName = os.path.realpath(__file__)
docExamplesDir = os.path.sep.join(fName.split(os.path.sep)[:-3] + ['docs', 'examples'])
shutil.rmtree(docExamplesDir)
os.makedirs(docExamplesDir)
# Get all the python examples in this folder
thispath = os.path.sep.join(__file__.split(os.path.sep)[:-1])
thispath = os.path.sep.join(fName.split(os.path.sep)[:-1])
exfiles = [f[:-3] for f in os.listdir(thispath) if os.path.isfile(os.path.join(thispath, f)) and f.endswith('.py') and not f.startswith('_')]
# Add the imports to the top in the AUTOIMPORTS section
f = file(__file__, 'r')
f = file(fName, 'r')
inimports = False
out = ''
for line in f:
@@ -52,7 +62,7 @@ if __name__ == '__main__':
out += '\n##### AUTOIMPORTS #####\n'
f.close()
f = file(__file__, 'w')
f = file(fName, 'w')
f.write(out)
f.close()
+35 -35
View File
@@ -8,7 +8,7 @@ class RichardsRx(Survey.BaseTimeRx):
knownRxTypes = ['saturation','pressureHead']
def projectFields(self, U, m, mapping, mesh, timeMesh):
def eval(self, U, m, mapping, mesh, timeMesh):
if self.rxType == 'pressureHead':
u = np.concatenate(U)
@@ -17,7 +17,7 @@ class RichardsRx(Survey.BaseTimeRx):
return self.getP(mesh, timeMesh) * u
def projectFieldsDeriv(self, U, m, mapping, mesh, timeMesh):
def evalDeriv(self, U, m, mapping, mesh, timeMesh):
P = self.getP(mesh, timeMesh)
if self.rxType == 'pressureHead':
@@ -45,25 +45,25 @@ class RichardsSurvey(Survey.BaseSurvey):
@Utils.count
@Utils.requires('prob')
def dpred(self, m, u=None):
def dpred(self, m, f=None):
"""
Create the projected data from a model.
The field, u, (if provided) will be used for the predicted data
The field, f, (if provided) will be used for the predicted data
instead of recalculating the fields (which may be expensive!).
.. math::
d_\\text{pred} = P(u(m), m)
d_\\text{pred} = P(f(m), m)
Where P is a projection of the fields onto the data space.
"""
if u is None: u = self.prob.fields(m)
return Utils.mkvc(self.projectFields(u, m))
if f is None: f = self.prob.fields(m)
return Utils.mkvc(self.eval(f, m))
@Utils.requires('prob')
def projectFields(self, U, m):
def eval(self, U, m):
Ds = range(len(self.rxList))
for ii, rx in enumerate(self.rxList):
Ds[ii] = rx.projectFields(U, m,
Ds[ii] = rx.eval(U, m,
self.prob.mapping,
self.prob.mesh,
self.prob.timeMesh)
@@ -71,11 +71,11 @@ class RichardsSurvey(Survey.BaseSurvey):
return np.concatenate(Ds)
@Utils.requires('prob')
def projectFieldsDeriv(self, U, m):
def evalDeriv(self, U, m):
"""The Derivative with respect to the fields."""
Ds = range(len(self.rxList))
for ii, rx in enumerate(self.rxList):
Ds[ii] = rx.projectFieldsDeriv(U, m,
Ds[ii] = rx.evalDeriv(U, m,
self.prob.mapping,
self.prob.mesh,
self.prob.timeMesh)
@@ -233,16 +233,16 @@ class RichardsProblem(Problem.BaseTimeProblem):
return r, J
@Utils.timeIt
def Jfull(self, m, u=None):
if u is None:
u = self.fields(m)
def Jfull(self, m, f=None):
if f is None:
f = self.fields(m)
nn = len(u)-1
nn = len(f)-1
Asubs, Adiags, Bs = range(nn), range(nn), range(nn)
for ii in range(nn):
dt = self.timeSteps[ii]
bc = self.getBoundaryConditions(ii, u[ii])
Asubs[ii], Adiags[ii], Bs[ii] = self.diagsJacobian(m, u[ii], u[ii+1], dt, bc)
bc = self.getBoundaryConditions(ii, f[ii])
Asubs[ii], Adiags[ii], Bs[ii] = self.diagsJacobian(m, f[ii], f[ii+1], dt, bc)
Ad = sp.block_diag(Adiags)
zRight = Utils.spzeros((len(Asubs)-1)*Asubs[0].shape[0],Adiags[0].shape[1])
zTop = Utils.spzeros(Adiags[0].shape[0], len(Adiags)*Adiags[0].shape[1])
@@ -251,7 +251,7 @@ class RichardsProblem(Problem.BaseTimeProblem):
B = np.array(sp.vstack(Bs).todense())
Ainv = self.Solver(A, **self.solverOpts)
P = self.survey.projectFieldsDeriv(u, m)
P = self.survey.evalDeriv(f, m)
AinvB = Ainv * B
z = np.zeros((self.mesh.nC, B.shape[1]))
zAinvB = np.vstack((z, AinvB))
@@ -259,41 +259,41 @@ class RichardsProblem(Problem.BaseTimeProblem):
return J
@Utils.timeIt
def Jvec(self, m, v, u=None):
if u is None:
u = self.fields(m)
def Jvec(self, m, v, f=None):
if f is None:
f = self.fields(m)
JvC = range(len(u)-1) # Cell to hold each row of the long vector.
JvC = range(len(f)-1) # Cell to hold each row of the long vector.
# This is done via forward substitution.
bc = self.getBoundaryConditions(0, u[0])
temp, Adiag, B = self.diagsJacobian(m, u[0], u[1], self.timeSteps[0], bc)
bc = self.getBoundaryConditions(0, f[0])
temp, Adiag, B = self.diagsJacobian(m, f[0], f[1], self.timeSteps[0], bc)
Adiaginv = self.Solver(Adiag, **self.solverOpts)
JvC[0] = Adiaginv * (B*v)
for ii in range(1,len(u)-1):
bc = self.getBoundaryConditions(ii, u[ii])
Asub, Adiag, B = self.diagsJacobian(m, u[ii], u[ii+1], self.timeSteps[ii], bc)
for ii in range(1,len(f)-1):
bc = self.getBoundaryConditions(ii, f[ii])
Asub, Adiag, B = self.diagsJacobian(m, f[ii], f[ii+1], self.timeSteps[ii], bc)
Adiaginv = self.Solver(Adiag, **self.solverOpts)
JvC[ii] = Adiaginv * (B*v - Asub*JvC[ii-1])
P = self.survey.projectFieldsDeriv(u, m)
P = self.survey.evalDeriv(f, m)
return P * np.concatenate([np.zeros(self.mesh.nC)] + JvC)
@Utils.timeIt
def Jtvec(self, m, v, u=None):
if u is None:
u = self.field(m)
def Jtvec(self, m, v, f=None):
if f is None:
f = self.field(m)
P = self.survey.projectFieldsDeriv(u, m)
P = self.survey.evalDeriv(f, m)
PTv = P.T*v
# This is done via backward substitution.
minus = 0
BJtv = 0
for ii in range(len(u)-1,0,-1):
bc = self.getBoundaryConditions(ii-1, u[ii-1])
Asub, Adiag, B = self.diagsJacobian(m, u[ii-1], u[ii], self.timeSteps[ii-1], bc)
for ii in range(len(f)-1,0,-1):
bc = self.getBoundaryConditions(ii-1, f[ii-1])
Asub, Adiag, B = self.diagsJacobian(m, f[ii-1], f[ii], self.timeSteps[ii-1], bc)
#select the correct part of v
vpart = range((ii)*Adiag.shape[0], (ii+1)*Adiag.shape[0])
AdiaginvT = self.Solver(Adiag.T, **self.solverOpts)
+15 -15
View File
@@ -66,8 +66,8 @@ class BaseInvProblem(object):
self.curModel = m0
print """SimPEG.InvProblem is setting bfgsH0 to the inverse of the eval2Deriv.
***Done using same solver as the problem***"""
self.opt.bfgsH0 = self.prob.Solver(self.reg.eval2Deriv(self.curModel))
***Done using same Solver and solverOpts as the problem***"""
self.opt.bfgsH0 = self.prob.Solver(self.reg.eval2Deriv(self.curModel), **self.prob.solverOpts)
@property
def warmstart(self):
@@ -82,23 +82,23 @@ class BaseInvProblem(object):
self._warmstart = value
def getFields(self, m, store=False, deleteWarmstart=True):
u = None
f = None
for mtest, u_ofmtest in self.warmstart:
if m is mtest:
u = u_ofmtest
f = u_ofmtest
if self.debug: print 'InvProb is Warm Starting!'
break
if u is None:
u = self.prob.fields(m)
if f is None:
f = self.prob.fields(m)
if deleteWarmstart:
self.warmstart = []
if store:
self.warmstart += [(m,u)]
self.warmstart += [(m,f)]
return u
return f
@Utils.timeIt
def evalFunction(self, m, return_g=True, return_H=True):
@@ -109,21 +109,21 @@ class BaseInvProblem(object):
gc.collect()
# Store fields if doing a line-search
u = self.getFields(m, store=(return_g==False and return_H==False))
f = self.getFields(m, store=(return_g==False and return_H==False))
phi_d = self.dmisfit.eval(m, u=u)
phi_d = self.dmisfit.eval(m, f=f)
phi_m = self.reg.eval(m)
self.dpred = self.survey.dpred(m, u=u) # This is a cheap matrix vector calculation.
self.dpred = self.survey.dpred(m, f=f) # This is a cheap matrix vector calculation.
self.phi_d, self.phi_d_last = phi_d, self.phi_d
self.phi_m, self.phi_m_last = phi_m, self.phi_m
f = phi_d + self.beta * phi_m
phi = phi_d + self.beta * phi_m
out = (f,)
out = (phi,)
if return_g:
phi_dDeriv = self.dmisfit.evalDeriv(m, u=u)
phi_dDeriv = self.dmisfit.evalDeriv(m, f=f)
phi_mDeriv = self.reg.evalDeriv(m)
g = phi_dDeriv + self.beta * phi_mDeriv
@@ -131,7 +131,7 @@ class BaseInvProblem(object):
if return_H:
def H_fun(v):
phi_d2Deriv = self.dmisfit.eval2Deriv(m, v, u=u)
phi_d2Deriv = self.dmisfit.eval2Deriv(m, v, f=f)
phi_m2Deriv = self.reg.eval2Deriv(m, v=v)
return phi_d2Deriv + self.beta * phi_m2Deriv
+3 -1
View File
@@ -33,7 +33,9 @@ class BaseInversion(object):
self._directiveList = value
self._directiveList.inversion = self
def __init__(self, invProb, directiveList=[], **kwargs):
def __init__(self, invProb, directiveList=None, **kwargs):
if directiveList is None:
directiveList = []
self.directiveList = directiveList
Utils.setKwargs(self, **kwargs)
+132
View File
@@ -0,0 +1,132 @@
from SimPEG import SolverLU as SimpegSolver, PropMaps, Utils, mkvc, sp, np
from SimPEG.EM.FDEM.ProblemFDEM import BaseFDEMProblem
from SurveyMT import Survey, Data
from FieldsMT import BaseMTFields
class BaseMTProblem(BaseFDEMProblem):
"""
Base class for all Natural source problems.
"""
def __init__(self, mesh, **kwargs):
BaseFDEMProblem.__init__(self, mesh, **kwargs)
Utils.setKwargs(self, **kwargs)
# Set the default pairs of the problem
surveyPair = Survey
dataPair = Data
fieldsPair = BaseMTFields
# Set the solver
Solver = SimpegSolver
solverOpts = {}
verbose = False
# Notes:
# Use the forward and devs from BaseFDEMProblem
# Might need to add more stuff here.
## NEED to clean up the Jvec and Jtvec to use Zero and Identities for None components.
def Jvec(self, m, v, f=None):
"""
Function to calculate the data sensitivities dD/dm times a vector.
:param numpy.ndarray m (nC, 1) - conductive model
:param numpy.ndarray v (nC, 1) - random vector
:param MTfields object (optional) - MT fields object, if not given it is calculated
:rtype: MTdata object
:return: Data sensitivities wrt m
"""
# Calculate the fields
if f is None:
f= self.fields(m)
# Set current model
self.curModel = m
# Initiate the Jv object
Jv = self.dataPair(self.survey)
# Loop all the frequenies
for freq in self.survey.freqs:
dA_du = self.getA(freq) #
dA_duI = self.Solver(dA_du, **self.solverOpts)
for src in self.survey.getSrcByFreq(freq):
# We need fDeriv_m = df/du*du/dm + df/dm
# Construct du/dm, it requires a solve
# NOTE: need to account for the 2 polarizations in the derivatives.
f_src = f[src,:]
# dA_dm and dRHS_dm should be of size nE,2, so that we can multiply by dA_duI. The 2 columns are each of the polarizations.
dA_dm = self.getADeriv_m(freq, f_src, v) # Size: nE,2 (u_px,u_py) in the columns.
dRHS_dm = self.getRHSDeriv_m(freq, v) # Size: nE,2 (u_px,u_py) in the columns.
if dRHS_dm is None:
du_dm = dA_duI * ( -dA_dm )
else:
du_dm = dA_duI * ( -dA_dm + dRHS_dm )
# Calculate the projection derivatives
for rx in src.rxList:
# Get the projection derivative
# v should be of size 2*nE (for 2 polarizations)
PDeriv_u = lambda t: rx.evalDeriv(src, self.mesh, f, t) # wrt u, we don't have have PDeriv wrt m
Jv[src, rx] = PDeriv_u(mkvc(du_dm))
dA_duI.clean()
# Return the vectorized sensitivities
return mkvc(Jv)
def Jtvec(self, m, v, f=None):
"""
Function to calculate the transpose of the data sensitivities (dD/dm)^T times a vector.
:param numpy.ndarray m (nC, 1) - conductive model
:param numpy.ndarray v (nD, 1) - vector
:param MTfields object u (optional) - MT fields object, if not given it is calculated
:rtype: MTdata object
:return: Data sensitivities wrt m
"""
if f is None:
f = self.fields(m)
self.curModel = m
# Ensure v is a data object.
if not isinstance(v, self.dataPair):
v = self.dataPair(self.survey, v)
Jtv = np.zeros(m.size)
for freq in self.survey.freqs:
AT = self.getA(freq).T
ATinv = self.Solver(AT, **self.solverOpts)
for src in self.survey.getSrcByFreq(freq):
ftype = self._fieldType + 'Solution'
f_src = f[src, :]
for rx in src.rxList:
# Get the adjoint evalDeriv
# PTv needs to be nE,
PTv = rx.evalDeriv(src, self.mesh, f, mkvc(v[src, rx],2), adjoint=True) # wrt u, need possibility wrt m
# Get the
dA_duIT = ATinv * PTv
dA_dmT = self.getADeriv_m(freq, f_src, mkvc(dA_duIT), adjoint=True)
dRHS_dmT = self.getRHSDeriv_m(freq, mkvc(dA_duIT), adjoint=True)
# Make du_dmT
if dRHS_dmT is None:
du_dmT = -dA_dmT
else:
du_dmT = -dA_dmT + dRHS_dmT
# Select the correct component
# du_dmT needs to be of size nC,
real_or_imag = rx.projComp
if real_or_imag == 'real':
Jtv += du_dmT.real
elif real_or_imag == 'imag':
Jtv += -du_dmT.real
else:
raise Exception('Must be real or imag')
# Clean the factorization, clear memory.
ATinv.clean()
return Jtv
+351
View File
@@ -0,0 +1,351 @@
from SimPEG import Survey, Utils, Problem, np, sp, mkvc
from scipy.constants import mu_0
import sys
from numpy.lib import recfunctions as recFunc
from SimPEG.EM.Utils import omega
##############
### Fields ###
##############
class BaseMTFields(Problem.Fields):
"""Field Storage for a MT survey."""
knownFields = {}
dtype = complex
class Fields1D_e(BaseMTFields):
"""
Fields storage for the 1D MT solution.
"""
knownFields = {'e_1dSolution':'F'}
aliasFields = {
'e_1d' : ['e_1dSolution','F','_e'],
'e_1dPrimary' : ['e_1dSolution','F','_ePrimary'],
'e_1dSecondary' : ['e_1dSolution','F','_eSecondary'],
'b_1d' : ['e_1dSolution','E','_b'],
'b_1dPrimary' : ['e_1dSolution','E','_bPrimary'],
'b_1dSecondary' : ['e_1dSolution','E','_bSecondary']
}
def __init__(self,mesh,survey,**kwargs):
BaseMTFields.__init__(self,mesh,survey,**kwargs)
def _ePrimary(self, eSolution, srcList):
ePrimary = np.zeros_like(eSolution)
for i, src in enumerate(srcList):
ep = src.ePrimary(self.survey.prob)
if ep is not None:
ePrimary[:,i] = ep[:,-1]
return ePrimary
def _eSecondary(self, eSolution, srcList):
return eSolution
def _e(self, eSolution, srcList):
return self._ePrimary(eSolution,srcList) + self._eSecondary(eSolution,srcList)
def _eDeriv_u(self, src, v, adjoint = False):
return v
def _eDeriv_m(self, src, v, adjoint = False):
# assuming primary does not depend on the model
return None
def _bPrimary(self, eSolution, srcList):
bPrimary = np.zeros([self.survey.mesh.nE,eSolution.shape[1]], dtype = complex)
for i, src in enumerate(srcList):
bp = src.bPrimary(self.survey.prob)
if bp is not None:
bPrimary[:,i] += bp[:,-1]
return bPrimary
def _bSecondary(self, eSolution, srcList):
C = self.mesh.nodalGrad
b = (C * eSolution)
for i, src in enumerate(srcList):
b[:,i] *= - 1./(1j*omega(src.freq))
# There is no magnetic source in the MT problem
# S_m, _ = src.eval(self.survey.prob)
# if S_m is not None:
# b[:,i] += 1./(1j*omega(src.freq)) * S_m
return b
def _b(self, eSolution, srcList):
return self._bPrimary(eSolution, srcList) + self._bSecondary(eSolution, srcList)
def _bSecondaryDeriv_u(self, src, v, adjoint = False):
C = self.mesh.nodalGrad
if adjoint:
return - 1./(1j*omega(src.freq)) * (C.T * v)
return - 1./(1j*omega(src.freq)) * (C * v)
def _bSecondaryDeriv_m(self, src, v, adjoint = False):
# Doesn't depend on m
# _, S_eDeriv = src.evalDeriv(self.survey.prob, adjoint)
# S_eDeriv = S_eDeriv(v)
# if S_eDeriv is not None:
# return 1./(1j * omega(src.freq)) * S_eDeriv
return None
def _bDeriv_u(self, src, v, adjoint=False):
# Primary does not depend on u
return self._bSecondaryDeriv_u(src, v, adjoint)
def _bDeriv_m(self, src, v, adjoint=False):
# Assuming the primary does not depend on the model
return self._bSecondaryDeriv_m(src, v, adjoint)
def _fDeriv_u(self, src, v, adjoint=False):
"""
Derivative of the fields object wrt u.
:param MTsrc src: MT source
:param numpy.ndarray v: random vector of f_sol.size
This function stacks the fields derivatives appropriately
return a vector of size (nreEle+nrbEle)
"""
de_du = v #Utils.spdiag(np.ones((self.nF,)))
db_du = self._bDeriv_u(src, v, adjoint)
# Return the stack
# This doesn't work...
return np.vstack((de_du,db_du))
def _fDeriv_m(self, src, v, adjoint=False):
"""
Derivative of the fields object wrt m.
This function stacks the fields derivatives appropriately
"""
return None
class Fields3D_e(BaseMTFields):
"""
Fields storage for the 3D MT solution. Labels polarizations by px and py.
:param SimPEG object mesh: The solution mesh
:param SimPEG object survey: A survey object
"""
# Define the known the alias fields
# Assume that the solution of e on the E.
## NOTE: Need to make this more general, to allow for other solutions formats.
knownFields = {'e_pxSolution':'E','e_pySolution':'E'}
aliasFields = {
'e_px' : ['e_pxSolution','E','_e_px'],
'e_pxPrimary' : ['e_pxSolution','E','_e_pxPrimary'],
'e_pxSecondary' : ['e_pxSolution','E','_e_pxSecondary'],
'e_py' : ['e_pySolution','E','_e_py'],
'e_pyPrimary' : ['e_pySolution','E','_e_pyPrimary'],
'e_pySecondary' : ['e_pySolution','E','_e_pySecondary'],
'b_px' : ['e_pxSolution','F','_b_px'],
'b_pxPrimary' : ['e_pxSolution','F','_b_pxPrimary'],
'b_pxSecondary' : ['e_pxSolution','F','_b_pxSecondary'],
'b_py' : ['e_pySolution','F','_b_py'],
'b_pyPrimary' : ['e_pySolution','F','_b_pyPrimary'],
'b_pySecondary' : ['e_pySolution','F','_b_pySecondary']
}
def __init__(self,mesh,survey,**kwargs):
BaseMTFields.__init__(self,mesh,survey,**kwargs)
def _e_pxPrimary(self, e_pxSolution, srcList):
e_pxPrimary = np.zeros_like(e_pxSolution)
for i, src in enumerate(srcList):
ep = src.ePrimary(self.survey.prob)
if ep is not None:
e_pxPrimary[:,i] = ep[:,0]
return e_pxPrimary
def _e_pyPrimary(self, e_pySolution, srcList):
e_pyPrimary = np.zeros_like(e_pySolution)
for i, src in enumerate(srcList):
ep = src.ePrimary(self.survey.prob)
if ep is not None:
e_pyPrimary[:,i] = ep[:,1]
return e_pyPrimary
def _e_pxSecondary(self, e_pxSolution, srcList):
return e_pxSolution
def _e_pySecondary(self, e_pySolution, srcList):
return e_pySolution
def _e_px(self, e_pxSolution, srcList):
return self._e_pxPrimary(e_pxSolution,srcList) + self._e_pxSecondary(e_pxSolution,srcList)
def _e_py(self, e_pySolution, srcList):
return self._e_pyPrimary(e_pySolution,srcList) + self._e_pySecondary(e_pySolution,srcList)
#NOTE: For e_p?Deriv_u,
# v has to be u(2*nE) long for the not adjoint and nE long for adjoint.
# Returns nE long for not adjoint and 2*nE long for adjoint
def _e_pxDeriv_u(self, src, v, adjoint = False):
'''
Takes the derivative of e_px wrt u
'''
if adjoint:
# adjoint: returns a 2*nE long vector with zero's for py
return np.vstack((v,np.zeros_like(v)))
# Not adjoint: return only the px part of the vector
return v[:len(v)/2]
def _e_pyDeriv_u(self, src, v, adjoint = False):
'''
Takes the derivative of e_py wrt u
'''
if adjoint:
# adjoint: returns a 2*nE long vector with zero's for px
return np.vstack((np.zeros_like(v),v))
# Not adjoint: return only the px part of the vector
return v[len(v)/2::]
def _e_pxDeriv_m(self, src, v, adjoint = False):
# assuming primary does not depend on the model
return None
def _e_pyDeriv_m(self, src, v, adjoint = False):
# assuming primary does not depend on the model
return None
def _b_pxPrimary(self, e_pxSolution, srcList):
b_pxPrimary = np.zeros([self.survey.mesh.nF,e_pxSolution.shape[1]], dtype = complex)
for i, src in enumerate(srcList):
bp = src.bPrimary(self.survey.prob)
if bp is not None:
b_pxPrimary[:,i] += bp[:,0]
return b_pxPrimary
def _b_pyPrimary(self, e_pySolution, srcList):
b_pyPrimary = np.zeros([self.survey.mesh.nF,e_pySolution.shape[1]], dtype = complex)
for i, src in enumerate(srcList):
bp = src.bPrimary(self.survey.prob)
if bp is not None:
b_pyPrimary[:,i] += bp[:,1]
return b_pyPrimary
def _b_pxSecondary(self, e_pxSolution, srcList):
C = self.mesh.edgeCurl
b = (C * e_pxSolution)
for i, src in enumerate(srcList):
b[:,i] *= - 1./(1j*omega(src.freq))
# There is no magnetic source in the MT problem
# S_m, _ = src.eval(self.survey.prob)
# if S_m is not None:
# b[:,i] += 1./(1j*omega(src.freq)) * S_m
return b
def _b_pySecondary(self, e_pySolution, srcList):
C = self.mesh.edgeCurl
b = (C * e_pySolution)
for i, src in enumerate(srcList):
b[:,i] *= - 1./(1j*omega(src.freq))
# There is no magnetic source in the MT problem
# S_m, _ = src.eval(self.survey.prob)
# if S_m is not None:
# b[:,i] += 1./(1j*omega(src.freq)) * S_m
return b
def _b_px(self, eSolution, srcList):
return self._b_pxPrimary(eSolution, srcList) + self._b_pxSecondary(eSolution, srcList)
def _b_py(self, eSolution, srcList):
return self._b_pyPrimary(eSolution, srcList) + self._b_pySecondary(eSolution, srcList)
# NOTE: v needs to be length 2*nE to account for both polarizations
def _b_pxSecondaryDeriv_u(self, src, v, adjoint = False):
# C = sp.kron(self.mesh.edgeCurl,[[1,0],[0,0]])
C = sp.hstack((self.mesh.edgeCurl,Utils.spzeros(self.mesh.nF,self.mesh.nE))) # This works for adjoint = None
if adjoint:
return - 1./(1j*omega(src.freq)) * (C.T * v)
return - 1./(1j*omega(src.freq)) * (C * v)
def _b_pySecondaryDeriv_u(self, src, v, adjoint = False):
# C = sp.kron(self.mesh.edgeCurl,[[0,0],[0,1]])
C = sp.hstack((Utils.spzeros(self.mesh.nF,self.mesh.nE),self.mesh.edgeCurl)) # This works for adjoint = None
if adjoint:
return - 1./(1j*omega(src.freq)) * (C.T * v)
return - 1./(1j*omega(src.freq)) * (C * v)
def _b_pxSecondaryDeriv_m(self, src, v, adjoint = False):
# Doesn't depend on m
# _, S_eDeriv = src.evalDeriv(self.survey.prob, adjoint)
# S_eDeriv = S_eDeriv(v)
# if S_eDeriv is not None:
# return 1./(1j * omega(src.freq)) * S_eDeriv
return None
def _b_pySecondaryDeriv_m(self, src, v, adjoint = False):
# Doesn't depend on m
# _, S_eDeriv = src.evalDeriv(self.survey.prob, adjoint)
# S_eDeriv = S_eDeriv(v)
# if S_eDeriv is not None:
# return 1./(1j * omega(src.freq)) * S_eDeriv
return None
def _b_pxDeriv_u(self, src, v, adjoint=False):
# Primary does not depend on u
return self._b_pxSecondaryDeriv_u(src, v, adjoint)
def _b_pyDeriv_u(self, src, v, adjoint=False):
# Primary does not depend on u
return self._b_pySecondaryDeriv_u(src, v, adjoint)
def _b_pxDeriv_m(self, src, v, adjoint=False):
# Assuming the primary does not depend on the model
return self._b_pxSecondaryDeriv_m(src, v, adjoint)
def _b_pyDeriv_m(self, src, v, adjoint=False):
# Assuming the primary does not depend on the model
return self._b_pySecondaryDeriv_m(src, v, adjoint)
def _f_pxDeriv_u(self, src, v, adjoint=False):
"""
Derivative of the fields object wrt u.
:param MTsrc src: MT source
:param numpy.ndarray v: random vector of f_sol.size
This function stacks the fields derivatives appropriately
return a vector of size (nreEle+nrbEle)
"""
de_du = v #Utils.spdiag(np.ones((self.nF,)))
db_du = self._b_pxDeriv_u(src, v, adjoint)
# Return the stack
# This doesn't work...
return np.vstack((de_du,db_du))
def _f_pyDeriv_u(self, src, v, adjoint=False):
"""
Derivative of the fields object wrt u.
:param MTsrc src: MT source
:param numpy.ndarray v: random vector of f_sol.size
This function stacks the fields derivatives appropriately
return a vector of size (nreEle+nrbEle)
"""
de_du = v #Utils.spdiag(np.ones((self.nF,)))
db_du = self._b_pyDeriv_u(src, v, adjoint)
# Return the stack
# This doesn't work...
return np.vstack((de_du,db_du))
def _f_pxDeriv_m(self, src, v, adjoint=False):
"""
Derivative of the fields object wrt m.
This function stacks the fields derivatives appropriately
"""
# The fields have no dependance to the model.
return None
def _f_pyDeriv_m(self, src, v, adjoint=False):
"""
Derivative of the fields object wrt m.
This function stacks the fields derivatives appropriately
"""
# The fields have no dependance to the model.
return None
+291
View File
@@ -0,0 +1,291 @@
from SimPEG.EM.Utils import omega
from SimPEG import mkvc
from scipy.constants import mu_0
from SimPEG.MT.BaseMT import BaseMTProblem
from SimPEG.MT.SurveyMT import Survey, Data
from SimPEG.MT.FieldsMT import Fields1D_e
from SimPEG.MT.Utils.MT1Danalytic import getEHfields
import numpy as np
import multiprocessing, sys, time
class eForm_psField(BaseMTProblem):
"""
A MT problem soving a e formulation and primary/secondary fields decomposion.
By eliminating the magnetic flux density using
.. math ::
\mathbf{b} = \\frac{1}{i \omega}\\left(-\mathbf{C} \mathbf{e} \\right)
we can write Maxwell's equations as a second order system in \\\(\\\mathbf{e}\\\) only:
.. math ::
\\left(\mathbf{C}^T \mathbf{M^e_{\mu^{-1}}} \mathbf{C} + i \omega \mathbf{M^f_\sigma}] \mathbf{e}_{s} =& i \omega \mathbf{M^f_{\delta \sigma}} \mathbf{e}_{p}
which we solve for \\\(\\\mathbf{e_s}\\\). The total field \\\mathbf{e}\\ = \\\mathbf{e_p}\\ + \\\mathbf{e_s}\\.
The primary field is estimated from a background model (commonly half space ).
"""
# From FDEMproblem: Used to project the fields. Currently not used for MTproblem.
_fieldType = 'e_1d'
_eqLocs = 'EF'
_sigmaPrimary = None
def __init__(self, mesh, **kwargs):
BaseMTProblem.__init__(self, mesh, **kwargs)
self.fieldsPair = Fields1D_e
# self._sigmaPrimary = sigmaPrimary
@property
def MeMui(self):
"""
Edge inner product matrix
"""
if getattr(self, '_MeMui', None) is None:
self._MeMui = self.mesh.getEdgeInnerProduct(1.0/mu_0)
return self._MeMui
@property
def MfSigma(self):
"""
Edge inner product matrix
"""
if getattr(self, '_MfSigma', None) is None:
self._MfSigma = self.mesh.getFaceInnerProduct(self.curModel.sigma)
return self._MfSigma
@property
def sigmaPrimary(self):
"""
A background model, use for the calculation of the primary fields.
"""
return self._sigmaPrimary
@sigmaPrimary.setter
def sigmaPrimary(self, val):
# Note: TODO add logic for val, make sure it is the correct size.
self._sigmaPrimary = val
def getA(self, freq):
"""
Function to get the A matrix.
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
# Note: need to use the code above since in the 1D problem I want
# e to live on Faces(nodes) and h on edges(cells). Might need to rethink this
# Possible that _fieldType and _eqLocs can fix this
MeMui = self.MeMui
MfSigma = self.MfSigma
C = self.mesh.nodalGrad
# Make A
A = C.T*MeMui*C + 1j*omega(freq)*MfSigma
# Either return full or only the inner part of A
return A
def getADeriv_m(self, freq, u, v, adjoint=False):
"""
The derivative of A wrt sigma
"""
dsig_dm = self.curModel.sigmaDeriv
MeMui = self.MeMui
#
u_src = u['e_1dSolution']
dMfSigma_dm = self.mesh.getFaceInnerProductDeriv(self.curModel.sigma)(u_src) * self.curModel.sigmaDeriv
if adjoint:
return 1j * omega(freq) * ( dMfSigma_dm.T * v )
# Note: output has to be nN/nF, not nC/nE.
# v should be nC
return 1j * omega(freq) * ( dMfSigma_dm * v )
def getRHS(self, freq):
"""
Function to return the right hand side for the system.
:param float freq: Frequency
:rtype: numpy.ndarray (nF, 1), numpy.ndarray (nF, 1)
:return: RHS for 1 polarizations, primary fields
"""
# Get sources for the frequncy(polarizations)
Src = self.survey.getSrcByFreq(freq)[0]
S_e = Src.S_e(self)
return -1j * omega(freq) * S_e
def getRHSDeriv_m(self, freq, v, adjoint=False):
"""
The derivative of the RHS wrt sigma
"""
Src = self.survey.getSrcByFreq(freq)[0]
S_eDeriv = Src.S_eDeriv_m(self, v, adjoint)
return -1j * omega(freq) * S_eDeriv
def fields(self, m):
'''
Function to calculate all the fields for the model m.
:param np.ndarray (nC,) m: Conductivity model
'''
# Set the current model
self.curModel = m
F = Fields1D_e(self.mesh, self.survey)
for freq in self.survey.freqs:
if self.verbose:
startTime = time.time()
print 'Starting work for {:.3e}'.format(freq)
sys.stdout.flush()
A = self.getA(freq)
rhs = self.getRHS(freq)
Ainv = self.Solver(A, **self.solverOpts)
e_s = Ainv * rhs
# Store the fields
Src = self.survey.getSrcByFreq(freq)[0]
# NOTE: only store the e_solution(secondary), all other components calculated in the fields object
F[Src, 'e_1dSolution'] = e_s[:,-1] # Only storing the yx polarization as 1d
# Note curl e = -iwb so b = -curl e /iw
# b = -( self.mesh.nodalGrad * e )/( 1j*omega(freq) )
# F[Src, 'b_1d'] = b[:,1]
if self.verbose:
print 'Ran for {:f} seconds'.format(time.time()-startTime)
sys.stdout.flush()
return F
# Note this is not fully functional.
# Missing:
# Fields class corresponding to the fields
# Update Jvec and Jtvec to include all the derivatives components
# Other things ...
class eForm_TotalField(BaseMTProblem):
"""
A MT problem solving a e formulation and a Total bondary domain decompostion.
Solves the equation:
Math:
"""
# From FDEMproblem: Used to project the fields. Currently not used for MTproblem.
_fieldType = 'e'
_eqLocs = 'EF'
def __init__(self, mesh, **kwargs):
BaseMTProblem.__init__(self, mesh, **kwargs)
@property
def MeMui(self):
"""
Edge inner product matrix
"""
if getattr(self, '_MeMui', None) is None:
self._MeMui = self.mesh.getEdgeInnerProduct(1.0/mu_0)
return self._MeMui
@property
def MfSigma(self):
"""
Edge inner product matrix
"""
if getattr(self, '_MfSigma', None) is None:
self._MfSigma = self.mesh.getFaceInnerProduct(self.curModel.sigma)
return self._MfSigma
def getA(self, freq, full=False):
"""
Function to get the A matrix.
:param float freq: Frequency
:param logic full: Return full A or the inner part
:rtype: scipy.sparse.csr_matrix
:return: A
"""
MeMui = self.MeMui
MfSigma = self.MfSigma
# Note: need to use the code above since in the 1D problem I want
# e to live on Faces(nodes) and h on edges(cells). Might need to rethink this
# Possible that _fieldType and _eqLocs can fix this
# MeMui = self.MfMui
# MfSigma = self.MfSigma
C = self.mesh.nodalGrad
# Make A
A = C.T*MeMui*C + 1j*omega(freq)*MfSigma
# Either return full or only the inner part of A
if full:
return A
else:
return A[1:-1,1:-1]
def getADeriv_m(self, freq, u, v, adjoint=False):
raise NotImplementedError('getADeriv is not implemented')
def getRHS(self, freq):
"""
Function to return the right hand side for the system.
:param float freq: Frequency
:rtype: numpy.ndarray (nE, 2), numpy.ndarray (nE, 2)
:return: RHS for both polarizations, primary fields
"""
# Get sources for the frequency
# NOTE: Need to use the source information, doesn't really apply in 1D
src = self.survey.getSrcByFreq(freq)
# Get the full A
A = self.getA(freq,full=True)
# Define the outer part of the solution matrix
Aio = A[1:-1,[0,-1]]
Ed, Eu, Hd, Hu = getEHfields(self.mesh,self.curModel.sigma,freq,self.mesh.vectorNx)
Etot = (Ed + Eu)
sourceAmp = 1.0
Etot = ((Etot/Etot[-1])*sourceAmp) # Scale the fields to be equal to sourceAmp at the top
## Note: The analytic solution is derived with e^iwt
eBC = np.r_[Etot[0],Etot[-1]]
# The right hand side
return -Aio*eBC, eBC
def getRHSderiv_m(self, freq, backSigma, u, v, adjoint=False):
raise NotImplementedError('getRHSDeriv not implemented yet')
return None
def fields(self, m):
'''
Function to calculate all the fields for the model m.
:param np.ndarray (nC,) m: Conductivity model
:param np.ndarray (nC,) m_back: Background conductivity model
'''
self.curModel = m
# RHS, CalcFields = self.getRHS(freq,m_back), self.calcFields
F = Fields1D_e(self.mesh, self.survey)
for freq in self.survey.freqs:
if self.verbose:
startTime = time.time()
print 'Starting work for {:.3e}'.format(freq)
sys.stdout.flush()
A = self.getA(freq)
rhs, e_o = self.getRHS(freq)
Ainv = self.Solver(A, **self.solverOpts)
e_i = Ainv * rhs
e = mkvc(np.r_[e_o[0], e_i, e_o[1]],2)
# Store the fields
Src = self.survey.getSrcByFreq(freq)
# NOTE: only store e fields
F[Src, 'e_1dSolution'] = e[:,0]
if self.verbose:
print 'Ran for {:f} seconds'.format(time.time()-startTime)
sys.stdout.flush()
return F
+1
View File
@@ -0,0 +1 @@
from Probs import eForm_TotalField, eForm_psField
View File
+1
View File
@@ -0,0 +1 @@
pass
+138
View File
@@ -0,0 +1,138 @@
from SimPEG import Survey, Problem, Utils, Models, np, sp, mkvc, SolverLU as SimpegSolver
from SimPEG.EM.Utils import omega
from scipy.constants import mu_0
from SimPEG.MT.BaseMT import BaseMTProblem
from SimPEG.MT.SurveyMT import Survey, Data
from SimPEG.MT.FieldsMT import Fields3D_e
import multiprocessing, sys, time
class eForm_ps(BaseMTProblem):
"""
A MT problem solving a e formulation and a primary/secondary fields decompostion.
By eliminating the magnetic flux density using
.. math ::
\mathbf{b} = \\frac{1}{i \omega}\\left(-\mathbf{C} \mathbf{e} \\right)
we can write Maxwell's equations as a second order system in \\\(\\\mathbf{e}\\\) only:
.. math ::
\\left(\mathbf{C}^T \mathbf{M^f_{\mu^{-1}}} \mathbf{C} + i \omega \mathbf{M^e_\sigma}] \mathbf{e}_{s} =& i \omega \mathbf{M^e_{\delta \sigma}} \mathbf{e}_{p}
which we solve for \\\(\\\mathbf{e_s}\\\). The total field \\\mathbf{e}\\ = \\\mathbf{e_p}\\ + \\\mathbf{e_s}\\.
The primary field is estimated from a background model (commonly as a 1D model).
"""
# From FDEMproblem: Used to project the fields. Currently not used for MTproblem.
_fieldType = 'e'
_eqLocs = 'FE'
fieldsPair = Fields3D_e
_sigmaPrimary = None
def __init__(self, mesh, **kwargs):
BaseMTProblem.__init__(self, mesh, **kwargs)
@property
def sigmaPrimary(self):
"""
A background model, use for the calculation of the primary fields.
"""
return self._sigmaPrimary
@sigmaPrimary.setter
def sigmaPrimary(self, val):
# Note: TODO add logic for val, make sure it is the correct size.
self._sigmaPrimary = val
def getA(self, freq):
"""
Function to get the A system.
:param float freq: Frequency
:rtype: scipy.sparse.csr_matrix
:return: A
"""
Mmui = self.MfMui
Msig = self.MeSigma
C = self.mesh.edgeCurl
return C.T*Mmui*C + 1j*omega(freq)*Msig
def getADeriv_m(self, freq, u, v, adjoint=False):
"""
Calculate the derivative of A wrt m.
"""
# This considers both polarizations and returns a nE,2 matrix for each polarization
if adjoint:
dMe_dsigV = sp.hstack(( self.MeSigmaDeriv( u['e_pxSolution'] ).T, self.MeSigmaDeriv(u['e_pySolution'] ).T ))*v
else:
# Need a nE,2 matrix to be returned
dMe_dsigV = np.hstack(( mkvc(self.MeSigmaDeriv( u['e_pxSolution'] )*v,2), mkvc( self.MeSigmaDeriv(u['e_pySolution'] )*v,2) ))
return 1j * omega(freq) * dMe_dsigV
def getRHS(self, freq):
"""
Function to return the right hand side for the system.
:param float freq: Frequency
:rtype: numpy.ndarray (nE, 2), numpy.ndarray (nE, 2)
:return: RHS for both polarizations, primary fields
"""
# Get sources for the frequncy(polarizations)
Src = self.survey.getSrcByFreq(freq)[0]
S_e = Src.S_e(self)
return -1j * omega(freq) * S_e
def getRHSDeriv_m(self, freq, v, adjoint=False):
"""
The derivative of the RHS with respect to sigma
"""
Src = self.survey.getSrcByFreq(freq)[0]
S_eDeriv = Src.S_eDeriv_m(self, v, adjoint)
return -1j * omega(freq) * S_eDeriv
def fields(self, m):
'''
Function to calculate all the fields for the model m.
:param np.ndarray (nC,) m: Conductivity model
'''
# Set the current model
self.curModel = m
F = Fields3D_e(self.mesh, self.survey)
for freq in self.survey.freqs:
if self.verbose:
startTime = time.time()
print 'Starting work for {:.3e}'.format(freq)
sys.stdout.flush()
A = self.getA(freq)
rhs = self.getRHS(freq)
# Solve the system
Ainv = self.Solver(A, **self.solverOpts)
e_s = Ainv * rhs
# Store the fields
Src = self.survey.getSrcByFreq(freq)[0]
# Store the fieldss
F[Src, 'e_pxSolution'] = e_s[:,0]
F[Src, 'e_pySolution'] = e_s[:,1]
# Note curl e = -iwb so b = -curl/iw
if self.verbose:
print 'Ran for {:f} seconds'.format(time.time()-startTime)
sys.stdout.flush()
Ainv.clean()
return F
+1
View File
@@ -0,0 +1 @@
from Probs import eForm_ps
+206
View File
@@ -0,0 +1,206 @@
from SimPEG import Utils, Problem, Maps, np, sp, mkvc
from SimPEG.EM.FDEM.SrcFDEM import BaseSrc as FDEMBaseSrc
from SimPEG.EM.Utils import omega
from scipy.constants import mu_0
from numpy.lib import recfunctions as recFunc
from Utils.sourceUtils import homo1DModelSource
from Utils import rec2ndarr
import sys
#################
### Sources ###
#################
class BaseMTSrc(FDEMBaseSrc):
'''
Sources for the MT problem.
Use the SimPEG BaseSrc, since the source fields share properties with the transmitters.
:param float freq: The frequency of the source
:param list rxList: A list of receivers associated with the source
'''
freq = None #: Frequency (float)
def __init__(self, rxList, freq):
self.freq = float(freq)
FDEMBaseSrc.__init__(self, rxList)
# 1D sources
class polxy_1DhomotD(BaseMTSrc):
"""
MT source for both polarizations (x and y) for the total Domain.
It calculates fields calculated based on conditions on the boundary of the domain.
"""
def __init__(self, rxList, freq):
BaseMTSrc.__init__(self, rxList, freq)
# TODO: need to add the primary fields calc and source terms into the problem.
# Need to implement such that it works for all dims.
class polxy_1Dprimary(BaseMTSrc):
"""
MT source for both polarizations (x and y) given a 1D primary models.
It assigns fields calculated from the 1D model as fields in the full space of the problem.
"""
def __init__(self, rxList, freq):
# assert mkvc(self.mesh.hz.shape,1) == mkvc(sigma1d.shape,1),'The number of values in the 1D background model does not match the number of vertical cells (hz).'
self.sigma1d = None
BaseMTSrc.__init__(self, rxList, freq)
# Hidden property of the ePrimary
self._ePrimary = None
def ePrimary(self,problem):
# Get primary fields for both polarizations
if self.sigma1d is None:
# Set the sigma1d as the 1st column in the background model
if len(problem._sigmaPrimary) == problem.mesh.nC:
if problem.mesh.dim == 1:
self.sigma1d = problem.mesh.r(problem._sigmaPrimary,'CC','CC','M')[:]
elif problem.mesh.dim == 3:
self.sigma1d = problem.mesh.r(problem._sigmaPrimary,'CC','CC','M')[0,0,:]
# Or as the 1D model that matches the vertical cell number
elif len(problem._sigmaPrimary) == problem.mesh.nCz:
self.sigma1d = problem._sigmaPrimary
if self._ePrimary is None:
self._ePrimary = homo1DModelSource(problem.mesh,self.freq,self.sigma1d)
return self._ePrimary
def bPrimary(self,problem):
# Project ePrimary to bPrimary
# Satisfies the primary(background) field conditions
if problem.mesh.dim == 1:
C = problem.mesh.nodalGrad
elif problem.mesh.dim == 3:
C = problem.mesh.edgeCurl
bBG_bp = (- C * self.ePrimary(problem) )*(1/( 1j*omega(self.freq) ))
return bBG_bp
def S_e(self,problem):
"""
Get the electrical field source
"""
e_p = self.ePrimary(problem)
Map_sigma_p = Maps.Vertical1DMap(problem.mesh)
sigma_p = Map_sigma_p._transform(self.sigma1d)
# Make mass matrix
# Note: M(sig) - M(sig_p) = M(sig - sig_p)
# Need to deal with the edge/face discrepencies between 1d/2d/3d
if problem.mesh.dim == 1:
Mesigma = problem.mesh.getFaceInnerProduct(problem.curModel.sigma)
Mesigma_p = problem.mesh.getFaceInnerProduct(sigma_p)
if problem.mesh.dim == 2:
pass
if problem.mesh.dim == 3:
Mesigma = problem.MeSigma
Mesigma_p = problem.mesh.getEdgeInnerProduct(sigma_p)
return (Mesigma - Mesigma_p) * e_p
def S_eDeriv_m(self, problem, v, adjoint = False):
'''
Get the derivative of S_e wrt to sigma (m)
'''
# Need to deal with
if problem.mesh.dim == 1:
# Need to use the faceInnerProduct
MsigmaDeriv = problem.mesh.getFaceInnerProductDeriv(problem.curModel.sigma)(self.ePrimary(problem)[:,1]) * problem.curModel.sigmaDeriv
# MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2
if problem.mesh.dim == 2:
pass
if problem.mesh.dim == 3:
# Need to take the derivative of both u_px and u_py
ePri = self.ePrimary(problem)
# MsigmaDeriv = problem.MeSigmaDeriv(ePri[:,0]) + problem.MeSigmaDeriv(ePri[:,1])
# MsigmaDeriv = problem.MeSigmaDeriv(np.sum(ePri,axis=1))
if adjoint:
return sp.hstack(( problem.MeSigmaDeriv(ePri[:,0]).T, problem.MeSigmaDeriv(ePri[:,1]).T ))*v
else:
return np.hstack(( mkvc(problem.MeSigmaDeriv(ePri[:,0]) * v,2), mkvc(problem.MeSigmaDeriv(ePri[:,1])*v,2) ))
if adjoint:
#
return MsigmaDeriv.T * v
else:
# v should be nC size
return MsigmaDeriv * v
class polxy_3Dprimary(BaseMTSrc):
"""
MT source for both polarizations (x and y) given a 3D primary model. It assigns fields calculated from the 1D model
as fields in the full space of the problem.
"""
def __init__(self, rxList, freq):
# assert mkvc(self.mesh.hz.shape,1) == mkvc(sigma1d.shape,1),'The number of values in the 1D background model does not match the number of vertical cells (hz).'
self.sigmaPrimary = None
BaseMTSrc.__init__(self, rxList, freq)
# Hidden property of the ePrimary
self._ePrimary = None
def ePrimary(self,problem):
# Get primary fields for both polarizations
self.sigmaPrimary = problem._sigmaPrimary
if self._ePrimary is None:
self._ePrimary = homo3DModelSource(problem.mesh,self.sigmaPrimary,self.freq)
return self._ePrimary
def bPrimary(self,problem):
# Project ePrimary to bPrimary
# Satisfies the primary(background) field conditions
if problem.mesh.dim == 1:
C = problem.mesh.nodalGrad
elif problem.mesh.dim == 3:
C = problem.mesh.edgeCurl
bBG_bp = (- C * self.ePrimary(problem) )*(1/( 1j*omega(self.freq) ))
return bBG_bp
def S_e(self,problem):
"""
Get the electrical field source
"""
e_p = self.ePrimary(problem)
Map_sigma_p = Maps.Vertical1DMap(problem.mesh)
sigma_p = Map_sigma_p._transform(self.sigma1d)
# Make mass matrix
# Note: M(sig) - M(sig_p) = M(sig - sig_p)
# Need to deal with the edge/face discrepencies between 1d/2d/3d
if problem.mesh.dim == 1:
Mesigma = problem.mesh.getFaceInnerProduct(problem.curModel.sigma)
Mesigma_p = problem.mesh.getFaceInnerProduct(sigma_p)
if problem.mesh.dim == 2:
pass
if problem.mesh.dim == 3:
Mesigma = problem.MeSigma
Mesigma_p = problem.mesh.getEdgeInnerProduct(sigma_p)
return (Mesigma - Mesigma_p) * e_p
def S_eDeriv_m(self, problem, v, adjoint = False):
'''
Get the derivative of S_e wrt to sigma (m)
'''
# Need to deal with
if problem.mesh.dim == 1:
# Need to use the faceInnerProduct
MsigmaDeriv = problem.mesh.getFaceInnerProductDeriv(problem.curModel.sigma)(self.ePrimary(problem)[:,1]) * problem.curModel.sigmaDeriv
# MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2
if problem.mesh.dim == 2:
pass
if problem.mesh.dim == 3:
# Need to take the derivative of both u_px and u_py
ePri = self.ePrimary(problem)
# MsigmaDeriv = problem.MeSigmaDeriv(ePri[:,0]) + problem.MeSigmaDeriv(ePri[:,1])
# MsigmaDeriv = problem.MeSigmaDeriv(np.sum(ePri,axis=1))
if adjoint:
return sp.hstack(( problem.MeSigmaDeriv(ePri[:,0]).T, problem.MeSigmaDeriv(ePri[:,1]).T ))*v
else:
return np.hstack(( mkvc(problem.MeSigmaDeriv(ePri[:,0]) * v,2), mkvc(problem.MeSigmaDeriv(ePri[:,1])*v,2) ))
if adjoint:
#
return MsigmaDeriv.T * v
else:
# v should be nC size
return MsigmaDeriv * v
+562
View File
@@ -0,0 +1,562 @@
from SimPEG import Survey as SimPEGsurvey, Utils, Problem, Maps, np, sp, mkvc
from SimPEG.EM.FDEM.SrcFDEM import BaseSrc as FDEMBaseSrc
from SimPEG.EM.Utils import omega
from scipy.constants import mu_0
from numpy.lib import recfunctions as recFunc
from Utils import rec2ndarr
import SrcMT
import sys
#################
### Receivers ###
#################
class Rx(SimPEGsurvey.BaseRx):
"""
Class that defines natural source receivers.
See knownRxTypes for types of allowed receivers.
:param ndArray locs: Locations of the receivers
:param str rxType: The type of receiver
"""
knownRxTypes = {
# 3D impedance
'zxxr':['Z3D', 'real'],
'zxyr':['Z3D', 'real'],
'zyxr':['Z3D', 'real'],
'zyyr':['Z3D', 'real'],
'zxxi':['Z3D', 'imag'],
'zxyi':['Z3D', 'imag'],
'zyxi':['Z3D', 'imag'],
'zyyi':['Z3D', 'imag'],
# 2D impedance
# TODO:
# 1D impedance
'z1dr':['Z1D', 'real'],
'z1di':['Z1D', 'imag'],
# Tipper
'tzxr':['T3D','real'],
'tzxi':['T3D','imag'],
'tzyr':['T3D','real'],
'tzyi':['T3D','imag']
}
# TODO: Have locs as single or double coordinates for both or numerator and denominator separately, respectively.
def __init__(self, locs, rxType):
SimPEGsurvey.BaseRx.__init__(self, locs, rxType)
@property
def projType(self):
"""
Receiver type for projection.
"""
return self.knownRxTypes[self.rxType][0]
@property
def projComp(self):
"""Component projection (real/imag)"""
return self.knownRxTypes[self.rxType][1]
def eval(self, src, mesh, f):
'''
Project the fields to natural source data.
:param SrcMT src: The source of the fields to project
:param SimPEG.Mesh mesh:
:param FieldsMT f: Natural source fields object to project
'''
## NOTE: Assumes that e is on t
if self.projType is 'Z1D':
Pex = mesh.getInterpolationMat(self.locs[:,-1],'Fx')
Pbx = mesh.getInterpolationMat(self.locs[:,-1],'Ex')
ex = Pex*mkvc(f[src,'e_1d'],2)
bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0
# Note: Has a minus sign in front, to comply with quadrant calculations.
# Can be derived from zyx case for the 3D case.
f_part_complex = -ex/bx
# elif self.projType is 'Z2D':
elif self.projType is 'Z3D':
## NOTE: Assumes that e is on edges and b on the faces. Need to generalize that or use a prop of fields to determine that.
if self.locs.ndim == 3:
eFLocs = self.locs[:,:,0]
bFLocs = self.locs[:,:,1]
else:
eFLocs = self.locs
bFLocs = self.locs
# Get the projection
Pex = mesh.getInterpolationMat(eFLocs,'Ex')
Pey = mesh.getInterpolationMat(eFLocs,'Ey')
Pbx = mesh.getInterpolationMat(bFLocs,'Fx')
Pby = mesh.getInterpolationMat(bFLocs,'Fy')
# Get the fields at location
# px: x-polaration and py: y-polaration.
ex_px = Pex*f[src,'e_px']
ey_px = Pey*f[src,'e_px']
ex_py = Pex*f[src,'e_py']
ey_py = Pey*f[src,'e_py']
hx_px = Pbx*f[src,'b_px']/mu_0
hy_px = Pby*f[src,'b_px']/mu_0
hx_py = Pbx*f[src,'b_py']/mu_0
hy_py = Pby*f[src,'b_py']/mu_0
# Make the complex data
if 'zxx' in self.rxType:
f_part_complex = ( ex_px*hy_py - ex_py*hy_px)/(hx_px*hy_py - hx_py*hy_px)
elif 'zxy' in self.rxType:
f_part_complex = (-ex_px*hx_py + ex_py*hx_px)/(hx_px*hy_py - hx_py*hy_px)
elif 'zyx' in self.rxType:
f_part_complex = ( ey_px*hy_py - ey_py*hy_px)/(hx_px*hy_py - hx_py*hy_px)
elif 'zyy' in self.rxType:
f_part_complex = (-ey_px*hx_py + ey_py*hx_px)/(hx_px*hy_py - hx_py*hy_px)
elif self.projType is 'T3D':
if self.locs.ndim == 3:
horLoc = self.locs[:,:,0]
vertLoc = self.locs[:,:,1]
else:
horLoc = self.locs
vertLoc = self.locs
Pbx = mesh.getInterpolationMat(horLoc,'Fx')
Pby = mesh.getInterpolationMat(horLoc,'Fy')
Pbz = mesh.getInterpolationMat(vertLoc,'Fz')
bx_px = Pbx*f[src,'b_px']
by_px = Pby*f[src,'b_px']
bz_px = Pbz*f[src,'b_px']
bx_py = Pbx*f[src,'b_py']
by_py = Pby*f[src,'b_py']
bz_py = Pbz*f[src,'b_py']
if 'tzx' in self.rxType:
f_part_complex = (- by_px*bz_py + by_py*bz_px)/(bx_px*by_py - bx_py*by_px)
if 'tzy' in self.rxType:
f_part_complex = ( bx_px*bz_py - bx_py*bz_px)/(bx_px*by_py - bx_py*by_px)
else:
NotImplementedError('Projection of {:s} receiver type is not implemented.'.format(self.rxType))
# Get the real or imag component
real_or_imag = self.projComp
f_part = getattr(f_part_complex, real_or_imag)
# print f_part
return f_part
def evalDeriv(self, src, mesh, f, v, adjoint=False):
"""
The derivative of the projection wrt u
:param MTsrc src: MT source
:param TensorMesh mesh: Mesh defining the topology of the problem
:param MTfields f: MT fields object of the source
:param numpy.ndarray v: Random vector of size
"""
real_or_imag = self.projComp
if not adjoint:
if self.projType is 'Z1D':
Pex = mesh.getInterpolationMat(self.locs[:,-1],'Fx')
Pbx = mesh.getInterpolationMat(self.locs[:,-1],'Ex')
# ex = Pex*mkvc(f[src,'e_1d'],2)
# bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0
dP_de = -mkvc(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Pex*v),2)
dP_db = mkvc( Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)))*(Pbx*f._bDeriv_u(src,v)/mu_0),2)
PDeriv_complex = np.sum(np.hstack((dP_de,dP_db)),1)
elif self.projType is 'Z2D':
raise NotImplementedError('Has not been implement for 2D impedance tensor')
elif self.projType is 'Z3D':
if self.locs.ndim == 3:
eFLocs = self.locs[:,:,0]
bFLocs = self.locs[:,:,1]
else:
eFLocs = self.locs
bFLocs = self.locs
# Get the projection
Pex = mesh.getInterpolationMat(eFLocs,'Ex')
Pey = mesh.getInterpolationMat(eFLocs,'Ey')
Pbx = mesh.getInterpolationMat(bFLocs,'Fx')
Pby = mesh.getInterpolationMat(bFLocs,'Fy')
# Get the fields at location
# px: x-polaration and py: y-polaration.
ex_px = Pex*f[src,'e_px']
ey_px = Pey*f[src,'e_px']
ex_py = Pex*f[src,'e_py']
ey_py = Pey*f[src,'e_py']
hx_px = Pbx*f[src,'b_px']/mu_0
hy_px = Pby*f[src,'b_px']/mu_0
hx_py = Pbx*f[src,'b_py']/mu_0
hy_py = Pby*f[src,'b_py']/mu_0
# Derivatives as lambda functions
# The size of the diratives should be nD,nU
ex_px_u = lambda vec: Pex*f._e_pxDeriv_u(src,vec)
ey_px_u = lambda vec: Pey*f._e_pxDeriv_u(src,vec)
ex_py_u = lambda vec: Pex*f._e_pyDeriv_u(src,vec)
ey_py_u = lambda vec: Pey*f._e_pyDeriv_u(src,vec)
# NOTE: Think b_p?Deriv_u should return a 2*nF size matrix
hx_px_u = lambda vec: Pbx*f._b_pxDeriv_u(src,vec)/mu_0
hy_px_u = lambda vec: Pby*f._b_pxDeriv_u(src,vec)/mu_0
hx_py_u = lambda vec: Pbx*f._b_pyDeriv_u(src,vec)/mu_0
hy_py_u = lambda vec: Pby*f._b_pyDeriv_u(src,vec)/mu_0
# Update the input vector
sDiag = lambda t: Utils.sdiag(mkvc(t,2))
# Define the components of the derivative
Hd = sDiag(1./(sDiag(hx_px)*hy_py - sDiag(hx_py)*hy_px))
Hd_uV = sDiag(hy_py)*hx_px_u(v) + sDiag(hx_px)*hy_py_u(v) - sDiag(hx_py)*hy_px_u(v) - sDiag(hy_px)*hx_py_u(v)
# Calculate components
if 'zxx' in self.rxType:
Zij = sDiag(Hd*( sDiag(ex_px)*hy_py - sDiag(ex_py)*hy_px ))
ZijN_uV = sDiag(hy_py)*ex_px_u(v) + sDiag(ex_px)*hy_py_u(v) - sDiag(ex_py)*hy_px_u(v) - sDiag(hy_px)*ex_py_u(v)
elif 'zxy' in self.rxType:
Zij = sDiag(Hd*(-sDiag(ex_px)*hx_py + sDiag(ex_py)*hx_px ))
ZijN_uV = -sDiag(hx_py)*ex_px_u(v) - sDiag(ex_px)*hx_py_u(v) + sDiag(ex_py)*hx_px_u(v) + sDiag(hx_px)*ex_py_u(v)
elif 'zyx' in self.rxType:
Zij = sDiag(Hd*( sDiag(ey_px)*hy_py - sDiag(ey_py)*hy_px ))
ZijN_uV = sDiag(hy_py)*ey_px_u(v) + sDiag(ey_px)*hy_py_u(v) - sDiag(ey_py)*hy_px_u(v) - sDiag(hy_px)*ey_py_u(v)
elif 'zyy' in self.rxType:
Zij = sDiag(Hd*(-sDiag(ey_px)*hx_py + sDiag(ey_py)*hx_px ))
ZijN_uV = -sDiag(hx_py)*ey_px_u(v) - sDiag(ey_px)*hx_py_u(v) + sDiag(ey_py)*hx_px_u(v) + sDiag(hx_px)*ey_py_u(v)
# Calculate the complex derivative
PDeriv_complex = Hd * (ZijN_uV - Zij * Hd_uV )
elif self.projType is 'T3D':
if self.locs.ndim == 3:
eFLocs = self.locs[:,:,0]
bFLocs = self.locs[:,:,1]
else:
eFLocs = self.locs
bFLocs = self.locs
# Get the projection
Pbx = mesh.getInterpolationMat(bFLocs,'Fx')
Pby = mesh.getInterpolationMat(bFLocs,'Fy')
Pbz = mesh.getInterpolationMat(bFLocs,'Fz')
# Get the fields at location
# px: x-polaration and py: y-polaration.
bx_px = Pbx*f[src,'b_px']
by_px = Pby*f[src,'b_px']
bz_px = Pbz*f[src,'b_px']
bx_py = Pbx*f[src,'b_py']
by_py = Pby*f[src,'b_py']
bz_py = Pbz*f[src,'b_py']
# Derivatives as lambda functions
# NOTE: Think b_p?Deriv_u should return a 2*nF size matrix
bx_px_u = lambda vec: Pbx*f._b_pxDeriv_u(src,vec)
by_px_u = lambda vec: Pby*f._b_pxDeriv_u(src,vec)
bz_px_u = lambda vec: Pbz*f._b_pxDeriv_u(src,vec)
bx_py_u = lambda vec: Pbx*f._b_pyDeriv_u(src,vec)
by_py_u = lambda vec: Pby*f._b_pyDeriv_u(src,vec)
bz_py_u = lambda vec: Pbz*f._b_pyDeriv_u(src,vec)
# Update the input vector
sDiag = lambda t: Utils.sdiag(mkvc(t,2))
# Define the components of the derivative
Hd = sDiag(1./(sDiag(bx_px)*by_py - sDiag(bx_py)*by_px))
Hd_uV = sDiag(by_py)*bx_px_u(v) + sDiag(bx_px)*by_py_u(v) - sDiag(bx_py)*by_px_u(v) - sDiag(by_px)*bx_py_u(v)
if 'tzx' in self.rxType:
Tij = sDiag(Hd*( - sDiag(by_px)*bz_py + sDiag(by_py)*bz_px ))
TijN_uV = -sDiag(by_px)*bz_py_u(v) - sDiag(bz_py)*by_px_u(v) + sDiag(by_py)*bz_px_u(v) + sDiag(bz_px)*by_py_u(v)
elif 'tzy' in self.rxType:
Tij = sDiag(Hd*( sDiag(bx_px)*bz_py - sDiag(bx_py)*bz_px ))
TijN_uV = sDiag(bz_py)*bx_px_u(v) + sDiag(bx_px)*bz_py_u(v) - sDiag(bx_py)*bz_px_u(v) - sDiag(bz_px)*bx_py_u(v)
# Calculate the complex derivative
PDeriv_complex = Hd * (TijN_uV - Tij * Hd_uV )
# Extract the real number for the real/imag components.
Pv = np.array(getattr(PDeriv_complex, real_or_imag))
elif adjoint:
# Note: The v vector is real and the return should be complex
if self.projType is 'Z1D':
Pex = mesh.getInterpolationMat(self.locs[:,-1],'Fx')
Pbx = mesh.getInterpolationMat(self.locs[:,-1],'Ex')
# ex = Pex*mkvc(f[src,'e_1d'],2)
# bx = Pbx*mkvc(f[src,'b_1d'],2)/mu_0
dP_deTv = -mkvc(Pex.T*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0)).T*v,2)
db_duv = Pbx.T/mu_0*Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))*(Utils.sdiag(1./(Pbx*mkvc(f[src,'b_1d'],2)/mu_0))).T*Utils.sdiag(Pex*mkvc(f[src,'e_1d'],2)).T*v
dP_dbTv = mkvc(f._bDeriv_u(src,db_duv,adjoint=True),2)
PDeriv_real = np.sum(np.hstack((dP_deTv,dP_dbTv)),1)
elif self.projType is 'Z2D':
raise NotImplementedError('Has not be implement for 2D impedance tensor')
elif self.projType is 'Z3D':
if self.locs.ndim == 3:
eFLocs = self.locs[:,:,0]
bFLocs = self.locs[:,:,1]
else:
eFLocs = self.locs
bFLocs = self.locs
# Get the projection
Pex = mesh.getInterpolationMat(eFLocs,'Ex')
Pey = mesh.getInterpolationMat(eFLocs,'Ey')
Pbx = mesh.getInterpolationMat(bFLocs,'Fx')
Pby = mesh.getInterpolationMat(bFLocs,'Fy')
# Get the fields at location
# px: x-polaration and py: y-polaration.
aex_px = mkvc(mkvc(f[src,'e_px'],2).T*Pex.T)
aey_px = mkvc(mkvc(f[src,'e_px'],2).T*Pey.T)
aex_py = mkvc(mkvc(f[src,'e_py'],2).T*Pex.T)
aey_py = mkvc(mkvc(f[src,'e_py'],2).T*Pey.T)
ahx_px = mkvc(mkvc(f[src,'b_px'],2).T/mu_0*Pbx.T)
ahy_px = mkvc(mkvc(f[src,'b_px'],2).T/mu_0*Pby.T)
ahx_py = mkvc(mkvc(f[src,'b_py'],2).T/mu_0*Pbx.T)
ahy_py = mkvc(mkvc(f[src,'b_py'],2).T/mu_0*Pby.T)
# Derivatives as lambda functions
aex_px_u = lambda vec: f._e_pxDeriv_u(src,Pex.T*vec,adjoint=True)
aey_px_u = lambda vec: f._e_pxDeriv_u(src,Pey.T*vec,adjoint=True)
aex_py_u = lambda vec: f._e_pyDeriv_u(src,Pex.T*vec,adjoint=True)
aey_py_u = lambda vec: f._e_pyDeriv_u(src,Pey.T*vec,adjoint=True)
ahx_px_u = lambda vec: f._b_pxDeriv_u(src,Pbx.T*vec,adjoint=True)/mu_0
ahy_px_u = lambda vec: f._b_pxDeriv_u(src,Pby.T*vec,adjoint=True)/mu_0
ahx_py_u = lambda vec: f._b_pyDeriv_u(src,Pbx.T*vec,adjoint=True)/mu_0
ahy_py_u = lambda vec: f._b_pyDeriv_u(src,Pby.T*vec,adjoint=True)/mu_0
# Update the input vector
# Define shortcuts
sDiag = lambda t: Utils.sdiag(mkvc(t,2))
sVec = lambda t: Utils.sp.csr_matrix(mkvc(t,2))
# Define the components of the derivative
aHd = sDiag(1./(sDiag(ahx_px)*ahy_py - sDiag(ahx_py)*ahy_px))
aHd_uV = lambda x: ahx_px_u(sDiag(ahy_py)*x) + ahx_px_u(sDiag(ahy_py)*x) - ahy_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(ahy_px)*x)
# Need to fix this to reflect the adjoint
if 'zxx' in self.rxType:
Zij = sDiag(aHd*( sDiag(ahy_py)*aex_px - sDiag(ahy_px)*aex_py))
ZijN_uV = lambda x: aex_px_u(sDiag(ahy_py)*x) + ahy_py_u(sDiag(aex_px)*x) - ahy_px_u(sDiag(aex_py)*x) - aex_py_u(sDiag(ahy_px)*x)
elif 'zxy' in self.rxType:
Zij = sDiag(aHd*(-sDiag(ahx_py)*aex_px + sDiag(ahx_px)*aex_py))
ZijN_uV = lambda x:-aex_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(aex_px)*x) + ahx_px_u(sDiag(aex_py)*x) + aex_py_u(sDiag(ahx_px)*x)
elif 'zyx' in self.rxType:
Zij = sDiag(aHd*( sDiag(ahy_py)*aey_px - sDiag(ahy_px)*aey_py))
ZijN_uV = lambda x: aey_px_u(sDiag(ahy_py)*x) + ahy_py_u(sDiag(aey_px)*x) - ahy_px_u(sDiag(aey_py)*x) - aey_py_u(sDiag(ahy_px)*x)
elif 'zyy' in self.rxType:
Zij = sDiag(aHd*(-sDiag(ahx_py)*aey_px + sDiag(ahx_px)*aey_py))
ZijN_uV = lambda x:-aey_px_u(sDiag(ahx_py)*x) - ahx_py_u(sDiag(aey_px)*x) + ahx_px_u(sDiag(aey_py)*x) + aey_py_u(sDiag(ahx_px)*x)
# Calculate the complex derivative
PDeriv_real = ZijN_uV(aHd*v) - aHd_uV(Zij.T*aHd*v)#
# NOTE: Need to reshape the output to go from 2*nU array to a (nU,2) matrix for each polarization
# PDeriv_real = np.hstack((mkvc(PDeriv_real[:len(PDeriv_real)/2],2),mkvc(PDeriv_real[len(PDeriv_real)/2::],2)))
PDeriv_real = PDeriv_real.reshape((2,mesh.nE)).T
elif self.projType is 'T3D':
if self.locs.ndim == 3:
bFLocs = self.locs[:,:,1]
else:
bFLocs = self.locs
# Get the projection
Pbx = mesh.getInterpolationMat(bFLocs,'Fx')
Pby = mesh.getInterpolationMat(bFLocs,'Fy')
Pbz = mesh.getInterpolationMat(bFLocs,'Fz')
# Get the fields at location
# px: x-polaration and py: y-polaration.
abx_px = mkvc(mkvc(f[src,'b_px'],2).T*Pbx.T)
aby_px = mkvc(mkvc(f[src,'b_px'],2).T*Pby.T)
abz_px = mkvc(mkvc(f[src,'b_px'],2).T*Pbz.T)
abx_py = mkvc(mkvc(f[src,'b_py'],2).T*Pbx.T)
aby_py = mkvc(mkvc(f[src,'b_py'],2).T*Pby.T)
abz_py = mkvc(mkvc(f[src,'b_py'],2).T*Pbz.T)
# Derivatives as lambda functions
abx_px_u = lambda vec: f._b_pxDeriv_u(src,Pbx.T*vec,adjoint=True)
aby_px_u = lambda vec: f._b_pxDeriv_u(src,Pby.T*vec,adjoint=True)
abz_px_u = lambda vec: f._b_pxDeriv_u(src,Pbz.T*vec,adjoint=True)
abx_py_u = lambda vec: f._b_pyDeriv_u(src,Pbx.T*vec,adjoint=True)
aby_py_u = lambda vec: f._b_pyDeriv_u(src,Pby.T*vec,adjoint=True)
abz_py_u = lambda vec: f._b_pyDeriv_u(src,Pbz.T*vec,adjoint=True)
# Update the input vector
# Define shortcuts
sDiag = lambda t: Utils.sdiag(mkvc(t,2))
sVec = lambda t: Utils.sp.csr_matrix(mkvc(t,2))
# Define the components of the derivative
aHd = sDiag(1./(sDiag(abx_px)*aby_py - sDiag(abx_py)*aby_px))
aHd_uV = lambda x: abx_px_u(sDiag(aby_py)*x) + abx_px_u(sDiag(aby_py)*x) - aby_px_u(sDiag(abx_py)*x) - abx_py_u(sDiag(aby_px)*x)
# Need to fix this to reflect the adjoint
if 'tzx' in self.rxType:
Tij = sDiag(aHd*( -sDiag(abz_py)*aby_px + sDiag(abz_px)*aby_py))
TijN_uV = lambda x: -abz_py_u(sDiag(aby_px)*x) - aby_px_u(sDiag(abz_py)*x) + aby_py_u(sDiag(abz_px)*x) + abz_px_u(sDiag(aby_py)*x)
elif 'tzy' in self.rxType:
Tij = sDiag(aHd*( sDiag(abz_py)*abx_px - sDiag(abz_px)*abx_py))
TijN_uV = lambda x: abx_px_u(sDiag(abz_py)*x) + abz_py_u(sDiag(abx_px)*x) - abx_py_u(sDiag(abz_px)*x) - abz_px_u(sDiag(abx_py)*x)
# Calculate the complex derivative
PDeriv_real = TijN_uV(aHd*v) - aHd_uV(Tij.T*aHd*v)#
# NOTE: Need to reshape the output to go from 2*nU array to a (nU,2) matrix for each polarization
# PDeriv_real = np.hstack((mkvc(PDeriv_real[:len(PDeriv_real)/2],2),mkvc(PDeriv_real[len(PDeriv_real)/2::],2)))
PDeriv_real = PDeriv_real.reshape((2,mesh.nE)).T
# Extract the data
if real_or_imag == 'imag':
Pv = 1j*PDeriv_real
elif real_or_imag == 'real':
Pv = PDeriv_real.astype(complex)
return Pv
#################
### Survey ###
#################
class Survey(SimPEGsurvey.BaseSurvey):
"""
Survey class for MT. Contains all the sources associated with the survey.
:param list srcList: List of sources associated with the survey
"""
srcPair = SrcMT.BaseMTSrc
def __init__(self, srcList, **kwargs):
# Sort these by frequency
self.srcList = srcList
SimPEGsurvey.BaseSurvey.__init__(self, **kwargs)
_freqDict = {}
for src in srcList:
if src.freq not in _freqDict:
_freqDict[src.freq] = []
_freqDict[src.freq] += [src]
self._freqDict = _freqDict
self._freqs = sorted([f for f in self._freqDict])
@property
def freqs(self):
"""Frequencies"""
return self._freqs
@property
def nFreq(self):
"""Number of frequencies"""
return len(self._freqDict)
# TODO: Rename to getSources
def getSrcByFreq(self, freq):
"""Returns the sources associated with a specific frequency."""
assert freq in self._freqDict, "The requested frequency is not in this survey."
return self._freqDict[freq]
def eval(self, f):
data = Data(self)
for src in self.srcList:
sys.stdout.flush()
for rx in src.rxList:
data[src, rx] = rx.eval(src, self.mesh, f)
return data
def evalDeriv(self, f):
raise Exception('Use Transmitters to project fields deriv.')
#################
### Data ###
#################
class Data(SimPEGsurvey.Data):
'''
Data class for MTdata. Stores the data vector indexed by the survey.
:param SimPEG survey object survey:
:param v vector of the data in order matching of the survey
'''
def __init__(self, survey, v=None):
# Pass the variables to the "parent" method
SimPEGsurvey.Data.__init__(self, survey, v)
# # Import data
# @classmethod
# def fromEDIFiles():
# pass
def toRecArray(self,returnType='RealImag'):
'''
Function that returns a numpy.recarray for a SimpegMT impedance data object.
:param str returnType: Switches between returning a rec array where the impedance is split to real and imaginary ('RealImag') or is a complex ('Complex')
'''
# Define the record fields
dtRI = [('freq',float),('x',float),('y',float),('z',float),('zxxr',float),('zxxi',float),('zxyr',float),('zxyi',float),
('zyxr',float),('zyxi',float),('zyyr',float),('zyyi',float),('tzxr',float),('tzxi',float),('tzyr',float),('tzyi',float)]
dtCP = [('freq',float),('x',float),('y',float),('z',float),('zxx',complex),('zxy',complex),('zyx',complex),('zyy',complex),('tzx',complex),('tzy',complex)]
impList = ['zxxr','zxxi','zxyr','zxyi','zyxr','zyxi','zyyr','zyyi']
for src in self.survey.srcList:
# Temp array for all the receivers of the source.
# Note: needs to be written more generally, using diffterent rxTypes and not all the data at the locaitons
# Assume the same locs for all RX
locs = src.rxList[0].locs
if locs.shape[1] == 1:
locs = np.hstack((np.array([[0.0,0.0]]),locs))
elif locs.shape[1] == 2:
locs = np.hstack((np.array([[0.0]]),locs))
tArrRec = np.concatenate((src.freq*np.ones((locs.shape[0],1)),locs,np.nan*np.ones((locs.shape[0],12))),axis=1).view(dtRI)
# np.array([(src.freq,rx.locs[0,0],rx.locs[0,1],rx.locs[0,2],np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ,np.nan ) for rx in src.rxList],dtype=dtRI)
# Get the type and the value for the DataMT object as a list
typeList = [[rx.rxType.replace('z1d','zyx'),self[src,rx]] for rx in src.rxList]
# Insert the values to the temp array
for nr,(key,val) in enumerate(typeList):
tArrRec[key] = mkvc(val,2)
# Masked array
mArrRec = np.ma.MaskedArray(rec2ndarr(tArrRec),mask=np.isnan(rec2ndarr(tArrRec))).view(dtype=tArrRec.dtype)
# Unique freq and loc of the masked array
uniFLmarr = np.unique(mArrRec[['freq','x','y','z']]).copy()
try:
outTemp = recFunc.stack_arrays((outTemp,mArrRec))
#outTemp = np.concatenate((outTemp,dataBlock),axis=0)
except NameError as e:
outTemp = mArrRec
if 'RealImag' in returnType:
outArr = outTemp
elif 'Complex' in returnType:
# Add the real and imaginary to a complex number
outArr = np.empty(outTemp.shape,dtype=dtCP)
for comp in ['freq','x','y','z']:
outArr[comp] = outTemp[comp].copy()
for comp in ['zxx','zxy','zyx','zyy','tzx','tzy']:
outArr[comp] = outTemp[comp+'r'].copy() + 1j*outTemp[comp+'i'].copy()
else:
raise NotImplementedError('{:s} is not implemented, as to be RealImag or Complex.')
# Return
return outArr
@classmethod
def fromRecArray(cls, recArray, srcType='primary'):
"""
Class method that reads in a numpy record array to MTdata object.
Only imports the impedance data.
"""
if srcType=='primary':
src = SrcMT.polxy_1Dprimary
elif srcType=='total':
src = SrcMT.polxy_1DhomotD
else:
raise NotImplementedError('{:s} is not a valid source type for MTdata')
# Find all the frequencies in recArray
uniFreq = np.unique(recArray['freq'])
srcList = []
dataList = []
for freq in uniFreq:
# Initiate rxList
rxList = []
# Find that data for freq
dFreq = recArray[recArray['freq'] == freq].copy()
# Find the impedance rxTypes in the recArray.
rxTypes = [ comp for comp in recArray.dtype.names if (len(comp)==4 or len(comp)==3) and 'z' in comp]
for rxType in rxTypes:
# Find index of not nan values in rxType
notNaNind = ~np.isnan(dFreq[rxType])
if np.any(notNaNind): # Make sure that there is any data to add.
locs = rec2ndarr(dFreq[['x','y','z']][notNaNind].copy())
if dFreq[rxType].dtype.name in 'complex128':
rxList.append(Rx(locs,rxType+'r'))
dataList.append(dFreq[rxType][notNaNind].real.copy())
rxList.append(Rx(locs,rxType+'i'))
dataList.append(dFreq[rxType][notNaNind].imag.copy())
else:
rxList.append(Rx(locs,rxType))
dataList.append(dFreq[rxType][notNaNind].copy())
srcList.append(src(rxList,freq))
# Make a survey
survey = Survey(srcList)
dataVec = np.hstack(dataList)
return cls(survey,dataVec)
+108
View File
@@ -0,0 +1,108 @@
# Analytic solution of EM fields due to a plane wave
import numpy as np, SimPEG as simpeg
from scipy.constants import mu_0, epsilon_0 as eps_0
def getEHfields(m1d,sigma,freq,zd,scaleUD=True):
'''Analytic solution for MT 1D layered earth. Returns E and H fields.
:param SimPEG.mesh, object m1d: Mesh object with the 1D spatial information.
:param numpy.array, vector sigma: Physical property of conductivity corresponding with the mesh.
:param float, freq: Frequency to calculate data at.
:param numpy array, vector zd: location to calculate EH fields at
:param bollean, scaleUD: scales the output to be 1 at the top, increases numeracal stability.
Assumes a halfspace with the same conductive as the last cell below.
'''
# Note add an error check for the mesh and sigma are the same size.
# Constants: Assume constant
mu = mu_0*np.ones((m1d.nC+1))
eps = eps_0*np.ones((m1d.nC+1))
# Angular freq
w = 2*np.pi*freq
# Add the halfspace value to the property
sig = np.concatenate((np.array([sigma[0]]),sigma))
# Calculate the wave number
k = np.sqrt(eps*mu*w**2-1j*mu*sig*w)
# Initiate the propagation matrix, in the order down up.
UDp = np.zeros((2,m1d.nC+1),dtype=complex)
UDp[1,0] = 1. # Set the wave amplitude as 1 into the half-space at the bottom of the mesh
# Loop over all the layers, starting at the bottom layer
for lnr, h in enumerate(m1d.hx): # lnr-number of layer, h-thickness of the layer
# Calculate
yp1 = k[lnr]/(w*mu[lnr]) # Admittance of the layer below the current layer
zp = (w*mu[lnr+1])/k[lnr+1] # Impedance in the current layer
# Build the propagation matrix
# Convert fields to down/up going components in layer below current layer
Pj1 = np.array([[1,1],[yp1,-yp1]])
# Convert fields to down/up going components in current layer
Pjinv = 1./2*np.array([[1,zp],[1,-zp]])
# Propagate down and up components through the current layer
elamh = np.array([[np.exp(-1j*k[lnr+1]*h),0],[0,np.exp(1j*k[lnr+1]*h)]])
# The down and up component in current layer.
UDp[:,lnr+1] = elamh.dot(Pjinv.dot(Pj1)).dot(UDp[:,lnr])
if scaleUD:
UDp[:,lnr+1::-1] = UDp[:,lnr+1::-1]/UDp[1,lnr+1]
# Calculate the fields
Ed = np.empty((zd.size,),dtype=complex)
Eu = np.empty((zd.size,),dtype=complex)
Hd = np.empty((zd.size,),dtype=complex)
Hu = np.empty((zd.size,),dtype=complex)
# Loop over the layers and calculate the fields
# In the halfspace below the mesh
dup = m1d.vectorNx[0]
dind = dup >= zd
Ed[dind] = UDp[1,0]*np.exp(-1j*k[0]*(dup-zd[dind]))
Eu[dind] = UDp[0,0]*np.exp(1j*k[0]*(dup-zd[dind]))
Hd[dind] = (k[0]/(w*mu[0]))*UDp[1,0]*np.exp(-1j*k[0]*(dup-zd[dind]))
Hu[dind] = -(k[0]/(w*mu[0]))*UDp[0,0]*np.exp(1j*k[0]*(dup-zd[dind]))
for ki,mui,epsi,dlow,dup,Up,Dp in zip(k[1::],mu[1::],eps[1::],m1d.vectorNx[:-1],m1d.vectorNx[1::],UDp[0,1::],UDp[1,1::]):
dind = np.logical_and(dup >= zd, zd > dlow)
Ed[dind] = Dp*np.exp(-1j*ki*(dup-zd[dind]))
Eu[dind] = Up*np.exp(1j*ki*(dup-zd[dind]))
Hd[dind] = (ki/(w*mui))*Dp*np.exp(-1j*ki*(dup-zd[dind]))
Hu[dind] = -(ki/(w*mui))*Up*np.exp(1j*ki*(dup-zd[dind]))
# Return return the fields
return Ed, Eu, Hd, Hu
def getImpedance(m1d,sigma,freq):
"""Analytic solution for MT 1D layered earth. Returns the impedance at the surface.
:param SimPEG.mesh, object m1d: Mesh object with the 1D spatial information.
:param numpy.array, vector sigma: Physical property corresponding with the mesh.
:param numpy.array, vector freq: Frequencies to calculate data at.
"""
# Initiate the impedances
Z1d = np.empty(len(freq) , dtype='complex')
h = m1d.hx #vectorNx[:-1]
# Start the process
for nrFr, fr in enumerate(freq):
om = 2*np.pi*fr
Zall = np.empty(len(h)+1,dtype='complex')
# Calculate the impedance for the bottom layer
Zall[0] = (mu_0*om)/np.sqrt(mu_0*eps_0*(om)**2 - 1j*mu_0*sigma[0]*om)
for nr,hi in enumerate(h):
# Calculate the wave number
# print nr,sigma[nr]
k = np.sqrt(mu_0*eps_0*om**2 - 1j*mu_0*sigma[nr]*om)
Z = (mu_0*om)/k
Zall[nr+1] = Z *((Zall[nr] + Z*np.tanh(1j*k*hi))/(Z + Zall[nr]*np.tanh(1j*k*hi)))
#pdb.set_trace()
Z1d[nrFr] = Zall[-1]
return Z1d
+45
View File
@@ -0,0 +1,45 @@
import numpy as np, SimPEG as simpeg
from MT1Danalytic import getEHfields
from scipy.constants import mu_0
def get1DEfields(m1d,sigma,freq,sourceAmp=1.0):
"""Function to get 1D electrical fields"""
# Get the gradient
G = m1d.nodalGrad
# Mass matrices
# Magnetic permeability
Mmu = simpeg.Utils.sdiag(m1d.vol*(1.0/mu_0))
# Conductivity
Msig = m1d.getFaceInnerProduct(sigma)
# Set up the solution matrix
A = G.T*Mmu*G + 1j*2.*np.pi*freq*Msig
# Define the inner part of the solution matrix
Aii = A[1:-1,1:-1]
# Define the outer part of the solution matrix
Aio = A[1:-1,[0,-1]]
# Set the boundary conditions
Ed, Eu, Hd, Hu = getEHfields(m1d,sigma,freq,m1d.vectorNx)
Etot = (Ed + Eu)
if sourceAmp is not None:
Etot = ((Etot/Etot[-1])*sourceAmp) # Scale the fields to be equal to sourceAmp at the top
## Note: The analytic solution is derived with e^iwt
bc = np.r_[Etot[0],Etot[-1]]
# The right hand side
rhs = Aio*bc
# Solve the system
Aii_inv = simpeg.Solver(Aii)
eii = Aii_inv*rhs
# Assign the boundary conditions
e = np.r_[bc[0],eii,bc[1]]
# Return the electrical fields
return e
if __name__ == '__main__':
hz = [(100.,18)]
M = simpeg.Mesh.TensorMesh([hz],'C')
sig = np.zeros(M.nC) + 1e-8
sig[M.vectorCCx<=0] = sigHalf
+4
View File
@@ -0,0 +1,4 @@
from MT1Dsolutions import * # Add the names of the functions
from MT1Danalytic import *
from dataUtils import *
from ediFilesUtils import *
+245
View File
@@ -0,0 +1,245 @@
# Utils used for the data,
import numpy as np, matplotlib.pyplot as plt, sys
import SimPEG as simpeg
import numpy.lib.recfunctions as recFunc
from scipy.constants import mu_0
from scipy import interpolate as sciint
def getAppRes(MTdata):
# Make impedance
zList = []
for src in MTdata.survey.srcList:
zc = [src.freq]
for rx in src.rxList:
if 'i' in rx.rxType:
m=1j
else:
m = 1
zc.append(m*MTdata[src,rx])
zList.append(zc)
return [appResPhs(zList[i][0],np.sum(zList[i][1:3])) for i in np.arange(len(zList))]
def rotateData(MTdata,rotAngle):
'''
Function that rotates clockwist by rotAngle (- negative for a counter-clockwise rotation)
'''
recData = MTdata.toRecArray('Complex')
impData = rec2ndarr(recData[['zxx','zxy','zyx','zyy']],complex)
# Make the rotation matrix
# c,s,zxx,zxy,zyx,zyy = sympy.symbols('c,s,zxx,zxy,zyx,zyy')
# rotM = sympy.Matrix([[c,-s],[s, c]])
# zM = sympy.Matrix([[zxx,zxy],[zyx,zyy]])
# rotM*zM*rotM.T
# [c*(c*zxx - s*zyx) - s*(c*zxy - s*zyy), c*(c*zxy - s*zyy) + s*(c*zxx - s*zyx)],
# [c*(c*zyx + s*zxx) - s*(c*zyy + s*zxy), c*(c*zyy + s*zxy) + s*(c*zyx + s*zxx)]])
s = np.sin(-np.deg2rad(rotAngle))
c = np.cos(-np.deg2rad(rotAngle))
rotMat = np.array([[c,-s],[s,c]])
rotData = (rotMat.dot(impData.reshape(-1,2,2).dot(rotMat.T))).transpose(1,0,2).reshape(-1,4)
outRec = recData.copy()
for nr,comp in enumerate(['zxx','zxy','zyx','zyy']):
outRec[comp] = rotData[:,nr]
from SimPEG import MT
return MT.Data.fromRecArray(outRec)
def appResPhs(freq,z):
app_res = ((1./(8e-7*np.pi**2))/freq)*np.abs(z)**2
app_phs = np.arctan2(z.imag,z.real)*(180/np.pi)
return app_res, app_phs
def skindepth(rho,freq):
''' Function to calculate the skindepth of EM waves'''
return np.sqrt( (rho*((1/(freq * mu_0 * np.pi )))))
def rec2ndarr(x,dt=float):
return x.view((dt, len(x.dtype.names)))
def makeAnalyticSolution(mesh,model,elev,freqs):
from SimPEG import MT
data1D = []
for freq in freqs:
anaEd, anaEu, anaHd, anaHu = MT.Utils.MT1Danalytic.getEHfields(mesh,model,freq,elev)
anaE = anaEd+anaEu
anaH = anaHd+anaHu
anaZ = anaE/anaH
# Add to the list
data1D.append((freq,0,0,elev,anaZ[0]))
dataRec = np.array(data1D,dtype=[('freq',float),('x',float),('y',float),('z',float),('zyx',complex)])
return dataRec
def plotMT1DModelData(problem,models,symList=None):
from SimPEG import MT
# Setup the figure
fontSize = 15
fig = plt.figure(figsize=[9,7])
axM = fig.add_axes([0.075,.1,.25,.875])
axM.set_xlabel('Resistivity [Ohm*m]',fontsize=fontSize)
axM.set_xlim(1e-1,1e5)
axM.set_ylim(-10000,5000)
axM.set_ylabel('Depth [km]',fontsize=fontSize)
axR = fig.add_axes([0.42,.575,.5,.4])
axR.set_xscale('log')
axR.set_yscale('log')
axR.invert_xaxis()
# axR.set_xlabel('Frequency [Hz]')
axR.set_ylabel('Apparent resistivity [Ohm m]',fontsize=fontSize)
axP = fig.add_axes([0.42,.1,.5,.4])
axP.set_xscale('log')
axP.invert_xaxis()
axP.set_ylim(0,90)
axP.set_xlabel('Frequency [Hz]',fontsize=fontSize)
axP.set_ylabel('Apparent phase [deg]',fontsize=fontSize)
# if not symList:
# symList = ['x']*len(models)
import plotDataTypes as pDt
# Loop through the models.
modelList = [problem.survey.mtrue]
modelList.extend(models)
if False:
modelList = [problem.mapping.sigmaMap*mod for mod in modelList]
for nr, model in enumerate(modelList):
# Calculate the data
if nr==0:
data1D = problem.dataPair(problem.survey,problem.survey.dobs).toRecArray('Complex')
else:
data1D = problem.dataPair(problem.survey,problem.survey.dpred(model)).toRecArray('Complex')
# Plot the data and the model
colRat = nr/((len(modelList)-1.999)*1.)
if colRat > 1.:
col = 'k'
else:
col = plt.cm.seismic(1-colRat)
# The model - make the pts to plot
meshPts = np.concatenate((problem.mesh.gridN[0:1],np.kron(problem.mesh.gridN[1::],np.ones(2))[:-1]))
modelPts = np.kron(1./(problem.mapping.sigmaMap*model),np.ones(2,))
axM.semilogx(modelPts,meshPts,color=col)
## Data
# Appres
pDt.plotIsoStaImpedance(axR,np.array([0,0]),data1D,'zyx','res',pColor=col)
# Appphs
pDt.plotIsoStaImpedance(axP,np.array([0,0]),data1D,'zyx','phs',pColor=col)
try:
allData = np.concatenate((allData,simpeg.mkvc(data1D['zyx'],2)),1)
except:
allData = simpeg.mkvc(data1D['zyx'],2)
freq = simpeg.mkvc(data1D['freq'],2)
res, phs = appResPhs(freq,allData)
stdCol = 'gray'
axRtw = axR.twinx()
axRtw.set_ylabel('Std of log10',color=stdCol)
[(t.set_color(stdCol), t.set_rotation(-45)) for t in axRtw.get_yticklabels()]
axPtw = axP.twinx()
axPtw.set_ylabel('Std ',color=stdCol)
[t.set_color(stdCol) for t in axPtw.get_yticklabels()]
axRtw.plot(freq, np.std(np.log10(res),1),'--',color=stdCol)
axPtw.plot(freq, np.std(phs,1),'--',color=stdCol)
# Fix labels and ticks
yMtick = [l/1000 for l in axM.get_yticks().tolist()]
axM.set_yticklabels(yMtick)
[ l.set_rotation(90) for l in axM.get_yticklabels()]
[ l.set_rotation(90) for l in axR.get_yticklabels()]
[(t.set_color(stdCol), t.set_rotation(-45)) for t in axRtw.get_yticklabels()]
[t.set_color(stdCol) for t in axPtw.get_yticklabels()]
for ax in [axM,axR,axP]:
ax.xaxis.set_tick_params(labelsize=fontSize)
ax.yaxis.set_tick_params(labelsize=fontSize)
return fig
def printTime():
import time
print time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())
def convert3Dto1Dobject(MTdata,rxType3D='zyx'):
from SimPEG import MT
# Find the unique locations
# Need to find the locations
recDataTemp = MTdata.toRecArray()
# Check if survey.std has been assigned.
## NEED TO: write this...
# Calculte and add the DET of the tensor to the recArray
if 'det' in rxType3D:
Zon = (recDataTemp['zxxr']+1j*recDataTemp['zxxi'])*(recDataTemp['zyyr']+1j*recDataTemp['zyyi'])
Zoff = (recDataTemp['zxyr']+1j*recDataTemp['zxyi'])*(recDataTemp['zyxr']+1j*recDataTemp['zyxi'])
det = np.sqrt(Zon.data - Zoff.data)
recData = recFunc.append_fields(recDataTemp,['zdetr','zdeti'],[det.real,det.imag] )
else:
recData = recDataTemp
uniLocs = rec2ndarr(np.unique(recData[['x','y','z']])).data
mtData1DList = []
if 'zxy' in rxType3D:
corr = -1 # Shift the data to comply with the quadtrature of the 1d problem
else:
corr = 1
for loc in uniLocs:
# Make the receiver list
rx1DList = []
for rxType in ['z1dr','z1di']:
rx1DList.append(MT.Rx(simpeg.mkvc(loc,2).T,rxType))
# Source list
locrecData = recData[np.sqrt(np.sum( (rec2ndarr(recData[['x','y','z']]).data - loc )**2,axis=1)) < 1e-5]
dat1DList = []
src1DList = []
for freq in locrecData['freq']:
src1DList.append(MT.SrcMT.src_polxy_1Dprimary(rx1DList,freq))
for comp in ['r','i']:
dat1DList.append( corr * locrecData[rxType3D+comp][locrecData['freq']== freq].data )
# Make the survey
sur1D = MT.Survey(src1DList)
# Make the data
dataVec = np.hstack(dat1DList)
dat1D = MT.Data(sur1D,dataVec)
sur1D.dobs = dataVec
# Need to take MTdata.survey.std and split it as well.
std=0.05
sur1D.std = np.abs(sur1D.dobs*std) #+ 0.01*np.linalg.norm(sur1D.dobs)
mtData1DList.append(dat1D)
# Return the the list of data.
return mtData1DList
def resampleMTdataAtFreq(MTdata,freqs):
"""
Function to resample MTdata at set of frequencies
"""
from SimPEG import MT
# Make a rec array
MTrec = MTdata.toRecArray().data
# Find unique locations
uniLoc = np.unique(MTrec[['x','y','z']])
uniFreq = MTdata.survey.freqs
# Get the comps
dNames = MTrec.dtype
# Loop over all the locations and interpolate
for loc in uniLoc:
# Find the index of the station
ind = np.sqrt(np.sum((rec2ndarr(MTrec[['x','y','z']]) - rec2ndarr(loc))**2,axis=1)) < 1. # Find dist of 1 m accuracy
# Make a temporary recArray and interpolate all the components
tArrRec = np.concatenate((simpeg.mkvc(freqs,2),np.ones((len(freqs),1))*rec2ndarr(loc),np.nan*np.ones((len(freqs),12))),axis=1).view(dNames)
for comp in ['zxxr','zxxi','zxyr','zxyi','zyxr','zyxi','zyyr','zyyi','tzxr','tzxi','tzyr','tzyi']:
int1d = sciint.interp1d(MTrec[ind]['freq'],MTrec[ind][comp],bounds_error=False)
tArrRec[comp] = simpeg.mkvc(int1d(freqs),2)
# Join together
try:
outRecArr = recFunc.stack_arrays((outRecArr,tArrRec))
except NameError as e:
outRecArr = tArrRec
# Make the MTdata and return
return MT.Data.fromRecArray(outRecArr)
+180
View File
@@ -0,0 +1,180 @@
# Functions to import and export MT EDI files.
from SimPEG import mkvc
from scipy.constants import mu_0
from numpy.lib import recfunctions as recFunc
from SimPEG.MT.Utils.dataUtils import rec2ndarr
# Import modules
import numpy as np
import os, sys, re
class EDIimporter:
"""
A class to import EDIfiles.
"""
# Define data converters
_impUnitEDI2SI = 4*np.pi*1e-4 # Convert Z[mV/km/nT] (as in EDI)to Z[V/A] SI unit
_impUnitSI2EDI = 1./_impUnitEDI2SI # ConvertZ[V/A] SI unit to Z[mV/km/nT] (as in EDI)
# Properties
filesList = None
comps = None
# Hidden properties
_outEPSG = None # Project info
_2out = None # The projection operator
def __init__(self, EDIfilesList, compList=None, outEPSG=None):
# Set the fileList
self.filesList = EDIfilesList
# Set the components to import
if compList is None:
self.comps = ['ZXXR','ZXYR','ZYXR','ZYYR','ZXXI','ZXYI','ZYXI','ZYYI','ZXX.VAR','ZXY.VAR','ZYX.VAR','ZYY.VAR']
else:
self.comps = compList
if outEPSG is not None:
self._outEPSG = outEPSG
def __call__(self,comps=None):
if comps is None:
return self._data
return self._data[comps]
def importFiles(self):
"""
Function to import EDI files into a object.
"""
# Constants that are needed for convertion of units
# Temp lists
tmpStaList = []
tmpCompList = ['freq','x','y','z']
tmpCompList.extend(self.comps)
# Make the outarray
dtRI = [(compS.lower().replace('.',''),float) for compS in tmpCompList]
# Loop through all the files
for nrEDI, EDIfile in enumerate(self.filesList):
# Read the file into a list of the lines
with open(EDIfile,'r') as fid:
EDIlines = fid.readlines()
# Find the location
latD, longD, elevM = _findLatLong(EDIlines)
# Transfrom coordinates
transCoord = self._transfromPoints(longD,latD)
# Extract the name of the file (station)
EDIname = EDIfile.split(os.sep)[-1].split('.')[0]
# Arrange the data
staList = [EDIname, EDIfile, transCoord[0], transCoord[1], elevM[0]]
# Add to the station list
tmpStaList.extend(staList)
# Read the frequency data
freq = _findEDIcomp('>FREQ',EDIlines)
# Make the temporary rec array.
tArrRec = ( np.nan*np.ones( (len(freq),len(dtRI)) ) ).view(dtRI) #np.concatenate((freq*np.ones((locs.shape[0],1)),locs,np.nan*np.ones((locs.shape[0],8))),axis=1).view(dtRI)
# Add data to the array
tArrRec['freq'] = mkvc(freq,2)
tArrRec['x'] = mkvc(np.ones((len(freq),1))*transCoord[0],2)
tArrRec['y'] = mkvc(np.ones((len(freq),1))*transCoord[1],2)
tArrRec['z'] = mkvc(np.ones((len(freq),1))*elevM[0],2)
for comp in self.comps:
# Deal with converting units of the impedance tensor
if 'Z' in comp:
unitConvert = self._impUnitEDI2SI
else:
unitConvert = 1
# Rotate the data since EDI x is *north, y *east but Simpeg uses x *east, y *north (* means internal reference frame)
key = [comp.lower().replace('.','').replace(s,t) for s,t in [['xx','yy'],['xy','yx'],['yx','xy'],['yy','xx']] if s in comp.lower()][0]
tArrRec[key] = mkvc(unitConvert*_findEDIcomp('>'+comp,EDIlines),2)
# Make a masked array
mArrRec = np.ma.MaskedArray(rec2ndarr(tArrRec),mask=np.isnan(rec2ndarr(tArrRec))).view(dtype=tArrRec.dtype)
try:
outTemp = recFunc.stack_arrays((outTemp,mArrRec))
except NameError as e:
outTemp = mArrRec
# Assign the data
self._data = outTemp
# % Assign the data to the obj
# nOutData=length(obj.data);
# obj.data(nOutData+1:nOutData+length(TEMP.data),:) = TEMP.data;
def _transfromPoints(self,longD,latD):
# Import the coordinate projections
try:
import osr
except ImportError as e:
print 'Could not import osr, missing the gdal package\nCan not project coordinates'
raise e
# Coordinates convertor
if self._2out is None:
src = osr.SpatialReference()
src.ImportFromEPSG(4326)
out = osr.SpatialReference()
if self._outEPSG is None:
# Find the UTM EPSG number
Nnr = 700 if latD < 0.0 else 600
utmZ = int(1+(longD+180.0)/6.0)
self._outEPSG = 32000 + Nnr + utmZ
out.ImportFromEPSG(self._outEPSG)
self._2out = osr.CoordinateTransformation(src,out)
# Return the transfrom
return self._2out.TransformPoint(longD,latD)
# Hidden functions
def _findLatLong(fileLines):
latDMS = np.array(fileLines[_findLine('LAT=',fileLines)[0]].split('=')[1].split()[0].split(':'),float)
longDMS = np.array(fileLines[_findLine('LONG=',fileLines)[0]].split('=')[1].split()[0].split(':'),float)
elevM = np.array([fileLines[_findLine('ELEV=',fileLines)[0]].split('=')[1].split()[0]],float)
# Convert to D.ddddd values
latS = np.sign(latDMS[0])
longS = np.sign(longDMS[0])
latD = latDMS[0] + latS*latDMS[1]/60 + latS*latDMS[2]/3600
longD = longDMS[0] + longS*longDMS[1]/60 + longS*longDMS[2]/3600
return latD, longD, elevM
def _findLine(comp,fileLines):
""" Find a line number in the file"""
# Line counter
c = 0
# List of indices for found lines
found = []
# Loop through all the lines
for line in fileLines:
if comp in line:
# Append if found
found.append(c)
# Increse the counter
c += 1
# Return the found indices
return found
def _findEDIcomp(comp,fileLines,dt=float):
"""
Extract the data vector.
Returns a list of the data.
"""
# Find the data
headLine, indHead = [(st,nr) for nr,st in enumerate(fileLines) if re.search(comp,st)][0]
# Extract the data
nrVec = int(headLine.split()[-1])
c = 0
dataList = []
while c < nrVec:
indHead += 1
dataList.extend(fileLines[indHead].split())
c = len(dataList)
return np.array(dataList,dt)
+416
View File
@@ -0,0 +1,416 @@
from matplotlib import pyplot as plt, colors, numpy as np
def rec2nd(structArray):
""" Converts a structured/record array to ndarray to do operations on."""
return structArray.view((np.float,len(structArray.dtype.names)))
def plotIsoFreqNSimpedance(ax,freq,array,flag,par='abs',colorbar=True,colorNorm='SymLog',cLevel=True,contour=True):
indUniFreq = np.where(freq==array['freq'])
x, y = array['x'][indUniFreq],array['y'][indUniFreq]
if par == 'abs':
zPlot = np.abs(array[flag][indUniFreq])
cmap = plt.get_cmap('OrRd_r')#seismic')
level = np.logspace(0,-5,31)
clevel = np.logspace(0,-4,5)
plotNorm = colors.LogNorm()
elif par == 'real':
zPlot = np.real(array[flag][indUniFreq])
cmap = plt.get_cmap('RdYlBu')
if cLevel:
level = np.concatenate((-np.logspace(0,-10,31),np.logspace(-10,0,31)))
clevel = np.concatenate((-np.logspace(0,-8,5),np.logspace(-8,0,5)))
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
if colorNorm=='SymLog':
plotNorm = colors.SymLogNorm(1e-10,linscale=2)
else:
plotNorm = colors.Normalize()
elif par == 'imag':
zPlot = np.imag(array[flag][indUniFreq])
cmap = plt.get_cmap('RdYlBu')
level = np.concatenate((-np.logspace(0,-10,31),np.logspace(-10,0,31)))
clevel = np.concatenate((-np.logspace(0,-8,5),np.logspace(-8,0,5)))
plotNorm = colors.SymLogNorm(1e-10,linscale=2)
if cLevel:
level = np.concatenate((-np.logspace(0,-10,31),np.logspace(-10,0,31)))
clevel = np.concatenate((-np.logspace(0,-8,5),np.logspace(-8,0,5)))
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
if colorNorm=='SymLog':
plotNorm = colors.SymLogNorm(1e-10,linscale=2)
elif colorNorm=='Lin':
plotNorm = colors.Normalize()
if contour:
cs = ax.tricontourf(x,y,zPlot,levels=level,cmap=cmap,norm=plotNorm)#,extend='both')
else:
uniX,uniY = np.unique(x),np.unique(y)
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),cmap=cmap,norm=plotNorm)
if colorbar:
plt.colorbar(cs,cax=ax.cax,ticks=clevel,format='%1.2e')
ax.set_title(flag+' '+par,fontsize=8)
return cs
def plotIsoFreqNSDiff(ax,freq,arrayList,flag,par='abs',colorbar=True,cLevel=True,mask=None,contourLine=True,useLog=False):
indUniFreq0 = np.where(freq==arrayList[0]['freq'])
indUniFreq1 = np.where(freq==arrayList[1]['freq'])
seicmap = plt.get_cmap('RdYlBu')#seismic')
x, y = arrayList[0]['x'][indUniFreq0],arrayList[0]['y'][indUniFreq0]
if par == 'abs':
if useLog:
zPlot = (np.log10(np.abs(arrayList[0][flag][indUniFreq0])) - np.log10(np.abs(arrayList[1][flag][indUniFreq1])))/np.log10(np.abs(arrayList[1][flag][indUniFreq1]))
else:
zPlot = (np.abs(arrayList[0][flag][indUniFreq0]) - np.abs(arrayList[1][flag][indUniFreq1]))/np.abs(arrayList[1][flag][indUniFreq1])
if mask:
maskInd = np.logical_or(np.abs(arrayList[0][flag][indUniFreq0])< 1e-3,np.abs(arrayList[1][flag][indUniFreq1]) < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
if cLevel:
level = np.arange(-200,201,10)
clevel = np.arange(-200,201,25)
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
elif par == 'real':
if useLog:
zPlot = (np.log10(np.real(arrayList[0][flag][indUniFreq0])) -np.log10(np.real(arrayList[1][flag][indUniFreq1])))/np.log10(np.abs((np.real(arrayList[1][flag][indUniFreq1]))))
else:
zPlot = (np.real(arrayList[0][flag][indUniFreq0]) -np.real(arrayList[1][flag][indUniFreq1]))/np.abs((np.real(arrayList[1][flag][indUniFreq1])))
if mask:
maskInd = np.logical_or(np.abs(np.real(arrayList[0][flag][indUniFreq0])) < 1e-3,np.abs(np.real(arrayList[1][flag][indUniFreq1])) < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
if cLevel:
level = np.arange(-200,201,10)
clevel = np.arange(-200,201,25)
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
elif par == 'imag':
if useLog:
zPlot = (np.log10(np.imag(arrayList[0][flag][indUniFreq0])) -np.log10(np.imag(arrayList[1][flag][indUniFreq1])))/np.log10(np.abs((np.imag(arrayList[1][flag][indUniFreq1]))))
else:
zPlot = (np.imag(arrayList[0][flag][indUniFreq0]) -np.imag(arrayList[1][flag][indUniFreq1]))/np.abs((np.imag(arrayList[1][flag][indUniFreq1])))
if mask:
maskInd = np.logical_or(np.abs(np.imag(arrayList[0][flag][indUniFreq0])) < 1e-3,np.abs(np.imag(arrayList[1][flag][indUniFreq1])) < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
if cLevel:
level = np.arange(-200,201,10)
clevel = np.arange(-200,201,25)
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
cs = ax.tricontourf(x,y,zPlot*100,levels=level*100,cmap=seicmap,extend='both') #,norm=colors.SymLogNorm(1e-2,linscale=2))
if contourLine:
csl = ax.tricontour(x,y,zPlot*100,levels=clevel*100,colors='k')
plt.clabel(csl, fontsize=7, inline=1,fmt='%1.1e',inline_spacing=10)
if colorbar:
cb = plt.colorbar(cs,cax=ax.cax,ticks=clevel*100,format='%1.1e')
for t in cb.ax.get_yticklabels():
t.set_rotation(60)
t.set_fontsize(8)
ax.set_title(flag+' '+par,fontsize=8)
def plotIsoFreqNStipper(ax,freq,array,flag,par='abs',colorbar=True,colorNorm='SymLog',cLevel=True,contour=True):
indUniFreq = np.where(freq==array['freq'])
x, y = array['x'][indUniFreq],array['y'][indUniFreq]
if par == 'abs':
cmap = plt.get_cmap('OrRd_r')#seismic')
zPlot = np.abs(array[flag][indUniFreq])
if cLevel:
level = np.logspace(-4,0,33)
clevel = np.logspace(-4,0,5)
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
if colorNorm=='SymLog':
plotNorm = colors.LogNorm()
else:
plotNorm = colors.Normalize()
elif par == 'real':
cmap = plt.get_cmap('RdYlBu')
zPlot = np.real(array[flag][indUniFreq])
if cLevel:
level = np.concatenate((-np.logspace(0,-4,33),np.logspace(-4,0,33)))
clevel = np.concatenate((-np.logspace(0,-4,5),np.logspace(-4,0,5)))
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
if colorNorm=='SymLog':
plotNorm = colors.SymLogNorm(1e-4,linscale=2)
else:
plotNorm = colors.Normalize()
elif par == 'imag':
cmap = plt.get_cmap('RdYlBu')
zPlot = np.imag(array[flag][indUniFreq])
if cLevel:
level = np.concatenate((-np.logspace(0,-4,33),np.logspace(-4,0,33)))
clevel = np.concatenate((-np.logspace(0,-4,5),np.logspace(-4,0,5)))
else:
level = np.linspace(zPlot.min(),zPlot.max(),100)
clevel = np.linspace(zPlot.min(),zPlot.max(),10)
if colorNorm=='SymLog':
plotNorm = colors.SymLogNorm(1e-4,linscale=2)
else:
plotNorm = colors.Normalize()
if contour:
cs = ax.tricontourf(x,y,zPlot,levels=level,cmap=cmap,norm=plotNorm)#,extend='both')
else:
uniX,uniY = np.unique(x),np.unique(y)
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),levels=level,cmap=cmap,norm=plotNorm,edgecolors='k', linewidths=0.5)
if colorbar:
plt.colorbar(cs,cax=ax.cax,ticks=clevel,format='%1.2e')
ax.set_title(flag+' '+par,fontsize=8)
def plotIsoStaImpedance(ax,loc,array,flag,par='abs',pSym='s',pColor=None):
appResFact = 1/(8*np.pi**2*10**(-7))
treshold = 1.0 # 1 meter
indUniSta = np.sqrt(np.sum((rec2nd(array[['x','y']])-loc)**2,axis=1)) < treshold
freq = array['freq'][indUniSta]
if par == 'abs':
zPlot = np.abs(array[flag][indUniSta])
elif par == 'real':
zPlot = np.real(array[flag][indUniSta])
elif par == 'imag':
zPlot = np.imag(array[flag][indUniSta])
elif par == 'res':
zPlot = (appResFact/freq)*np.abs(array[flag][indUniSta])**2
elif par == 'phs':
zPlot = np.arctan2(array[flag][indUniSta].imag,array[flag][indUniSta].real)*(180/np.pi)
if not pColor:
if 'xx' in flag:
lab = 'XX'
pColor = 'g'
elif 'xy' in flag:
lab = 'XY'
pColor = 'r'
elif 'yx' in flag:
lab = 'YX'
pColor = 'b'
elif 'yy' in flag:
lab = 'YY'
pColor = 'y'
ax.plot(freq,zPlot,color=pColor,marker=pSym,label=flag)
def plotPsudoSectNSimpedance(ax,sectDict,array,flag,par='abs',colorbar=True,colorNorm='None',cLevel=None,contour=True):
indSect = np.where(sectDict.values()[0]==array[sectDict.keys()[0]])
# Define the plot axes
if 'x' in sectDict.keys()[0]:
x = array['y'][indSect]
else:
x = array['x'][indSect]
y = array['freq'][indSect]
if par == 'abs':
zPlot = np.abs(array[flag][indSect])
cmap = plt.get_cmap('OrRd_r')#seismic')
if cLevel:
level = np.logspace(0,-5,31,endpoint=True)
clevel = np.logspace(0,-4,5,endpoint=True)
else:
level = np.linspace(zPlot.min(),zPlot.max(),100,endpoint=True)
clevel = np.linspace(zPlot.min(),zPlot.max(),10,endpoint=True)
elif par == 'ares':
zPlot = np.abs(array[flag][indSect])**2/(8*np.pi**2*10**(-7)*array['freq'][indSect])
cmap = plt.get_cmap('RdYlBu')#seismic)
if cLevel:
zMax = np.log10(cLevel[1])
zMin = np.log10(cLevel[0])
else:
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
level = np.logspace(zMin,zMax,(zMax-zMin)*8+1,endpoint=True)
clevel = np.logspace(zMin,zMax,(zMax-zMin)*2+1,endpoint=True)
plotNorm = colors.LogNorm()
elif par == 'aphs':
zPlot = np.arctan2(array[flag][indSect].imag,array[flag][indSect].real)*(180/np.pi)
cmap = plt.get_cmap('RdYlBu')#seismic)
if cLevel:
zMax = cLevel[1]
zMin = cLevel[0]
else:
zMax = (np.ceil(zPlot).max())
zMin = (np.floor(zPlot).min())
level = np.arange(zMin,zMax+.1,1)
clevel = np.arange(zMin,zMax+.1,10)
plotNorm = colors.Normalize()
elif par == 'real':
zPlot = np.real(array[flag][indSect])
cmap = plt.get_cmap('Spectral') #('RdYlBu')
if cLevel:
zMax = np.log10(cLevel[1])
zMin = np.log10(cLevel[0])
else:
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
level = np.concatenate((-np.logspace(zMax,zMin-.125,(zMax-zMin)*8+1,endpoint=True),np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)))
clevel = np.concatenate((-np.logspace(zMax,zMin,(zMax-zMin)*1+1,endpoint=True),np.logspace(zMin,zMax,(zMax-zMin)*1+1,endpoint=True)))
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
elif par == 'imag':
zPlot = np.imag(array[flag][indSect])
cmap = plt.get_cmap('Spectral') #('RdYlBu')
if cLevel:
zMax = np.log10(cLevel[1])
zMin = np.log10(cLevel[0])
else:
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
level = np.concatenate((-np.logspace(zMax,zMin-.125,(zMax-zMin)*8+1,endpoint=True),np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)))
clevel = np.concatenate((-np.logspace(zMax,zMin,(zMax-zMin)*1+1,endpoint=True),np.logspace(zMin,zMax,(zMax-zMin)*1+1,endpoint=True)))
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
if colorNorm=='SymLog':
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
elif colorNorm=='Lin':
plotNorm = colors.Normalize()
elif colorNorm=='Log':
plotNorm = colors.LogNorm()
if contour:
cs = ax.tricontourf(x,y,zPlot,levels=level,cmap=cmap,norm=plotNorm)#,extend='both')
else:
uniX,uniY = np.unique(x),np.unique(y)
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),cmap=cmap,norm=plotNorm)
if colorbar:
csB = plt.colorbar(cs,cax=ax.cax,ticks=clevel,format='%1.2e')
# csB.on_mappable_changed(cs)
ax.set_title(flag+' '+par,fontsize=8)
return cs, csB
return cs,None
def plotPsudoSectNSDiff(ax,sectDict,arrayList,flag,par='abs',colorbar=True,colorNorm='SymLog',cLevel=None,contour=True,mask=None,useLog=False):
def sortInArr(arr):
return np.sort(arr,order=['freq','x','y','z'])
# Find the index for the slice
indSect0 = np.where(sectDict.values()[0]==arrayList[0][sectDict.keys()[0]])
indSect1 = np.where(sectDict.values()[0]==arrayList[1][sectDict.keys()[0]])
# Extract and sort the mats
arr0 = sortInArr(arrayList[0][indSect0])
arr1 = sortInArr(arrayList[1][indSect1])
# Define the plot axes
if 'x' in sectDict.keys()[0]:
x0 = arr0['y']
x1 = arr1['y']
else:
x0 = arr0['x']
x1 = arr1['x']
y0 = arr0['freq']
y1 = arr1['freq']
if par == 'abs':
if useLog:
zPlot = (np.log10(np.abs(arr0[flag])) - np.log10(np.abs(arr1[flag])))/np.log10(np.abs(arr1[flag]))
else:
zPlot = (np.abs(arr0[flag]) - np.abs(arr1[flag]))/np.abs(arr1[flag])
if mask:
maskInd = np.logical_or(np.abs(arr0[flag])< 1e-3,np.abs(arr1[flag]) < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
cmap = plt.get_cmap('RdYlBu')#seismic)
elif par == 'ares':
arF = 1/(8*np.pi**2*10**(-7))
if useLog:
zPlot = (np.log10((arF/arr0['freq'])*np.abs(arr0[flag])**2) - np.log10((arF/arr1['freq'])*np.abs(arr1[flag])**2))/np.log10((arF/arr1['freq'])*np.abs(arr1[flag])**2)
else:
zPlot = ((arF/arr0['freq'])*np.abs(arr0[flag])**2 - (arF/arr1['freq'])*np.abs(arr1[flag])**2)/((arF/arr1['freq'])*np.abs(arr1[flag])**2)
if mask:
maskInd = np.logical_or(np.abs(arr0[flag])< 1e-3,np.abs(arr1[flag]) < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
cmap = plt.get_cmap('Spectral')#seismic)
elif par == 'aphs':
if useLog:
zPlot = (np.log10(np.arctan2(arr0[flag].imag,arr0[flag].real)*(180/np.pi)) - np.log10(np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi)) )/np.log10(np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi))
else:
zPlot = ( np.arctan2(arr0[flag].imag,arr0[flag].real)*(180/np.pi) - np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi) )/(np.arctan2(arr1[flag].imag,arr1[flag].real)*(180/np.pi))
if mask:
maskInd = np.logical_or(np.abs(arr0[flag])< 1e-3,np.abs(arr1[flag]) < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
cmap = plt.get_cmap('Spectral')#seismic)
elif par == 'real':
if useLog:
zPlot = (np.log10(arr0[flag].real) - np.log10(arr1[flag].real))/np.log10(arr1[flag].real)
else:
zPlot = (arr0[flag].real - arr1[flag].real)/arr1[flag].real
if mask:
maskInd = np.logical_or(arr0[flag].real< 1e-3,arr1[flag].real < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
cmap = plt.get_cmap('Spectral') #('Spectral')
elif par == 'imag':
if useLog:
zPlot = (np.log10(arr0[flag].imag) - np.log10(arr1[flag].imag))/np.log10(arr1[flag].imag)
else:
zPlot = (arr0[flag].imag - arr1[flag].imag)/arr1[flag].imag
if mask:
maskInd = np.logical_or(arr0[flag].imag< 1e-3,arr1[flag].imag < 1e-3)
zPlot = np.ma.array(zPlot)
zPlot[maskInd] = mask
cmap = plt.get_cmap('Spectral') #('RdYlBu')
if cLevel:
zMax = np.log10(cLevel[1])
zMin = np.log10(cLevel[0])
else:
zMax = (np.ceil(np.log10(np.abs(zPlot).max())))
zMin = (np.floor(np.log10(np.abs(zPlot).min())))
if colorNorm=='SymLog':
level = np.concatenate((-np.logspace(zMax,zMin-.125,(zMax-zMin)*8+1,endpoint=True),np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)))
clevel = np.concatenate((-np.logspace(zMax,zMin,(zMax-zMin)*1+1,endpoint=True),np.logspace(zMin,zMax,(zMax-zMin)*1+1,endpoint=True)))
plotNorm = colors.SymLogNorm(np.abs(level).min(),linscale=0.1)
elif colorNorm=='Lin':
if cLevel:
level = np.arange(cLevel[0],cLevel[1]+.1,(cLevel[1] - cLevel[0])/50.)
clevel = np.arange(cLevel[0],cLevel[1]+.1,(cLevel[1] - cLevel[0])/10.)
else:
level = np.arange(zPlot.min(),zPlot.max(),(zPlot.max() - zPlot.min())/50.)
clevel = np.arange(zPlot.min(),zPlot.max(),(zPlot.max() - zPlot.min())/10.)
plotNorm = colors.Normalize()
elif colorNorm=='Log':
level = np.logspace(zMin-.125,zMax,(zMax-zMin)*8+1,endpoint=True)
clevel = np.logspace(zMin,zMax,(zMax-zMin)*2+1,endpoint=True)
plotNorm = colors.LogNorm()
if contour:
cs = ax.tricontourf(x0,y0,zPlot*100,levels=level*100,cmap=cmap,norm=plotNorm,extend='both')#,extend='both')
else:
uniX,uniY = np.unique(x0),np.unique(y0)
X,Y = np.meshgrid(np.append(uniX-25,uniX[-1]+25),np.append(uniY-25,uniY[-1]+25))
cs = ax.pcolor(X,Y,np.reshape(zPlot,(len(uniY),len(uniX))),cmap=cmap,norm=plotNorm)
if colorbar:
csB = plt.colorbar(cs,cax=ax.cax,ticks=clevel*100,format='%1.2e')
# csB.on_mappable_changed(cs)
ax.set_title(flag+' '+par + ' diff',fontsize=8)
return cs, csB
return cs,None
+178
View File
@@ -0,0 +1,178 @@
import SimPEG as simpeg, numpy as np
def homo1DModelSource(mesh,freq,sigma_1d):
'''
Function that calculates and return background fields
:param Simpeg mesh object mesh: Holds information on the discretization
:param float freq: The frequency to solve at
:param np.array sigma_1d: Background model of conductivity to base the calculations on, 1d model.
:rtype: numpy.ndarray (mesh.nE,2)
:return: eBG_bp, E fields for the background model at both polarizations.
'''
# import
from SimPEG.MT.Utils import get1DEfields
# Get a 1d solution for a halfspace background
if mesh.dim == 1:
mesh1d = mesh
elif mesh.dim == 2:
mesh1d = simpeg.Mesh.TensorMesh([mesh.hy],np.array([mesh.x0[1]]))
elif mesh.dim == 3:
mesh1d = simpeg.Mesh.TensorMesh([mesh.hz],np.array([mesh.x0[2]]))
# # Note: Everything is using e^iwt
e0_1d = get1DEfields(mesh1d,sigma_1d,freq)
if mesh.dim == 1:
eBG_px = simpeg.mkvc(e0_1d,2)
eBG_py = -simpeg.mkvc(e0_1d,2) # added a minus to make the results in the correct quadrents.
elif mesh.dim == 2:
ex_px = np.zeros(mesh.vnEx,dtype=complex)
ey_px = np.zeros((mesh.nEy,1),dtype=complex)
for i in np.arange(mesh.vnEx[0]):
ex_px[i,:] = -e0_1d
eBG_px = np.vstack((simpeg.Utils.mkvc(ex_px,2),ey_px))
# Setup y (north) polarization (_py)
ex_py = np.zeros((mesh.nEx,1), dtype='complex128')
ey_py = np.zeros(mesh.vnEy, dtype='complex128')
# Assign the source to ey_py
for i in np.arange(mesh.vnEy[0]):
ey_py[i,:] = e0_1d
# ey_py[1:-1,1:-1,1:-1] = 0
eBG_py = np.vstack((ex_py,simpeg.Utils.mkvc(ey_py,2),ez_py))
elif mesh.dim == 3:
# Setup x (east) polarization (_x)
ex_px = np.zeros(mesh.vnEx,dtype=complex)
ey_px = np.zeros((mesh.nEy,1),dtype=complex)
ez_px = np.zeros((mesh.nEz,1),dtype=complex)
# Assign the source to ex_x
for i in np.arange(mesh.vnEx[0]):
for j in np.arange(mesh.vnEx[1]):
ex_px[i,j,:] = -e0_1d
eBG_px = np.vstack((simpeg.Utils.mkvc(ex_px,2),ey_px,ez_px))
# Setup y (north) polarization (_py)
ex_py = np.zeros((mesh.nEx,1), dtype='complex128')
ey_py = np.zeros(mesh.vnEy, dtype='complex128')
ez_py = np.zeros((mesh.nEz,1), dtype='complex128')
# Assign the source to ey_py
for i in np.arange(mesh.vnEy[0]):
for j in np.arange(mesh.vnEy[1]):
ey_py[i,j,:] = e0_1d
# ey_py[1:-1,1:-1,1:-1] = 0
eBG_py = np.vstack((ex_py,simpeg.Utils.mkvc(ey_py,2),ez_py))
# Return the electric fields
eBG_bp = np.hstack((eBG_px,eBG_py))
return eBG_bp
def analytic1DModelSource(mesh,freq,sigma_1d):
'''
Function that calculates and return background fields
:param Simpeg mesh object mesh: Holds information on the discretization
:param float freq: The frequency to solve at
:param np.array sigma_1d: Background model of conductivity to base the calculations on, 1d model.
:rtype: numpy.ndarray (mesh.nE,2)
:return: eBG_bp, E fields for the background model at both polarizations.
'''
# import
from SimPEG.MT.Utils import getEHfields
# Get a 1d solution for a halfspace background
if mesh.dim == 1:
mesh1d = mesh
elif mesh.dim == 2:
mesh1d = simpeg.Mesh.TensorMesh([mesh.hy],np.array([mesh.x0[1]]))
elif mesh.dim == 3:
mesh1d = simpeg.Mesh.TensorMesh([mesh.hz],np.array([mesh.x0[2]]))
# # Note: Everything is using e^iwt
Eu, Ed, _, _ = getEHfields(mesh1d,sigma_1d,freq,mesh.vectorNz)
# Make the fields into a dictionary of location and the fields
e0_1d = Eu+Ed
E1dFieldDict = dict(zip(mesh.vectorNz,e0_1d))
if mesh.dim == 1:
eBG_px = simpeg.mkvc(e0_1d,2)
eBG_py = -simpeg.mkvc(e0_1d,2) # added a minus to make the results in the correct quadrents.
elif mesh.dim == 2:
ex_px = np.zeros(mesh.vnEx,dtype=complex)
ey_px = np.zeros((mesh.nEy,1),dtype=complex)
for i in np.arange(mesh.vnEx[0]):
ex_px[i,:] = -e0_1d
eBG_px = np.vstack((simpeg.Utils.mkvc(ex_px,2),ey_px))
# Setup y (north) polarization (_py)
ex_py = np.zeros((mesh.nEx,1), dtype='complex128')
ey_py = np.zeros(mesh.vnEy, dtype='complex128')
# Assign the source to ey_py
for i in np.arange(mesh.vnEy[0]):
ey_py[i,:] = e0_1d
# ey_py[1:-1,1:-1,1:-1] = 0
eBG_py = np.vstack((ex_py,simpeg.Utils.mkvc(ey_py,2),ez_py))
elif mesh.dim == 3:
# Setup x (east) polarization (_x)
ex_px = -np.array([E1dFieldDict[i] for i in mesh.gridEx[:,2]]).reshape(-1,1)
ey_px = np.zeros((mesh.nEy,1),dtype=complex)
ez_px = np.zeros((mesh.nEz,1),dtype=complex)
# Construct the full fields
eBG_px = np.vstack((ex_px,ey_px,ez_px))
# Setup y (north) polarization (_py)
ex_py = np.zeros((mesh.nEx,1), dtype='complex128')
ey_py = np.array([E1dFieldDict[i] for i in mesh.gridEy[:,2]]).reshape(-1,1)
ez_py = np.zeros((mesh.nEz,1), dtype='complex128')
# Construct the full fields
eBG_py = np.vstack((ex_py,simpeg.Utils.mkvc(ey_py,2),ez_py))
# Return the electric fields
eBG_bp = np.hstack((eBG_px,eBG_py))
return eBG_bp
# def homo3DModelSource(mesh,model,freq):
# '''
# Function that estimates 1D analytic background fields from a 3D model.
# :param Simpeg mesh object mesh: Holds information on the discretization
# :param float freq: The frequency to solve at
# :param np.array sigma_1d: Background model of conductivity to base the calculations on, 1d model.
# :rtype: numpy.ndarray (mesh.nE,2)
# :return: eBG_bp, E fields for the background model at both polarizations.
# '''
# if mesh.dim < 3:
# raise IOError('Input mesh has to have 3 dimensions.')
# # Get the locations
# a = mesh.gridCC[:,0:2].copy()
# unixy = np.unique(a.view(a.dtype.descr * a.shape[1])).view(float).reshape(-1,2)
# uniz = np.unique(mesh.gridCC[:,2])
# # # Note: Everything is using e^iwt
# # Need to loop thourgh the xy locations, assess the model and calculate the fields at the phusdo cell centers.
# # Then interpolate the cc fields to the edges.
# e0_1d = get1DEfields(mesh1d,sigma_1d,freq)
# elif mesh.dim == 3:
# # Setup x (east) polarization (_x)
# ex_px = np.zeros(mesh.vnEx,dtype=complex)
# ey_px = np.zeros((mesh.nEy,1),dtype=complex)
# ez_px = np.zeros((mesh.nEz,1),dtype=complex)
# # Assign the source to ex_x
# for i in np.arange(mesh.vnEx[0]):
# for j in np.arange(mesh.vnEx[1]):
# ex_px[i,j,:] = -e0_1d
# eBG_px = np.vstack((simpeg.Utils.mkvc(ex_px,2),ey_px,ez_px))
# # Setup y (north) polarization (_py)
# ex_py = np.zeros((mesh.nEx,1), dtype='complex128')
# ey_py = np.zeros(mesh.vnEy, dtype='complex128')
# ez_py = np.zeros((mesh.nEz,1), dtype='complex128')
# # Assign the source to ey_py
# for i in np.arange(mesh.vnEy[0]):
# for j in np.arange(mesh.vnEy[1]):
# ey_py[i,j,:] = e0_1d
# # ey_py[1:-1,1:-1,1:-1] = 0
# eBG_py = np.vstack((ex_py,simpeg.Utils.mkvc(ey_py,2),ez_py))
# # Return the electric fields
# eBG_bp = np.hstack((eBG_px,eBG_py))
# return eBG_bp
+46
View File
@@ -0,0 +1,46 @@
import SimPEG as simpeg, numpy as np
def homo1DModelSource(mesh,freq,m_back):
'''
Function that calculates and return background fields for a 3D mesh and model.
The calculuations use 1D field solution for a vertical slice throught model (south-western most column),
which is assigned at the fields everywhere for the respective polarizations.2
:param Simpeg mesh object mesh: Holds information on the discretization
:param float freq: The frequency to solve at
:param np.array m_back: Background model of conductivity to base the calculations on.
:rtype: numpy.ndarray (mesh.nE,2)
:return: eBG_bp, E fields for the background model at both polarizations.
'''
# import
from SimPEG.MT.Utils import get1DEfields
# Get a 1d solution for a halfspace background
mesh1d = simpeg.Mesh.TensorMesh([mesh.hz],np.array([mesh.x0[2]]))
# Note: Everything is using e^iwt
e0_1d = get1DEfields(mesh1d,mesh.r(m_back,'CC','CC','M')[0,0,:],freq)
# Setup x (east) polarization (_x)
ex_px = np.zeros(mesh.vnEx,dtype=complex)
ey_px = np.zeros((mesh.nEy,1),dtype=complex)
ez_px = np.zeros((mesh.nEz,1),dtype=complex)
# Assign the source to ex_x
for i in np.arange(mesh.vnEx[0]):
for j in np.arange(mesh.vnEx[1]):
ex_px[i,j,:] = -e0_1d
eBG_px = np.vstack((simpeg.Utils.mkvc(ex_px,2),ey_px,ez_px))
# Setup y (north) polarization (_py)
ex_py = np.zeros((mesh.nEx,1), dtype='complex128')
ey_py = np.zeros(mesh.vnEy, dtype='complex128')
ez_py = np.zeros((mesh.nEz,1), dtype='complex128')
# Assign the source to ey_py
for i in np.arange(mesh.vnEy[0]):
for j in np.arange(mesh.vnEy[1]):
ey_py[i,j,:] = e0_1d
# ey_py[1:-1,1:-1,1:-1] = 0
eBG_py = np.vstack((ex_py,simpeg.Utils.mkvc(ey_py,2),ez_py))
# Return the electric fields
eBG_bp = np.hstack((eBG_px,eBG_py))
return eBG_bp
+5
View File
@@ -0,0 +1,5 @@
import Utils
from SurveyMT import Rx, Survey, Data
from FieldsMT import Fields1D_e, Fields3D_e
import Problem1D, Problem2D, Problem3D
import SrcMT
+887 -136
View File
File diff suppressed because it is too large Load Diff
+12 -9
View File
@@ -330,7 +330,7 @@ class CylMesh(BaseTensorMesh, BaseRectangularMesh, InnerProducts, CylView):
raise NotImplementedError('wrapping in the averaging is not yet implemented')
return self._aveF2CCV
def getInterpolationMatCartMesh(self, Mrect, locType='CC'):
def getInterpolationMatCartMesh(self, Mrect, locType='CC', locTypeTo=None):
"""
Takes a cartesian mesh and returns a projection to translate onto the cartesian grid.
"""
@@ -338,19 +338,22 @@ class CylMesh(BaseTensorMesh, BaseRectangularMesh, InnerProducts, CylView):
assert self.isSymmetric, "Currently we have not taken into account other projections for more complicated CylMeshes"
if locTypeTo is None:
locTypeTo = locType
if locType == 'F':
# do this three times for each component
X = self.getInterpolationMatCartMesh(Mrect, locType='Fx')
Y = self.getInterpolationMatCartMesh(Mrect, locType='Fy')
Z = self.getInterpolationMatCartMesh(Mrect, locType='Fz')
X = self.getInterpolationMatCartMesh(Mrect, locType='Fx', locTypeTo=locTypeTo+'x')
Y = self.getInterpolationMatCartMesh(Mrect, locType='Fy', locTypeTo=locTypeTo+'y')
Z = self.getInterpolationMatCartMesh(Mrect, locType='Fz', locTypeTo=locTypeTo+'z')
return sp.vstack((X,Y,Z))
if locType == 'E':
X = self.getInterpolationMatCartMesh(Mrect, locType='Ex')
Y = self.getInterpolationMatCartMesh(Mrect, locType='Ey')
Z = spzeros(Mrect.nEz, self.nE)
X = self.getInterpolationMatCartMesh(Mrect, locType='Ex', locTypeTo=locTypeTo+'x')
Y = self.getInterpolationMatCartMesh(Mrect, locType='Ey', locTypeTo=locTypeTo+'y')
Z = spzeros(getattr(Mrect, 'n' + locTypeTo + 'z'), self.nE)
return sp.vstack((X,Y,Z))
grid = getattr(Mrect, 'grid' + locType)
grid = getattr(Mrect, 'grid' + locTypeTo)
# This is unit circle stuff, 0 to 2*pi, starting at x-axis, rotating counter clockwise in an x-y slice
theta = - np.arctan2(grid[:,0] - self.cartesianOrigin[0], grid[:,1] - self.cartesianOrigin[1]) + np.pi/2
theta[theta < 0] += np.pi*2.0
@@ -366,7 +369,7 @@ class CylMesh(BaseTensorMesh, BaseRectangularMesh, InnerProducts, CylView):
'Ex': Mrect.tangents[:Mrect.nEx,:],
'Ey': Mrect.tangents[Mrect.nEx:(Mrect.nEx+Mrect.nEy),:],
'Ez': Mrect.tangents[-Mrect.nEz:,:],
}[locType]
}[locTypeTo]
if 'F' in locType:
normals = np.c_[np.cos(theta), np.sin(theta), np.zeros(theta.size)]
proj = ( normals * dotMe ).sum(axis=1)
+109 -31
View File
@@ -307,24 +307,28 @@ class DiffOperators(object):
return BC
_cellGradBC_list = 'neumann'
def _cellGradStencil(self):
BC = self.setCellGradBC(self._cellGradBC_list)
n = self.vnC
if(self.dim == 1):
G = ddxCellGrad(n[0], BC[0])
elif(self.dim == 2):
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC[0]))
G2 = sp.kron(ddxCellGrad(n[1], BC[1]), speye(n[0]))
G = sp.vstack((G1, G2), format="csr")
elif(self.dim == 3):
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC[0]))
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC[1]), speye(n[0]))
G3 = kron3(ddxCellGrad(n[2], BC[2]), speye(n[1]), speye(n[0]))
G = sp.vstack((G1, G2, G3), format="csr")
return G
def cellGrad():
doc = "The cell centered Gradient, takes you to cell faces."
def fget(self):
if(self._cellGrad is None):
BC = self.setCellGradBC(self._cellGradBC_list)
n = self.vnC
if(self.dim == 1):
G = ddxCellGrad(n[0], BC[0])
elif(self.dim == 2):
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC[0]))
G2 = sp.kron(ddxCellGrad(n[1], BC[1]), speye(n[0]))
G = sp.vstack((G1, G2), format="csr")
elif(self.dim == 3):
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC[0]))
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC[1]), speye(n[0]))
G3 = kron3(ddxCellGrad(n[2], BC[2]), speye(n[1]), speye(n[0]))
G = sp.vstack((G1, G2, G3), format="csr")
G = self._cellGradStencil()
# Compute areas of cell faces & volumes
S = self.area
V = self.aveCC2F*self.vol # Average volume between adjacent cells
@@ -361,19 +365,24 @@ class DiffOperators(object):
_cellGradBC = None
cellGradBC = property(**cellGradBC())
def _cellGradxStencil(self):
BC = ['neumann', 'neumann']
n = self.vnC
if(self.dim == 1):
G1 = ddxCellGrad(n[0], BC)
elif(self.dim == 2):
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC))
elif(self.dim == 3):
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC))
return G1
def cellGradx():
doc = "Cell centered Gradient in the x dimension. Has neumann boundary conditions."
def fget(self):
if getattr(self, '_cellGradx', None) is None:
BC = ['neumann', 'neumann']
n = self.vnC
if(self.dim == 1):
G1 = ddxCellGrad(n[0], BC)
elif(self.dim == 2):
G1 = sp.kron(speye(n[1]), ddxCellGrad(n[0], BC))
elif(self.dim == 3):
G1 = kron3(speye(n[2]), speye(n[1]), ddxCellGrad(n[0], BC))
G1 = self._cellGradxStencil()
# Compute areas of cell faces & volumes
V = self.aveCC2F*self.vol
L = self.r(self.area/V, 'F','Fx', 'V')
@@ -382,17 +391,22 @@ class DiffOperators(object):
return locals()
cellGradx = property(**cellGradx())
def _cellGradyStencil(self):
if self.dim < 2: return None
BC = ['neumann', 'neumann']
n = self.vnC
if(self.dim == 2):
G2 = sp.kron(ddxCellGrad(n[1], BC), speye(n[0]))
elif(self.dim == 3):
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC), speye(n[0]))
return G2
def cellGrady():
doc = "Cell centered Gradient in the x dimension. Has neumann boundary conditions."
def fget(self):
if self.dim < 2: return None
if getattr(self, '_cellGrady', None) is None:
BC = ['neumann', 'neumann']
n = self.vnC
if(self.dim == 2):
G2 = sp.kron(ddxCellGrad(n[1], BC), speye(n[0]))
elif(self.dim == 3):
G2 = kron3(speye(n[2]), ddxCellGrad(n[1], BC), speye(n[0]))
G2 = self._cellGradyStencil()
# Compute areas of cell faces & volumes
V = self.aveCC2F*self.vol
L = self.r(self.area/V, 'F','Fy', 'V')
@@ -401,14 +415,19 @@ class DiffOperators(object):
return locals()
cellGrady = property(**cellGrady())
def _cellGradzStencil(self):
if self.dim < 3: return None
BC = ['neumann', 'neumann']
n = self.vnC
G3 = kron3(ddxCellGrad(n[2], BC), speye(n[1]), speye(n[0]))
return G3
def cellGradz():
doc = "Cell centered Gradient in the x dimension. Has neumann boundary conditions."
def fget(self):
if self.dim < 3: return None
if getattr(self, '_cellGradz', None) is None:
BC = ['neumann', 'neumann']
n = self.vnC
G3 = kron3(ddxCellGrad(n[2], BC), speye(n[1]), speye(n[0]))
G3 = self._cellGradzStencil()
# Compute areas of cell faces & volumes
V = self.aveCC2F*self.vol
L = self.r(self.area/V, 'F','Fz', 'V')
@@ -565,7 +584,67 @@ class DiffOperators(object):
return Pbc, Pin, Pout
def getBCProjWF_simple(self, discretization='CC'):
"""
The weak form boundary condition projection matrices
when mixed boundary condition is used
"""
if discretization is not 'CC':
raise NotImplementedError('Boundary conditions only implemented for CC discretization.')
def projBC(n):
ij = ([0,n], [0,1])
vals = [0,0]
vals[0] = 1
vals[1] = 1
return sp.csr_matrix((vals, ij), shape=(n+1,2))
def projDirichlet(n, bc):
bc = checkBC(bc)
ij = ([0,n], [0,1])
vals = [0,0]
if(bc[0] == 'dirichlet'):
vals[0] = -1
if(bc[1] == 'dirichlet'):
vals[1] = 1
return sp.csr_matrix((vals, ij), shape=(n+1,2))
BC = [['dirichlet','dirichlet'],['dirichlet','dirichlet'],['dirichlet','dirichlet']]
n = self.vnC
indF = self.faceBoundaryInd
if(self.dim == 1):
Pbc = projDirichlet(n[0], BC[0])
B = projBC(n[0])
indF = indF[0] | indF[1]
Pbc = Pbc*sdiag(self.area[indF])
elif(self.dim == 2):
Pbc1 = sp.kron(speye(n[1]), projDirichlet(n[0], BC[0]))
Pbc2 = sp.kron(projDirichlet(n[1], BC[1]), speye(n[0]))
Pbc = sp.block_diag((Pbc1, Pbc2), format="csr")
B1 = sp.kron(speye(n[1]), projBC(n[0]))
B2 = sp.kron(projBC(n[1]), speye(n[0]))
B = sp.block_diag((B1, B2), format="csr")
indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3])]
Pbc = Pbc*sdiag(self.area[indF])
elif(self.dim == 3):
Pbc1 = kron3(speye(n[2]), speye(n[1]), projDirichlet(n[0], BC[0]))
Pbc2 = kron3(speye(n[2]), projDirichlet(n[1], BC[1]), speye(n[0]))
Pbc3 = kron3(projDirichlet(n[2], BC[2]), speye(n[1]), speye(n[0]))
Pbc = sp.block_diag((Pbc1, Pbc2, Pbc3), format="csr")
B1 = kron3(speye(n[2]), speye(n[1]), projBC(n[0]))
B2 = kron3(speye(n[2]), projBC(n[1]), speye(n[0]))
B3 = kron3(projBC(n[2]), speye(n[1]), speye(n[0]))
B = sp.block_diag((B1, B2, B3), format="csr")
indF = np.r_[(indF[0] | indF[1]), (indF[2] | indF[3]), (indF[4] | indF[5])]
Pbc = Pbc*sdiag(self.area[indF])
return Pbc, B.T
# --------------- Averaging ---------------------
@property
@@ -746,4 +825,3 @@ class DiffOperators(object):
kron3(av(n[2]), speye(n[1]+1), av(n[0])),
kron3(speye(n[2]+1), av(n[1]), av(n[0]))), format="csr")
return self._aveN2F
+415
View File
@@ -0,0 +1,415 @@
import numpy as np, os
from SimPEG import Utils
class TensorMeshIO(object):
@classmethod
def readUBC(TensorMesh, fileName):
"""
Read UBC GIF 3DTensor mesh and generate 3D Tensor mesh in simpegTD
Input:
:param fileName, path to the UBC GIF mesh file
Output:
:param SimPEG TensorMesh object
"""
# Interal function to read cell size lines for the UBC mesh files.
def readCellLine(line):
for seg in line.split():
if '*' in seg:
st = seg
sp = seg.split('*')
re = int(sp[0])*(' ' + sp[1])
line = line.replace(st,re.strip())
return np.array(line.split(),dtype=float)
# Read the file as line strings, remove lines with comment = !
msh = np.genfromtxt(fileName,delimiter='\n',dtype=np.str,comments='!')
# Fist line is the size of the model
sizeM = np.array(msh[0].split(),dtype=float)
# Second line is the South-West-Top corner coordinates.
x0 = np.array(msh[1].split(),dtype=float)
# Read the cell sizes
h1 = readCellLine(msh[2])
h2 = readCellLine(msh[3])
h3temp = readCellLine(msh[4])
h3 = h3temp[::-1] # Invert the indexing of the vector to start from the bottom.
# Adjust the reference point to the bottom south west corner
x0[2] = x0[2] - np.sum(h3)
# Make the mesh
tensMsh = TensorMesh([h1,h2,h3],x0)
return tensMsh
@classmethod
def readVTK(TensorMesh, fileName):
"""
Read VTK Rectilinear (vtr xml file) and return SimPEG Tensor mesh and model
Input:
:param vtrFileName, path to the vtr model file to write to
Output:
:return SimPEG TensorMesh object
:return SimPEG model dictionary
"""
# Import
from vtk import vtkXMLRectilinearGridReader as vtrFileReader
from vtk.util.numpy_support import vtk_to_numpy
# Read the file
vtrReader = vtrFileReader()
vtrReader.SetFileName(fileName)
vtrReader.Update()
vtrGrid = vtrReader.GetOutput()
# Sort information
hx = np.abs(np.diff(vtk_to_numpy(vtrGrid.GetXCoordinates())))
xR = vtk_to_numpy(vtrGrid.GetXCoordinates())[0]
hy = np.abs(np.diff(vtk_to_numpy(vtrGrid.GetYCoordinates())))
yR = vtk_to_numpy(vtrGrid.GetYCoordinates())[0]
zD = np.diff(vtk_to_numpy(vtrGrid.GetZCoordinates()))
# Check the direction of hz
if np.all(zD < 0):
hz = np.abs(zD[::-1])
zR = vtk_to_numpy(vtrGrid.GetZCoordinates())[-1]
else:
hz = np.abs(zD)
zR = vtk_to_numpy(vtrGrid.GetZCoordinates())[0]
x0 = np.array([xR,yR,zR])
# Make the SimPEG object
tensMsh = TensorMesh([hx,hy,hz],x0)
# Grap the models
models = {}
for i in np.arange(vtrGrid.GetCellData().GetNumberOfArrays()):
modelName = vtrGrid.GetCellData().GetArrayName(i)
if np.all(zD < 0):
modFlip = vtk_to_numpy(vtrGrid.GetCellData().GetArray(i))
tM = tensMsh.r(modFlip,'CC','CC','M')
modArr = tensMsh.r(tM[:,:,::-1],'CC','CC','V')
else:
modArr = vtk_to_numpy(vtrGrid.GetCellData().GetArray(i))
models[modelName] = modArr
# Return the data
return tensMsh, models
def writeVTK(mesh, fileName, models=None):
"""
Makes and saves a VTK rectilinear file (vtr) for a simpeg Tensor mesh and model.
Input:
:param str, path to the output vtk file
:param mesh, SimPEG TensorMesh object - mesh to be transfer to VTK
:param models, dictionary of numpy.array - Name('s) and array('s). Match number of cells
"""
# Import
from vtk import vtkRectilinearGrid as rectGrid, vtkXMLRectilinearGridWriter as rectWriter, VTK_VERSION
from vtk.util.numpy_support import numpy_to_vtk
# Deal with dimensionalities
if mesh.dim >= 1:
vX = mesh.vectorNx
xD = mesh.nNx
yD,zD = 1,1
vY, vZ = np.array([0,0])
if mesh.dim >= 2:
vY = mesh.vectorNy
yD = mesh.nNy
if mesh.dim == 3:
vZ = mesh.vectorNz
zD = mesh.nNz
# Use rectilinear VTK grid.
# Assign the spatial information.
vtkObj = rectGrid()
vtkObj.SetDimensions(xD,yD,zD)
vtkObj.SetXCoordinates(numpy_to_vtk(vX,deep=1))
vtkObj.SetYCoordinates(numpy_to_vtk(vY,deep=1))
vtkObj.SetZCoordinates(numpy_to_vtk(vZ,deep=1))
# Assign the model('s) to the object
if models is not None:
for item in models.iteritems():
# Convert numpy array
vtkDoubleArr = numpy_to_vtk(item[1],deep=1)
vtkDoubleArr.SetName(item[0])
vtkObj.GetCellData().AddArray(vtkDoubleArr)
# Set the active scalar
vtkObj.GetCellData().SetActiveScalars(models.keys()[0])
# vtkObj.Update()
# Check the extension of the fileName
ext = os.path.splitext(fileName)[1]
if ext is '':
fileName = fileName + '.vtr'
elif ext not in '.vtr':
raise IOError('{:s} is an incorrect extension, has to be .vtr')
# Write the file.
vtrWriteFilter = rectWriter()
if float(VTK_VERSION.split('.')[0]) >=6:
vtrWriteFilter.SetInputData(vtkObj)
else:
vtuWriteFilter.SetInput(vtuObj)
vtrWriteFilter.SetFileName(fileName)
vtrWriteFilter.Update()
def readModelUBC(mesh, fileName):
"""
Read UBC 3DTensor mesh model and generate 3D Tensor mesh model in simpeg
Input:
:param fileName, path to the UBC GIF mesh file to read
:param mesh, TensorMesh object, mesh that coresponds to the model
Output:
:return numpy array, model with TensorMesh ordered
"""
f = open(fileName, 'r')
model = np.array(map(float, f.readlines()))
f.close()
model = np.reshape(model, (mesh.nCz, mesh.nCx, mesh.nCy), order = 'F')
model = model[::-1,:,:]
model = np.transpose(model, (1, 2, 0))
model = Utils.mkvc(model)
return model
def writeModelUBC(mesh, fileName, model):
"""
Writes a model associated with a SimPEG TensorMesh
to a UBC-GIF format model file.
:param str fileName: File to write to
:param simpeg.Mesh.TensorMesh mesh: The mesh
:param numpy.ndarray model: The model
"""
# Reshape model to a matrix
modelMat = mesh.r(model,'CC','CC','M')
# Transpose the axes
modelMatT = modelMat.transpose((2,0,1))
# Flip z to positive down
modelMatTR = Utils.mkvc(modelMatT[::-1,:,:])
np.savetxt(fileName, modelMatTR.ravel())
def writeUBC(mesh, fileName, models=None):
"""
Writes a SimPEG TensorMesh to a UBC-GIF format mesh file.
:param str fileName: File to write to
:param simpeg.Mesh.TensorMesh mesh: The mesh
"""
assert mesh.dim == 3
s = ''
s += '%i %i %i\n' %tuple(mesh.vnC)
origin = mesh.x0 + np.array([0,0,mesh.hz.sum()]) # Have to it in the same operation or use mesh.x0.copy(), otherwise the mesh.x0 is updated.
origin.dtype = float
s += '%.2f %.2f %.2f\n' %tuple(origin)
s += ('%.2f '*mesh.nCx+'\n')%tuple(mesh.hx)
s += ('%.2f '*mesh.nCy+'\n')%tuple(mesh.hy)
s += ('%.2f '*mesh.nCz+'\n')%tuple(mesh.hz[::-1])
f = open(fileName, 'w')
f.write(s)
f.close()
if models is None: return
assert type(models) is dict, 'models must be a dict'
for key in models:
assert type(key) is str, 'The dict key is a file name'
mesh.writeModelUBC(key, models[key])
class TreeMeshIO(object):
def writeUBC(mesh, fileName, models=None):
"""
Write UBC ocTree mesh and model files from a simpeg ocTree mesh and model.
:param str fileName: File to write to
:param simpeg.Mesh.TreeMesh mesh: The mesh
:param dictionary models: The models in a dictionary, where the keys is the name of the of the model file
"""
# Calculate information to write in the file.
# Number of cells in the underlying mesh
nCunderMesh = np.array([h.size for h in mesh.h],dtype=np.int64)
# The top-south-west most corner of the mesh
tswCorn = mesh.x0 + np.array([0,0,np.sum(mesh.h[2])])
# Smallest cell size
smallCell = np.array([h.min() for h in mesh.h])
# Number of cells
nrCells = mesh.nC
## Extract iformation about the cells.
# cell pointers
cellPointers = np.array([c._pointer for c in mesh])
# cell with
cellW = np.array([ mesh._levelWidth(i) for i in cellPointers[:,-1] ])
# Need to shift the pointers to work with UBC indexing
# UBC Octree indexes always the top-left-close (top-south-west) corner first and orders the cells in z(top-down),x,y vs x,y,z(bottom-up).
# Shift index up by 1
ubcCellPt = cellPointers[:,0:-1].copy() + np.array([1.,1.,1.])
# Need reindex the z index to be from the top-left-close corner and to be from the global top.
ubcCellPt[:,2] = ( nCunderMesh[-1] + 2) - (ubcCellPt[:,2] + cellW)
# Reorder the ubcCellPt
ubcReorder = np.argsort(ubcCellPt.view(','.join(3*['float'])),axis=0,order=['f2','f1','f0'])[:,0]
# Make a array with the pointers and the withs, that are order in the ubc ordering
indArr = np.concatenate((ubcCellPt[ubcReorder,:],cellW[ubcReorder].reshape((-1,1)) ),axis=1)
## Write the UBC octree mesh file
with open(fileName,'w') as mshOut:
mshOut.write('{:.0f} {:.0f} {:.0f}\n'.format(nCunderMesh[0],nCunderMesh[1],nCunderMesh[2]))
mshOut.write('{:.4f} {:.4f} {:.4f}\n'.format(tswCorn[0],tswCorn[1],tswCorn[2]))
mshOut.write('{:.3f} {:.3f} {:.3f}\n'.format(smallCell[0],smallCell[1],smallCell[2]))
mshOut.write('{:.0f} \n'.format(nrCells))
np.savetxt(mshOut,indArr,fmt='%i')
## Print the models
# Assign the model('s) to the object
if models is not None:
# indUBCvector = np.argsort(cX0[np.argsort(np.concatenate((cX0[:,0:2],cX0[:,2:3].max() - cX0[:,2:3]),axis=1).view(','.join(3*['float'])),axis=0,order=('f2','f1','f0'))[:,0]].view(','.join(3*['float'])),axis=0,order=('f2','f1','f0'))[:,0]
for item in models.iteritems():
# Save the data
np.savetxt(item[0],item[1][ubcReorder],fmt='%3.5e')
@classmethod
def readUBC(TreeMesh, meshFile):
"""
Read UBC 3D OcTree mesh and/or modelFiles
Input:
:param str meshFile: path to the UBC GIF OcTree mesh file to read
Output:
:return SimPEG.Mesh.TreeMesh mesh: The octree mesh
:return list of ndarray's: models as a list of numpy array's
"""
## Read the file lines
fileLines = np.genfromtxt(meshFile,dtype=str,delimiter='\n')
# Extract the data
nCunderMesh = np.array(fileLines[0].split(),dtype=float)
# I think this is the case?
if np.unique(nCunderMesh).size >1:
raise Exception('SimPEG TreeMeshes have the same number of cell in all directions')
tswCorn = np.array(fileLines[1].split(),dtype=float)
smallCell = np.array(fileLines[2].split(),dtype=float)
nrCells = np.array(fileLines[3].split(),dtype=float)
# Read the index array
indArr = np.genfromtxt(fileLines[4::],dtype=np.int)
## Calculate simpeg parameters
h1,h2,h3 = [np.ones(nr)*sz for nr,sz in zip(nCunderMesh,smallCell)]
x0 = tswCorn - np.array([0,0,np.sum(h3)])
# Need to convert the index array to a points list that complies with SimPEG TreeMesh.
# Shift to start at 0
simpegCellPt = indArr[:,0:-1].copy()
simpegCellPt[:,2] = ( nCunderMesh[-1] + 2) - (simpegCellPt[:,2] + indArr[:,3])
# Need reindex the z index to be from the bottom-left-close corner and to be from the global bottom.
simpegCellPt = simpegCellPt - np.array([1.,1.,1.])
# Calculate the cell level
simpegLevel = np.log2(np.min(nCunderMesh)) - np.log2(indArr[:,3])
# Make a pointer matrix
simpegPointers = np.concatenate((simpegCellPt,simpegLevel.reshape((-1,1))),axis=1)
## Make the tree mesh
mesh = TreeMesh([h1,h2,h3],x0)
mesh._cells = set([mesh._index(p) for p in simpegPointers.tolist()])
# Figure out the reordering
mesh._simpegReorderUBC = np.argsort(np.array([mesh._index(i) for i in simpegPointers.tolist()]))
# mesh._simpegReorderUBC = np.argsort((np.array([[1,1,1,-1]])*simpegPointers).view(','.join(4*['float'])),axis=0,order=['f3','f2','f1','f0'])[:,0]
return mesh
def readModelUBC(mesh, fileName):
"""
Read UBC OcTree model and get vector
Input:
:param fileName, path to the UBC GIF model file to read
Output:
:return numpy array, OcTree model
"""
if type(fileName) is list:
out = {}
for f in fileName:
out[f] = mesh.readModelUBC(f)
return out
assert hasattr(mesh, '_simpegReorderUBC'), 'The file must have been loaded from a UBC format.'
assert mesh.dim == 3
modList = []
modArr = np.loadtxt(fileName)
if len(modArr.shape) == 1:
modList.append(modArr[mesh._simpegReorderUBC])
else:
modList.append(modArr[mesh._simpegReorderUBC,:])
return modList
def writeVTK(mesh, fileName, models=None):
"""
Function to write a VTU file from a SimPEG TreeMesh and model.
"""
import vtk
from vtk import vtkXMLUnstructuredGridWriter as Writer, VTK_VERSION
from vtk.util.numpy_support import numpy_to_vtk, numpy_to_vtkIdTypeArray
if str(type(mesh)).split()[-1][1:-2] not in 'SimPEG.Mesh.TreeMesh.TreeMesh':
raise IOError('mesh is not a SimPEG TreeMesh.')
# Make the data parts for the vtu object
# Points
mesh.number()
ptsMat = mesh._gridN + mesh.x0
vtkPts = vtk.vtkPoints()
vtkPts.SetData(numpy_to_vtk(ptsMat,deep=True))
# Cells
cellConn = np.array([c.nodes for c in mesh],dtype=np.int64)
cellsMat = np.concatenate((np.ones((cellConn.shape[0],1),dtype=np.int64)*cellConn.shape[1],cellConn),axis=1).ravel()
cellsArr = vtk.vtkCellArray()
cellsArr.SetNumberOfCells(cellConn.shape[0])
cellsArr.SetCells(cellConn.shape[0],numpy_to_vtkIdTypeArray(cellsMat,deep=True))
# Make the object
vtuObj = vtk.vtkUnstructuredGrid()
vtuObj.SetPoints(vtkPts)
vtuObj.SetCells(vtk.VTK_VOXEL,cellsArr)
# Add the level of refinement as a cell array
cellSides = np.array([np.array(vtuObj.GetCell(i).GetBounds()).reshape((3,2)).dot(np.array([-1, 1])) for i in np.arange(vtuObj.GetNumberOfCells())])
uniqueLevel, indLevel = np.unique(np.prod(cellSides,axis=1),return_inverse=True)
refineLevelArr = numpy_to_vtk(indLevel.max() - indLevel,deep=1)
refineLevelArr.SetName('octreeLevel')
vtuObj.GetCellData().AddArray(refineLevelArr)
# Assign the model('s) to the object
if models is not None:
for item in models.iteritems():
# Convert numpy array
vtkDoubleArr = numpy_to_vtk(item[1],deep=1)
vtkDoubleArr.SetName(item[0])
vtuObj.GetCellData().AddArray(vtkDoubleArr)
# Make the writer
vtuWriteFilter = Writer()
if float(VTK_VERSION.split('.')[0]) >=6:
vtuWriteFilter.SetInputData(vtuObj)
else:
vtuWriteFilter.SetInput(vtuObj)
vtuWriteFilter.SetFileName(fileName)
# Write the file
vtuWriteFilter.Update()
+572 -558
View File
File diff suppressed because it is too large Load Diff
+89 -124
View File
@@ -90,11 +90,6 @@
#
from SimPEG import np, sp, Utils, Solver
import matplotlib.pyplot as plt
import matplotlib
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as colors
import matplotlib.cm as cmx
try:
import TreeUtils
@@ -105,11 +100,12 @@ except Exception, e:
from InnerProducts import InnerProducts
from TensorMesh import TensorMesh, BaseTensorMesh
from MeshIO import TreeMeshIO
import time
MAX_BITS = 20
class TreeMesh(BaseTensorMesh, InnerProducts):
class TreeMesh(BaseTensorMesh, InnerProducts, TreeMeshIO):
_meshType = 'TREE'
@@ -569,15 +565,18 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
return [p - (p % mod) for p in pointer[:-1]] + [pointer[-1]-1]
def _cellN(self, p):
"""Node location [x,y(,z)] of a single cell, closest to origin, given a pointer."""
p = self._asPointer(p)
return [hi[:p[ii]].sum() for ii, hi in enumerate(self.h)]
def _cellH(self, p):
"""Widths of a single cell given a pointer."""
p = self._asPointer(p)
w = self._levelWidth(p[-1])
return [hi[p[ii]:p[ii]+w].sum() for ii, hi in enumerate(self.h)]
def _cellC(self, p):
"""Cell center of a single cell (without origin correction), given a pointer."""
return (np.array(self._cellH(p))/2.0 + self._cellN(p)).tolist()
def _levelWidth(self, level):
@@ -832,8 +831,10 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
def _numberCells(self, force=False):
if not self.__dirtyCells__ and not force: return
self._cc2i = dict()
self._i2cc = dict()
for ii, c in enumerate(sorted(self._cells)):
self._cc2i[c] = ii
self._i2cc[ii] = c
self.__dirtyCells__ = False
def _numberNodes(self, force=False):
@@ -1709,9 +1710,9 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
"Construct the averaging operator on cell faces to cell centers."
if getattr(self, '_aveF2CC', None) is None:
if self.dim == 2:
self._aveF2CC = 1./self.dim*sp.hstack([self.aveFx2CC, self.aveFy2CC])
self._aveF2CC = 1./self.dim*sp.hstack([self.aveFx2CC, self.aveFy2CC]).tocsr()
elif self.dim == 3:
self._aveF2CC = 1./self.dim*sp.hstack([self.aveFx2CC, self.aveFy2CC, self.aveFz2CC])
self._aveF2CC = 1./self.dim*sp.hstack([self.aveFx2CC, self.aveFy2CC, self.aveFz2CC]).tocsr()
return self._aveF2CC
@property
@@ -1719,9 +1720,9 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
"Construct the averaging operator on cell faces to cell centers."
if getattr(self, '_aveF2CCV', None) is None:
if self.dim == 2:
self._aveF2CCV = sp.block_diag([self.aveFx2CC, self.aveFy2CC])
self._aveF2CCV = sp.block_diag([self.aveFx2CC, self.aveFy2CC]).tocsr()
elif self.dim == 3:
self._aveF2CCV = sp.block_diag([self.aveFx2CC, self.aveFy2CC, self.aveFz2CC])
self._aveF2CCV = sp.block_diag([self.aveFx2CC, self.aveFy2CC, self.aveFz2CC]).tocsr()
return self._aveF2CCV
@property
@@ -1973,6 +1974,13 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
facesX=False, facesY=False, facesZ=False,
edgesX=False, edgesY=False, edgesZ=False):
import matplotlib.pyplot as plt
import matplotlib
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as colors
import matplotlib.cm as cmx
# self.number()
axOpts = {'projection':'3d'} if self.dim == 3 else {}
@@ -2094,6 +2102,13 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
def plotImage(self, I, ax=None, showIt=False, grid=False, clim=None):
if self.dim == 3: raise Exception('Use plot slice?')
import matplotlib.pyplot as plt
import matplotlib
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as colors
import matplotlib.cm as cmx
if ax is None: ax = plt.subplot(111)
jet = cm = plt.get_cmap('jet')
cNorm = colors.Normalize(
@@ -2116,13 +2131,26 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
def plotSlice(self, v, vType='CC',
normal='Z', ind=None, grid=True, view='real',
ax=None, clim=None, showIt=False,
pcolorOpts={},
streamOpts={'color':'k'},
gridOpts={'color':'k', 'alpha':0.5}):
pcolorOpts=None,
streamOpts=None,
gridOpts=None):
if pcolorOpts is None:
pcolorOpts = {}
if streamOpts is None:
streamOpts = {'color':'k'}
if gridOpts is None:
gridOpts = {'color':'k', 'alpha':0.5}
assert vType in ['CC','F','E']
assert self.dim == 3
import matplotlib.pyplot as plt
import matplotlib
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as colors
import matplotlib.cm as cmx
szSliceDim = len(getattr(self, 'h'+normal.lower())) #: Size of the sliced dimension
if ind is None: ind = int(szSliceDim/2)
assert type(ind) in [int, long], 'ind must be an integer'
@@ -2202,6 +2230,25 @@ class TreeMesh(BaseTensorMesh, InnerProducts):
if showIt: plt.show()
return tuple(out)
def __len__(self): return self.nC
def __getitem__(self, key):
if isinstance( key, slice ) :
#Get the start, stop, and step from the slice
return [self[ii] for ii in xrange(*key.indices(len(self)))]
elif isinstance( key, int ) :
if key < 0 : #Handle negative indices
key += len( self )
if key >= len( self ) :
raise IndexError, "The index (%d) is out of range."%key
self._numberCells() # no-op if numbered
index = self._i2cc[key]
pointer = self._asPointer(index)
return Cell(self, index, pointer)
else:
raise TypeError, "Invalid argument type."
class Cell(object):
def __init__(self, mesh, index, pointer):
@@ -2209,6 +2256,35 @@ class Cell(object):
self._index = index
self._pointer = pointer
@property
def nodes(self):
"""The node index in _gridN (this may include hanging nodes)."""
M = self.mesh
M._numberNodes()
p = self._pointer
i = self._index
w = M._levelWidth(p[-1])
if M.dim == 2:
n = [
i,
M._index([ p[0] + w, p[1] , p[2]]),
M._index([ p[0] , p[1]+ w, p[2]]),
M._index([ p[0] + w, p[1]+ w, p[2]]),
]
elif self.dim == 3:
n = [
i,
M._index([ p[0] + w, p[1] , p[2] ,p[3]]),
M._index([ p[0] , p[1] + w, p[2] ,p[3]]),
M._index([ p[0] + w, p[1] + w, p[2] ,p[3]]),
M._index([ p[0] , p[1] , p[2] + w,p[3]]),
M._index([ p[0] + w, p[1] , p[2] + w,p[3]]),
M._index([ p[0] , p[1] + w, p[2] + w,p[3]]),
M._index([ p[0] + w, p[1] + w, p[2] + w,p[3]]),
]
return [M._n2i[_] for _ in n]
@property
def center(self):
if getattr(self, '_center', None) is None:
@@ -2266,114 +2342,3 @@ class NotBalancedException(TreeException):
pass
class CellLookUpException(TreeException):
pass
if __name__ == '__main__':
def topo(x):
return np.sin(x*(2.*np.pi))*0.3 + 0.5
def function(cell):
r = cell.center - np.array([0.5]*len(cell.center))
dist = np.sqrt(r.dot(r))
# dist2 = np.abs(cell.center[-1] - topo(cell.center[0]))
# dist = min([dist1,dist2])
# if dist < 0.05:
# return 5
if dist < 0.1:
return 5
if dist < 0.2:
return 4
if dist < 0.4:
return 3
return 2
# T = TreeMesh([[(1,128)],[(1,128)],[(1,128)]],levels=7)
# T = TreeMesh([128,128,128])
# T = TreeMesh([64,64],levels=6)
T = TreeMesh([4,4,4])
# T = TreeMesh([[(1,128)],[(1,128)]],levels=7)
# T.refine(lambda xc:2, balance=False)
# T._index([0,0,0])
# T._pointer(0)
# tic = time.time()
T.refine(function)#, balance=False)
# print time.time() - tic
# print T.nC
T.plotSlice(np.log(T.vol))#np.random.rand(T.nC))
plt.show()
blah
# T.plotImage(np.arange(len(T.vol)),showIt=True)
# print T.getFaceInnerProduct()
# print T.gridFz
# T._refineCell([8,0,1])
# T._refineCell([8,0,2])
# T._refineCell([12,0,2])
# T._refineCell([8,4,2])
# T._refineCell([6,0,3])
# T._refineCell([8,8,1])
# T._refineCell([0,0,0,1])
# T.__dirty__ = True
# print T.gridFx.shape[0], T.nFx
ax = plt.subplot(211)
ax.spy(T.edgeCurl)
# print Mesh.TensorMesh([2,2,2]).edgeCurl.todense()
# print T.edgeCurl.todense()
# print Mesh.TensorMesh([2,2,2]).edgeCurl.todense() - T.edgeCurl.todense()
# print T.gridEy - Mesh.TensorMesh([2,2,2]).gridEy
# print T.edge
# T.plotGrid(ax=ax)
# R = deflationMatrix(T._facesX, T._hangingFx, T._fx2i)
# print R
ax = plt.subplot(212)#, projection='3d')
ax.spy(Mesh.TensorMesh([2,2,2]).edgeCurl)
# ax = plt.subplot(313)
# ax.spy(T.faceDiv[:,:T.nFx] * R)
# T.balance()
# T.plotGrid(ax=ax)
# cx = T._getNextCell([0,0,1],direction=0,positive=True)
# print cx
# # print [T._asPointer(_) for _ in cx]
# cx = T._getNextCell([8,0,3],direction=0,positive=False)
# print T._asPointer(cx)
# cx = T._getNextCell([8,8,1],direction=1,positive=False)
# print cx, #[T._asPointer(_) for _ in cx]
# cm = T._getNextCell([64,80,4],direction=0,positive=False)
# cy = T._getNextCell([64,80,4],direction=1,positive=True)
# cp = T._getNextCell([64,80,4],direction=1,positive=False)
# ax.plot( T._cellN([4,0,1])[0],T._cellN([4,0,1])[1], 'yd')
# ax.plot( T._cellN(cx)[0],T._cellN(cx)[1], 'ys')
# ax.plot( T._cellN(cm)[0],T._cellN(cm)[1], 'ys')
# ax.plot( T._cellN(cy)[0],T._cellN(cy)[1], 'ys')
# ax.plot( T._cellN(cp[0])[0],T._cellN(cp[0])[1], 'ys')
# ax.plot( T._cellN(cp[1])[0],T._cellN(cp[1])[1], 'ys')
# print T.nN
plt.show()

Some files were not shown because too many files have changed in this diff Show More