Changeset 5ff1b03 in sasmodels for sasmodels/generate.py
- Timestamp:
- Mar 25, 2016 11:44:37 AM (8 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:
- c499331
- Parents:
- ba32cdd
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/generate.py
r380e8c9 r5ff1b03 508 508 # faster by not using/transferring the volume normalizations, but 509 509 # the ifdef's reduce readability more than is worthwhile. 510 call_volume = "#define CALL_VOLUME(v) 0.0"510 call_volume = "#define CALL_VOLUME(v) 1.0" 511 511 source.append(call_volume) 512 512 … … 579 579 model_info['max_pd'] = min(partable.num_pd, MAX_PD) 580 580 581 class CoordinationDetails(object): 582 def __init__(self, model_info): 583 max_pd = model_info['max_pd'] 584 npars = len(model_info['parameters'].kernel_pars()) 585 par_offset = 4*max_pd 586 self.details = np.zeros(par_offset + 3*npars + 4, 'i4') 587 588 # generate views on different parts of the array 589 self._pd_par = self.details[0*max_pd:1*max_pd] 590 self._pd_length = self.details[1*max_pd:2*max_pd] 591 self._pd_offset = self.details[2*max_pd:3*max_pd] 592 self._pd_stride = self.details[3*max_pd:4*max_pd] 593 self._par_offset = self.details[par_offset+0*npars:par_offset+1*npars] 594 self._par_coord = self.details[par_offset+1*npars:par_offset+2*npars] 595 self._pd_coord = self.details[par_offset+2*npars:par_offset+3*npars] 596 597 # theta_par is fixed 598 self.details[-1] = model_info['parameters'].theta_par 599 600 @property 601 def ctypes(self): return self.details.ctypes 602 @property 603 def pd_par(self): return self._pd_par 604 @property 605 def pd_length(self): return self._pd_length 606 @property 607 def pd_offset(self): return self._pd_offset 608 @property 609 def pd_stride(self): return self._pd_stride 610 @property 611 def pd_coord(self): return self._pd_coord 612 @property 613 def par_coord(self): return self._par_coord 614 @property 615 def par_offset(self): return self._par_offset 616 @property 617 def num_coord(self): return self.details[-2] 618 @num_coord.setter 619 def num_coord(self, v): self.details[-2] = v 620 @property 621 def total_pd(self): return self.details[-3] 622 @total_pd.setter 623 def total_pd(self, v): self.details[-3] = v 624 @property 625 def num_active(self): return self.details[-4] 626 @num_active.setter 627 def num_active(self, v): self.details[-4] = v 628 629 def show(self): 630 print("total_pd", self.total_pd) 631 print("num_active", self.num_active) 632 print("pd_par", self.pd_par) 633 print("pd_length", self.pd_length) 634 print("pd_offset", self.pd_offset) 635 print("pd_stride", self.pd_stride) 636 print("par_offsets", self.par_offset) 637 print("num_coord", self.num_coord) 638 print("par_coord", self.par_coord) 639 print("pd_coord", self.pd_coord) 640 print("theta par", self.details[-1]) 641 581 642 def mono_details(model_info): 582 # TODO: move max_pd into ParameterTable? 583 max_pd = model_info['max_pd'] 584 pars = model_info['parameters'].kernel_pars() 585 npars = len(pars) 586 par_offset = 5*max_pd 587 constants_offset = par_offset + 3*npars 588 589 details = np.zeros(constants_offset + 2, 'int32') 590 details[0*max_pd:1*max_pd] = range(max_pd) # pd_par: arbitrary order; use first 591 details[1*max_pd:2*max_pd] = [1]*max_pd # pd_length: only one element 592 details[2*max_pd:3*max_pd] = range(max_pd) # pd_offset: consecutive 1.0 weights 593 details[3*max_pd:4*max_pd] = [1]*max_pd # pd_stride: vectors of length 1 594 details[4*max_pd:5*max_pd] = [0]*max_pd # pd_isvol: doens't matter if no norm 595 details[par_offset+0*npars:par_offset+1*npars] = range(2, npars+2) # par_offset: skip scale and background 596 details[par_offset+1*npars:par_offset+2*npars] = [0]*npars # no coordination 597 #details[p+npars] = 1 # par_coord[0] is coordinated with the first par? 598 details[par_offset+2*npars:par_offset+3*npars] = 0 # fast coord with 0 599 details[constants_offset] = 1 # fast_coord_count: one fast index 600 details[constants_offset+1] = -1 # theta_par: None 643 details = CoordinationDetails(model_info) 644 # The zero defaults for monodisperse systems are mostly fine 645 details.par_offset[:] = np.arange(2, len(details.par_offset)+2) 601 646 return details 602 647 603 648 def poly_details(model_info, weights): 604 649 weights = weights[2:] 605 606 # TODO: move max_pd into ParameterTable?607 650 max_pd = model_info['max_pd'] 608 pars = model_info['parameters'].kernel_pars()609 npars = len(pars)610 par_offset = 5*max_pd611 constants_offset = par_offset + 3*npars612 651 613 652 # Decreasing list of polydispersity lengths 614 653 # Note: the reversing view, x[::-1], does not require a copy 615 654 pd_length = np.array([len(w) for w in weights]) 655 num_active = np.sum(pd_length>1) 656 if num_active > max_pd: 657 raise ValueError("Too many polydisperse parameters") 658 616 659 pd_offset = np.cumsum(np.hstack((0, pd_length))) 617 pd_isvol = np.array([p.type=='volume' for p in pars]) 618 idx = np.argsort(pd_length)[::-1][:max_pd] 619 pd_stride = np.cumprod(np.hstack((1, pd_length[idx][:-1]))) 620 par_offsets = np.cumsum(np.hstack((2, pd_length)))[:-1] 621 coord_offset = par_offset+npars 622 fast_coord_offset = par_offset+2*npars 623 624 theta_par = -1 625 if 'theta_par' in model_info: 626 theta_par = model_info['theta_par'] 627 if theta_par >= 0 and pd_length[theta_par] <= 1: 628 theta_par = -1 629 630 details = np.empty(constants_offset + 2, 'int32') 631 details[0*max_pd:1*max_pd] = idx # pd_par 632 details[1*max_pd:2*max_pd] = pd_length[idx] 633 details[2*max_pd:3*max_pd] = pd_offset[idx] 634 details[3*max_pd:4*max_pd] = pd_stride 635 details[4*max_pd:5*max_pd] = pd_isvol[idx] 636 details[par_offset+0*npars:par_offset+1*npars] = par_offsets 637 details[par_offset+1*npars:par_offset+2*npars] = 0 # no coordination for most 638 for k,parameter_num in enumerate(idx): 639 details[coord_offset+parameter_num] = 2**k 640 details[fast_coord_offset] = idx[0] 641 details[fast_coord_offset+1:fast_coord_offset+npars] = 0 # no fast coord with 0 642 details[constants_offset] = 1 # fast_coord_count: one fast index 643 details[constants_offset+1] = theta_par 644 print("polydispersity details") 645 print_details(model_info, details) 660 idx = np.argsort(pd_length)[::-1][:num_active] 661 par_length = np.array([max(len(w),1) for w in weights]) 662 pd_stride = np.cumprod(np.hstack((1, par_length[idx]))) 663 par_offsets = np.cumsum(np.hstack((2, par_length))) 664 665 details = CoordinationDetails(model_info) 666 details.pd_par[:num_active] = idx 667 details.pd_length[:num_active] = pd_length[idx] 668 details.pd_offset[:num_active] = pd_offset[idx] 669 details.pd_stride[:num_active] = pd_stride[:-1] 670 details.par_offset[:] = par_offsets[:-1] 671 details.total_pd = pd_stride[-1] 672 details.num_active = num_active 673 # Without constraints coordinated parameters are just the pd parameters 674 details.par_coord[:num_active] = idx 675 details.pd_coord[:num_active] = 2**np.arange(num_active) 676 details.num_coord = num_active 677 #details.show() 646 678 return details 647 648 def print_details(model_info, details):649 max_pd = model_info['max_pd']650 pars = model_info['parameters'].kernel_pars()651 npars = len(pars)652 par_offset = 5*max_pd653 constants_offset = par_offset + 3*npars654 655 print("pd_par", details[0*max_pd:1*max_pd])656 print("pd_length", details[1*max_pd:2*max_pd])657 print("pd_offset", details[2*max_pd:3*max_pd])658 print("pd_stride", details[3*max_pd:4*max_pd])659 print("pd_isvol", details[4*max_pd:5*max_pd])660 print("par_offsets", details[par_offset+0*npars:par_offset+1*npars])661 print("par_coord", details[par_offset+1*npars:par_offset+2*npars])662 print("fast_coord_pars", details[par_offset+2*npars:par_offset+3*npars])663 print("fast_coord_count", details[constants_offset])664 print("theta par", details[constants_offset+1])665 679 666 680 def constrained_poly_details(model_info, weights, constraints):
Note: See TracChangeset
for help on using the changeset viewer.