source: ThirdParty/mpqc_open/src/lib/chemistry/qc/basis/obint.cc

Candidate_v1.6.1
Last change on this file was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 18.6 KB
Line 
1//
2// obint.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <stdexcept>
33
34#include <util/misc/formio.h>
35
36#include <math/scmat/block.h>
37#include <math/scmat/blkiter.h>
38#include <math/scmat/offset.h>
39
40#include <chemistry/qc/basis/obint.h>
41#include <chemistry/qc/basis/basis.h>
42
43using namespace sc;
44
45///////////////////////////////////////////////////////////////////////
46
47EfieldDotVectorData::~EfieldDotVectorData()
48{
49}
50
51void
52EfieldDotVectorData::set_position(double*p)
53{
54 position[0] = p[0];
55 position[1] = p[1];
56 position[2] = p[2];
57}
58
59void
60EfieldDotVectorData::set_vector(double*v)
61{
62 vector[0] = v[0];
63 vector[1] = v[1];
64 vector[2] = v[2];
65}
66
67///////////////////////////////////////////////////////////////////////
68
69DipoleData::~DipoleData()
70{
71}
72
73void
74DipoleData::set_origin(double*o)
75{
76 origin[0] = o[0];
77 origin[1] = o[1];
78 origin[2] = o[2];
79}
80
81///////////////////////////////////////////////////////////////////////
82
83PointChargeData::PointChargeData(int ncharges,
84 const double *const*positions,
85 const double *charges,
86 int copy_data)
87{
88 ncharges_ = ncharges;
89 if (copy_data) {
90 alloced_positions_ = new double*[ncharges];
91 alloced_charges_ = new double[ncharges];
92 memcpy(alloced_charges_, charges, sizeof(double)*ncharges);
93 double *tmp = new double[ncharges*3];
94 for (int i=0; i<ncharges; i++) {
95 alloced_positions_[i] = tmp;
96 for (int j=0; j<3; j++) {
97 *tmp++ = positions[i][j];
98 }
99 }
100 positions_ = alloced_positions_;
101 charges_ = alloced_charges_;
102 }
103 else {
104 charges_ = charges;
105 alloced_charges_ = 0;
106 alloced_positions_ = 0;
107 charges_ = charges;
108 positions_ = positions;
109 }
110}
111
112PointChargeData::~PointChargeData()
113{
114 if (alloced_positions_) {
115 delete[] alloced_positions_[0];
116 delete[] alloced_positions_;
117 }
118 delete[] alloced_charges_;
119}
120
121///////////////////////////////////////////////////////////////////////
122
123OneBodyInt::OneBodyInt(Integral* integral,
124 const Ref<GaussianBasisSet>&bs1,
125 const Ref<GaussianBasisSet>&bs2) :
126 integral_(integral),
127 bs1_(bs1), bs2_(bs2)
128{
129 buffer_ = 0;
130}
131
132OneBodyInt::~OneBodyInt()
133{
134}
135
136int
137OneBodyInt::nbasis() const
138{
139 return bs1_->nbasis();
140}
141
142int
143OneBodyInt::nbasis1() const
144{
145 return bs1_->nbasis();
146}
147
148int
149OneBodyInt::nbasis2() const
150{
151 return bs2_->nbasis();
152}
153
154int
155OneBodyInt::nshell() const
156{
157 return bs1_->nshell();
158}
159
160int
161OneBodyInt::nshell1() const
162{
163 return bs1_->nshell();
164}
165
166int
167OneBodyInt::nshell2() const
168{
169 return bs2_->nshell();
170}
171
172Ref<GaussianBasisSet>
173OneBodyInt::basis()
174{
175 return bs1_;
176}
177
178Ref<GaussianBasisSet>
179OneBodyInt::basis1()
180{
181 return bs1_;
182}
183
184Ref<GaussianBasisSet>
185OneBodyInt::basis2()
186{
187 return bs2_;
188}
189
190const double *
191OneBodyInt::buffer() const
192{
193 return buffer_;
194}
195
196void
197OneBodyInt::reinitialize()
198{
199}
200
201bool
202OneBodyInt::cloneable()
203{
204 return false;
205}
206
207Ref<OneBodyInt>
208OneBodyInt::clone()
209{
210 throw std::runtime_error("OneBodyInt::clone() not implemented");
211}
212
213///////////////////////////////////////////////////////////////////////
214
215OneBodyOneCenterInt::OneBodyOneCenterInt(Integral* integral,
216 const Ref<GaussianBasisSet>&bs1) :
217 integral_(integral),
218 bs1_(bs1)
219{
220 buffer_ = 0;
221}
222
223OneBodyOneCenterInt::~OneBodyOneCenterInt()
224{
225}
226
227int
228OneBodyOneCenterInt::nbasis() const
229{
230 return bs1_->nbasis();
231}
232
233int
234OneBodyOneCenterInt::nbasis1() const
235{
236 return bs1_->nbasis();
237}
238
239int
240OneBodyOneCenterInt::nshell() const
241{
242 return bs1_->nshell();
243}
244
245int
246OneBodyOneCenterInt::nshell1() const
247{
248 return bs1_->nshell();
249}
250
251Ref<GaussianBasisSet>
252OneBodyOneCenterInt::basis()
253{
254 return bs1_;
255}
256
257Ref<GaussianBasisSet>
258OneBodyOneCenterInt::basis1()
259{
260 return bs1_;
261}
262
263const double *
264OneBodyOneCenterInt::buffer() const
265{
266 return buffer_;
267}
268
269void
270OneBodyOneCenterInt::reinitialize()
271{
272}
273
274bool
275OneBodyOneCenterInt::cloneable()
276{
277 return false;
278}
279
280Ref<OneBodyOneCenterInt>
281OneBodyOneCenterInt::clone()
282{
283 throw std::runtime_error("OneBodyOneCenterInt::clone() not implemented");
284}
285
286///////////////////////////////////////////////////////////////////////
287
288OneBodyOneCenterWrapper::OneBodyOneCenterWrapper(const Ref<OneBodyInt>& ob,
289 int jsh):
290 OneBodyOneCenterInt(ob->integral(),ob->basis1()),
291 ob_(ob),
292 jsh_(jsh)
293{
294 buffer_ = const_cast<double*>(ob_->buffer());
295}
296
297void
298OneBodyOneCenterWrapper::compute_shell(int ish)
299{
300 ob_->compute_shell(ish,jsh_);
301}
302
303
304///////////////////////////////////////////////////////////////////////
305
306ShellPairIter::ShellPairIter()
307{
308}
309
310ShellPairIter::~ShellPairIter()
311{
312}
313
314void
315ShellPairIter::init(const double * b, int ishell, int jshell,
316 int fi, int fj, int ni, int nj,
317 int red, double scl)
318{
319 e12 = ((ishell==jshell) && red);
320
321 ioffset=fi;
322 joffset=fj;
323
324 iend=ni;
325 jend=nj;
326
327 buf=b;
328 scale_=scl;
329}
330
331///////////////////////////////////////////////////////////////////////
332
333OneBodyIntIter::OneBodyIntIter()
334{
335}
336
337OneBodyIntIter::OneBodyIntIter(const Ref<OneBodyInt>& o) :
338 obi(o)
339{
340}
341
342OneBodyIntIter::~OneBodyIntIter()
343{
344}
345
346void
347OneBodyIntIter::start(int ist, int jst, int ien, int jen)
348{
349 istart=ist;
350 jstart=jst;
351 iend=ien;
352 jend=jen;
353
354 icur=istart;
355 jcur=jstart;
356
357 if (!iend) {
358 iend=obi->nshell1();
359 jend=obi->nshell2();
360 }
361
362 ij = (icur*(icur+1)>>1) + jcur;
363}
364
365static inline int
366min(int i, int j)
367{
368 return (i<j) ? i : j;
369}
370
371void
372OneBodyIntIter::next()
373{
374 int jlast = (redund) ? min(icur,jend-1) : jend-1;
375
376 if (jcur < jlast) {
377 jcur++;
378 ij++;
379 return;
380 }
381
382 jcur=jstart;
383 icur++;
384
385 ij = (icur*(icur+1)>>1) + jcur;
386}
387
388double
389OneBodyIntIter::scale() const
390{
391 return 1.0;
392}
393
394ShellPairIter&
395OneBodyIntIter::current_pair()
396{
397 obi->compute_shell(icur,jcur);
398 spi.init(obi->buffer(), icur, jcur,
399 obi->basis1()->shell_to_function(icur),
400 obi->basis2()->shell_to_function(jcur),
401 obi->basis1()->operator()(icur).nfunction(),
402 obi->basis2()->operator()(jcur).nfunction(),
403 redund, scale()
404 );
405
406 return spi;
407}
408
409bool
410OneBodyIntIter::cloneable()
411{
412 return obi->cloneable();
413}
414
415Ref<OneBodyIntIter>
416OneBodyIntIter::clone()
417{
418 return new OneBodyIntIter(obi->clone());
419}
420
421///////////////////////////////////////////////////////////////////////
422
423OneBodyIntOp::OneBodyIntOp(const Ref<OneBodyInt>& it)
424{
425 iter = new OneBodyIntIter(it);
426}
427
428OneBodyIntOp::OneBodyIntOp(const Ref<OneBodyIntIter>& it) :
429 iter(it)
430{
431}
432
433OneBodyIntOp::~OneBodyIntOp()
434{
435}
436
437bool
438OneBodyIntOp::cloneable()
439{
440 return iter->cloneable();
441}
442
443Ref<SCElementOp>
444OneBodyIntOp::clone()
445{
446 return new OneBodyIntOp(iter->clone());
447}
448
449void
450OneBodyIntOp::process(SCMatrixBlockIter& b)
451{
452 ExEnv::err0() << indent
453 << "OneBodyIntOp::process: cannot handle generic case\n";
454 abort();
455}
456
457void
458OneBodyIntOp::process_spec_rect(SCMatrixRectBlock* b)
459{
460 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
461 Ref<GaussianBasisSet> bs2 = iter->one_body_int()->basis2();
462
463 // convert basis function indices into shell indices
464 int ishstart = bs1->function_to_shell(b->istart);
465 int jshstart = bs2->function_to_shell(b->jstart);
466
467 int b1end = b->iend;
468 int ishend = (b1end?bs1->function_to_shell(b1end-1) + 1 : 0);
469
470 int b2end = b->jend;
471 int jshend = (b2end?bs2->function_to_shell(b2end-1) + 1 : 0);
472
473 int njdata = b->jend - b->jstart;
474
475 iter->set_redundant(0);
476
477 for (iter->start(ishstart,jshstart,ishend,jshend);
478 iter->ready(); iter->next()) {
479 ShellPairIter& spi = iter->current_pair();
480
481 for (spi.start(); spi.ready(); spi.next()) {
482 int ifn = spi.i();
483 int jfn = spi.j();
484
485 if (ifn < b->istart || ifn >= b->iend ||
486 jfn < b->jstart || jfn >= b->jend)
487 continue;
488
489 int data_index = (ifn - b->istart)*njdata + jfn - b->jstart;
490 b->data[data_index] += spi.val();
491 }
492 }
493}
494
495void
496OneBodyIntOp::process_spec_ltri(SCMatrixLTriBlock* b)
497{
498 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
499
500 // convert basis function indices into shell indices
501 int fnstart = b->start;
502 int fnend = b->end;
503 int shstart = bs1->function_to_shell(fnstart);
504 int shend = (fnend?bs1->function_to_shell(fnend - 1) + 1 : 0);
505
506 iter->set_redundant(1);
507
508 // loop over all needed shells
509 for (iter->start(shstart,shstart,shend,shend); iter->ready(); iter->next()) {
510 ShellPairIter& spi = iter->current_pair();
511
512 // compute a set of shell integrals
513 for (spi.start(); spi.ready(); spi.next()) {
514 int ifn = spi.i();
515 int jfn = spi.j();
516
517 if (ifn < fnstart || ifn >= fnend)
518 continue;
519
520 int ioff = ifn-fnstart;
521 int joff = jfn-fnstart;
522
523 int data_index = i_offset(ioff)+joff;
524
525 b->data[data_index] += spi.val();
526 }
527 }
528}
529
530void
531OneBodyIntOp::process_spec_rectsub(SCMatrixRectSubBlock* b)
532{
533 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
534 Ref<GaussianBasisSet> bs2 = iter->one_body_int()->basis2();
535
536 // convert basis function indices into shell indices
537 int istart = b->istart;
538 int jstart = b->jstart;
539 int iend = b->iend;
540 int jend = b->jend;
541
542 int ishstart = bs1->function_to_shell(istart);
543 int jshstart = bs2->function_to_shell(jstart);
544
545 int ishend = (iend ? bs1->function_to_shell(iend-1) + 1 : 0);
546 int jshend = (jend ? bs2->function_to_shell(jend-1) + 1 : 0);
547
548 int njdata = b->istride;
549
550 iter->set_redundant(0);
551
552 for (iter->start(ishstart,jshstart,ishend,jshend);
553 iter->ready(); iter->next()) {
554 ShellPairIter& spi = iter->current_pair();
555
556 for (spi.start(); spi.ready(); spi.next()) {
557 int ifn = spi.i();
558 int jfn = spi.j();
559
560 if (ifn < istart || ifn >= iend || jfn < jstart || jfn >= jend)
561 continue;
562
563 int data_index = ifn*njdata + jfn;
564 b->data[data_index] += spi.val();
565 }
566 }
567}
568
569void
570OneBodyIntOp::process_spec_ltrisub(SCMatrixLTriSubBlock* b)
571{
572 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
573
574 // convert basis function indices into shell indices
575 int istart = b->istart;
576 int iend = b->iend;
577
578 int jstart = b->jstart;
579 int jend = b->jend;
580
581 int ishstart = bs1->function_to_shell(istart);
582 int jshstart = bs1->function_to_shell(jstart);
583
584 int ishend = (iend ? bs1->function_to_shell(iend-1) + 1 : 0);
585 int jshend = (jend ? bs1->function_to_shell(jend-1) + 1 : 0);
586
587 iter->set_redundant(1);
588
589 // loop over all needed shells
590 for (iter->start(ishstart,jshstart,ishend,jshend);
591 iter->ready(); iter->next()) {
592 ShellPairIter& spi = iter->current_pair();
593
594 // compute a set of shell integrals
595 for (spi.start(); spi.ready(); spi.next()) {
596 int ifn = spi.i();
597 int jfn = spi.j();
598
599 if (ifn < istart || ifn >= iend || jfn < jstart || jfn >= jend)
600 continue;
601
602 int data_index = i_offset(ifn)+jfn;
603 b->data[data_index] += spi.val();
604 }
605 }
606}
607
608int
609OneBodyIntOp::has_side_effects()
610{
611 return 1;
612}
613
614///////////////////////////////////////////////////////////////////////
615
616OneBody3IntOp::OneBody3IntOp(const Ref<OneBodyInt>& it)
617{
618 iter = new OneBodyIntIter(it);
619}
620
621OneBody3IntOp::OneBody3IntOp(const Ref<OneBodyIntIter>& it) :
622 iter(it)
623{
624}
625
626OneBody3IntOp::~OneBody3IntOp()
627{
628}
629
630void
631OneBody3IntOp::process(SCMatrixBlockIter&,
632 SCMatrixBlockIter&,
633 SCMatrixBlockIter&)
634{
635 ExEnv::err0() << indent
636 << "OneBody3IntOp::process(SCMatrixBlockIter&): "
637 << "cannot handle generic case\n";
638 abort();
639}
640
641void
642OneBody3IntOp::process_spec_rect(SCMatrixRectBlock* a,
643 SCMatrixRectBlock* b,
644 SCMatrixRectBlock* c)
645{
646 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
647 Ref<GaussianBasisSet> bs2 = iter->one_body_int()->basis2();
648
649 // convert basis function indices into shell indices
650 int ishstart = bs1->function_to_shell(b->istart);
651 int jshstart = bs2->function_to_shell(b->jstart);
652
653 int ishend = bs1->function_to_shell(b->iend);
654 int jshend = bs2->function_to_shell(b->jend);
655
656 iter->set_redundant(0);
657
658 for (iter->start(ishstart,jshstart,ishend,jshend);
659 iter->ready(); iter->next()) {
660 // compute a set of shell integrals
661 ShellPairIter& spi = iter->current_pair();
662
663 for (spi.start(); spi.ready(); spi.next()) {
664 int ifn = spi.i();
665 int jfn = spi.j();
666
667 if (ifn < b->istart || ifn >= b->iend ||
668 jfn < b->jstart || jfn >= b->jend)
669 continue;
670
671#if 0
672 for (int i=0; i<nish; i++,ifn++) {
673 if (ifn < b->istart || ifn >= b->iend) {
674 tmp += njsh * 3;
675 }
676 else {
677 int jfn = jfnsave;
678 int data_index = (ifn - b->istart)*njdata + jfn - b->jstart;
679 for (int j=0; j<njsh; j++,jfn++) {
680 if (jfn >= b->jstart && jfn < b->jend) {
681 a->data[data_index] += tmp[0] * scale;
682 b->data[data_index] += tmp[1] * scale;
683 c->data[data_index] += tmp[2] * scale;
684 data_index++;
685 }
686 tmp += 3;
687 }
688 }
689 }
690#endif
691 }
692 }
693}
694
695void
696OneBody3IntOp::process_spec_ltri(SCMatrixLTriBlock* a,
697 SCMatrixLTriBlock* b,
698 SCMatrixLTriBlock* c)
699{
700#if 0
701 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
702
703 // convert basis function indices into shell indices
704 int fnstart = b->start;
705 int fnend = b->end;
706 int shstart = bs1->function_to_shell(fnstart);
707 int shend = (fnend?bs1->function_to_shell(fnend - 1) + 1 : 0);
708
709 // loop over all needed shells
710 iter->reset(shstart, shend, 0, 0);
711 for (iter->start_ltri(); iter->ready_ltri(); iter->next_ltri()) {
712 int ish=iter->ishell();
713 int jsh=iter->jshell();
714
715 int nish = bs1->operator[](ish).nfunction();
716 int njsh = bs1->operator[](jsh).nfunction();
717
718 double scale = iter->scale();
719
720 // compute a set of shell integrals
721 compute_shell(ish,jsh,buffer_);
722
723 // take the integrals from buffer and put them into the LTri block
724 double*tmp = buffer_;
725 int ifn = bs1->shell_to_function(ish);
726 int jfnsave = bs1->shell_to_function(jsh);
727 for (int i=0; i<nish; i++,ifn++) {
728 // skip over basis functions that are not needed
729 if (ifn < fnstart || ifn >= fnend) {
730 tmp += njsh * 3;
731 }
732 else {
733 int jfn = jfnsave;
734 int irelfn = ifn - fnstart;
735 int data_index = ((irelfn+1)*irelfn>>1) + jfn - fnstart;
736 for (int j=0; j<njsh; j++,jfn++) {
737 // skip over basis functions that are not needed
738 if (jfn <= ifn && jfn >= fnstart) {
739 a->data[data_index] += tmp[0] * scale;
740 b->data[data_index] += tmp[1] * scale;
741 c->data[data_index] += tmp[2] * scale;
742 data_index++;
743 }
744 tmp += 3;
745 }
746 }
747 }
748 }
749#endif
750}
751
752int
753OneBody3IntOp::has_side_effects()
754{
755 return 1;
756}
757
758int
759OneBody3IntOp::has_side_effects_in_arg1()
760{
761 return 1;
762}
763
764int
765OneBody3IntOp::has_side_effects_in_arg2()
766{
767 return 1;
768}
769
770///////////////////////////////////////////////////////////////////////
771
772OneBodyDerivInt::OneBodyDerivInt(Integral *integral,
773 const Ref<GaussianBasisSet>&b) :
774 integral_(integral),
775 bs1(b), bs2(b)
776{
777 // allocate a buffer
778 int biggest_shell = b->max_nfunction_in_shell();
779 biggest_shell *= biggest_shell * 3;
780
781 if (biggest_shell) {
782 buffer_ = new double[biggest_shell];
783 } else {
784 buffer_ = 0;
785 }
786}
787
788OneBodyDerivInt::OneBodyDerivInt(Integral *integral,
789 const Ref<GaussianBasisSet>&b1,
790 const Ref<GaussianBasisSet>&b2) :
791 integral_(integral),
792 bs1(b1), bs2(b2)
793{
794 buffer_ = 0;
795}
796
797OneBodyDerivInt::~OneBodyDerivInt()
798{
799}
800
801int
802OneBodyDerivInt::nbasis() const
803{
804 return bs1->nbasis();
805}
806
807int
808OneBodyDerivInt::nbasis1() const
809{
810 return bs1->nbasis();
811}
812
813int
814OneBodyDerivInt::nbasis2() const
815{
816 return bs2->nbasis();
817}
818
819int
820OneBodyDerivInt::nshell() const
821{
822 return bs1->nshell();
823}
824
825int
826OneBodyDerivInt::nshell1() const
827{
828 return bs1->nshell();
829}
830
831int
832OneBodyDerivInt::nshell2() const
833{
834 return bs2->nshell();
835}
836
837Ref<GaussianBasisSet>
838OneBodyDerivInt::basis()
839{
840 return bs1;
841}
842
843Ref<GaussianBasisSet>
844OneBodyDerivInt::basis1()
845{
846 return bs1;
847}
848
849Ref<GaussianBasisSet>
850OneBodyDerivInt::basis2()
851{
852 return bs2;
853}
854
855const double *
856OneBodyDerivInt::buffer() const
857{
858 return buffer_;
859}
860
861///////////////////////////////////////////////////////////////////////
862
863OneBodyOneCenterDerivInt::OneBodyOneCenterDerivInt(Integral *integral,
864 const Ref<GaussianBasisSet>&b) :
865 integral_(integral),
866 bs1(b)
867{
868 // allocate a buffer
869 int biggest_shell = b->max_nfunction_in_shell();
870 biggest_shell *= biggest_shell * 3;
871
872 if (biggest_shell) {
873 buffer_ = new double[biggest_shell];
874 } else {
875 buffer_ = 0;
876 }
877}
878
879OneBodyOneCenterDerivInt::~OneBodyOneCenterDerivInt()
880{
881}
882
883int
884OneBodyOneCenterDerivInt::nbasis() const
885{
886 return bs1->nbasis();
887}
888
889int
890OneBodyOneCenterDerivInt::nbasis1() const
891{
892 return bs1->nbasis();
893}
894
895int
896OneBodyOneCenterDerivInt::nshell() const
897{
898 return bs1->nshell();
899}
900
901int
902OneBodyOneCenterDerivInt::nshell1() const
903{
904 return bs1->nshell();
905}
906
907Ref<GaussianBasisSet>
908OneBodyOneCenterDerivInt::basis()
909{
910 return bs1;
911}
912
913Ref<GaussianBasisSet>
914OneBodyOneCenterDerivInt::basis1()
915{
916 return bs1;
917}
918
919const double *
920OneBodyOneCenterDerivInt::buffer() const
921{
922 return buffer_;
923}
924
925/////////////////////////////////////////////////////////////////////////////
926
927// Local Variables:
928// mode: c++
929// c-file-style: "ETS"
930// End:
Note: See TracBrowser for help on using the repository browser.