Changeset ff7119b in sasmodels for sasmodels/gen.py
- Timestamp:
- Aug 26, 2014 10:27:06 PM (10 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 5d4777d
- Parents:
- a7684e5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/gen.py
ra7684e5 rff7119b 55 55 them with the desired polydispersity. 56 56 57 The available kernel parameters are defined as a list, with each parameter 58 defined as a sublist with the following elements: 59 60 *name* is the name that will be used in the call to the kernel 61 function and the name that will be displayed to the user. Names 62 should be lower case, with words separated by underscore. If 63 acronyms are used, the whole acronym should be upper case. 64 65 *units* should be one of *degrees* for angles, *Ang* for lengths, 66 *1e-6/Ang^2* for SLDs. 67 68 *default value* will be the initial value for the model when it 69 is selected, or when an initial value is not otherwise specified. 70 71 [*lb*, *ub*] are the hard limits on the parameter value, used to limit 72 the polydispersity density function. In the fit, the parameter limits 73 given to the fit are the limits on the central value of the parameter. 74 If there is polydispersity, it will evaluate parameter values outside 75 the fit limits, but not outside the hard limits specified in the model. 76 If there are no limits, use +/-inf imported from numpy. 77 78 *type* indicates how the parameter will be used. "volume" parameters 79 will be used in all functions. "orientation" parameters will be used 80 in *Iqxy* and *Imagnetic*. "magnetic* parameters will be used in 81 *Imagnetic* only. If *type* is the empty string, the parameter will 82 be used in all of *Iq*, *Iqxy* and *Imagnetic*. 83 84 *description* is a short description of the parameter. This will 85 be displayed in the parameter table and used as a tool tip for the 86 parameter value in the user interface. 87 57 88 The kernel module must set variables defining the kernel meta data: 58 89 … … 65 96 while the model parameters are being edited. 66 97 67 *parameters* is a list of parameters. Each parameter is itself a 68 list containing *name*, *units*, *default value*, 69 [*lower bound*, *upper bound*], *type* and *description*. 98 *parameters* is the list of parameters. Parameters in the kernel 99 functions must appear in the same order as they appear in the 100 parameters list. Two additional parameters, *scale* and *background* 101 are added to the beginning of the parameter list. They will show up 102 in the documentation as model parameters, but they are never sent to 103 the kernel functions. 70 104 71 105 *source* is the list of C-99 source files that must be joined to … … 78 112 *VR* is a python function defining the volume ratio. If it is not 79 113 present, the volume ratio is 1. 114 115 An *info* dictionary is constructed from the kernel meta data and 116 returned to the caller. It includes the additional fields 117 118 119 The model evaluator, function call sequence consists of q inputs and the return vector, 120 followed by the loop value/weight vector, followed by the values for 121 the non-polydisperse parameters, followed by the lengths of the 122 polydispersity loops. To construct the call for 1D models, the 123 categories *fixed-1d* and *pd-1d* list the names of the parameters 124 of the non-polydisperse and the polydisperse parameters respectively. 125 Similarly, *fixed-2d* and *pd-2d* provide parameter names for 2D models. 126 The *pd-rel* category is a set of those parameters which give 127 polydispersitiy as a portion of the value (so a 10% length dispersity 128 would use a polydispersity value of 0.1) rather than absolute 129 dispersity such as an angle plus or minus 15 degrees. 130 131 The *volume* category lists the volume parameters in order for calls 132 to volume within the kernel (used for volume normalization) and for 133 calls to ER and VR for effective radius and volume ratio respectively. 134 135 The *orientation* and *magnetic* categories list the orientation and 136 magnetic parameters. These are used by the sasview interface. The 137 blank category is for parameters such as scale which don't have any 138 other marking. 80 139 81 140 The doc string at the start of the kernel module will be used to … … 86 145 file names and extensions. 87 146 88 Parameters are defined as follows:89 90 *name* is the name that will be used in the call to the kernel91 function and the name that will be displayed to the user. Names92 should be lower case, with words separated by underscore. If93 acronyms are used, the whole acronym should be upper case.94 95 *units* should be one of *degrees* for angles, *Ang* for lengths,96 *1e-6/Ang^2* for SLDs.97 98 *default value* will be the initial value for the model when it99 is selected, or when an initial value is not otherwise specified.100 101 *limits* are the valid bounds of the parameter, used to limit the102 polydispersity density function. In the fit, the parameter limits103 given to the fit are the limits on the central value of the parameter.104 If there is polydispersity, it will evaluate parameter values outside105 the fit limits, but not outside the hard limits specified in the model.106 If there are no limits, use +/-inf imported from numpy.107 108 *type* indicates how the parameter will be used. "volume" parameters109 will be used in all functions. "orientation" parameters will be used110 in *Iqxy* and *Imagnetic*. "magnetic* parameters will be used in111 *Imagnetic* only. If *type* is none, the parameter will be used in112 all of *Iq*, *Iqxy* and *Imagnetic*. This will probably be a113 is the empty string if the parameter is used in all model calculations,114 it is "volu115 116 *description* is a short description of the parameter. This will117 be displayed in the parameter table and used as a tool tip for the118 parameter value in the user interface.119 147 120 148 The function :func:`make` loads the metadata from the module and returns 121 the kernel source. The function :func:`doc` extracts 149 the kernel source. The function :func:`doc` extracts the doc string 150 and adds the parameter table to the top. The function :func:`sources` 151 returns a list of files required by the model. 122 152 """ 123 153 124 154 # TODO: identify model files which have changed since loading and reload them. 125 155 126 __all__ = ["make, doc" ]156 __all__ = ["make, doc", "sources"] 127 157 128 158 import os.path … … 158 188 ] 159 189 190 # Minimum width for a default value (this is shorter than the column header 191 # width, so will be ignored). 160 192 PARTABLE_VALUE_WIDTH = 10 161 193 162 194 # Header included before every kernel. 163 # This makes sure that the appropriate math constants are defined, and 195 # This makes sure that the appropriate math constants are defined, and does 196 # whatever is required to make the kernel compile as pure C rather than 197 # as an OpenCL kernel. 164 198 KERNEL_HEADER = """\ 165 199 // GENERATED CODE --- DO NOT EDIT --- … … 231 265 } 232 266 233 # Generic kernel template for opencl/openmp.267 # Generic kernel template for the polydispersity loop. 234 268 # This defines the opencl kernel that is available to the host. The same 235 269 # structure is used for Iq and Iqxy kernels, so extra flexibility is needed … … 333 367 334 368 def kernel_name(info, is_2D): 369 """ 370 Name of the exported kernel symbol. 371 """ 335 372 return info['name'] + "_" + ("Iqxy" if is_2D else "Iq") 336 373 … … 431 468 432 469 def make_partable(info): 470 """ 471 Generate the parameter table to include in the sphinx documentation. 472 """ 433 473 pars = info['parameters'] 434 474 column_widths = [ … … 467 507 raise ValueError("%r not found in %s"%(filename, search_path)) 468 508 469 def make_model(search_path, info): 509 def sources(info): 510 """ 511 Return a list of the sources file paths for the module. 512 """ 513 from os.path import abspath, dirname, join as joinpath 514 search_path = [ dirname(info['filename']), 515 abspath(joinpath(dirname(__file__),'models')) ] 516 return [_search(search_path) for f in info['source']] 517 518 def make_model(info): 519 """ 520 Generate the code for the kernel defined by info, using source files 521 found in the given search path. 522 """ 470 523 kernel_Iq = make_kernel(info, is_2D=False) 471 524 kernel_Iqxy = make_kernel(info, is_2D=True) 472 source = [open( _search(search_path, f)).read() for f in info['source']]525 source = [open(f).read() for f in sources(info)] 473 526 kernel = "\n\n".join([KERNEL_HEADER]+source+[kernel_Iq, kernel_Iqxy]) 474 527 return kernel … … 479 532 480 533 Returns a dictionary of categories. 481 482 The function call sequence consists of q inputs and the return vector,483 followed by the loop value/weight vector, followed by the values for484 the non-polydisperse parameters, followed by the lengths of the485 polydispersity loops. To construct the call for 1D models, the486 categories *fixed-1d* and *pd-1d* list the names of the parameters487 of the non-polydisperse and the polydisperse parameters respectively.488 Similarly, *fixed-2d* and *pd-2d* provide parameter names for 2D models.489 The *pd-rel* category is a set of those parameters which give490 polydispersitiy as a portion of the value (so a 10% length dispersity491 would use a polydispersity value of 0.1) rather than absolute492 dispersity such as an angle plus or minus 15 degrees.493 494 The *volume* category lists the volume parameters in order for calls495 to volume within the kernel (used for volume normalization) and for496 calls to ER and VR for effective radius and volume ratio respectively.497 498 The *orientation* and *magnetic* categories list the orientation and499 magnetic parameters. These are used by the sasview interface. The500 blank category is for parameters such as scale which don't have any501 other marking.502 534 """ 503 535 partype = { … … 535 567 """ 536 568 # TODO: allow Iq and Iqxy to be defined in python 537 from os.path import abspath , dirname, join as joinpath569 from os.path import abspath 538 570 #print kernelfile 539 571 info = dict( … … 550 582 info['partype'] = categorize_parameters(info['parameters']) 551 583 552 search_path = [ dirname(info['filename']), 553 abspath(joinpath(dirname(__file__),'models')) ] 554 source = make_model(search_path, info) 584 source = make_model(info) 555 585 556 586 return source, info … … 565 595 doc=kernel_module.__doc__) 566 596 return DOC_HEADER%subst 597 598 # Compiler platform details 599 if sys.platform == 'darwin': 600 COMPILE = "gcc-mp-4.7 -shared -fPIC -std=c99 -fopenmp -O2 -Wall %s -o %s -lm -lgomp" 601 elif os.name == 'nt': 602 COMPILE = "gcc -shared -fPIC -std=c99 -fopenmp -O2 -Wall %s -o %s -lm" 603 else: 604 COMPILE = "cc -shared -fPIC -std=c99 -fopenmp -O2 -Wall %s -o %s -lm" 605 DLL_PATH = "/tmp" 606 607 608 def dll_path(info): 609 """ 610 Path to the compiled model defined by *info*. 611 """ 612 from os.path import join as joinpath, split as splitpath, splitext 613 basename = splitext(splitpath(info['filename'])[1])[0] 614 return joinpath(DLL_PATH, basename+'.so') 615 616 617 def dll_model(kernel_module, dtype=None): 618 """ 619 Load the compiled model defined by *kernel_module*. 620 621 Recompile if any files are newer than the model file. 622 623 *dtype* is ignored. Compiled files are always double. 624 625 The DLL is not loaded until the kernel is called so models an 626 be defined without using too many resources. 627 """ 628 import tempfile 629 from sasmodels import dll 630 631 source, info = make(kernel_module) 632 source_files = sources(info) + [info['filename']] 633 newest = max(os.path.getmtime(f) for f in source_files) 634 dllpath = dll_path(info) 635 if not os.path.exists(dllpath) or os.path.getmtime(dllpath)<newest: 636 # Replace with a proper temp file 637 srcfile = tempfile.mkstemp(suffix=".c",prefix="sas_"+info['name']) 638 open(srcfile, 'w').write(source) 639 os.system(COMPILE%(srcfile, dllpath)) 640 ## comment the following to keep the generated c file 641 os.unlink(srcfile) 642 return dll.DllModel(dllpath, info) 643 644 645 def opencl_model(kernel_module, dtype="single"): 646 """ 647 Load the OpenCL model defined by *kernel_module*. 648 649 Access to the OpenCL device is delayed until the kernel is called 650 so models can be defined without using too many resources. 651 """ 652 from sasmodels import gpu 653 654 source, info = make(kernel_module) 655 ## for debugging, save source to a .cl file, edit it, and reload as model 656 #open(modelname+'.cl','w').write(source) 657 #source = open(modelname+'.cl','r').read() 658 return gpu.GpuModel(source, info, dtype) 567 659 568 660
Note: See TracChangeset
for help on using the changeset viewer.